feat: added integration with yandexgpt
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# ruff: noqa: E501, W291
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from yandex_cloud_ml_sdk import YCloudML
|
||||
from yandex_cloud_ml_sdk.exceptions import YCloudMLError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
AD_PROMPT_TEMPLATE = """
|
||||
Сгенерируй креативный рекламный текст для рекламодателя с именем: "{advertiser_name}",
|
||||
название рекламной кампании: "{ad_title}".
|
||||
|
||||
Требования:
|
||||
1. Текст должен быть максимально привлекательным и продающим
|
||||
2. Использовать современные маркетинговые приемы
|
||||
3. Включить призыв к действию
|
||||
4. Соблюдать структуру: заголовок - основной текст - заключение
|
||||
5. Длина: 3-5 коротких предложений
|
||||
6. Ответ должен содержать только текст рекламы без дополнительных комментариев
|
||||
7. Весь текст должен быть на одной строчке
|
||||
|
||||
Пример хорошего текста:
|
||||
"Запустите свой бизнес в космос с {{advertiser_name}}! Кампания "{{ad_title}}" предлагает
|
||||
уникальные решения для цифрового продвижения. Присоединяйтесь к лидерам рынка - получите
|
||||
персональную консультацию сегодня!"
|
||||
""".strip()
|
||||
|
||||
|
||||
class YandexAIAdTextGenerator:
|
||||
def __init__(self) -> None:
|
||||
self.sdk = YCloudML(
|
||||
folder_id=settings.YANDEX_CLOUD_FOLDER_ID,
|
||||
auth=settings.YANDEX_CLOUD_API_KEY,
|
||||
)
|
||||
|
||||
def generate_ad_text(
|
||||
self, advertiser_name: str, ad_title: str
|
||||
) -> str | None:
|
||||
try:
|
||||
prompt = AD_PROMPT_TEMPLATE.format(
|
||||
advertiser_name=advertiser_name, ad_title=ad_title
|
||||
)
|
||||
|
||||
promise = (
|
||||
self.sdk.models.completions(
|
||||
"yandexgpt-lite", model_version="latest"
|
||||
)
|
||||
.configure(max_tokens=400, temperature=0.9)
|
||||
.run_deferred([{"role": "system", "text": prompt}])
|
||||
)
|
||||
|
||||
result = promise.wait()
|
||||
logger.debug("Generated ad text: %s", result)
|
||||
|
||||
return self._clean_response(result.alternatives[0].text)
|
||||
|
||||
except YCloudMLError:
|
||||
return None
|
||||
|
||||
def _clean_response(self, text: str) -> str:
|
||||
cleaned = text.strip()
|
||||
cleaned = cleaned.replace('"', "")
|
||||
return " ".join(cleaned.splitlines())
|
||||
@@ -0,0 +1,25 @@
|
||||
from django.conf import settings
|
||||
from health_check.backends import BaseHealthCheckBackend
|
||||
from yandex_cloud_ml_sdk import YCloudML
|
||||
from yandex_cloud_ml_sdk.exceptions import YCloudMLError
|
||||
|
||||
|
||||
class YandexAIHealthCheck(BaseHealthCheckBackend):
|
||||
critical_service = False
|
||||
|
||||
def check_status(self) -> None:
|
||||
try:
|
||||
sdk = YCloudML(
|
||||
folder_id=settings.YANDEX_CLOUD_FOLDER_ID,
|
||||
auth=settings.YANDEX_CLOUD_API_KEY,
|
||||
)
|
||||
result = sdk.models.completions(
|
||||
"yandexgpt-lite", model_version="latest"
|
||||
).tokenize("ping")
|
||||
if not result:
|
||||
self.add_error("YandexAI API is unaccessible")
|
||||
except YCloudMLError:
|
||||
self.add_error("YandexAI API is unaccessible")
|
||||
|
||||
def identifier(self) -> str:
|
||||
return self.__class__.__name__
|
||||
@@ -0,0 +1,57 @@
|
||||
# ruff: noqa: E501, W291
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
from yandex_cloud_ml_sdk import YCloudML
|
||||
from yandex_cloud_ml_sdk.exceptions import YCloudMLError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_INVALID_SIGNAL = (
|
||||
"В интернете есть много сайтов с информацией на эту тему. "
|
||||
"[Посмотрите, что нашлось в поиске](https://ya.ru)"
|
||||
).lower()
|
||||
|
||||
MODERATION_PROMPT = """
|
||||
Ты — строгий AI-модератор контента. Анализируй текст ПО ВСЕМ указанным критериям.
|
||||
Если ЛЮБОЙ из критериев нарушен — верни true. Только если ВСЕ критерии соблюдены — верни false.
|
||||
|
||||
Критерии нарушений (true):
|
||||
1. Нецензурная лексика: мат, эвфемизмы, оскорбительные выражения
|
||||
2. Угрозы: прямые/косвенные угрозы жизни, шантаж, буллинг
|
||||
3. Дискриминация: расизм, сексизм, ксенофобия, гомофобия
|
||||
""".strip()
|
||||
|
||||
|
||||
class YandexAIModerator:
|
||||
def __init__(self) -> None:
|
||||
self.sdk = YCloudML(
|
||||
folder_id=settings.YANDEX_CLOUD_FOLDER_ID,
|
||||
auth=settings.YANDEX_CLOUD_API_KEY,
|
||||
)
|
||||
|
||||
def get_moderation_verdict(self, text: str) -> bool:
|
||||
try:
|
||||
promise = (
|
||||
self.sdk.models.completions(
|
||||
"yandexgpt-lite", model_version="latest"
|
||||
)
|
||||
.configure(max_tokens=200, temperature=0.1)
|
||||
.run_deferred(
|
||||
[
|
||||
{"role": "system", "text": MODERATION_PROMPT},
|
||||
{"role": "user", "text": text},
|
||||
]
|
||||
)
|
||||
)
|
||||
result = promise.wait()
|
||||
logger.debug("Moderation API response: %s", result)
|
||||
|
||||
return self._normalize_response(result.alternatives[0].text)
|
||||
|
||||
except YCloudMLError:
|
||||
return False
|
||||
|
||||
def _normalize_response(self, text: str) -> bool:
|
||||
clean_verdict = text.strip().lower().split("\n")[0]
|
||||
return clean_verdict in ("true", DEFAULT_INVALID_SIGNAL)
|
||||
Reference in New Issue
Block a user