Skip to content

karinversan/ankigen_miniapp

Repository files navigation

Telegram Anki

Полноценный бот для генерации Anki‑колод из учебных материалов с помощью Telegram‑бота и Mini App. Проект включает веб‑интерфейс, API, асинхронного воркера, хранение файлов и AI‑пайплайн генерации.

Основные возможности

  • Загрузка PDF/DOCX/TXT и генерация Anki‑колод.
  • Асинхронная обработка через Celery + Redis.
  • LLM‑генерация через OpenRouter/Gemini API.
  • Эмбеддинги (Gemini) и RAG‑retrieval для «привязки» к источнику.
  • Дедупликация вопросов и базовая валидация качества.
  • Сохранение метрик генерации: latency, throughput, stage timings, dedupe и др.
  • Экспорт в .apkg, готовый к импорту в Anki.

Скриншоты

Telegram bot entry
Telegram entry
Topics list
Topics
Empty files state
Empty files
Files with PDF
Files with PDF
Generation params
Generation params
Generation progress
Generation progress

Архитектура

┌──────────────────────────────────────────────────────────────────────────┐
│                             USER / INTERFACE                             │
└──────────────────────────────────────────────────────────────────────────┘
   ┌──────────────┐     ┌────────────────────┐     ┌──────────────────────┐
   │ Telegram Bot │ ──▶ │ Web Mini App (UI)  │ ──▶ │      API (FastAPI)   │
   └──────────────┘     └────────────────────┘     └─────────┬────────────┘
                                                            │
                                                            ▼
                                                 ┌──────────────────────┐
                                                 │   Queue (Redis)      │
                                                 └─────────┬────────────┘
                                                           ▼
┌──────────────────────────────────────────────────────────────────────────┐
│                               WORKER (Celery)                            │
└──────────────────────────────────────────────────────────────────────────┘

  ┌─────────────────┐  ┌───────────────┐  ┌───────────────────┐
  │  Extraction     │→ │   Chunking    │→ │  Normalize Chunks │
  └─────────────────┘  └───────────────┘  └─────────┬─────────┘
                                                    │
                                                    ▼
  ┌───────────────────────────────────────────────────────────────┐
  │                 Index / Retrieval (RAG)                      │
  │  • Vector DB (Chroma + Embeddings)                           │
  │  • Fallback: Lexical retrieval                               │
  └───────────────┬──────────────────────────────────────────────┘
                  │
                  ▼
  ┌───────────────────────┐        ┌───────────────────────────┐
  │ Planner (Topics)      │ ─────▶ │ Evidence Builder          │
  │ LLM: short topic list │        │ top‑k chunks per topic    │
  └──────────┬────────────┘        └──────────────┬────────────┘
             │                                    │
             └────────────────────────────────────┘
                              ▼
                   ┌────────────────────┐
                   │ QGen (LLM)         │
                   │ open / mcq / tf    │
                   └──────────┬─────────┘
                              ▼
                   ┌────────────────────┐
                   │ Verify / Tagging   │
                   │ sources / unverified│
                   └──────────┬─────────┘
                              ▼
                   ┌────────────────────┐
                   │ Mix + Dedupe       │
                   │ simhash + jaccard  │
                   └──────────┬─────────┘
                              ▼
                   ┌────────────────────┐
                   │ Export (.apkg)     │
                   └──────────┬─────────┘
                              ▼
┌──────────────────────────────────────────────────────────────────────────┐
│                                 STORAGE                                  │
│   Encrypted files + Exports                                               │
└──────────────────────────────────────────────────────────────────────────┘

                              ▼
┌──────────────────────────────────────────────────────────────────────────┐
│                            STATUS TO USER                                │
│         Worker → API → Web App → Telegram User                            │
└──────────────────────────────────────────────────────────────────────────┘

Сервисы

  • bot/ — aiogram‑бот, открывает Mini App и управляет доступом.
  • web/ — React Mini App UI (Telegram WebApp SDK).
  • api/ — FastAPI backend (auth, темы, файлы, запуск задач).
  • worker/ — Celery‑воркер (извлечение, генерация, экспорт).
  • infra/ — Dockerfiles, compose, миграции.
  • data/ / storage/ — зашифрованное хранение файлов и экспортов.

AI‑пайплайн генерации (подробнее)

┌───────────────┐  ┌───────────────┐  ┌───────────────────┐  ┌─────────────────────┐
│  Extraction   │→ │   Chunking    │→ │  Normalize Chunks │→ │ Index / Retrieval    │
└───────────────┘  └───────────────┘  └───────────────────┘  │ (RAG + fallback)     │
                                                             └──────────┬──────────┘
                                                                        │
                                                                        ▼
┌───────────────────────┐   ┌──────────────────────────┐   ┌──────────────────────┐
│ Planner (Topics)      │→→ │ Evidence Builder         │→→ │ QGen (LLM)            │
│ short topic list      │   │ top‑k chunks per topic   │   │ open / mcq / tf       │
└───────────────────────┘   └──────────────────────────┘   └──────────┬───────────┘
                                                                       ▼
                                                        ┌──────────────────────┐
                                                        │ Verify / Tagging     │
                                                        │ sources / unverified │
                                                        └──────────┬───────────┘
                                                                       ▼
                                                        ┌──────────────────────┐
                                                        │ Mix + Dedupe         │
                                                        │ simhash + jaccard    │
                                                        └──────────┬───────────┘
                                                                       ▼
                                                        ┌──────────────────────┐
                                                        │ Export (.apkg)       │
                                                        └──────────────────────┘

Ниже — как устроена генерация и зачем нужен каждый шаг.

1) Извлечение текста (Extraction)

Что делает: распаковывает входные файлы (PDF/DOCX/TXT) в чистый текст.
Почему так: нормализация входа нужна, чтобы работать с разными форматами одинаково.

2) Чанкинг (Chunking)

Что делает: режет текст на смысловые куски ~250–450 слов, overlap ~60 слов.
Почему так: LLM лучше работает с небольшими фрагментами; overlap сохраняет контекст на стыках и уменьшает потери смысла.

3) Нормализация чанков (Normalize)

Что делает: очищает и унифицирует фрагменты (обрезка пустых, нормализация пробелов).
Почему так: уменьшает шум в retrieval и повышает стабильность генерации.

4) Индексация и Retrieval (Index / Retrieval)

Что делает: строит векторный индекс (Chroma + embeddings); если embeddings недоступны — fallback на лексическое извлечение.
Почему так: retrieval подбирает релевантные фрагменты под каждую тему, снижая «галлюцинации».

5) Планирование тем (Plan Topics)

Что делает: LLM строит список ключевых тем для каждого файла.
Почему так: обеспечивает равномерное покрытие и снижает повторения.

6) Пакеты доказательств (Evidence Packets)

Что делает: собирает короткие контекстные блоки для каждой темы.
Почему так: QGen получает только релевантные факты, а не весь документ.

7) Генерация вопросов (QGen)

Что делает: генерирует open/mcq/tf‑вопросы + ответы + источники.
Почему так: стандартизированный формат облегчает экспорт в Anki и последующую проверку.

8) Проверка и теги (Verify)

Что делает: отмечает вопросы без источников (например, тегом unverified).
Почему так: помогает отсекать «сомнительные» вопросы при финальной сборке.

9) Микс и дедупликация (Mix + Dedupe)

Что делает: объединяет вопросы с разных файлов и удаляет повторы (simhash + Jaccard по токенам/символьным n‑граммам).
Почему так: экономит место в колоде и повышает разнообразие карточек.

10) Экспорт (Export APKG)

Что делает: формирует .apkg через genanki.
Почему так: Anki‑колода сразу готова к импорту.

Запуск проекта

Быстрый старт (Docker)

cp .env.example .env
# заполнить обязательные секреты:
# BOT_TOKEN, JWT_SECRET, ENCRYPTION_KEY_BASE64
# задай уникальное имя стека для этого проекта (важно при нескольких compose-проектах на одном сервере)
# STACK_NAME=tg_anki_prod

docker compose up -d --build
# или разово без правки .env:
# STACK_NAME=tg_anki_prod docker compose up -d --build

Конфигурация

Минимально нужны:

  • STACK_NAME — уникальное имя docker compose-стека (например, tg_anki_prod)
  • BOT_TOKEN — токен Telegram‑бота
  • JWT_SECRET — секрет для JWT
  • ENCRYPTION_KEY_BASE64 — 32 байта (AES‑GCM)
  • ADMIN_TELEGRAM_IDS — список Telegram ID админов через запятую (например, 123456789)

Дополнительно:

  • LLM_PROVIDER=openrouter — генерация через OpenRouter API
  • OPENROUTER_API_KEY — ключ OpenRouter (если выбран openrouter)
  • OPENROUTER_MODEL — модель OpenRouter, например qwen/qwen3-8b:free
  • GEMINI_API_KEY — только если используешь LLM_PROVIDER=gemini
  • RAG_USE_EMBEDDINGS=true включает embeddings
  • EMBEDDING_PROVIDER=gemini (рекомендуется для production)
  • RAG_REUSE_VECTOR_STORE=true — переиспользовать существующий Chroma-индекс (сильно ускоряет повторные генерации)
  • JOB_EXTRACT_CONCURRENCY=4 — параллелизм извлечения текста
  • JOB_CHUNK_CONCURRENCY=4 — параллелизм chunking

Метрики и бенчмарк

В Mini App для админа доступна кнопка Метрики на главной странице (только если ваш telegram_id есть в ADMIN_TELEGRAM_IDS). На странице метрик можно посчитать отчёт, скачать JSON/MD и отправить отчёт в Telegram.

Для контрольного end-to-end прогона (создать тему -> загрузить файл -> запустить генерацию -> дождаться результата -> собрать метрики):

uv run python scripts/generation_benchmark_run.py \
  --api-base-url https://your-api.example.com \
  --bot-token "$BOT_TOKEN" \
  --runs 3 \
  --questions 20 \
  --json-out results/benchmark-summary.json

Опционально можно передать свои входные файлы (повтори флаг несколько раз):

uv run python scripts/generation_benchmark_run.py \
  --api-base-url https://your-api.example.com \
  --bot-token "$BOT_TOKEN" \
  --file ./samples/doc1.txt \
  --file ./samples/doc2.txt

После нескольких запусков генерации можно собрать агрегированный отчёт:

uv run python scripts/generation_metrics_report.py --limit 50 \
  --json-out results/metrics-summary.json \
  --md-out results/metrics-summary.md

Скрипт считает core KPI для продукта:

  • completion_rate, failed_rate, rate_limited_failure_rate
  • TTV (e2e_seconds) p50/p95
  • нормализованную скорость: sec_per_question, sec_per_1k_chars
  • качество: quality_score, source_coverage_ratio, duplicate_rate
  • устойчивость: retries_per_job, failed_calls_per_job

Пример реального агрегированного отчёта (2026-03-22, 22 задач, файл отчёта от Telegram):

  • Среднее время до готового результата (ttv_mean): 42.463s
  • Среднее время на одну карточку (sec_per_question_mean): 2.123s
  • Среднее время на 1000 символов входного текста (sec_per_1k_chars_mean): 0.557s
  • Оценка качества карточек (quality_score): 59.800 Эта метрика собирается из четырёх факторов: сколько карточек удалось сгенерировать от запрошенного количества, у скольких карточек есть источник, насколько источники покрывают входные файлы и насколько вопросы уникальны.
  • Доля карточек с привязкой к источнику (source_coverage_ratio): 1.000
  • Доля дубликатов в генерации (duplicate_rate): 0.000

Эти цифры отражают текущее фактическое состояние системы, а не целевые значения.

Что важно знать

  • Файлы хранятся зашифрованно (AES‑GCM).
  • При проблемах с embeddings включается лексический fallback.
  • Отмена/перезапуск генерации автоматически завершает старые задачи.

About

End‑to‑end Telegram Mini App that ingests PDFs/notes, extracts text, chunks and dedupes content, and generates Anki decks through an LLM pipeline. Built with FastAPI + SQLAlchemy/Alembic, Celery + Redis + PostgreSQL, React/TypeScript (Vite), aiogram bot, Docker, and LLMs with local embeddings

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors