Files
LawBot/SYSTEM_AUDIT.md
T
2026-05-25 01:12:43 +03:00

24 KiB
Raw Blame History

SYSTEM AUDIT: LawBot

1. Что это за проект

LawBot — это Telegram-бот, который:

  1. принимает вопрос пользователя;
  2. ищет подходящие нормы закона РФ;
  3. достает текст из своей базы;
  4. передает найденные фрагменты в LLM;
  5. возвращает пользователю ответ простыми словами.

Проект состоит из 4 основных частей:

Часть Папка Что делает
Telegram-бот bot/ Общается с пользователем в Telegram
API для RAG api/ Делает поиск по законам и генерацию ответа
Парсер законов parser/ Скачивает и нормализует документы
Общий слой БД shared/ Хранит модели БД и методы работы с БД

2. Архитектура проекта

2.1. Общая схема

flowchart LR
    User["Пользователь Telegram"]
    Bot["bot/\nAiogram bot"]
    Api["api/\nFastAPI RAG API"]
    Parser["parser/\nCLI parser"]
    Shared["shared/\nDB layer"]
    Pg["PostgreSQL"]
    Redis["Redis"]
    Chroma["ChromaDB"]
    LLM["OpenRouter LLM"]
    Embed["Local embedding model"]
    Consultant["consultant.ru"]

    User --> Bot
    Bot --> Api
    Bot --> Shared
    Bot --> Redis

    Api --> Shared
    Api --> Chroma
    Api --> LLM
    Api --> Embed

    Shared --> Pg

    Parser --> Consultant
    Parser --> Shared
    Parser --> Pg

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. Точки входа

Компонент Точка входа Что происходит
Telegram-бот bot/aiogram_run.py Поднимает bot, middleware, routers и polling
FastAPI API api/main.py Поднимает API, проверяет БД, запускает автоиндексацию
Парсер parser/__main__.py -> parser/cli.py Запускает CLI пайплайн

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. Поток ответа пользователю

  1. Пользователь пишет в Telegram.
  2. bot/handlers/client/main.py принимает сообщение.
  3. Бот вызывает bot/utils/rag_api.py.
  4. HTTP-запрос уходит в POST /api/v1/rag/answer.
  5. api/services/legal_ai.py классифицирует вопрос.
  6. api/services/retrieval.py ищет чанки:
    • через PostgreSQL full-text search;
    • через Chroma vector search.
  7. api/services/legal_ai.py генерирует ответ через OpenRouter.
  8. Если save_history=true, API сохраняет:
    • консультацию;
    • сообщения;
    • rag-запрос.
  9. Бот получает ответ, форматирует его и отправляет в Telegram.

8.2. Поток загрузки законов

  1. Команда python -m parser run.
  2. parser/discovery.py собирает manifest.
  3. parser/fetcher.py скачивает root HTML и статьи.
  4. parser/normalizer.py делает нормализованный JSON.
  5. parser/ingest.py записывает документы и чанки в PostgreSQL.
  6. api/services/indexing.py переносит чанки в Chroma.

8.3. Схема зависимости модулей

bot/handlers/client/main.py
  -> bot/utils/rag_api.py
  -> api/routers/rag.py
  -> api/services/legal_ai.py
  -> api/services/retrieval.py
  -> shared/repositories.py
  -> PostgreSQL / ChromaDB / OpenRouter

parser/cli.py
  -> parser/discovery.py
  -> parser/fetcher.py
  -> parser/normalizer.py
  -> parser/ingest.py
  -> shared/repositories.py
  -> PostgreSQL

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-слой.

Главная архитектурная идея понятная:

  1. parser наполняет PostgreSQL законами;
  2. api строит векторный индекс и отвечает на вопросы;
  3. bot общается с пользователем;
  4. shared соединяет все это с БД.

Главные слабые места сейчас:

  • смешение ролей bot и parser;
  • отсутствие миграций;
  • слишком крупные файлы shared/repositories.py и api/services/legal_ai.py;
  • отсутствие автоматических тестов.

Для новичка проект уже читаемый, но поддерживать его дальше будет проще после разделения больших модулей на более мелкие.