# 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.