Kirana — интеллектуальная RAG (Retrieval-Augmented Generation) система для глубокого анализа художественных книг: парсинг FB2, чанкинг, гибридный поиск (Qdrant + Elasticsearch + RRF), переранжировка и генерация ответов с цитированием фрагментов. Режим Deep Research — многошаговая оркестрация по корпусу.
Репозиторий собран вокруг инженерного контура: пайплайн обработки длинных художественных текстов, гибридный поиск, цитирование и Deep Research — с кодом и документацией по каждому шагу. Художественная проза — домен с большой читательской и фандом-активностью, но без готовых воспроизводимых решений под корпуса романов: иерархия частей и глав, персонажи, длинный сюжетный контекст. Здесь эти практики сведены в один стек — от FB2 ingest до RAG с проверкой evidence — чтобы можно было развернуть, прогнать и доработать под свой корпус.
В git — код, конфиги и документация. Артефакты eval (JSON/CSV, логи, MLflow) в репозиторий не входят; опубликованные метрики — в PDF выпускной работы. Скрипты локального eval — scripts/eval/, библиотека — src/kirana/evaluation/.
Корпус книг — локально в src/kirana/library/ (каталог в .gitignore). Эталонный FB2 для smoke лежит в git: tests/fixtures/mvp_golden.fb2. После клонирования для ingest через API скопируйте его в library или укажите путь к fixture:
mkdir -p src/kirana/library/{raw,processed,lightrag_inputs}
cp tests/fixtures/mvp_golden.fb2 src/kirana/library/raw/
# Подробнее: docs/FB2_INPUT_CONTRACT.mdАрхитектура: docs/architecture.md. Навигация по документации: docs/README.md.
- Парсинг: полноценный путь MVP — FB2 (FictionBook 2.0). В коде для PDF/TXT пока стоят заглушки; DOCX/HTML в реестр не подключены (см. docs/architecture.md)
- Извлечение структуры с сохранением иерархии (части → главы → разделы → чанки)
- Разбиение на чанки с использованием LangChain (RecursiveCharacter, TokenOverlap)
- Векторизация текста через HuggingFace embeddings модели
- Суммаризация на уровне чанков и структурных единиц (LLM-based)
- RAPTOR — иерархическая суммаризация для создания резюме документов
- NER и кореференция: GLiNER по чанкам, LLM coref — канонические имена персонажей, запись в PostgreSQL (
entities,named_entity_mentions); приprocess_only_chunks=True(смоук MVP) шаги отключены; entity-aware retrieval пока частично (см. docs/ner_coref/README.md, docs/architecture.md) - Граф персонажей: рёбра
entity_relationsв PG — не в основном ingest, а импорт GraphML из LightRAG sidecar (профиль composelightrag, ETLscripts/import_lightrag_graphml.py); опционально подмешивается в гибридный поиск (RAG_USE_GRAPH_EXPANSION,kirana/rag/graph_context_retrieval.py) - Статьи о персонажах (fandom_wiki): Phase A/B/C — факты с дословными цитатами, слияние, черновики в
fandom_wiki_entity_*; по умолчанию выключено (character_profile_pipeline_enabled=false), отдельный прогон —scripts/run_fandom_wiki.py - Локальная MediaWiki (опционально): публикация wikitext из черновиков fandom_wiki в локальный экземпляр (compose-профиль
wiki,scripts/wiki_sync.py); см. docs/infra/mediawiki_local.md
- Гибридный поиск — комбинация векторного (Qdrant) и полнотекстового (Elasticsearch) поиска
- RAG цепочки для генерации ответов на основе извлеченённой информации; ответы ссылаются на фрагменты контекста
[1]…[N], постобработка проверяет ссылки и цитаты (см. ниже «Контракт цитирования») - Поддержка LLM — OpenAI, Ollama, локальные модели
- FastAPI REST API с автоматической документацией (Swagger/ReDoc)
- Асинхронная обработка через Celery
- Кэширование через Redis
- Мониторинг через Prometheus + Grafana
- Улучшенный веб-интерфейс с real-time мониторингом
- Структурированное логирование (structlog)
- Retry логика для всех внешних сервисов (tenacity)
- Ингест: валидный FB2 по контракту; эталон в git:
tests/fixtures/mvp_golden.fb2(для Docker/worker — скопировать вsrc/kirana/library/raw/). - LLM обязателен и при обработке документа (Celery worker: кореференция и суммаризация чанков), и при ответах RAG (FastAPI при старте поднимает цепочку). Переменные
LLM_PROVIDER,OPENAI_BASE_URL,LLM_MODEL_NAME,OPENAI_API_KEYи т.д. должны совпадать у API и воркера. - Поток данных и границы продукта: docs/architecture.md.
- Шаблон переменных окружения под локальный запуск и compose: mvp.env.example (копия в
.envв корне репозитория). - Сквозной смоук-тест (нужны поднятые сервисы, LLM, доступный путь к
.fb2для API и worker):
poetry run python scripts/mvp_e2e_smoke.py --base-url http://localhost:8000В Docker используйте путь внутри контейнера, например /app/src/kirana/library/raw/mvp_golden.fb2 (том library уже смонтирован в compose).
Сквозной тест по живому API (и опционально с проверками PostgreSQL/ES/Qdrant): docs/TESTING_GUIDE.md — раздел «MVP end-to-end».
Если Streamlit запущен на хосте, а API и Celery — в Docker, UI сохраняет файл по абсолютному пути хоста (…/src/kirana/library/raw/…), а worker внутри контейнера этого пути не видит. Задайте в .env для API и worker пару INGEST_FILEPATH_HOST_PREFIX (префикс пути на вашей машине до каталога kirana в репозитории) и INGEST_FILEPATH_CONTAINER_PREFIX=/app/src/kirana, либо вызывайте POST /documents/process сразу с путём внутри контейнера. Подробнее: docs/architecture.md.
- Python 3.10+
- Poetry для управления зависимостями
- Docker и Docker Compose для инфраструктуры
- 8GB+ RAM (рекомендуется для работы с моделями embeddings)
git clone https://github.com/bugkira/kirana.git
cd kirana# Установка Poetry (если не установлен)
curl -sSL https://install.python-poetry.org | python3 -
# Установка зависимостей проекта
poetry install
# Активация виртуального окружения
poetry shellСоздайте .env в корне репозитория из шаблона MVP. Файл src/kirana/.env.example — устаревший фрагмент для запуска отдельных скриптов из src/kirana/ (другие порты, в т.ч. PostgreSQL 5432); для Docker Compose и MVP используйте только mvp.env.example:
cp mvp.env.example .env
# Отредактируйте LLM, при необходимости порты (POSTGRES_PORT=5433 и др. — см. mvp.env.example)Ключевые переменные из mvp.env.example (полный список — в файле и src/kirana/config/settings.py):
POSTGRES_PORT=5433
POSTGRES_URL=postgresql+asyncpg://admin:admin@localhost:5433/db
QDRANT_REST_PORT=6333
CELERY_BROKER_URL=amqp://admin:admin@localhost:5672//
LLM_PROVIDER=local
OPENAI_BASE_URL=http://127.0.0.1:1234/v1
LLM_MODEL_NAME=your-model-idCompose-файл: src/kirana/infra/docker/docker-compose.yml. Единая команда из корня репозитория (нужен .env из шага 3):
cd src/kirana/infra/docker
docker compose --env-file ../../../../.env up -dПоднимаются PostgreSQL, Elasticsearch, Qdrant, RabbitMQ, Redis, API, Celery worker, Streamlit; опционально Prometheus, Grafana, Flower. Миграции Alembic применяет сервис migrations до старта API — отдельный шаг не нужен.
Порты по умолчанию (mvp.env.example):
| Сервис | Порт на хосте |
|---|---|
| PostgreSQL | 5433 (в контейнере 5432) |
| API | 8000 (API_PORT) |
| Метрики API (отдельный порт) | 8001 (METRICS_PORT) |
| Streamlit | 8501 |
| Qdrant REST / dashboard | 6333 |
| Elasticsearch | 9200 |
| RabbitMQ / management | 5672 / 15672 |
| Redis | 6379 |
| Prometheus | 9090 |
| Grafana | 3000 |
| Flower | 5555 |
Остановка (из src/kirana/infra/docker):
docker compose --env-file ../../../../.env downМиграции вручную — только если PostgreSQL на хосте, без Docker-сервиса migrations:
# из корня репозитория
make -C src/kirana/infra migrate
# или:
cd src/kirana/migrations && poetry run alembic upgrade headalembic.ini лежит в src/kirana/migrations/, не в src/kirana/.
# Health check
curl http://localhost:8000/api/v1/health/
# API документация
# Swagger UI: http://localhost:8000/docs
# ReDoc: http://localhost:8000/redoc
# Статус контейнеров (из src/kirana/infra/docker)
docker compose psПосле обработки документа можно задавать вопросы по его содержанию (RAG):
- Streamlit: откройте http://localhost:8501 → страница «Чат с ассистентом». Можно выбрать документ в списке «Документы» и нажать «Чат по этому документу», чтобы ограничить ответы одним произведением.
- API:
POST /api/v1/rag/queryс телом{"query": "Ваш вопрос"}. Опционально:filter_metadata: {"source_id": "<uuid>"}— только по одному документу;source_ids: ["<uuid1>", "<uuid2>"]— по нескольким (цикл/серия);top_k— число фрагментов в контексте.
Чтобы быстро проверить цепочку (рассказ → обработка → вопросы), запустите демо-скрипт (API и Celery worker должны быть запущены):
poetry run python src/kirana/scripts/chatbot_demo.pyПодробности и настройка LLM (локальный сервер, Ollama, OpenAI) — в src/kirana/scripts/README_CHATBOT_DEMO.md; переменные — в .env из mvp.env.example.
Подробная документация по использованию веб-интерфейса доступна в docs/web_interface.md.
Новый веб-интерфейс включает:
- 📊 Dashboard - общая статистика системы
- 🔍 Мониторинг - доступ ко всем веб-интерфейсам сервисов
- ⏱️ Real-time обработка - отслеживание статуса в реальном времени
- 📈 Grafana дашборды - визуализация метрик
- 🎨 Улучшенный UI - современный дизайн с цветовыми индикаторами
Загрузка и обработка документа:
POST /api/v1/documents/process
Content-Type: application/json
{
"filepath": "/path/to/document.fb2",
"chunk_size": 1000,
"chunk_overlap": 200,
"chunker_strategy": "recursive_character",
"embedding_model": "sentence-transformers/all-MiniLM-L6-v2"
}Проверка статуса обработки:
GET /api/v1/documents/{source_id}/statusСписок документов:
GET /api/v1/documents?limit=10&offset=0Полнотекстовый поиск:
POST /api/v1/search
Content-Type: application/json
{
"query": "поисковый запрос",
"limit": 10
}RAG запрос (с генерацией ответа):
POST /api/v1/rag/query
Content-Type: application/json
{
"query": "Что говорится о главном герое?",
"top_k": 5,
"filter_metadata": {"source_id": "uuid-документа"},
"source_ids": []
}Параметры: top_k — количество фрагментов для контекста; filter_metadata.source_id — ограничить поиск одним документом; source_ids — список UUID для поиска по нескольким документам (цикл).
Резюме чанка:
GET /api/v1/chunks/{chunk_id}/summaryРезюме структурной единицы:
GET /api/v1/units/{unit_id}/summaryРезюме документа:
GET /api/v1/documents/{doc_id}/summaryДерево структуры с резюме:
GET /api/v1/documents/{doc_id}/structure# Health check
GET /api/v1/health/
# Readiness check
GET /api/v1/health/ready
# Prometheus метрики (на порту API)
GET /metrics/Streamlit UI: http://localhost:8501
- 📊 Dashboard - общая статистика
- 🔍 Мониторинг - доступ ко всем сервисам
- 📄 Обработка документов с real-time статусом
- 📚 Список документов
- 🔎 Поиск и RAG запросы
- 📋 Резюме и структура
Системы мониторинга:
- 📈 Grafana - дашборды и визуализация
- 📊 Prometheus - сбор метрик
- 🌸 Flower - мониторинг Celery
- 🐰 RabbitMQ - управление очередями
- 🔍 Qdrant UI - векторная БД
- 🔎 Elasticsearch - полнотекстовый поиск
Доступные Grafana дашборды:
- Kirana - System Overview - общий обзор системы
- Kirana - Document Processing - мониторинг обработки документов
Обзор мониторинга: docs/monitoring/README.md; опциональный стек (Prometheus/Grafana и т.д.): docs/monitoring/optional_stack.md
Обработка FB2 файла через API:
import requests
# Загрузка документа
response = requests.post(
"http://localhost:8000/api/v1/documents/process",
json={
"filepath": "/path/to/book.fb2",
"chunk_size": 1000,
"chunk_overlap": 200
}
)
source_id = response.json()["source_id"]
# Проверка статуса
status_response = requests.get(
f"http://localhost:8000/api/v1/documents/{source_id}/status"
)
print(status_response.json())Поиск по документам:
# Полнотекстовый поиск
search_response = requests.post(
"http://localhost:8000/api/v1/search",
json={"query": "главный герой", "limit": 5}
)
results = search_response.json()["results"]
# RAG запрос
rag_response = requests.post(
"http://localhost:8000/api/v1/rag/query",
json={"query": "О чем эта книга?", "top_k": 3}
)
answer = rag_response.json()["answer"]src/kirana/
├── api/ # FastAPI приложение
│ ├── main.py # Основное приложение
│ ├── health.py # Health checks
│ └── schemas.py # Pydantic схемы
├── config/ # Конфигурация
│ └── settings.py # Pydantic Settings
├── core/ # Базовые компоненты
│ ├── cache.py # Redis кэширование
│ ├── logging_config.py # Структурированное логирование
│ ├── metrics.py # Prometheus метрики
│ └── retry.py # Retry логика (tenacity)
├── database/ # Работа с базами данных
│ ├── postgres/ # PostgreSQL модели и репозитории
│ ├── elastic_search/ # Elasticsearch клиент
│ └── qdrant/ # Qdrant векторная БД
├── processing/ # Обработка документов
│ ├── chunkers/ # Разбиение на чанки (LangChain)
│ │ └── validation.py # Pydantic валидация параметров
│ ├── common/ # Общие модели и утилиты
│ │ └── llm_utils.py # Утилиты для работы с LLM
│ ├── parsers/ # Парсеры документов
│ ├── steps/ # Шаги пайплайна обработки
│ │ ├── initialization_step.py
│ │ ├── parsing_step.py
│ │ ├── chunking_step.py
│ │ ├── vectorization_step.py
│ │ ├── enrichment_step.py # Суммаризация чанков
│ │ ├── raptor_step.py # RAPTOR суммаризация
│ │ └── storage_step.py
│ ├── vectorizers/ # Векторизация текста
│ └── pipeline.py # Главный пайплайн
├── rag/ # RAG система
│ ├── chain.py # RAG цепочка
│ └── retriever.py # Гибридный retriever
└── tasks/ # Celery задачи
└── document_processing.py
- Инициализация — создание записи
SourceDocumentв PostgreSQL - Предобработка — определение формата и извлечение метаданных
- Парсинг — извлечение структуры и текста документа
- Сохранение структуры — сохранение
ProcessedDocumentиStructuralUnitв PostgreSQL - Чанкинг — разбиение текста на чанки
- Векторизация — создание векторных представлений
- Обогащение — генерация резюме для чанков (LLM)
- Сохранение чанков — сохранение чанков и резюме в PostgreSQL и Elasticsearch
- RAPTOR — иерархическая суммаризация структурных единиц
- Сохранение векторов — сохранение векторов в Qdrant
- PostgreSQL — основное хранилище (документы, структурные единицы, чанки, метаданные)
- Elasticsearch — полнотекстовый поиск и хранение резюме
- Qdrant — векторный поиск (семантический поиск)
- Redis — кэширование результатов поиска и RAG запросов
Полный список параметров конфигурации доступен в src/kirana/config/settings.py.
Ключевые параметры:
# Обработка
CHUNK_SIZE=1000 # Размер чанка
CHUNK_OVERLAP=200 # Перекрытие чанков
CHUNKER_STRATEGY=recursive_character # Стратегия чанкинга
EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
# RAG (Qdrant + Elasticsearch → RRF; ранжирование — Qwen Reranker, см. rag_* в settings)
RAG_TOP_K_VECTOR=5 # Лимит кандидатов из векторного поиска
RAG_TOP_K_TEXT=5 # Лимит кандидатов из полнотекстового поиска
# LLM
LLM_PROVIDER=openai # openai, ollama, local
LLM_TEMPERATURE=0.7 # Температура для генерации
# Для локальных серверов:
# OPENAI_BASE_URL=http://192.168.1.151:1234/v1 # Адрес локального сервера
# OPENAI_API_KEY= # Не обязателен для локальных серверовОтвет RAG нумерует фрагменты контекста как [1]…[N]; постобработка проверяет, что ссылки указывают на реально переданные документы, а дословные цитаты «…» совпадают с первичным текстом чанков (не с LLM-резюме). Реализация: src/kirana/rag/postprocess.py (validate_citations, validate_quotes); включение — rag_validate_citations, rag_validate_quotes в settings. Скрипт оценки faithfulness/evidence: scripts/eval/run_evidence_validation_eval.py (артефакты локально, см. scripts/eval/README.md).
Из корня репозитория (testpaths = src/kirana/tests в pyproject.toml):
# Все тесты
poetry run pytest
# С покрытием
poetry run pytest --cov=src/kirana --cov-report=html
# Только API тесты
poetry run pytest src/kirana/tests/api/
# Только тесты обработки
poetry run pytest src/kirana/tests/processing/
# Мок-тесты пайплайна
poetry run pytest src/kirana/tests/processing/test_pipeline.pyMVP: полноценный ingest и RAG по FB2; PDF/TXT — заглушки в коде; DOCX/HTML не подключены. Метрики экспериментов (retrieval, DeepEval, evidence) — в PDF выпускной работы; скрипты воспроизведения — scripts/eval/.
- Парсинг FB2 с извлечением структуры, чанкинг, векторизация, пайплайн Celery
- Гибридный поиск (Qdrant + Elasticsearch + RRF), RAG с проверкой цитирования
- FastAPI, Streamlit, миграции Alembic, Prometheus/Grafana (опционально)
- Парсеры PDF, DOCX, HTML
- NER/кореференция — экспериментальный контур (GLiNER, eval-скрипты)
- Deep Research — отдельный режим оркестрации
Подробная документация доступна в docs/:
- Обзор документации — структура и навигация
- Пайплайн обработки — детальное описание шагов
- RAG система — работа с RAG
- API документация — описание endpoints
- Базы данных — работа с БД
- Конфигурация — настройка системы
Дополнительные документы:
- Мониторинг 📊 — что доступно из коробки и ссылки; опциональный стек — optional_stack.md
Сборка документации (MkDocs Material): poetry install --with dev, затем mkdocs serve или make -C docs serve (http://127.0.0.1:8000). Подробнее: docs/README.md.
# Установка dev зависимостей
poetry install --with dev
# Установка pre-commit hooks
pre-commit install# Black
black src/kirana
# Ruff (linting)
ruff check src/kirana
ruff format src/kiranaРабочий каталог — src/kirana/migrations/ (там же alembic.ini):
cd src/kirana/migrations
# Создание новой миграции
poetry run alembic revision --autogenerate -m "description"
# Применение миграций
poetry run alembic upgrade head
# Откат миграции
poetry run alembic downgrade -1Логи доступны в консоли и (опционально) в файлах. Для production рекомендуется использовать JSON формат:
JSON_LOGS=true
LOG_LEVEL=INFO- Streamlit Dashboard: http://localhost:8501 - главный интерфейс
- Grafana: http://localhost:3000 - визуализация метрик (admin/admin)
- Prometheus: http://localhost:9090 - сбор метрик
- Метрики API: http://localhost:8000/metrics/ (основной эндпоинт на порту API); в Docker дополнительно проброшен
METRICS_PORT(8001 по умолчанию) — http://localhost:8001/metrics для scrape Prometheus - Flower (Celery): http://localhost:5555 - мониторинг задач
- RabbitMQ Management: http://localhost:15672 - управление очередями (логин/пароль из
.env, по умолчанию admin/admin) - Qdrant Dashboard: http://localhost:6333/dashboard - векторная БД
- Elasticsearch: http://localhost:9200 - полнотекстовый поиск
Документация: docs/monitoring/README.md, опциональный стек: optional_stack.md
Проблема: Elasticsearch не запускается
- Решение: Увеличьте лимит памяти:
sudo sysctl -w vm.max_map_count=262144
Проблема: Модель embeddings не загружается
- Решение: Проверьте доступное место на диске и интернет-соединение для загрузки модели
Проблема: Celery задачи не выполняются
- Решение: Убедитесь, что worker запущен и подключен к RabbitMQ
Репозиторий не инициализирован в git по умолчанию. На машине с корпоративным GitLab используйте только GitHub для Kirana:
cd /path/to/linter_polygon_jmlc
chmod +x scripts/git_init_github.sh .githooks/pre-push
GITHUB_REMOTE=https://github.com/bugkira/kirana.git \
GIT_USER_EMAIL=you@personal.email \
./scripts/git_init_github.sh
git config --local commit.gpgsign false # при необходимости, только локальноСкрипт делает git init с веткой main (или переименует master → main), задаёт локальные user.name / user.email (не трогает global), включает .githooks/pre-push (блокирует push на ptsecurity, gitlab.*, *.internal и др.) и remote.origin.pushurl только на GitHub. Если в URL остался placeholder (YOUR_GITHUB_LOGIN), скрипт выведет предупреждение — перед push подставьте реальный репозиторий. Пример remotes: GIT_REMOTES.example.
После init (реальный URL GitHub, репозиторий на github.com можно создать позже):
git remote set-url origin https://github.com/bugkira/kirana.git
git config --local remote.origin.pushurl https://github.com/bugkira/kirana.git
git add -A
git commit -m "Initial commit: Kirana MVP"
git push -u origin main # только когда empty repo уже создан на GitHubGlobal git на этой машине может содержать user.email=dsereda@ptsecurity.com — для публичного GitHub задайте личный email через GIT_USER_EMAIL или git config --local user.email. Скриншоты и .env в git не коммитить.
- Fork проекта
- Создайте feature branch (
git checkout -b feature/amazing-feature) - Commit изменения (
git commit -m 'Add amazing feature') - Push в branch (
git push origin feature/amazing-feature) - Откройте Pull Request
MIT License
- LangChain за инструменты для работы с LLM
- HuggingFace за модели embeddings
- FastAPI за отличный фреймворк для API
Версия: 0.1.0
Последнее обновление: 2025–2026