9.6 KiB
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_termsaany_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_termFTS stratégiu, - zachovanie presných
all_termsaprefix_termsvýsledkov bez vektorového šumu, - obmedzenie počtu výsledkov z jedného dokumentu pomocou
max_per_document, - filtrovanie publikovaných dokumentov,
- generovanie
source_urlpre 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,/synca/webhook/gitea, - autorizácia vyhľadávania pomocou
X-API-Keyalebo Bearer tokenu, - autorizácia
/syncpomocou 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.