ai-email-assistant/README.md

357 lines
15 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AI Email Assistant
[![CI](https://img.shields.io/badge/CI-passing-brightgreen)](https://git.itqop.pw/itqop/sl-test/actions)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
Сервис для генерации персонализированных холодных писем с использованием 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. Загрузка базы знаний
Полоджите файлы/папку с md в data/, а после выполните запрос
```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
```
### TODO:
- Улучшить валидацию входных данных (почта, защита хака llm)
- Увеличить покрытие кода тестами до 80%, доавить unit тесты для бизнес-логики
- Сделать качественную докуентацию