200 lines
5.7 KiB
Markdown
200 lines
5.7 KiB
Markdown
|
|
# GorychBot
|
||
|
|
|
||
|
|
Набор сервисов для Telegram-бота шаурмечной "Горыч" с отдельным парсером меню и отдельным RAG API.
|
||
|
|
|
||
|
|
Проект разделён на независимые части:
|
||
|
|
|
||
|
|
- `tgbot` — основной Telegram-бот на `aiogram`.
|
||
|
|
- `menu_scraper` — сервис, который парсит меню с `https://gorych34.ru/`.
|
||
|
|
- `rag_api` — FastAPI-сервис с RAG, локальными эмбеддингами `sergeyzh/rubert-mini-frida` и function calling для подбора блюд.
|
||
|
|
- `redisdb` — Redis для бота.
|
||
|
|
- `postgredb` — PostgreSQL для бота.
|
||
|
|
|
||
|
|
## Что делает проект
|
||
|
|
|
||
|
|
1. `menu_scraper` забирает меню с сайта Горыча и сохраняет нормализованный JSON в `data/menu/gorich_menu.json`.
|
||
|
|
2. `rag_api` индексирует:
|
||
|
|
- знания о заведении: описание, контакты, режим, доставка, соцсети;
|
||
|
|
- меню: названия, описания, ингредиенты, цены, размеры, фото.
|
||
|
|
3. `rag_api` умеет:
|
||
|
|
- отвечать на вопросы о заведении через RAG;
|
||
|
|
- вызывать tool `find_menu_items` для подбора блюд по бюджету, категории и ингредиентам.
|
||
|
|
4. `tgbot` работает отдельно от RAG API и использует PostgreSQL + Redis.
|
||
|
|
|
||
|
|
## Сервисы
|
||
|
|
|
||
|
|
### `tgbot`
|
||
|
|
|
||
|
|
Назначение:
|
||
|
|
- Telegram-бот на `aiogram`.
|
||
|
|
- Хранит данные в PostgreSQL.
|
||
|
|
- Использует Redis для FSM/storage.
|
||
|
|
|
||
|
|
Файл env:
|
||
|
|
- `bot/.env`
|
||
|
|
|
||
|
|
Зависимости:
|
||
|
|
- `redisdb`
|
||
|
|
- `postgredb`
|
||
|
|
|
||
|
|
Стартовая команда:
|
||
|
|
```bash
|
||
|
|
python aiogram_run.py
|
||
|
|
```
|
||
|
|
|
||
|
|
### `menu_scraper`
|
||
|
|
|
||
|
|
Назначение:
|
||
|
|
- Парсит меню с сайта Горыча.
|
||
|
|
- Берёт встроенный каталог товаров из JSON на странице `gorych34.ru`.
|
||
|
|
- Пишет результат в `data/menu/gorich_menu.json`.
|
||
|
|
|
||
|
|
Файл env:
|
||
|
|
- `menu_scraper/.env`
|
||
|
|
|
||
|
|
Порт:
|
||
|
|
- `8010`
|
||
|
|
|
||
|
|
Основные endpoints:
|
||
|
|
- `GET /health`
|
||
|
|
- `POST /scrape`
|
||
|
|
- `GET /items`
|
||
|
|
- `GET /items/{item_id}`
|
||
|
|
|
||
|
|
Пример ответа:
|
||
|
|
- один snapshot меню с `total_items` и массивом `items`
|
||
|
|
|
||
|
|
### `rag_api`
|
||
|
|
|
||
|
|
Назначение:
|
||
|
|
- Отдельный API для вопросов о заведении.
|
||
|
|
- RAG по сайту, доставке, контактам и соцсетям.
|
||
|
|
- Локальные эмбеддинги через `sergeyzh/rubert-mini-frida` на CPU.
|
||
|
|
- Function calling через OpenRouter для подбора блюд из меню.
|
||
|
|
|
||
|
|
Файл env:
|
||
|
|
- `rag_api/.env`
|
||
|
|
|
||
|
|
Порт:
|
||
|
|
- внешний `8001`
|
||
|
|
- внутренний контейнерный `8000`
|
||
|
|
|
||
|
|
Основные endpoints:
|
||
|
|
- `GET /health`
|
||
|
|
- `POST /chat`
|
||
|
|
- `POST /admin/reindex`
|
||
|
|
- `GET /menu/search`
|
||
|
|
|
||
|
|
`POST /chat` принимает:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"message": "Посоветуй что-нибудь острое из пиццы до 400 рублей",
|
||
|
|
"history": []
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
`GET /menu/search` умеет:
|
||
|
|
- `query`
|
||
|
|
- `max_price`
|
||
|
|
- `category`
|
||
|
|
- `must_include`
|
||
|
|
- `must_not_include`
|
||
|
|
- `limit`
|
||
|
|
|
||
|
|
Пример:
|
||
|
|
```bash
|
||
|
|
curl "http://localhost:8001/menu/search?query=острая%20пицца&max_price=450&category=пицца&limit=3"
|
||
|
|
```
|
||
|
|
|
||
|
|
## Структура данных
|
||
|
|
|
||
|
|
### `data/menu/gorich_menu.json`
|
||
|
|
|
||
|
|
Содержит:
|
||
|
|
- `item_id`
|
||
|
|
- `name`
|
||
|
|
- `category`
|
||
|
|
- `description`
|
||
|
|
- `ingredients`
|
||
|
|
- `price`
|
||
|
|
- `price_label`
|
||
|
|
- `size`
|
||
|
|
- `photo_url`
|
||
|
|
- `source_url`
|
||
|
|
- `scraped_at`
|
||
|
|
|
||
|
|
### `data/chroma/`
|
||
|
|
|
||
|
|
Локальная база ChromaDB для RAG:
|
||
|
|
- коллекция знаний о заведении;
|
||
|
|
- коллекция документов меню.
|
||
|
|
|
||
|
|
## Настройка
|
||
|
|
|
||
|
|
В проекте используются отдельные env-файлы по сервисам:
|
||
|
|
|
||
|
|
- `bot/.env`
|
||
|
|
- `menu_scraper/.env`
|
||
|
|
- `rag_api/.env`
|
||
|
|
|
||
|
|
Примеры:
|
||
|
|
|
||
|
|
- `.env.example`
|
||
|
|
- `bot/.env.example`
|
||
|
|
- `menu_scraper/.env.example`
|
||
|
|
- `rag_api/.env.example`
|
||
|
|
|
||
|
|
Минимум для запуска:
|
||
|
|
|
||
|
|
1. Заполнить `bot/.env`
|
||
|
|
2. Заполнить `rag_api/.env`
|
||
|
|
3. При необходимости поправить `menu_scraper/.env`
|
||
|
|
|
||
|
|
Важно:
|
||
|
|
- `OPENROUTER_API_KEY` нужен только для `rag_api`.
|
||
|
|
- Для OpenRouter лучше использовать модель, которая нормально работает с tools в вашем регионе. Сейчас в конфиге стоит `mistralai/mistral-medium-3-5`.
|
||
|
|
|
||
|
|
## Запуск
|
||
|
|
|
||
|
|
Поднять всё:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
docker compose up -d --build
|
||
|
|
```
|
||
|
|
|
||
|
|
Проверка сервисов:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
curl http://localhost:8010/health
|
||
|
|
curl http://localhost:8001/health
|
||
|
|
```
|
||
|
|
|
||
|
|
Пересобрать индекс RAG вручную:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
curl -X POST http://localhost:8001/admin/reindex
|
||
|
|
```
|
||
|
|
|
||
|
|
Перепарсить меню вручную:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
curl -X POST http://localhost:8010/scrape
|
||
|
|
```
|
||
|
|
|
||
|
|
## Что уже реализовано
|
||
|
|
|
||
|
|
- отдельный парсер меню;
|
||
|
|
- сохранение меню в JSON;
|
||
|
|
- отдельный RAG API;
|
||
|
|
- ChromaDB;
|
||
|
|
- локальные эмбеддинги `rubert-mini-frida`;
|
||
|
|
- function calling для подбора блюд;
|
||
|
|
- подбор по семантике + лексическим признакам меню;
|
||
|
|
- Docker Compose для всех сервисов.
|
||
|
|
|
||
|
|
## Что важно знать
|
||
|
|
|
||
|
|
- `rag_api` сейчас не вшит напрямую в `tgbot`; это отдельный сервис с HTTP API.
|
||
|
|
- `rag_api` на первом старте может подниматься дольше из-за загрузки модели эмбеддингов.
|
||
|
|
- `data/` хранит runtime-данные и не должен коммититься в git.
|