Agent pre manažment záverečných prác
Go to file
2026-08-15 23:54:10 +02:00
app oprava opewebui 2026-08-15 01:52:06 +02:00
evaluation Rozdelenie RAG evaluátora na runner a metriky 2026-08-15 23:54:10 +02:00
scripts utils 2026-08-15 01:00:43 +02:00
test ragtest 2026-08-15 01:01:00 +02:00
.dockerignore Zlepšenia 2026-07-28 23:56:03 +02:00
.gitignore Hybrid vyhladavanie s embedding 2026-08-12 00:53:26 +02:00
docker-compose.yml upravy 2026-08-13 21:39:42 +02:00
Dockerfile Dockerfile 2026-08-15 00:59:53 +02:00
README.md readme 2026-08-13 21:41:53 +02:00
requirements-dev.txt Zlepšenia 2026-07-28 23:56:03 +02:00
requirements.txt Hybrid vyhladavanie s embedding 2026-08-12 00:53:26 +02:00

ZP Agent

Backend pre indexovanie, hybridné vyhľadávanie a RAG nad repozitárom záverečných prác zpwiki.

Projekt načítava Markdown dokumenty, spracuje YAML metadata, rozdelí obsah na tokenové chunky a vytvorí SQLite index kombinujúci FTS5 fulltextové vyhľadávanie a embeddingy. Nad hybridným vyhľadávaním je vytvorená RAG vrstva, ktorá pripravuje kontext, zdroje a pravidlá pre odpoveď jazykového modelu. API je integrované so školským OpenWebUI ako OpenAPI Tool Server.

Implementované

  • načítanie Markdown súborov a YAML front matter,
  • normalizácia názvov, autorov, tagov, kategórií a published,
  • tokenové chunkovanie pomocou tiktoken,
  • konfigurovateľná maximálna veľkosť chunku, overlap a minimálna veľkosť chunku,
  • zachovanie názvu dokumentu a hierarchie nadpisov v chunku,
  • SQLite databáza a FTS5 fulltextový index,
  • BM25 vyhľadávanie s podporou diakritiky a prefixových výrazov,
  • vyhľadávacie stratégie all_terms, prefix_terms a any_term,
  • embeddingy pre každý chunk pomocou modelu intfloat/multilingual-e5-small,
  • uloženie embeddingov priamo v SQLite,
  • vektorové vyhľadávanie pomocou cosine similarity,
  • hybridné vyhľadávanie FTS5 + embeddings pomocou RRF,
  • nižšia váha pre slabú any_term FTS stratégiu,
  • zachovanie presných all_terms a prefix_terms výsledkov bez vektorového šumu,
  • obmedzenie počtu výsledkov z jedného dokumentu pomocou max_per_document,
  • filtrovanie publikovaných dokumentov,
  • generovanie source_url pre dohľadateľnosť výsledkov,
  • RAG vrstva s pripraveným kontextom, zdrojmi a pravidlami pre grounded odpoveď,
  • pravidlá proti používaniu neoverených informácií a zamieňaniu rôznych typov údajov,
  • FastAPI endpointy /health, /rag, /search, /sync a /webhook/gitea,
  • autorizácia vyhľadávania pomocou X-API-Key alebo Bearer tokenu,
  • autorizácia /sync pomocou samostatného API kľúča,
  • CORS konfigurácia pre OpenWebUI,
  • integrácia s OpenWebUI cez OpenAPI Tool Server,
  • Gitea webhook s HMAC-SHA256 podpisom a kontrolou udalosti a repozitára,
  • zámok proti súbežnému reindexovaniu,
  • atomická výmena databázy po úspešnom reindexovaní,
  • persistentná Hugging Face cache v Docker volume,
  • warm-up embeddingového modelu,
  • automatizované a integračné testy vrátane RAG endpointu.

Architektúra

zpwiki
  ↓
Markdown + YAML
  ↓
normalizácia dokumentov
  ↓
tokenové chunkovanie
  ↓
SQLite
├── dokumenty a metadata
├── chunky
├── FTS5
└── embeddingy
  ↓
