SYSTEM AUDIT: LawBot
1. Что это за проект
LawBot — это Telegram-бот, который:
- принимает вопрос пользователя;
- ищет подходящие нормы закона РФ;
- достает текст из своей базы;
- передает найденные фрагменты в LLM;
- возвращает пользователю ответ простыми словами.
Проект состоит из 4 основных частей:
| Часть |
Папка |
Что делает |
| Telegram-бот |
bot/ |
Общается с пользователем в Telegram |
| API для RAG |
api/ |
Делает поиск по законам и генерацию ответа |
| Парсер законов |
parser/ |
Скачивает и нормализует документы |
| Общий слой БД |
shared/ |
Хранит модели БД и методы работы с БД |
2. Архитектура проекта
2.1. Общая схема
2.2. Что запускается в Docker Compose
Файл: compose.yml
| Сервис |
Образ / Dockerfile |
Назначение |
Порт |
tgbot |
bot/Dockerfile |
Telegram-бот |
нет внешнего порта |
api |
api/Dockerfile |
FastAPI RAG API |
8080 |
postgredb |
postgres:16-alpine |
Основная БД |
нет внешнего порта |
redisdb |
redis:6-alpine |
FSM/storage для aiogram |
нет внешнего порта |
chromadb |
chromadb/chroma:1.0.12 |
Векторный поиск |
8000 |
Важно: отдельного контейнера для parser/ нет. Парсер запускается командой внутри контейнера tgbot.
3. Структура директорий
3.1. Корень проекта
| Путь |
Назначение |
compose.yml |
Запуск всех сервисов |
README.md |
Краткая инструкция по запуску |
mvp.md |
Текстовое описание MVP |
postgres.env |
Настройки подключения к PostgreSQL |
postgres.env.example |
Пример env для PostgreSQL |
SYSTEM_AUDIT.md |
Этот аудит |
volumes/ |
Постоянные данные контейнеров |
protocol/ |
Документы для курсовой |
3.2. Папка api/
| Путь |
Назначение |
api/main.py |
Точка входа FastAPI |
api/config.py |
Чтение env-переменных API |
api/deps.py |
Создание singleton-зависимостей |
api/schemas.py |
Pydantic-схемы API |
api/logging.py |
Настройка логов API |
api/routers/ |
HTTP-роуты (health, indexing, rag) |
api/services/ |
Основная логика: embeddings, retrieval, indexing, LLM |
api/clients/ |
Клиенты для OpenRouter и Chroma |
api/prompts/ |
Промпты для классификации и ответа |
api/requirements.txt |
Зависимости API |
api/Dockerfile |
Сборка контейнера API |
3.3. Папка bot/
| Путь |
Назначение |
bot/aiogram_run.py |
Точка входа Telegram-бота |
bot/create_bot.py |
Создание Bot / Dispatcher / Redis / ORM |
bot/handlers/ |
Обработчики команд, кнопок и сценариев |
bot/keyboards/ |
Reply и inline клавиатуры |
bot/middlewares/ |
Антифлуд, blacklist, album middleware |
bot/states/ |
FSM состояния aiogram |
bot/utils/rag_api.py |
HTTP-клиент бота для вызова api |
bot/utils/text_tools.py |
Форматирование и нарезка текста для Telegram |
bot/templates/ |
Шаблоны файлов (users.xlsx) |
bot/requirements.txt |
Зависимости бота |
bot/Dockerfile |
Сборка контейнера бота |
bot/webhooks.py |
Отдельный тестовый FastAPI webhook, не подключен к compose.yml |
3.4. Папка parser/
| Путь |
Назначение |
parser/__main__.py |
Позволяет запускать python -m parser |
parser/cli.py |
CLI-команды discover/fetch/normalize/ingest/run |
parser/config.py |
Список целевых документов и пути сохранения |
parser/discovery.py |
Проверка категорий на consultant.ru/popular/ |
parser/fetcher.py |
Скачивание root HTML и страниц статей |
parser/normalizer.py |
Разбор HTML и сборка нормализованного JSON |
parser/ingest.py |
Запись документов и чанков в PostgreSQL |
parser/utils.py |
Общие функции парсера |
3.5. Папка shared/
| Путь |
Назначение |
shared/models.py |
SQLAlchemy-модели |
shared/repositories.py |
Класс ORM и методы работы с БД |
shared/engine.py |
Создание async engine и sessionmaker |
shared/types.py |
Вспомогательные типы |
shared/__init__.py |
Единая точка импорта DB-слоя |
3.6. Папка protocol/
| Путь |
Назначение |
protocol/generate_protocol_docx.py |
Генератор .docx протокола курсовой |
protocol/Протокол_курсовой_работы_LawBot.docx |
Готовый документ |
protocol/task/ |
Входные материалы задания |
3.7. Папка volumes/
| Путь |
Назначение |
volumes/postgres/ |
Данные PostgreSQL |
volumes/chroma/ |
Данные ChromaDB |
volumes/huggingface/ |
Кеш embedding-модели |
volumes/parser/ |
Артефакты парсера: raw, normalized, state |
4. Ключевые сервисы, модули и точки входа
4.1. Точки входа
4.2. Основные модули API
| Модуль |
Файл |
Роль |
| Конфиг |
api/config.py |
Читает env и хранит настройки |
| Роуты |
api/routers/rag.py |
/search и /answer |
| Индексация |
api/routers/indexing.py |
/api/v1/index/rebuild |
| Retrieval |
api/services/retrieval.py |
Гибридный поиск: Postgres FTS + Chroma |
| Индексация |
api/services/indexing.py |
Перенос чанков из Postgres в Chroma |
| Embeddings |
api/services/local_embeddings.py |
Локальные эмбеддинги через sentence-transformers |
| LLM-логика |
api/services/legal_ai.py |
Классификация, генерация ответа, заголовка консультации |
| Векторное хранилище |
api/clients/chroma_store.py |
Работа с Chroma |
| LLM-клиент |
api/clients/openrouter_client.py |
AsyncOpenAI-клиент для OpenRouter |
4.3. Основные модули бота
| Модуль |
Файл |
Роль |
| Создание бота |
bot/create_bot.py |
Bot, Dispatcher, RedisStorage, ORM, timezone |
| Главный запуск |
bot/aiogram_run.py |
Сборка всех роутеров |
| Пользовательский сценарий |
bot/handlers/client/main.py |
Вопрос -> регион -> ответ -> история |
| Админка |
bot/handlers/admin/*.py |
Статистика, blacklist, рассылка, настройки |
| HTTP-клиент к API |
bot/utils/rag_api.py |
Отправляет запросы в FastAPI |
| Форматирование |
bot/utils/text_tools.py |
Подготовка текста под Telegram HTML |
4.4. Основные модули парсера
| Модуль |
Файл |
Роль |
| Discovery |
parser/discovery.py |
Собирает manifest целевых документов |
| Fetch |
parser/fetcher.py |
Скачивает страницы документов |
| Normalize |
parser/normalizer.py |
Превращает HTML в нормализованный JSON |
| Ingest |
parser/ingest.py |
Пишет law_sources и law_chunks в БД |
4.5. Основной DB-слой
| Модуль |
Файл |
Роль |
| ORM |
shared/repositories.py |
Все операции с PostgreSQL |
| Модели |
shared/models.py |
Таблицы пользователей, консультаций, законов, чанков |
5. Кто за что отвечает
| Сервис / модуль |
Отвечает за |
tgbot |
UI для пользователя и администратора |
api |
Поиск по законам и генерацию ответа |
parser |
Наполнение базы законами |
shared |
Единый доступ к PostgreSQL |
postgredb |
Хранение пользователей, консультаций, законов и чанков |
redisdb |
Хранение FSM-состояний aiogram |
chromadb |
Векторный индекс чанков |
OpenRouter |
LLM для классификации и ответа |
| Локальная embedding-модель |
Преобразование текста в векторы |
6. Переменные окружения
6.1. bot/.env
Источник: bot/.env.example
| Переменная |
Назначение |
TOKEN |
Telegram bot token |
TELEGRAM_BOT_PROXY |
Прокси для Telegram Bot API |
BASE_ADMIN |
Telegram ID администратора |
RAG_API_URL |
URL FastAPI сервиса |
REDIS_URL |
Подключение к Redis |
POSTGRES_DB |
Имя БД |
POSTGRES_USER |
Логин БД |
POSTGRES_PASSWORD |
Пароль БД |
POSTGRES_HOST |
Хост PostgreSQL |
POSTGRES_PORT |
Порт PostgreSQL |
TIMEZONE |
Часовой пояс для отображения дат |
6.2. api/.env
Источник: api/.env.example
| Переменная |
Назначение |
OPENAI_BASE_URL |
Базовый URL OpenRouter |
OPENAI_API_KEY |
Ключ доступа к OpenRouter |
LLM_MODEL |
Модель LLM для классификации и ответа |
EMBEDDING_MODEL |
Локальная embedding-модель |
EMBEDDING_DEVICE |
Устройство (cpu) |
CHROMA_HOST |
Хост ChromaDB |
CHROMA_PORT |
Порт ChromaDB |
CHROMA_COLLECTION |
Название коллекции Chroma |
CHROMA_SSL |
Использовать ли SSL |
RAG_TOP_K |
Дефолтное число результатов RAG |
FTS_TOP_K |
Сколько брать из full-text поиска |
VECTOR_TOP_K |
Сколько брать из vector search |
INDEX_BATCH_SIZE |
Размер батча для индексации и embeddings |
LLM_TIMEOUT_SECONDS |
Таймаут LLM-запросов |
API_HOST |
Хост FastAPI |
API_PORT |
Порт FastAPI |
LOG_LEVEL |
Уровень логов |
AUTO_INDEX_ON_STARTUP |
Запускать ли автоиндексацию при старте API |
AUTO_INDEX_ONLY_IF_EMPTY |
Индексировать только если Chroma пустая/не синхронизирована |
AUTO_INDEX_RESET_COLLECTION |
Сбрасывать ли коллекцию при автоиндексации |
AUTO_INDEX_RETRY_DELAY_SECONDS |
Пауза между попытками автоиндексации |
AUTO_INDEX_MAX_ATTEMPTS |
Максимум попыток автоиндексации |
6.3. postgres.env
Источник: postgres.env.example
| Переменная |
Назначение |
POSTGRES_DB |
Имя БД PostgreSQL |
POSTGRES_USER |
Пользователь БД |
POSTGRES_PASSWORD |
Пароль БД |
POSTGRES_HOST |
Хост БД |
POSTGRES_PORT |
Порт БД |
7. Основные таблицы данных
Источник: shared/models.py
| Таблица |
Назначение |
users |
Пользователи Telegram |
admins |
Администраторы |
blacklist |
Заблокированные пользователи |
settings |
Настройки бота |
consultations |
Диалоги пользователя с ботом |
messages |
Сообщения внутри консультаций |
rag_queries |
История поисковых запросов и найденных чанков |
law_sources |
Документы законов |
law_chunks |
Чанки статей законов |
8. Потоки данных
8.1. Поток ответа пользователю
- Пользователь пишет в Telegram.
bot/handlers/client/main.py принимает сообщение.
- Бот вызывает
bot/utils/rag_api.py.
- HTTP-запрос уходит в
POST /api/v1/rag/answer.
api/services/legal_ai.py классифицирует вопрос.
api/services/retrieval.py ищет чанки:
- через PostgreSQL full-text search;
- через Chroma vector search.
api/services/legal_ai.py генерирует ответ через OpenRouter.
- Если
save_history=true, API сохраняет:
- консультацию;
- сообщения;
- rag-запрос.
- Бот получает ответ, форматирует его и отправляет в Telegram.
8.2. Поток загрузки законов
- Команда
python -m parser run.
parser/discovery.py собирает manifest.
parser/fetcher.py скачивает root HTML и статьи.
parser/normalizer.py делает нормализованный JSON.
parser/ingest.py записывает документы и чанки в PostgreSQL.
api/services/indexing.py переносит чанки в Chroma.
8.3. Схема зависимости модулей
9. Используемые технологии и зависимости
9.1. По сервисам
| Область |
Технологии |
| Bot |
aiogram, aiohttp, httpx, redis, uvloop |
| API |
FastAPI, uvicorn, openai, chromadb, sentence-transformers, SQLAlchemy, asyncpg |
| Parser |
requests, beautifulsoup4 |
| DB |
PostgreSQL, SQLAlchemy, asyncpg |
| Vector search |
ChromaDB |
| LLM |
OpenRouter через AsyncOpenAI |
| Embeddings |
sentence-transformers + локальная модель |
9.2. Замеченные версии
Источники:
| Пакет |
Версия |
fastapi |
0.115.9 |
uvicorn |
0.34.2 |
openai |
1.82.0 |
chromadb |
1.0.12 |
SQLAlchemy |
2.0.38 |
asyncpg |
0.30.0 |
sentence-transformers |
5.1.2 |
aiogram |
3.17.0 |
httpx |
0.28.1 |
redis |
5.2.1 |
beautifulsoup4 |
4.13.4 |
10. Что выглядит слабо или странно
Ниже только то, что видно по текущему коду.
| Проблема |
Где видно |
Почему это слабое место |
Нет отдельного сервиса parser |
compose.yml |
Парсер живет внутри контейнера бота. Это смешивает роли и зависимости. |
| Нет миграций БД |
shared/repositories.py:97 |
Схема создается через create_all() и ALTER TABLE, что плохо масштабируется. |
| Один большой репозиторий БД |
shared/repositories.py |
Класс ORM содержит слишком много обязанностей: users, laws, consultations, search. |
| Один большой сервис LLM |
api/services/legal_ai.py |
В одном файле смешаны классификация, ответ, fallback, sanitizing и генерация заголовка. |
bot/requirements.txt содержит лишнее |
bot/requirements.txt |
Там есть fastapi, uvicorn, parser-зависимости. Контейнер бота тяжелее, чем должен быть. |
cfg_loader.py выглядит мертвым кодом |
bot/utils/cfg_loader.py |
Ищет cfg/config.json, но такой папки в проекте нет и импортов почти нет. |
bot/webhooks.py не подключен |
bot/webhooks.py, compose.yml |
В проекте есть отдельный FastAPI webhook-файл, но он не участвует в основном запуске. |
| Нет тестов |
по структуре файлов |
В проекте не найдено папки tests/ или явных unit/integration тестов. |
| Парсер завязан на HTML-структуру сайта |
parser/fetcher.py, parser/normalizer.py |
Любое изменение верстки consultant.ru может сломать парсинг. |
| Full-text поиск только на русском tsvector |
shared/repositories.py |
Это нормально для РФ, но поиск по сложным формулировкам может быть нестабилен без доп. нормализации. |
В api автоиндексация идет при старте |
api/main.py |
Удобно для MVP, но на большом объеме это может тормозить старт сервиса. |
В репозитории есть .venv/ |
структура проекта |
Локальное окружение лежит внутри проекта. Это легко случайно потащить в архив или deploy-контекст. |
10.1. Неясные или частично подтвержденные зоны
| Наблюдение |
Что именно неясно |
| Админская часть |
Полный функционал не анализировался построчно во всех admin handlers |
protocol/ |
Это не runtime-часть приложения, а документы для курсовой |
bot/keyboards/inline_keyboards.py |
Файл существует, но по структуре почти пустой и не играет заметной роли |
11. Рекомендации по улучшению структуры
11.1. Что стоит сделать в первую очередь
| Рекомендация |
Зачем |
Выделить parser в отдельный контейнер |
Чтобы бот не таскал лишние parser-зависимости |
Ввести миграции (alembic) |
Чтобы схема БД менялась предсказуемо |
Разбить shared/repositories.py на несколько репозиториев |
Например: users, consultations, laws, rag |
Разбить api/services/legal_ai.py |
Отдельно: classifier, answer renderer, title generator, fallback |
Добавить tests/ |
Минимум smoke-тесты для api, parser, shared |
Вынести parser-зависимости из bot/requirements.txt |
Уменьшить размер и сложность контейнера бота |
11.2. Что улучшит понятность проекта
| Рекомендация |
Зачем |
Добавить docs/architecture.md |
Новичку будет проще понять проект |
Сделать единый settings-слой и для bot, и для parser |
Сейчас конфигурация читается разными способами |
| Удалить или подключить мертвые файлы |
Например bot/webhooks.py, bot/utils/cfg_loader.py |
| Добавить схему “как идет запрос” в README |
Снизит порог входа |
11.3. Что важно для production
| Рекомендация |
Зачем |
| Ограничить и логировать ошибки внешних API |
OpenRouter и Consultant могут вести себя нестабильно |
| Добавить rate limiting и retry policy на уровне API-клиентов |
Улучшит устойчивость |
| Отдельно мониторить время поиска и генерации |
Позволит понять, где тормозит система |
Добавить backup-стратегию для volumes/postgres и volumes/chroma |
Сейчас данные локально персистентны, но не защищены от потери |
12. Краткий вывод
Проект уже собран как рабочий MVP:
- есть Telegram-бот;
- есть FastAPI-сервис для RAG;
- есть парсер законов;
- есть PostgreSQL и ChromaDB;
- есть единый DB-слой.
Главная архитектурная идея понятная:
parser наполняет PostgreSQL законами;
api строит векторный индекс и отвечает на вопросы;
bot общается с пользователем;
shared соединяет все это с БД.
Главные слабые места сейчас:
- смешение ролей
bot и parser;
- отсутствие миграций;
- слишком крупные файлы
shared/repositories.py и api/services/legal_ai.py;
- отсутствие автоматических тестов.
Для новичка проект уже читаемый, но поддерживать его дальше будет проще после разделения больших модулей на более мелкие.