add fixes for service validator and serializator
This commit is contained in:
parent
ebbe667c9d
commit
600fdaee0c
@ -1,129 +1,61 @@
|
|||||||
ROLE = """
|
ROLE = """
|
||||||
Вы являетесь опытным маркетологом в компании,
|
Вы являетесь опытным маркетологом в компании,
|
||||||
которая разрабатывает программное обеспечение любой сложности на основе аутсорсинга.
|
которая разрабатывает программное обеспечение любой сложности на основе аутсорсинга.
|
||||||
|
Компания специализируется на:
|
||||||
|
✓ Backend: Python, ...
|
||||||
|
✓ Frontend: React, JS, CSS
|
||||||
|
✓ Мобильная разработка: Flutter, iOS/Android (Kotlin/Swift)
|
||||||
|
✓ Data Science & AI: машинное обучение, компьютерное зрение
|
||||||
|
✓ Кибербезопасность
|
||||||
|
|
||||||
Ваша задача — анализировать переписку и находить потенциальных клиентов, которым нужна разработка ПО.
|
Ваша задача — анализировать переписку и находить потенциальных клиентов, которым нужна разработка ПО.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ANALYTIC_PROMT = """
|
ANALYTIC_PROMPT = """
|
||||||
Ты получаешь json с такими полями
|
Ты получаешь json с такими полями:
|
||||||
{
|
{
|
||||||
chats: [
|
"chats": [
|
||||||
"slice_id": UUID4
|
{
|
||||||
|
"slice_id": "UUID4",
|
||||||
"messages": [
|
"messages": [
|
||||||
{
|
{
|
||||||
"user_id: integer,
|
"user_id": integer,
|
||||||
"message_id": integer,
|
"message_id": integer,
|
||||||
"text": string,
|
"text": string,
|
||||||
"date": datetime
|
"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: [
|
|
||||||
{
|
|
||||||
"user_id": integer,
|
|
||||||
"slice_id": integer,
|
|
||||||
"reason": string
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
поле 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",
|
"role": "user",
|
||||||
"parts": [
|
"parts": [
|
||||||
{"text": ROLE},
|
{"text": ROLE},
|
||||||
{"text": ANALYTIC_PROMT},
|
{"text": ANALYTIC_PROMPT},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -1,9 +1,12 @@
|
|||||||
import json
|
import json
|
||||||
|
from json import JSONDecodeError
|
||||||
|
from typing import List
|
||||||
|
|
||||||
import google.generativeai as genai
|
import google.generativeai as genai
|
||||||
|
from pydantic import ValidationError
|
||||||
|
|
||||||
from src.gemini_sdk.promt import GEMINI_BASE_MESSAGE
|
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.schemas import MessagesForSendToWorkersSchema
|
||||||
from src.settings.base import settings
|
from src.settings.base import settings
|
||||||
|
|
||||||
@ -16,53 +19,48 @@ class GoogleHelper:
|
|||||||
) -> None:
|
) -> None:
|
||||||
self.api_key = api_key
|
self.api_key = api_key
|
||||||
self.model = model_name
|
self.model = model_name
|
||||||
|
|
||||||
genai.configure(api_key=api_key)
|
genai.configure(api_key=api_key)
|
||||||
self._model = genai.GenerativeModel(model_name=model_name)
|
self._model = genai.GenerativeModel(model_name=model_name)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _serialize_messages_to_promt(
|
def _serialize_messages_to_prompt(
|
||||||
chats: MessagesForSendToWorkersSchema,
|
chats: MessagesForSendToWorkersSchema,
|
||||||
) -> list[dict]:
|
) -> List[dict]:
|
||||||
messages_for_request = GEMINI_BASE_MESSAGE.copy()
|
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 = {
|
extend_message = {
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"parts": [
|
"parts": [{"text": text_for_request}],
|
||||||
{
|
|
||||||
"text": text_for_request,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
messages_for_request.append(extend_message)
|
messages_for_request.append(extend_message)
|
||||||
|
|
||||||
return messages_for_request
|
return messages_for_request
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _serialize_response_to_json(
|
def _serialize_response_to_json(
|
||||||
response_text: str,
|
response_text: str,
|
||||||
) -> ResponseFromGeminiSchema:
|
) -> ResponseFromGeminiSchema:
|
||||||
response = response_text.replace('\n', '')
|
try:
|
||||||
response_as_dict = json.loads(response_text)
|
# Удаляем возможные обертки и форматирование
|
||||||
|
cleaned_response = response_text.strip().replace('```json\n', '').replace('\n```', '')
|
||||||
|
response_as_dict = json.loads(cleaned_response)
|
||||||
return ResponseFromGeminiSchema(**response_as_dict)
|
return ResponseFromGeminiSchema(**response_as_dict)
|
||||||
|
except (JSONDecodeError, ValidationError) as e:
|
||||||
|
# Логирование ошибки можно добавить здесь
|
||||||
|
return ResponseFromGeminiSchema(success=None)
|
||||||
|
|
||||||
def create_request_ai(
|
def create_request_ai(
|
||||||
self,
|
self,
|
||||||
messages: MessagesForSendToWorkersSchema,
|
messages: MessagesForSendToWorkersSchema,
|
||||||
) -> ResponseFromGeminiSchema:
|
) -> ResponseFromGeminiSchema:
|
||||||
contents = self._serialize_messages_to_promt(messages)
|
contents = self._serialize_messages_to_prompt(messages)
|
||||||
response = self._model.generate_content(
|
response = self._model.generate_content(contents=contents)
|
||||||
contents=contents
|
|
||||||
)
|
|
||||||
|
|
||||||
return self._serialize_response_to_json(response.text)
|
return self._serialize_response_to_json(response.text)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gemini_helper = GoogleHelper(
|
gemini_helper = GoogleHelper(
|
||||||
api_key=settings.GEMINI.API_KEY,
|
api_key=settings.GEMINI.API_KEY,
|
||||||
model_name=settings.GEMINI.MODEL_NAME,
|
model_name=settings.GEMINI.MODEL_NAME,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user