Первый коммит: модульный монолит ядра (.NET 10) и gRPC-сервисы ai/ml/telegram, фронтенд Vue 3/Vite/Tailwind, документация (ТЗ, инструкция пользователя, техдокументация, код-стайл), бэклог, скрипты развёртывания и архив прототипа LeadRadar.
2.8 KiB
2.8 KiB
Task 5: Оценка контента (язык, темы, fit по профилю задачи)
Files:
- Create:
backend/app/services/discovery_eval.py
Interfaces:
-
Consumes:
store,ml_client,ai_service(chat_json),pipeline.clean_short. -
Produces:
def detect_lang_ru(texts: list[str]) -> bool | None— доля кириллических букв от всех букв в сумме:>=0.15 → True;<=0.03 → False; между порогами →None(неопределённо).def group_by_topic(messages: list[dict]) -> list[dict]— группировка поtopic_id(None → "main"); возвращает[{"topic_id", "title", "messages": [...]}], title = сниппет первого текста темы (≤60 симв.), сортировка по количеству сообщений (убыв.).async def evaluate_message(task: dict, text: str) -> dict—{"fit": bool, "reason": str, "source": "heuristic"|"ml"|"ai"}:- текст пустой/длина <10 → fit False «слишком короткое»;
- ML: если
ml_client.is_enabled()и прогнозtakeиlabel=='spam'→ fit False «ML: спам»; - ИИ: если
aiEnabled→ один JSON-вызовai_service.chat_json(промпт, user=text)с промптом из описания задачи и ключей ({fit, reason}); ошибка → шаг 4; - эвристика: fit = любой ключ входит в
clean_short(text)casefold; reason «совпал ключ "…"» / «нет совпадений с ключами».
async def evaluate_sample(task: dict, messages: list[dict]) -> dict— последовательно по каждому сообщению; вернуть{"fit_count": int, "total": int, "fit_ratio": float, "per_message": [{"text": …, "fit", "reason", "topic_id"}]}.def passed(ev: dict, task: dict) -> bool—ev["total"] >= 3 and ev["fit_ratio"]*100 >= task["threshold"].
-
Step 1: Реализовать модуль. Промпт ИИ (внутри модуля, константа):
Оцени, относится ли сообщение к сфере/задаче. Описание: {description}. Ключи: {keywords}. Верни JSON {"fit": 0|1, "reason": "краткая причина"}. -
Step 2: Проверить на временной БД (без сети):
detect_lang_ru(["Ищем python разработчика"]) is True;detect_lang_ru(["we need a python developer"]) is False;group_by_topicобъединяет по topic_id и сортирует;evaluate_messageна задаче без ИИ/ML возвращает эвристический fit по ключу.