Add full README
CI / lint_and_test (push) Successful in 2m30s Details

This commit is contained in:
itqop 2025-07-19 19:42:03 +03:00
parent 79b773f843
commit 9f616aaf1d
1 changed files with 346 additions and 0 deletions

346
README.md
View File

@ -6,3 +6,349 @@
Сервис для генерации персонализированных холодных писем с использованием RAG и LangGraph. Сервис для генерации персонализированных холодных писем с использованием RAG и LangGraph.
## О программе
- Персонализация писем под роль, индустрию и компанию лида
- RAG-подход с базой знаний реальных кейсов
- LangGraph пайплайн обработки запросов
- Векторный поиск в ChromaDB
- Поддержка OpenAI и Google Gemini
- RESTful API для интеграции с CRM
### Логика работы
Система обрабатывает запросы через 10-этапный LangGraph пайплайн:
1. **Валидация входа** - проверка обязательных полей лида
2. **Извлечение признаков** - нормализация роли, индустрии из входных данных
3. **Построение запроса** - формирование поискового запроса на основе профиля лида
4. **Векторный поиск** - поиск релевантных кейсов в ChromaDB (top-30)
5. **Ранжирование контекста** - отбор лучших кейсов (top-6) и создание bullets
6. **Построение промпта** - формирование системного и пользовательского промптов
7. **LLM генерация** - создание письма через OpenAI/Gemini
8. **Парсинг ответа** - извлечение JSON с темой и телом письма
9. **Проверка качества** - валидация длины, структуры, наличия CTA
10. **Формирование результата** - финальная структура ответа с метаданными
## Промпт-инжиниринг: обоснование подхода
### Почему именно такая структура письма?
Структура **Приветствие -> Хук -> Ценность -> Кейс -> CTA -> Подпись** выбрана на основе исследований конверсии холодных писем:
**1. Приветствие по имени**
- Персонализация создает впечатление индивидуального подхода
- Снижает восприятие письма как спама
**2. Хук-вопрос в первых строках**
- Привлекает внимание и активирует любопытство
- Касается специфики индустрии лида -> создает ощущение релевантности
**3. Конкретная ценность с цифрами**
- Мозг лучше воспринимает конкретные числа vs абстракции
- "15 минут" vs "быстро", "95%" vs "значительно"
- Снижает скептицизм -> повышает доверие
**4. Социальное доказательство с кейсом**
- Название реальной компании + численный результат
- Психология: "если помогли похожей компании, помогут и нам"
- Снижает воспринимаемый риск принятия решения
**5. Мягкий CTA без давления**
- "Если интересно" vs "Давайте встретимся завтра"
- Оставляет ощущение выбора -> снижает сопротивление
- 15-минутный формат -> низкий барьер входа
**6. Эмоциональные триггеры**
- "Спокойствие", "контроль" -> позитивные эмоции от решения проблем
- "Избежите", "снизьте риски" -> страх потерь (loss aversion)
- Комбинация мотивирует к действию
### Ограничения для максимальной эффективности
- **≤ 1000 символов**: оптимальная длина письма для цифрового потребления. Согласно Nielsen Norman Group, пользователи читают в среднем 2028% текста на веб-странице и быстро теряют внимание после первых 200250 слов (~10001200 символов).
Источник: [How Users Read on the Web](https://www.nngroup.com/articles/how-users-read-on-the-web/)
- **Микро-абзацы 1-2 предложения**: улучшают восприятие текста на экранах смартфонов. Люди сканируют информацию взглядом, и короткие абзацы помогают быстрее вычленять ключевые мысли.
Источник: [F-Shaped Pattern of Reading Web Content](https://www.nngroup.com/articles/f-shaped-pattern-reading-web-content/)
- **1 конкретный CTA**: письма с одним призывом к действию получают на **371% больше кликов** и могут увеличить доход на **1617%** по сравнению с письмами с несколькими CTA.
Источник: [Unlayer - Call to Action in Emails](https://unlayer.com/blog/call-to-action-in-emails)
### Настройка промптов
Системные промпты: `src/services/prompt_templates.py`
- Тон: деловой, лаконичный, дружелюбный
- Длина: до 1000 символов
- Структура: Приветствие -> Хук -> Ценность -> Кейс -> CTA -> Подпись
## Быстрый старт
### 1. Подготовка окружения
```bash
git clone https://git.itqop.pw/itqop/ai-email-assistant.git
cd ai-email-assistant
# Создание конфигурации
cp .env.example .env
# Или создайте .env файл сами
```
### 2. Базовая конфигурация .env
```bash
LLM_PROVIDER=openai
OPENAI_API_KEY=your_openai_api_key_here
API_SECRET_KEY=your_admin_token
```
### 3. Запуск через Docker
```bash
docker compose up --build
```
### 4. Загрузка базы знаний
```bash
curl -X POST "http://localhost:8000/api/v1/admin/ingest" \
-H "Authorization: Bearer your_admin_token"
```
### 5. Использование
```bash
curl -X POST "http://localhost:8000/api/v1/generate_email" \
-H "Content-Type: application/json" \
-d '{
"contact": "Помящий Никита",
"position": "Технический директор",
"company_name": "FIVE",
"segment": "маркетинговое агентство"
}'
```
## Альтернативный запуск (без Docker)
```bash
# Создание виртуального окружения
python -m venv .venv
.venv\Scripts\activate # Windows
source .venv/bin/activate # Linux/Mac
# Установка зависимостей
pip install -r requirements.txt
# Загрузка данных
python -m src.ingest.ingest_cli --data-dir articles_konsol_pro --recreate
# Запуск сервиса
python -m src.app.main
```
## API документация
### Основные эндпоинты
- `GET /healthz` - Проверка здоровья
- `GET /readiness` - Готовность к работе
- `GET /docs` - Swagger документация
- `POST /api/v1/generate_email` - Генерация письма
### Формат запроса
**Обязательные поля:**
```json
{
"contact": "string",
"position": "string",
"company_name": "string",
"segment": "string"
}
```
**Полный формат:**
```json
{
"contact": "Помящий Никита",
"position": "Технический директор",
"company_name": "FIVE",
"segment": "маркетинговое агентство",
"email": "nikita@five.agency",
"locale": "ru",
"notes": "Дополнительная информация"
}
```
### Формат ответа
```json
{
"subject": "Как упростить работу с самозанятыми в FIVE?",
"body": "Здравствуйте, Никита!....",
"meta": {
"locale": "ru",
"lead_normalized": {
"contact_name": "Помящий Никита",
"contact_first_name": "Никита",
"contact_last_name": "Помящий",
"role_title": "Технический директор",
"role_category": "tech",
"company_name": "FIVE",
"industry_segment": "маркетинговое агентство",
"industry_tag": "marketing_agency",
"email": null,
"locale": "ru",
"notes": null
},
"used_chunks": [
"sds_podkluchenie_k_konsoli#sds_podkluchenie_k_konsoli#c7",
"vysotnik_rental#vysotnik_rental#c2"
],
"model": "gpt-4o",
"tokens_prompt": 1132,
"tokens_completion": 289,
"guardrails_violations": 0,
"context_chunks_used": 5,
"context_quality_score": 0.87
}
}
```
**Структура meta:**
- `locale` - Язык, на котором сгенерировано письмо (например, ru)
- `lead_normalized` - Объект с нормализованной и обогащенной информацией о лиде:
- `contact_first_name/contact_last_name` - Распознанные имя и фамилия
- `role_category/industry_tag` - Машинно-читаемые теги для должности и сегмента компании (например, tech, marketing_agency)
- `used_chunks` - Массив с ID фрагментов из базы знаний, которые были использованы для генерации ответа
- `model` - Использованная LLM модель
- `tokens_prompt/tokens_completion` - Расход токенов на запрос и ответ для мониторинга затрат
- `guardrails_violations` - Количество нарушений правил безопасности (guardrails). 0 означает, что все проверки пройдены
- `context_chunks_used` - Общее количество фрагментов контекста, которые были использованы для генерации
- `context_quality_score` - Оценка релевантности найденного контекста (0-1):
- 1.0 - отличное качество контекста
- 0.8+ - хорошее качество (высокая релевантность)
- 0.6+ - приемлемое качество (достаточная релевантность)
- <0.6 - низкое качество (слабая релевантность)
## Конфигурация
### Переменные окружения
| Параметр | Описание | По умолчанию |
|----------|----------|--------------|
| `LLM_PROVIDER` | openai или gemini | openai |
| `LLM_MODEL` | Модель генерации | gpt-4o |
| `EMBEDDING_MODEL` | Модель векторизации | text-embedding-3-large |
| `TOP_K` | Чанков для поиска | 30 |
| `TOP_N_CONTEXT` | Чанков в контексте | 6 |
| `CHUNK_SIZE` | Размер чанка (токены) | 500 |
| `CHUNK_OVERLAP` | Перекрытие чанков | 100 |
## Мониторинг
### Качество контекста
Метрика `context_quality_score` вычисляется на основе:
- **Средний similarity score** (40%) - релевантность найденных кейсов
- **Доля высококачественных chunks** (25%) - процент кейсов с similarity > 0.7
- **Консистентность результатов** (20%) - равномерность качества chunks
- **Фактор количества** (15%) - достаточность объема контекста
**Интерпретация для мониторинга:**
- `context_quality_score < 0.5` - критически низкое качество, требует обновления базы знаний
- `context_quality_score < 0.7` - предупреждение о качестве контекста
- `context_quality_score >= 0.8` - хорошее качество генерации
### Логи
Все запросы логируются в JSON:
```json
{
"request_id": "1641234567890",
"method": "POST",
"url": "http://localhost:8000/api/v1/generate_email",
"status_code": 200,
"process_time": 2.341
}
```
### Проверка состояния
```bash
# Статус сервиса
curl http://localhost:8000/healthz
# Статистика базы знаний
curl -H "Authorization: Bearer secret" \
http://localhost:8000/api/v1/admin/knowledge-base/stats
# Docker логи
docker-compose logs -f ai-email-assistant
```
## Устранение ошибок
### Частые проблемы
**404 No relevant knowledge found**
```bash
# Загрузите базу знаний
curl -X POST -H "Authorization: Bearer secret" \
"http://localhost:8000/api/v1/admin/ingest"
```
**502 External service error**
- Проверьте API ключи LLM провайдера в .env
**400 Validation failed**
- Убедитесь что все обязательные поля заполнены
## Обновление базы знаний
### Добавление кейсов
1. Поместите `.md` файлы в `data`
2. Файлы должны содержать:
- Заголовки для структуры
- Числовые метрики
- Ключевые слова индустрии
- Упоминания ролей
3. Дополните базу (инкрементально):
```bash
curl -X POST -H "Authorization: Bearer secret" \
"http://localhost:8000/api/v1/admin/ingest"
```
4. (альтернативно) Пересоздайте базу:
```bash
curl -X POST -H "Authorization: Bearer secret" \
"http://localhost:8000/api/v1/admin/ingest?recreate=true"
```
### Формат кейсов
```markdown
# Кейс компании FIVE
Маркетинговое агентство автоматизировало работу с подрядчиками.
## Результаты
- Онбординг: с 2 дней до 15 минут
- Снижение ошибок: на 95%
- Выплаты: мгновенные
Технический директор Никита отмечает эффективность.
```
## Тестирование
```bash
# Все тесты
pytest src/tests/
# Только API
pytest src/tests/test_api.py
```