Skip to content

Repository files navigation

Kirana - Интеллектуальная система для глубокого анализа книг

Python FastAPI License

Kirana — интеллектуальная RAG (Retrieval-Augmented Generation) система для глубокого анализа художественных книг: парсинг FB2, чанкинг, гибридный поиск (Qdrant + Elasticsearch + RRF), переранжировка и генерация ответов с цитированием фрагментов. Режим Deep Research — многошаговая оркестрация по корпусу.

Зачем Kirana

Репозиторий собран вокруг инженерного контура: пайплайн обработки длинных художественных текстов, гибридный поиск, цитирование и 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 (профиль compose lightrag, ETL scripts/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

Поиск и RAG

  • Гибридный поиск — комбинация векторного (Qdrant) и полнотекстового (Elasticsearch) поиска
  • RAG цепочки для генерации ответов на основе извлеченённой информации; ответы ссылаются на фрагменты контекста [1]…[N], постобработка проверяет ссылки и цитаты (см. ниже «Контракт цитирования»)
  • Поддержка LLM — OpenAI, Ollama, локальные модели

Инфраструктура

  • FastAPI REST API с автоматической документацией (Swagger/ReDoc)
  • Асинхронная обработка через Celery
  • Кэширование через Redis
  • Мониторинг через Prometheus + Grafana
  • Улучшенный веб-интерфейс с real-time мониторингом
  • Структурированное логирование (structlog)
  • Retry логика для всех внешних сервисов (tenacity)

MVP: зелёная дорожка

  • Ингест: валидный 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)

🚀 Быстрый старт

1. Клонирование репозитория

git clone https://github.com/bugkira/kirana.git
cd kirana

2. Установка зависимостей

# Установка Poetry (если не установлен)
curl -sSL https://install.python-poetry.org | python3 -

# Установка зависимостей проекта
poetry install

# Активация виртуального окружения
poetry shell

3. Настройка окружения

Создайте .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-id

4. Запуск стека

Compose-файл: 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 head

alembic.ini лежит в src/kirana/migrations/, не в src/kirana/.

5. Проверка работоспособности

# 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

6. Чат-бот: вопросы по тексту

После обработки документа можно задавать вопросы по его содержанию (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 - современный дизайн с цветовыми индикаторами

📖 Использование

API Endpoints

Обработка документов

Загрузка и обработка документа:

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 дашборды:

  1. Kirana - System Overview - общий обзор системы
  2. 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

Пайплайн обработки

  1. Инициализация — создание записи SourceDocument в PostgreSQL
  2. Предобработка — определение формата и извлечение метаданных
  3. Парсинг — извлечение структуры и текста документа
  4. Сохранение структуры — сохранение ProcessedDocument и StructuralUnit в PostgreSQL
  5. Чанкинг — разбиение текста на чанки
  6. Векторизация — создание векторных представлений
  7. Обогащение — генерация резюме для чанков (LLM)
  8. Сохранение чанков — сохранение чанков и резюме в PostgreSQL и Elasticsearch
  9. RAPTOR — иерархическая суммаризация структурных единиц
  10. Сохранение векторов — сохранение векторов в 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=  # Не обязателен для локальных серверов

Контракт цитирования (evidence)

Ответ 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.py

📊 Статус проекта

MVP: полноценный ingest и RAG по FB2; PDF/TXT — заглушки в коде; DOCX/HTML не подключены. Метрики экспериментов (retrieval, DeepEval, evidence) — в PDF выпускной работы; скрипты воспроизведения — scripts/eval/.

Реализовано в MVP

  • Парсинг FB2 с извлечением структуры, чанкинг, векторизация, пайплайн Celery
  • Гибридный поиск (Qdrant + Elasticsearch + RRF), RAG с проверкой цитирования
  • FastAPI, Streamlit, миграции Alembic, Prometheus/Grafana (опционально)

Вне scope submission / в разработке

  • Парсеры PDF, DOCX, HTML
  • NER/кореференция — экспериментальный контур (GLiNER, eval-скрипты)
  • Deep Research — отдельный режим оркестрации

📚 Документация

Подробная документация доступна в docs/:

Дополнительные документы:

Сборка документации (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

Мониторинг

Документация: docs/monitoring/README.md, опциональный стек: optional_stack.md

Типичные проблемы

Проблема: Elasticsearch не запускается

  • Решение: Увеличьте лимит памяти: sudo sysctl -w vm.max_map_count=262144

Проблема: Модель embeddings не загружается

  • Решение: Проверьте доступное место на диске и интернет-соединение для загрузки модели

Проблема: Celery задачи не выполняются

  • Решение: Убедитесь, что worker запущен и подключен к RabbitMQ

Публикация в GitHub

Репозиторий не инициализирован в 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 (или переименует mastermain), задаёт локальные 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 уже создан на GitHub

Global git на этой машине может содержать user.email=dsereda@ptsecurity.com — для публичного GitHub задайте личный email через GIT_USER_EMAIL или git config --local user.email. Скриншоты и .env в git не коммитить.

🤝 Вклад в проект

  1. Fork проекта
  2. Создайте feature branch (git checkout -b feature/amazing-feature)
  3. Commit изменения (git commit -m 'Add amazing feature')
  4. Push в branch (git push origin feature/amazing-feature)
  5. Откройте Pull Request

📝 Лицензия

MIT License

🙏 Благодарности

  • LangChain за инструменты для работы с LLM
  • HuggingFace за модели embeddings
  • FastAPI за отличный фреймворк для API

Версия: 0.1.0
Последнее обновление: 2025–2026

About

RAG/AutoWiki/Graph of knowledge для художественной литературы.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages