# RAG-ассистент техподдержки Система поиска решений по истории обращений в техподдержку. Основана на RAG (Retrieval-Augmented Generation) — находит похожие решённые тикеты и формирует ответ на их основе. --- ## Архитектура ``` tickets.json (792 тикета) │ ▼ prepare_data.py ← фильтрация, очистка, нарезка чанков │ ▼ sentence-transformers ← векторизация (intfloat/multilingual-e5-small, GPU CUDA) │ ▼ chroma_db/ ← векторная база данных (416 чанков) │ ▼ app.py ← Streamlit-интерфейс │ ├── вопрос специалиста → embedding → поиск топ-5 │ │ │ ▼ └── контекст → LM Studio (qwen2.5-7b) → ответ ``` ## Как это работает ### 1. Подготовка данных (`prepare_data.py`) Что делает скрипт: - Читает все файлы `tickets*.json` в папке проекта (сейчас 6 файлов, ~3300 тикетов) - **Чистит текст**: удаляет цитаты `[q]...[/q]`, ссылки, лишние пробелы - **Фильтрует**: оставляет только тикеты с реальным решением. Отбрасываются: - тикеты, где последнее сообщение support — просьба уточнить / прислать скрин - тикеты без ответа / с закрытием "нет обратной связи" - слишком короткие сообщения (< 100 символов) - **Формирует чанки**: каждый тикет = один чанк вида: ``` Категория: ... Проблема: <описание> Решение: <все сообщения support> ``` - **Векторизует**: превращает текст в вектор (384 числа) через `intfloat/multilingual-e5-small` на GPU - **Сохраняет** в ChromaDB (папка `chroma_db/`) Результат: 416 чанков с реальными решениями (376 тикетов отфильтровано как бесполезные). ### 2. Поиск и генерация (`app.py`) Специалист вводит проблему клиента. Приложение: 1. **Векторизует вопрос** той же моделью эмбеддингов 2. **Ищет 5 похожих чанков** в ChromaDB по косинусной близости 3. **Формирует контекст** из найденных тикетов 4. **Отправляет в LM Studio** (чат-модель Qwen2.5-7B) с промптом: > "Ответь на основе ТОЛЬКО переданного контекста. Не придумывай, не отсылай в другую поддержку" 5. **Показывает ответ** и исходные тикеты для проверки ## Установка и запуск ### Требования - Python 3.11+ - NVIDIA GPU с 8+ GB VRAM (для эмбеддингов и LLM) - [LM Studio](https://lmstudio.ai/) (для чат-модели) ### Установка ```bash pip install -r requirements.txt ``` Установить PyTorch с CUDA (если ещё не): ```bash pip install torch torchvision --index-url https://download.pytorch.org/whl/cu124 ``` ### Подготовка базы знаний ```bash python prepare_data.py ``` Скрипт создаст папку `chroma_db/` с векторной базой. ### Запуск ```bash streamlit run app.py --server.headless true ``` Открыть в браузере: http://localhost:8501 ### Запуск чат-модели Для генерации ответов нужна чат-модель в LM Studio: 1. Открыть LM Studio 2. Вкладка Developer → загрузить модель (например, `Qwen2.5-7B-Instruct`) 3. Нажать Start Server 4. API будет доступен на `http://localhost:1234/v1` Без чат-модели приложение работает в режиме поиска — показывает похожие тикеты без генерации ответа. ## Структура проекта ``` support-bot/ ├── tickets*.json # исходные данные (несколько файлов) ├── prepare_data.py # подготовка и векторизация ├── app.py # Streamlit-интерфейс + RAG ├── requirements.txt # зависимости ├── chroma_db/ # векторная БД (создаётся prepare_data.py) └── .gitignore ``` ## Системные промпты Главный системный промпт — в файле **`app.py:15`**, переменная `SYSTEM_PROMPT`: ```python SYSTEM_PROMPT = """Ты — специалист техподдержки. Отвечай клиенту, используя ТОЛЬКО информацию из переданных тикетов (контекст). Правила: - Если контекст содержит подходящее решение — напиши ответ своими словами, адаптируя под вопрос - Если контекст не относится к вопросу — напиши: «Недостаточно информации в истории обращений» - НЕ придумывай ответы, НЕ используй общие знания - НЕ говори «обратитесь в службу поддержки» — ты сам и есть поддержка - Укажи в конце: «Основано на тикете №...»""" ``` Именно этот промпт управляет тем, **как LLM отвечает** на вопрос специалиста. Если нужно изменить стиль ответа, тон, правила или требования к формату — редактировать здесь. Промпт отправляется в LM Studio как `system`-сообщение при каждом запросе генерации ответа (строка `app.py:120-127`). ### Фильтрация тикетов без решения Паттерны для отбраковки пустых тикетов — в **`prepare_data.py:19-22`**, переменная `NON_SOLUTION`: ```python NON_SOLUTION = re.compile( r"(уточнит|приложите скрин|какая ошибка|с какой проблемой" r"|нет обратной связи|запрос завершу|открыть его снова" r"|откройте новый|обратиться в службу поддержки" r"|свяжитесь с технической" r"|напишите нам|позвоните нам)", re.I ) ``` Если в последнем сообщении support встречается одно из этих слов — тикет считается бесполезным и не попадает в базу знаний. Можно расширять или уточнять список. --- ## Технологии | Компонент | Технология | |-----------|-----------| | Эмбеддинги | `intfloat/multilingual-e5-small` (384d, GPU) через `sentence-transformers` | | Векторная БД | ChromaDB | | Чат-модель | Qwen2.5-7B-Instruct через LM Studio (OpenAI-совместимый API) | | Фреймворк | LangChain + Streamlit | | Язык | Python 3.11 | | GPU | CUDA 12.4+ | ## Git ```bash git remote add origin https://git.itoservice.ru/dosnav/support-bot.git git push -u origin master ```