hybridné vyhľadávanie
├── FTS5 / BM25
└── embeddingové vyhľadávanie
  ↓
RRF fusion
  ↓
RAG kontext + zdroje
  ↓
FastAPI /rag
  ↓
OpenWebUI / ZP Agent
  ↓
jazykový model
  ↓
odpoveď so source_url

Štruktúra

zp-agent/
├── app/
│   └── main.py
├── scripts/
│   ├── common.py
│   ├── scan_zpwiki.py
│   ├── build_chunks.py
│   ├── build_sqlite_index.py
│   ├── embedding_utils.py
│   ├── rag_utils.py
│   ├── rebuild_index.py
│   ├── search_db.py
│   └── search_utils.py
├── test/
├── data/
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── requirements-dev.txt
└── README.md

Projekt očakáva repozitáre v tejto štruktúre:

~/DP/
├── zpwiki/
└── zp-agent/

Konfigurácia

V koreňovom priečinku vytvor .env:

WEBHOOK_SECRET=<náhodná hodnota s minimálne 32 znakmi>
SYNC_API_KEY=<iná náhodná hodnota s minimálne 32 znakmi>
SEARCH_API_KEY=<ďalšia náhodná hodnota s minimálne 32 znakmi>
EXPECTED_GITEA_REPOSITORY=KEMT/zpwiki
WEBHOOK_PULL_GIT=false

# Voliteľné
EMBEDDING_MODEL=intfloat/multilingual-e5-small
EMBEDDING_BATCH_SIZE=32

Tajomstvá je možné vygenerovať príkazom:

openssl rand -hex 32

Súbor .env sa nesmie commitovať.

Chunkovanie je možné konfigurovať pomocou premenných prostredia:

CHUNK_MAX_TOKENS=450
CHUNK_OVERLAP_TOKENS=70
CHUNK_MIN_TOKENS=80
CHUNK_TOKEN_ENCODING=cl100k_base

Spustenie cez Docker

docker compose up -d --build

Kontrola služby:

curl http://127.0.0.1:8000/health

Swagger UI:

http://127.0.0.1:8000/docs

Logy:

docker compose logs -f zp-agent-api

Zastavenie:

docker compose down

Hugging Face cache je uložená v persistentnom Docker volume, takže sa embeddingový model pri bežnom reštarte kontajnera nemusí znova sťahovať.

Reindexovanie

Celý proces načíta dokumenty, vytvorí chunky, obnoví FTS5 index a vytvorí embedding pre každý chunk:

docker compose run --rm zp-agent-api python scripts/rebuild_index.py

Vzniknú súbory:

data/documents.json
data/chunks.json
data/zp_index.sqlite

Databáza obsahuje dokumenty, chunky, FTS5 index, metadata a embeddingy.

Pri automatickom reindexovaní sa používa zámok proti súbežnému spusteniu a atomická výmena databázy po úspešnom vytvorení nového indexu.

Hybridné vyhľadávanie

Vyhľadávanie kombinuje:

dotaz
├── FTS5 / BM25
└── embeddingové vyhľadávanie
        ↓
   RRF fusion
        ↓
   výsledky

FTS5 používa stratégie:

all_terms
prefix_terms
any_term

Presné lexikálne výsledky majú prednosť pred slabšími sémantickými zhodami. Pri slabšej any_term stratégii sa znižuje jej váha a väčší význam môže dostať embeddingové vyhľadávanie.

Test z terminálu:

docker compose run --rm zp-agent-api   python scripts/search_db.py "rag agent" --limit 5

Pred volaním API načítaj premenné z .env:

set -a
source .env
set +a

Vyhľadávanie cez zabezpečené API:

curl -X POST http://127.0.0.1:8000/search   -H "Content-Type: application/json"   -H "Authorization: Bearer $SEARCH_API_KEY"   -d '{
    "query": "strojový preklad",
    "limit": 3,
    "published_only": false,
    "max_per_document": 1
  }'

API používa hybridný engine:

hybrid_fts5_embeddings

max_per_document=1 zabezpečí, že sa pri požiadavke na viac výsledkov preferujú rôzne dokumenty namiesto viacerých chunkov z rovnakého dokumentu.

RAG

Nad hybridným retrievalom je implementovaná RAG vrstva v scripts/rag_utils.py.

Endpoint /rag vyhľadá relevantné dokumenty a pripraví:

  • textový kontext pre jazykový model,
  • metadata použitých zdrojov,
  • názov a autora dokumentu,
  • source_url,
  • interné retrieval informácie,
  • pravidlá pre grounded odpoveď.

RAG pravidlá požadujú, aby model odpovedal iba podľa poskytnutých zdrojov. Zároveň rozlišujú údaje, ktoré sa môžu ľahko zameniť, napríklad autora dokumentu, osobu, o ktorej dokument pojednáva, rok začiatku štúdia a rok záverečnej práce.

Príklad:

curl -X POST http://127.0.0.1:8000/rag   -H "Content-Type: application/json"   -H "Authorization: Bearer $SEARCH_API_KEY"   -d '{
    "query": "V akom roku robil Ján Holp diplomovú prácu?",
    "limit": 5,
    "published_only": false,
    "max_per_document": 1
  }'

OpenWebUI

ZP Agent je pripojený do OpenWebUI ako OpenAPI Tool Server.

OpenWebUI používa:

OpenAPI URL: http://localhost:8000/openapi.json
Authentication: Bearer
Token: SEARCH_API_KEY

V reálnom nasadení musí byť URL API dostupná z prostredia, v ktorom beží OpenWebUI; localhost je vhodný iba vtedy, ak sa OpenWebUI pripája k API z rovnakého hostiteľa.

OpenAPI schéma určená pre integráciu vystavuje RAG nástroj, ktorý môže jazykový model použiť pri otázkach nad ZP Wiki.

Tok požiadavky:

používateľ
  ↓
OpenWebUI
  ↓
jazykový model
  ↓
ZP Agent /rag
  ↓
hybrid retrieval
  ↓
RAG kontext + zdroje
  ↓
jazykový model
  ↓
odpoveď

Príklad otázky:

Použi ZP Agent a zisti, v akom roku robil Ján Holp diplomovú prácu.

Výsledná odpoveď obsahuje stručnú informáciu získanú zo ZP Wiki a príslušný source_url.

Manuálna synchronizácia

Manuálne reindexovanie cez zabezpečený endpoint:

curl -X POST http://127.0.0.1:8000/sync   -H "Content-Type: application/json"   -H "X-API-Key: $SYNC_API_KEY"   -d '{"pull_git": false}'

Gitea webhook

Endpoint:

POST /webhook/gitea

Webhook overuje:

  • HMAC-SHA256 podpis,
  • typ Gitea udalosti,
  • očakávaný repozitár,
  • stav reindexovacieho zámku.

Očakávaný repozitár:

EXPECTED_GITEA_REPOSITORY=KEMT/zpwiki

Ak je povolené:

WEBHOOK_PULL_GIT=true

pred reindexovaním sa vykoná:

git pull --ff-only

Bezpečnosť

Vyhľadávanie podporuje API key:

X-API-Key: <SEARCH_API_KEY>

aj Bearer autentifikáciu:

Authorization: Bearer <SEARCH_API_KEY>

Bearer autentifikácia sa používa najmä pri integrácii s OpenWebUI.

Endpoint /sync používa samostatný SYNC_API_KEY a webhook samostatný WEBHOOK_SECRET.

Tajomstvá sa ukladajú do .env, ktorý nesmie byť súčasťou Git repozitára.

Testy

Inštalácia testovacích závislostí:

pip install -r requirements-dev.txt

Bežné automatizované testy:

pytest -q test

Aktuálny stav:

77 passed, 2 skipped

Testy vrátane kontroly reálnych dát a databázy:

RUN_LIVE_TESTS=1 pytest -q test

Aktuálny stav:

79 passed

Testovacia sada pokrýva indexovanie, vyhľadávanie, hybridný retrieval, API, autentifikáciu, RAG utility, RAG endpoint a OpenAPI integráciu.