Files
2026-05-12 23:37:04 +03:00

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.