From 600fdaee0c61d5543b0c8121f5fa1493798e6632 Mon Sep 17 00:00:00 2001 From: harold Date: Sun, 20 Apr 2025 14:26:10 +0500 Subject: [PATCH] add fixes for service validator and serializator --- gemini_worker/src/gemini_sdk/promt.py | 154 +++++++----------------- gemini_worker/src/gemini_sdk/service.py | 42 +++---- 2 files changed, 63 insertions(+), 133 deletions(-) diff --git a/gemini_worker/src/gemini_sdk/promt.py b/gemini_worker/src/gemini_sdk/promt.py index cc0083c..eabfb33 100644 --- a/gemini_worker/src/gemini_sdk/promt.py +++ b/gemini_worker/src/gemini_sdk/promt.py @@ -1,129 +1,61 @@ ROLE = """ Вы являетесь опытным маркетологом в компании, которая разрабатывает программное обеспечение любой сложности на основе аутсорсинга. - Ваша задача — анализировать переписку и находить потенциальных клиентов, которым нужна разработка ПО. + Компания специализируется на: +✓ Backend: Python, ... +✓ Frontend: React, JS, CSS +✓ Мобильная разработка: Flutter, iOS/Android (Kotlin/Swift) +✓ Data Science & AI: машинное обучение, компьютерное зрение +✓ Кибербезопасность + +Ваша задача — анализировать переписку и находить потенциальных клиентов, которым нужна разработка ПО. """ -ANALYTIC_PROMT = """ -Ты получаешь json с такими полями +ANALYTIC_PROMPT = """ +Ты получаешь json с такими полями: { - chats: [ - "slice_id": UUID4 - "messages": [ - { - "user_id: integer, - "message_id": integer, - "text": string, - "date": datetime - } - ] - - ] -} - -chats - это список чатов. -messages - Это представляет собой беседу в чате. - -ВАЖНО. Каждый slice_id это отдельный чат и они не связаны между собой. - -user_id никак не учитывается в обработке смысла диалога. - - -Анализируйте только текст сообщений, игнорируя рекламные хэштеги и подписи. Реагируйте исключительно на технико-коммерческие предложения с четкими параметрами. - -Критерии отбора. Обязательные условия: - -1. Четкое описание проекта/проблемы - -2. Упоминание технологий или типа разработки - -3. Наличие хотя бы одного из: -✓ Бюджета/сроков -✓ Технического задания -✓ Бизнес-цели проекта - -3. Ключевые фразы (только с конкретикой): -✓ "Нужна разработка [тип системы] для [цель]" -✓ "Ищем разработчиков для [конкретный проект]" -✓ "Требуется автоматизация [процесс] с использованием [технология]" -✓ "Готовы инвестировать в разработку [чего именно]" - -Примеры валидных запросов: -"Нужна команда для разработки ERP-системы на Python, бюджет 1.5 млн руб" -"Ищем подрядчика для интеграции API нашего CRM с телефонией" -"Хотим автоматизировать учет товаров на складе. Сейчас всё в Excel, нужна система с API для подключения" -"Ищем подрядчика для создания мобильного приложения под iOS/Android" -"Проблемы с нагрузкой на текущий BI-инструмент. Ищем решение для обработки 1 млн+ строк данных в день" -"Нужна команда для создания MVP: бэкенд (Node.js), фронтенд (React), мобильное приложение." -"Текущий разработчик пропал. Нужен срочный аудит кода и исправление багов в модуле оплат" - -Фильтры исключения: - -Любые упоминания: -✓ Заработка/дохода/инвестиционных схем -✓ Подработки/удаленной работы без технических деталей -✓ Партнерских программ -✓ Вакансий не связанных с разработкой - -Сообщения содержащие: -✓ "пишите в ЛС/личку" -✓ "напишите '+'/комментарий" -✓ "интересует? писать..." -✓ "быстрый старт" -✓ "без вложений" -✓ Более 3 эмодзи/восклицательных знаков -✓ Гиперболы ("золотая возможность", "гарантированный доход") - -Финансовые маркеры: -✓ Любые упоминания: "доход/заработок/прибыль" + временной период -✓ "инвестиции" без технического контекста -✓ "пассивный доход", "подработка", "выгодные условия" -✓ "удаленная работа", "гибкий график" -✓ "оплата ежедневно/еженедельно" - -Бот-активность: -✓ Сообщения от ботов (содержащие "нажмите кнопку", "верификация") -✓ Автоматические уведомления -✓ Повторяющиеся идентичные сообщения -✓ Контекстные исключения: -✓ Обсуждения вакансий/услуг (менеджеры, выгул собак и т.д.) -✓ Сообщения короче 5 слов без технических деталей - -Примеры автоматического отклонения: -✓ "Нужны 2 человека для работы с телефоном" -✓ "Доход $500 в неделю, пишите '+'" -✓ Любые сообщения ботов о верификации -✓ "Ищем партнеров для заработка" - -Дополнительные правила: -✓ Игнорируйте диалоги, где более 50% сообщений попадают под фильтры исключения -✓ Отклоняйте сообщения с упоминанием "менеджер", если нет технических требований -✓ Не анализируйте повторяющиеся сообщения (дубли) - - -Условно в нескольких чатах может быть несколько потенциальных клиентов, тогда вот так выведи - -{ - success: [ + "chats": [ + { + "slice_id": "UUID4", + "messages": [ { - "user_id": integer, - "slice_id": integer, - "reason": string + "user_id": integer, + "message_id": integer, + "text": string, + "date": "datetime" } - ] + ] + } + ] } -поле reason: Кратко(до 100 симоволов) почему ты решил, что это потенциальный клиент. +Анализируй каждый чат отдельно. Ответ должен быть ТОЛЬКО в JSON формате, без каких-либо пояснений или форматирования. -Если ты хотя бы чуть чуть не уверен, то верни вот такую строку +Пример правильного ответа: { - success: null + "success": [ + { + "user_id": 123, + "slice_id": "550e8400-e29b-41d4-a716-446655440000", + "reason": "Упоминание разработки мобильного приложения с указанием технологий" + } + ] } +Если нет четких признаков или есть сомнения, верни: +{"success": null} -ВАЖНО: Ты должен вернуть ТОЛЬКО JSON и не словом больше. Иначе я разорюсь. -без ```json ``` просто так без каких либо спецсимволов +Правила анализа: +1. Игнорируй сообщения с рекламой, вакансиями или заработком +2. Обращай внимание на технические требования и конкретные цели +3. Проверяй наличие бюджета/сроков/технического задания +4. Отклоняй сообщения с чрезмерными эмодзи или восклицаниями +Критерии положительного решения: +- Четкое описание проекта +- Указание технологий/платформы +- Наличие сроков/бюджета/техзадания +- Конкретные бизнес-цели """ @@ -132,7 +64,7 @@ GEMINI_BASE_MESSAGE = [ "role": "user", "parts": [ {"text": ROLE}, - {"text": ANALYTIC_PROMT}, + {"text": ANALYTIC_PROMPT}, ] } ] \ No newline at end of file diff --git a/gemini_worker/src/gemini_sdk/service.py b/gemini_worker/src/gemini_sdk/service.py index dd9b93e..e15a498 100644 --- a/gemini_worker/src/gemini_sdk/service.py +++ b/gemini_worker/src/gemini_sdk/service.py @@ -1,9 +1,12 @@ import json +from json import JSONDecodeError +from typing import List import google.generativeai as genai +from pydantic import ValidationError from src.gemini_sdk.promt import GEMINI_BASE_MESSAGE -from src.gemini_sdk.schemas import FullRequestForGeminiSchema, ResponseFromGeminiSchema +from src.gemini_sdk.schemas import ResponseFromGeminiSchema from src.schemas import MessagesForSendToWorkersSchema from src.settings.base import settings @@ -16,53 +19,48 @@ class GoogleHelper: ) -> None: self.api_key = api_key self.model = model_name - genai.configure(api_key=api_key) self._model = genai.GenerativeModel(model_name=model_name) @staticmethod - def _serialize_messages_to_promt( + def _serialize_messages_to_prompt( chats: MessagesForSendToWorkersSchema, - ) -> list[dict]: + ) -> List[dict]: messages_for_request = GEMINI_BASE_MESSAGE.copy() - text_for_request = json.dumps(chats.model_dump_json()) + # Исправлена двойная сериализация + text_for_request = json.dumps(chats.model_dump(mode='json')) extend_message = { "role": "user", - "parts": [ - { - "text": text_for_request, - } - ], + "parts": [{"text": text_for_request}], } messages_for_request.append(extend_message) - return messages_for_request @staticmethod def _serialize_response_to_json( - response_text: str, + response_text: str, ) -> ResponseFromGeminiSchema: - response = response_text.replace('\n', '') - response_as_dict = json.loads(response_text) - - return ResponseFromGeminiSchema(**response_as_dict) + try: + # Удаляем возможные обертки и форматирование + cleaned_response = response_text.strip().replace('```json\n', '').replace('\n```', '') + response_as_dict = json.loads(cleaned_response) + return ResponseFromGeminiSchema(**response_as_dict) + except (JSONDecodeError, ValidationError) as e: + # Логирование ошибки можно добавить здесь + return ResponseFromGeminiSchema(success=None) def create_request_ai( self, messages: MessagesForSendToWorkersSchema, ) -> ResponseFromGeminiSchema: - contents = self._serialize_messages_to_promt(messages) - response = self._model.generate_content( - contents=contents - ) - + contents = self._serialize_messages_to_prompt(messages) + response = self._model.generate_content(contents=contents) return self._serialize_response_to_json(response.text) - gemini_helper = GoogleHelper( api_key=settings.GEMINI.API_KEY, model_name=settings.GEMINI.MODEL_NAME,