1139 lines
29 KiB
Markdown
1139 lines
29 KiB
Markdown
# 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.
|
||
|
||
Stabilná baseline retrieval vetva používa klasický hybridný RAG:
|
||
FTS5/BM25 + embeddingy + RRF. Nad týmto baseline sa vo vetve GraphRAG
|
||
dopĺňa knowledge graph uložený v Neo4j. Aktuálne je implementovaná
|
||
grafová infraštruktúra, deterministický builder, vizualizácia grafu a
|
||
samostatné grafové vyhľadávanie. Grafová vrstva má zdrojovo overený benchmark a zmrazenú opravenú
|
||
verziu v5.1 s regresiou 320 historických otázok, kontrolou všetkých vrátených
|
||
typovaných faktov a samostatným overením generovania odpovedí cez OpenWebUI API. Ďalším krokom je natívne zapojenie grafového
|
||
nástroja a hlavného agenta do OpenWebUI.
|
||
|
||
## 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,
|
||
- lexikálne zvýhodnenie presných alebo veľmi silných zhôd,
|
||
- 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ď,
|
||
- rozšírenie RAG kontextu o začiatok rovnakej sekcie
|
||
(`section-lead expansion`) bez globálneho zvýšenia
|
||
`max_per_document`,
|
||
- pravidlá proti používaniu neoverených informácií a zamieňaniu
|
||
rôznych typov údajov,
|
||
- no-answer správanie pri chýbajúcej alebo nedostatočne podloženej
|
||
informácii,
|
||
- FastAPI endpointy `/health`, `/rag`, `/search`, `/sync` a
|
||
`/webhook/gitea`,
|
||
- striktná validácia API vstupov,
|
||
- 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,
|
||
- bezpečnostné HTTP hlavičky,
|
||
- integrácia s OpenWebUI cez OpenAPI Tool Server,
|
||
- Gitea webhook s HMAC-SHA256 podpisom, limitom veľkosti payloadu 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,
|
||
- Neo4j databáza spúšťaná ako samostatná Docker služba,
|
||
- deterministická tvorba knowledge graphu z `documents.json` a
|
||
`chunks.json`,
|
||
- grafové entity `Person`, `Document`, `DocumentAuthor`, `Thesis`,
|
||
`Work`, `Keyword`, `Topic` a `Category`,
|
||
- grafové vzťahy pre dokumenty, práce, témy, kategórie a autorstvo,
|
||
- uniqueness constraints a opakovateľný rebuild GraphRAG grafu,
|
||
- Neo4j Browser na vizualizáciu a kontrolu vytvoreného grafu,
|
||
- samostatné grafové vyhľadávanie nad Neo4j s rozpoznaním entít, vzťahov, prác, tém a rokov,
|
||
- retrieval evaluácia pre FTS, embeddings a hybridný retrieval,
|
||
- answer-level RAG evaluácia cez OpenWebUI model a RAG tool,
|
||
- oddelené answer-level overrides bez úpravy frozen retrieval
|
||
benchmarku,
|
||
- príprava rozšírených datasetov pre extended RAG, GraphRAG,
|
||
robustness a performance experimenty.
|
||
|
||
## Architektúra
|
||
|
||
```text
|
||
zpwiki
|
||
↓
|
||
Markdown + YAML
|
||
↓
|
||
scan_zpwiki.py
|
||
↓
|
||
normalizované dokumenty
|
||
↓
|
||
build_chunks.py
|
||
↓
|
||
tokenové chunky
|
||
↓
|
||
build_sqlite_index.py
|
||
↓
|
||
SQLite
|
||
├── dokumenty
|
||
├── metadata
|
||
├── chunky
|
||
├── FTS5
|
||
└── embeddingy
|
||
↓
|
||
search_core.py / search_utils.py
|
||
↓
|
||
hybridné vyhľadávanie
|
||
├── FTS5 / BM25
|
||
├── embeddingové vyhľadávanie
|
||
└── RRF fusion + lexical anchor
|
||
↓
|
||
rag_utils.py
|
||
├── výber zdrojov
|
||
├── section-lead expansion
|
||
├── RAG kontext
|
||
└── grounding pravidlá
|
||
↓
|
||
FastAPI /rag
|
||
↓
|
||
OpenWebUI / ZP Agent
|
||
↓
|
||
jazykový model
|
||
↓
|
||
odpoveď + source_url
|
||
```
|
||
|
||
GraphRAG vývojová vetva:
|
||
|
||
```text
|
||
documents.json + chunks.json
|
||
↓
|
||
graphrag.py
|
||
↓
|
||
build_graphrag.py
|
||
↓
|
||
Neo4j
|
||
├── Person
|
||
├── Document
|
||
├── Thesis
|
||
├── Work
|
||
├── Keyword
|
||
├── Topic
|
||
├── Category
|
||
└── DocumentAuthor
|
||
↓
|
||
grafové vzťahy + vizualizácia
|
||
↓
|
||
graph_search.py
|
||
↓
|
||
grafové entity + cesty + zdrojové dokumenty
|
||
↓
|
||
spojenie s klasickým RAG
|
||
```
|
||
|
||
V aktuálnom stave je implementované vytvorenie a uloženie knowledge
|
||
graphu aj samostatné grafové vyhľadávanie. Jeho zapojenie do `/rag` a
|
||
OpenWebUI sa ešte dopĺňa.
|
||
|
||
Synchronizačná vetva:
|
||
|
||
```text
|
||
Gitea push
|
||
↓
|
||
POST /webhook/gitea
|
||
↓
|
||
HMAC + repository + event validácia
|
||
↓
|
||
voliteľný git pull --ff-only
|
||
↓
|
||
rebuild_index.py
|
||
↓
|
||
nový SQLite index
|
||
↓
|
||
atomická výmena databázy
|
||
```
|
||
|
||
Evaluačná vetva:
|
||
|
||
```text
|
||
tools/rag/evaluation/json_files/*.json
|
||
↓
|
||
retrieval evaluator / RAG answer evaluator
|
||
↓
|
||
runner
|
||
↓
|
||
metriky
|
||
↓
|
||
tools/rag/evaluation/results/
|
||
```
|
||
|
||
`tools/rag/evaluation/results/` nie je v nižšie uvedenom stromčeku,
|
||
pretože obsahuje generované výstupy experimentov.
|
||
|
||
## Štruktúra projektu
|
||
|
||
Nižšie je funkčná štruktúra projektu. Testovacie súbory, generované
|
||
výsledky, cache, `__pycache__`, Git interné súbory a podobné pomocné
|
||
artefakty sú zámerne vynechané.
|
||
|
||
```text
|
||
zp-agent/
|
||
├── app/
|
||
│ ├── main.py
|
||
│ ├── routes.py
|
||
│ └── security.py
|
||
│
|
||
├── tools/
|
||
│ ├── rag/
|
||
│ │ ├── common.py
|
||
│ │ ├── scan_zpwiki.py
|
||
│ │ ├── build_chunks.py
|
||
│ │ ├── build_sqlite_index.py
|
||
│ │ ├── embedding_utils.py
|
||
│ │ ├── rebuild_index.py
|
||
│ │ ├── search_core.py
|
||
│ │ ├── search_utils.py
|
||
│ │ ├── search_db.py
|
||
│ │ ├── rag_utils.py
|
||
│ │ ├── rag_document_expansion.py
|
||
│ │ ├── rag_query_evidence.py
|
||
│ │ ├── rag_supplemental_expansion.py
|
||
│ │ ├── run_e5_regression.sh
|
||
│ │ ├── run_e5_1_regression.sh
|
||
│ │ ├── evaluation/
|
||
│ │ │ ├── evaluate_retrieval.py
|
||
│ │ │ ├── evaluate_rag_answers.py
|
||
│ │ │ ├── retrieval_runner.py
|
||
│ │ │ ├── rag_runner.py
|
||
│ │ │ ├── metrics.py
|
||
│ │ │ ├── rag_metrics.py
|
||
│ │ │ └── json_files/
|
||
│ │ └── tests/
|
||
│ │
|
||
│ └── graphrag/
|
||
│ ├── graph_db.py
|
||
│ ├── graphrag.py
|
||
│ ├── build_graphrag.py
|
||
│ ├── graph_search.py
|
||
│ ├── neo4j_smoke.py
|
||
│ ├── evaluation/
|
||
│ │ └── graphrag_questions.json
|
||
│ └── tests/
|
||
│
|
||
├── test/
|
||
│ ├── test_api.py
|
||
│ ├── test_configuration.py
|
||
│ └── test_security.py
|
||
│
|
||
├── data/
|
||
│ ├── documents.json
|
||
│ ├── chunks.json
|
||
│ └── zp_index.sqlite
|
||
│
|
||
├── Dockerfile
|
||
├── docker-compose.yml
|
||
├── requirements.txt
|
||
├── requirements-dev.txt
|
||
└── README.md
|
||
```
|
||
|
||
### `app/`
|
||
|
||
`app/main.py`
|
||
|
||
- vytvára FastAPI aplikáciu,
|
||
- nastavuje lifespan aplikácie,
|
||
- validuje bezpečnostnú konfiguráciu pri štarte,
|
||
- vykonáva warm-up embeddingovej vrstvy,
|
||
- nastavuje CORS a bezpečnostné hlavičky,
|
||
- pripája API routery,
|
||
- ponecháva OpenAPI schému dostupnú pre OpenWebUI.
|
||
|
||
Interaktívne Swagger/Redoc rozhranie môže byť v produkčnej konfigurácii
|
||
vypnuté. Pre integráciu OpenWebUI je dôležitý endpoint:
|
||
|
||
```text
|
||
/openapi.json
|
||
```
|
||
|
||
`app/routes.py`
|
||
|
||
- definuje `/health`,
|
||
- definuje verejne publikovaný RAG nástroj `/rag`,
|
||
- obsahuje interné/zabezpečené `/search` a `/sync`,
|
||
- obsluhuje `/webhook/gitea`,
|
||
- vykonáva validáciu requestov a sanitizáciu chýb,
|
||
- používa reindexovací zámok,
|
||
- kontroluje webhook payload pred spracovaním.
|
||
|
||
`app/security.py`
|
||
|
||
- spracúva `SEARCH_API_KEY`,
|
||
- spracúva `SYNC_API_KEY`,
|
||
- spracúva `WEBHOOK_SECRET`,
|
||
- vyžaduje dostatočne dlhé a navzájom odlišné tajomstvá,
|
||
- používa bezpečné porovnávanie autentifikačných hodnôt,
|
||
- validuje očakávaný Gitea repozitár a súvisiacu konfiguráciu.
|
||
|
||
### `tools/rag/`
|
||
|
||
`common.py`
|
||
|
||
Spoločné utility a konfiguračné funkcie používané indexovacou a
|
||
vyhľadávacou vrstvou.
|
||
|
||
`scan_zpwiki.py`
|
||
|
||
- prechádza repozitár `zpwiki`,
|
||
- načítava Markdown a YAML front matter,
|
||
- normalizuje dokumentové metadata,
|
||
- pripravuje dokumenty na ďalšie spracovanie.
|
||
|
||
`build_chunks.py`
|
||
|
||
- rozdeľuje dokumenty na tokenové chunky,
|
||
- používa `tiktoken`,
|
||
- zachováva nadpisy, kódové bloky a tabuľky,
|
||
- podporuje tokenový overlap,
|
||
- eviduje token count a hash obsahu chunku.
|
||
|
||
`build_sqlite_index.py`
|
||
|
||
- vytvára SQLite databázu,
|
||
- ukladá dokumenty, chunky a metadata,
|
||
- vytvára FTS5 index,
|
||
- ukladá embeddingy do SQLite,
|
||
- pripravuje databázu pre hybridný retrieval.
|
||
|
||
`embedding_utils.py`
|
||
|
||
- načítava embeddingový model,
|
||
- vytvára embeddingy pre dokumenty a query,
|
||
- normalizuje vektory,
|
||
- poskytuje utility pre vektorové vyhľadávanie.
|
||
|
||
### `tools/graphrag/`
|
||
|
||
`graph_db.py`
|
||
|
||
- načítava konfiguráciu Neo4j,
|
||
- vytvára Neo4j driver,
|
||
- poskytuje kontrolu spojenia s grafovou databázou.
|
||
|
||
`graphrag.py`
|
||
|
||
- pripravuje dátový model knowledge graphu,
|
||
- normalizuje grafové identifikátory,
|
||
- extrahuje osoby, práce, roky, témy, kategórie a súvisiace metadata,
|
||
- pripravuje uzly a vzťahy pre zápis do Neo4j.
|
||
|
||
`build_graphrag.py`
|
||
|
||
- načíta `documents.json` a `chunks.json`,
|
||
- vytvorí GraphRAG payload,
|
||
- vytvorí Neo4j uniqueness constraints,
|
||
- zapíše uzly a vzťahy,
|
||
- podporuje opakovateľný rebuild spravovanej časti grafu,
|
||
- vypíše základné počty uzlov, vzťahov a kvalitu extrakcie názvov prác.
|
||
|
||
`graph_search.py`
|
||
|
||
- rozpoznáva relevantné osoby a obmedzenia v otázke,
|
||
- vyhľadáva práce, témy, roky a spoločné vzťahy v Neo4j,
|
||
- vracia grafové cesty, fakty a zdrojové dokumenty,
|
||
- slúži ako základ budúceho GraphRAG nástroja pre OpenWebUI.
|
||
|
||
`neo4j_smoke.py`
|
||
|
||
Jednoduchý smoke test pripojenia k Neo4j používaný pri kontrole Docker
|
||
prostredia.
|
||
|
||
`search_core.py`
|
||
|
||
Nízkoúrovňové jadro vyhľadávania:
|
||
|
||
- normalizácia query,
|
||
- FTS5 vyhľadávanie,
|
||
- embeddingové vyhľadávanie,
|
||
- scoring,
|
||
- RRF fusion,
|
||
- lexical anchor,
|
||
- metadata,
|
||
- diverzifikácia výsledkov.
|
||
|
||
`search_utils.py`
|
||
|
||
Vyššia orchestration vrstva nad `search_core.py` a kompatibilné
|
||
vyhľadávacie utility používané ostatnými časťami projektu.
|
||
|
||
`search_db.py`
|
||
|
||
CLI rozhranie na ručné vyhľadávanie nad lokálnym SQLite indexom.
|
||
|
||
`rag_utils.py`
|
||
|
||
- zostavuje RAG kontext,
|
||
- pripravuje zdrojové metadata,
|
||
- pridáva `source_url`,
|
||
- aplikuje grounding pravidlá,
|
||
- podporuje no-answer správanie,
|
||
- rozširuje primárny chunk o začiatok rovnakej sekcie,
|
||
- zachováva väzbu medzi primárnym chunkom a section-lead chunkom.
|
||
|
||
`rebuild_index.py`
|
||
|
||
Orchestruje kompletný rebuild:
|
||
|
||
```text
|
||
scan
|
||
→ chunking
|
||
→ SQLite/FTS
|
||
→ embeddings
|
||
→ validácia
|
||
→ atomická výmena DB
|
||
```
|
||
|
||
### `tools/rag/evaluation/`
|
||
|
||
`evaluate_retrieval.py`
|
||
|
||
CLI vstup pre retrieval benchmark. Umožňuje spúšťať DEV, TEST alebo
|
||
celý dataset a používa strict dataset validáciu.
|
||
|
||
`retrieval_runner.py`
|
||
|
||
Spúšťa jednotlivé retrieval stratégie nad evaluačnými otázkami.
|
||
|
||
`metrics.py`
|
||
|
||
Počíta retrieval metriky, napríklad:
|
||
|
||
```text
|
||
Hit@1
|
||
Hit@3
|
||
Hit@5
|
||
MRR
|
||
Recall@5
|
||
```
|
||
|
||
`evaluate_rag_answers.py`
|
||
|
||
CLI vstup pre answer-level RAG evaluáciu. Hodnotí celý tok:
|
||
|
||
```text
|
||
otázka
|
||
→ OpenWebUI model
|
||
→ ZP Agent tool
|
||
→ /rag
|
||
→ finálna odpoveď
|
||
```
|
||
|
||
Podporuje answer-level overrides, aby nebolo potrebné meniť frozen
|
||
retrieval benchmark pri otázkach, ktoré sú pre generatívnu evaluáciu
|
||
nejednoznačné.
|
||
|
||
`rag_runner.py`
|
||
|
||
Spúšťa jednotlivé answer-level prípady a komunikuje s OpenWebUI/API.
|
||
|
||
`rag_metrics.py`
|
||
|
||
Počíta answer-level metriky, napríklad:
|
||
|
||
- prítomnosť očakávaných faktov,
|
||
- správnosť `source_url`,
|
||
- `should_answer`,
|
||
- použitie toolu,
|
||
- strict pass,
|
||
- latency a tokenové údaje.
|
||
|
||
### `tools/rag/evaluation/json_files/`
|
||
|
||
`questions.json`
|
||
|
||
Hlavný frozen benchmark pre klasický retrieval a RAG. Po zmrazení
|
||
benchmarku sa nemá meniť len preto, aby sa zlepšil výsledok answer-level
|
||
evaluácie.
|
||
|
||
`rag_answer_overrides.json`
|
||
|
||
Obsahuje iba answer-level úpravy formulácie alebo očakávaní pri
|
||
nejednoznačných otázkach. Retrieval benchmark tým ostáva nezmenený.
|
||
|
||
`questions_before_ambiguity_cleanup.json`
|
||
|
||
Historická záloha datasetu pred úpravami nejednoznačností.
|
||
|
||
`questions_before_validation.json`
|
||
|
||
Historická záloha datasetu pred validačnými úpravami.
|
||
|
||
`questions_extended.json`
|
||
|
||
Rozšírený benchmark s presne 2000 otázkami. Je pripravený pre neskoršie
|
||
rozsiahlejšie experimenty nad klasickým retrievalom a RAG.
|
||
|
||
Obsahuje kombináciu:
|
||
|
||
- faktických otázok,
|
||
- parafráz,
|
||
- otázok bez diakritiky,
|
||
- preklepov,
|
||
- krátkych query,
|
||
- no-answer prípadov,
|
||
- negatívnej verifikácie,
|
||
- multi-document otázok,
|
||
- porovnávania,
|
||
- citation-oriented prípadov.
|
||
|
||
Tento dataset je zatiaľ pripravený, ale nemá sa používať na priebežné
|
||
ladenie frozen benchmarku.
|
||
|
||
GraphRAG benchmark je po oddelení nástrojov uložený samostatne v:
|
||
|
||
```text
|
||
tools/graphrag/evaluation/graphrag_questions.json
|
||
```
|
||
|
||
Obsahuje 500 otázok zameraných na grafové a viacvzťahové dopyty.
|
||
|
||
`robustness_questions.json`
|
||
|
||
Samostatný dataset s 200 otázkami pre testovanie robustnosti.
|
||
|
||
Pokrýva napríklad:
|
||
|
||
- chýbajúcu diakritiku,
|
||
- preklepy,
|
||
- nekonzistentnú kapitalizáciu a interpunkciu,
|
||
- nerelevantný šum,
|
||
- prompt injection,
|
||
- konfliktné tvrdenia používateľa,
|
||
- tlak na halucinovanie,
|
||
- no-answer grounding,
|
||
- ambiguity/disambiguation,
|
||
- integritu citácií,
|
||
- kombinovaný vstupný šum.
|
||
|
||
Každá položka obsahuje aj `robustness` metadata s typom útoku,
|
||
perturbáciou, očakávaným správaním a závažnosťou.
|
||
|
||
`performance_queries.json`
|
||
|
||
Samostatný workload s 200 query pre budúce performance a stress
|
||
experimenty.
|
||
|
||
Profily zahŕňajú:
|
||
|
||
- baseline single-document query,
|
||
- krátke query,
|
||
- noisy query,
|
||
- multi-document query,
|
||
- no-answer query,
|
||
- query s väčším retrieval limitom,
|
||
- context-heavy query,
|
||
- opakované hot query.
|
||
|
||
Súbor samotný performance nemeria. Je to vstup pre budúci samostatný
|
||
performance runner, ktorý bude volať `/rag` a merať napríklad:
|
||
|
||
```text
|
||
mean latency
|
||
median
|
||
P50
|
||
P95
|
||
P99
|
||
requests/second
|
||
error rate
|
||
timeout rate
|
||
cold vs warm latency
|
||
```
|
||
|
||
Stress režim bude nad rovnakým workloadom zvyšovať paralelizmus a
|
||
sledovať správanie systému pri rastúcej záťaži.
|
||
|
||
## Konfigurácia
|
||
|
||
V koreňovom priečinku vytvor `.env`:
|
||
|
||
```dotenv
|
||
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
|
||
|
||
# GraphRAG / Neo4j
|
||
NEO4J_URI=bolt://localhost:7687
|
||
NEO4J_USER=neo4j
|
||
NEO4J_PASSWORD=<silné lokálne heslo>
|
||
NEO4J_DATABASE=neo4j
|
||
```
|
||
|
||
Tajomstvá je možné vygenerovať príkazom:
|
||
|
||
```bash
|
||
openssl rand -hex 32
|
||
```
|
||
|
||
Súbor `.env` sa nesmie commitovať.
|
||
|
||
Chunkovanie je možné konfigurovať pomocou premenných prostredia:
|
||
|
||
```dotenv
|
||
CHUNK_MAX_TOKENS=450
|
||
CHUNK_OVERLAP_TOKENS=70
|
||
CHUNK_MIN_TOKENS=80
|
||
CHUNK_TOKEN_ENCODING=cl100k_base
|
||
```
|
||
|
||
## Spustenie cez Docker
|
||
|
||
```bash
|
||
docker compose up -d --build
|
||
```
|
||
|
||
Kontrola služby:
|
||
|
||
```bash
|
||
curl http://127.0.0.1:8000/health
|
||
```
|
||
|
||
OpenAPI schéma:
|
||
|
||
```text
|
||
http://127.0.0.1:8000/openapi.json
|
||
```
|
||
|
||
Logy:
|
||
|
||
```bash
|
||
docker compose logs -f zp-agent-api
|
||
```
|
||
|
||
Zastavenie:
|
||
|
||
```bash
|
||
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ť.
|
||
|
||
Neo4j je spustené ako samostatná služba v rovnakom Docker Compose
|
||
prostredí. Stav služieb je možné skontrolovať:
|
||
|
||
```bash
|
||
docker compose ps
|
||
```
|
||
|
||
Neo4j Browser je lokálne dostupný na:
|
||
|
||
```text
|
||
http://127.0.0.1:7474/browser/
|
||
```
|
||
|
||
Kontrola spojenia z API kontajnera:
|
||
|
||
```bash
|
||
docker compose exec zp-agent-api \
|
||
python -m tools.graphrag.neo4j_smoke
|
||
```
|
||
|
||
## Reindexovanie
|
||
|
||
Spoločná synchronizácia pripraví dokumenty, chunky, SQLite/FTS5, embeddingy
|
||
a Neo4j graf z jedného snapshotu wiki. Nová generácia sa aktivuje až po
|
||
úspešnej príprave oboch indexov:
|
||
|
||
```bash
|
||
docker compose run --rm zp-agent-api python -m tools.rag.rebuild_index
|
||
```
|
||
|
||
Vzniknú súbory:
|
||
|
||
```text
|
||
data/documents.json
|
||
data/chunks.json
|
||
data/zp_index.sqlite
|
||
data/index_version.json
|
||
```
|
||
|
||
Databáza obsahuje dokumenty, chunky, FTS5 index, metadata a embeddingy.
|
||
|
||
Manuálny `/sync`, push webhook a uvedený CLI príkaz používajú rovnakú pipeline.
|
||
SQLite, Neo4j a odpovede nástrojov evidujú spoločnú verziu dát a Git revíziu.
|
||
Pri krátkom prepnutí sa nové vyhľadávanie dočasne odmietne; chyba grafu
|
||
vyvolá rollback. Pri nedokončenom prepnutí po páde zostane vyhľadávanie
|
||
nedostupné do úspešného opakovania synchronizácie. Podrobnosti a zotavenie:
|
||
[Spoločná synchronizácia indexov](docs/synchronizacia_indexov.md).
|
||
|
||
## Publikovanie a dostupnosť nástrojov
|
||
|
||
Oba nástroje predvolene vylučujú iba explicitné `published=false`.
|
||
Chýbajúca hodnota sa považuje za publikovanú. Parameter
|
||
`published_only=false` výslovne zahrnie aj nepublikované dokumenty pri
|
||
autorizovanom volaní; CLI používa `--include-unpublished`.
|
||
|
||
`/health` uvádza samostatne `tools.rag`, `tools.neo4j` a `tools.graphrag`.
|
||
Globálne `ready` vyžaduje oba vyhľadávacie nástroje; pri výpadku Neo4j
|
||
môže klient ďalej používať RAG podľa `tools.rag.ready`.
|
||
[Politika, migrácia a príklady](docs/publikovanie_a_dostupnost.md).
|
||
|
||
## Hybridné vyhľadávanie
|
||
|
||
RAG aj GraphRAG používajú spoločné polia `status`, `reason`, `sources`,
|
||
`index_version`, `complete`, `truncated` a `truncation_reasons`. Pôvodný
|
||
RAG kontext aj grafové fakty a cesty zostávajú dostupné. Úplnosť vyhľadania
|
||
sa odlišuje od pravdivosti odpovede; pri RAG môže byť nezaručená (`null`).
|
||
[Výstupný kontrakt a spracovanie chýb](docs/vystupny_kontrakt.md).
|
||
|
||
Vyhľadávanie kombinuje:
|
||
|
||
```text
|
||
dotaz
|
||
├── FTS5 / BM25
|
||
└── embeddingové vyhľadávanie
|
||
↓
|
||
RRF fusion
|
||
↓
|
||
lexical anchor
|
||
↓
|
||
výsledky
|
||
```
|
||
|
||
FTS5 používa stratégie:
|
||
|
||
```text
|
||
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:
|
||
|
||
```bash
|
||
docker compose run --rm zp-agent-api \
|
||
python -m tools.rag.search_db "rag agent" --limit 5
|
||
```
|
||
|
||
Pred volaním API načítaj premenné z `.env`:
|
||
|
||
```bash
|
||
set -a
|
||
source .env
|
||
set +a
|
||
```
|
||
|
||
Vyhľadávanie cez zabezpečené API:
|
||
|
||
```bash
|
||
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": true,
|
||
"max_per_document": 1
|
||
}'
|
||
```
|
||
|
||
API používa hybridný engine:
|
||
|
||
```text
|
||
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
|
||
`tools/rag/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.
|
||
|
||
Ak sa relevantná informácia nenachádza priamo v primárnom chunke,
|
||
RAG vrstva môže k rovnakému zdroju doplniť začiatok rovnakej sekcie.
|
||
Táto section-lead expanzia umožňuje zachovať retrieval
|
||
`max_per_document=1`, ale zároveň doplniť názov témy, rok alebo inú
|
||
informáciu umiestnenú na začiatku sekcie.
|
||
|
||
Pri nedostatočnej podpore má model odmietnuť informáciu domýšľať.
|
||
|
||
Príklad:
|
||
|
||
```bash
|
||
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": true,
|
||
"max_per_document": 1
|
||
}'
|
||
```
|
||
|
||
## GraphRAG
|
||
|
||
GraphRAG vetva rozširuje existujúci klasický RAG o knowledge graph.
|
||
Graf sa vytvára deterministicky z už pripravených dokumentov a chunkov
|
||
a ukladá sa do Neo4j.
|
||
|
||
Aktuálne používané hlavné typy uzlov:
|
||
|
||
```text
|
||
Person
|
||
Document
|
||
DocumentAuthor
|
||
Thesis
|
||
Work
|
||
Keyword
|
||
Topic
|
||
Category
|
||
```
|
||
|
||
Hlavné vzťahy zahŕňajú napríklad:
|
||
|
||
```text
|
||
Person -[:HAS_DOCUMENT]-> Document
|
||
Person -[:AUTHORED]-> Thesis
|
||
Person -[:HAS_WORK]-> Work
|
||
Thesis/Work -[:EVIDENCED_BY]-> Document
|
||
Document -[:HAS_KEYWORD]-> Keyword
|
||
Document -[:IN_CATEGORY]-> Category
|
||
DocumentAuthor -[:AUTHORED_DOCUMENT]-> Document
|
||
Document -[:DESCRIBES]-> Topic
|
||
```
|
||
|
||
Knowledge graph sa vytvorí príkazom:
|
||
|
||
```bash
|
||
docker compose exec zp-agent-api \
|
||
python -m tools.graphrag.build_graphrag
|
||
```
|
||
|
||
Builder vytvára constraints, zapisuje uzly a vzťahy a pri štandardnom
|
||
spustení obnoví iba časť grafu spravovanú ZP Agentom. Zmazanie aj zápis
|
||
prebiehajú v jednej transakcii s kontrolou počtov, takže chyba zachová
|
||
pôvodný graf. Opakované spustenie nevytvára duplicitné uzly.
|
||
|
||
Graf je možné vizuálne kontrolovať v Neo4j Browseri. Samostatné
|
||
grafové vyhľadávanie je implementované v `tools/graphrag/graph_search.py`.
|
||
GraphRAG zatiaľ nezasahuje do stabilného klasického `/rag` toku; ďalšia
|
||
etapa spojí grafové výsledky s klasickým RAG a OpenWebUI nástrojom.
|
||
|
||
Aktuálna evaluácia GraphRAG **v5.1** má DEV **722/722** a historickú regresiu
|
||
**320/320**, vrátane kontroly všetkých vrátených typovaných faktov oproti raw
|
||
Markdownom. Generovanie sa meria samostatne: 39 DEV a finálna regresia 320
|
||
historických otázok vrátane týchto 39; nejde o nový nezávislý TEST.
|
||
LLM regresia dosiahla **317/320 (99,06 %)** bez neplatných JSON odpovedí.
|
||
Finálne metriky, opravy JSON, historické porovnanie a obmedzenia sú v
|
||
[finálnej správe v5.1](tools/graphrag/evaluation/results/final_v5_1_2026-10-25/REPORT.md).
|
||
|
||
Historická v4 mala grafový strict TEST 320/320, doplnkovú kontrolu kontextových
|
||
faktov 319/320 a LLM TEST 281/300 (93,67 %). Pôvodné otázky aj výsledky
|
||
v1–v4 zostávajú zachované. Aktuálne skóre nie je zárukou všeobecnej pravdivosti.
|
||
[Protokol a reprodukcia](tools/graphrag/evaluation/README.md).
|
||
|
||
## OpenWebUI
|
||
|
||
ZP Agent je pripojený do OpenWebUI ako OpenAPI Tool Server.
|
||
|
||
OpenWebUI používa OpenAPI schému ZP Agent API a Bearer autentifikáciu
|
||
pre vyhľadávací/RAG nástroj.
|
||
|
||
Tok požiadavky:
|
||
|
||
```text
|
||
používateľ
|
||
↓
|
||
OpenWebUI
|
||
↓
|
||
jazykový model
|
||
↓
|
||
ZP Agent /rag
|
||
↓
|
||
hybrid retrieval
|
||
↓
|
||
RAG kontext + zdroje
|
||
↓
|
||
jazykový model
|
||
↓
|
||
odpoveď
|
||
```
|
||
|
||
Výsledná odpoveď má byť grounded v ZP Wiki a má používať relevantný
|
||
`source_url`.
|
||
|
||
## Retrieval evaluácia
|
||
|
||
Frozen retrieval benchmark sa spúšťa napríklad:
|
||
|
||
```bash
|
||
python -m tools.rag.evaluation.evaluate_retrieval \
|
||
--split dev \
|
||
--strict-dataset
|
||
```
|
||
|
||
Podporované režimy:
|
||
|
||
```text
|
||
dev
|
||
test
|
||
all
|
||
```
|
||
|
||
Vyhodnocujú sa samostatne:
|
||
|
||
```text
|
||
FTS
|
||
vector
|
||
hybrid
|
||
```
|
||
|
||
a metriky:
|
||
|
||
```text
|
||
Hit@1
|
||
Hit@3
|
||
Hit@5
|
||
MRR
|
||
Recall@5
|
||
```
|
||
|
||
TEST split sa nemá používať na priebežné ladenie retrieval konfigurácie.
|
||
|
||
## RAG answer evaluácia
|
||
|
||
Answer-level evaluácia používa:
|
||
|
||
```bash
|
||
python -m tools.rag.evaluation.evaluate_rag_answers --split dev
|
||
```
|
||
|
||
Evaluuje kompletný model/tool/RAG tok a od retrieval benchmarku je
|
||
oddelená.
|
||
|
||
Ak je pôvodná otázka vhodná pre retrieval, ale nejednoznačná pre
|
||
generatívnu odpoveď, jej answer-level formulácia sa upraví iba cez:
|
||
|
||
```text
|
||
tools/rag/evaluation/json_files/rag_answer_overrides.json
|
||
```
|
||
|
||
Pôvodný frozen `questions.json` tým ostáva nezmenený.
|
||
|
||
## Manuálna synchronizácia
|
||
|
||
Manuálne reindexovanie cez zabezpečený endpoint:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```text
|
||
POST /webhook/gitea
|
||
```
|
||
|
||
Webhook overuje:
|
||
|
||
- HMAC-SHA256 podpis,
|
||
- typ Gitea udalosti,
|
||
- očakávaný repozitár,
|
||
- maximálnu veľkosť payloadu,
|
||
- stav reindexovacieho zámku.
|
||
|
||
Očakávaný repozitár:
|
||
|
||
```dotenv
|
||
EXPECTED_GITEA_REPOSITORY=KEMT/zpwiki
|
||
```
|
||
|
||
Ak je povolené:
|
||
|
||
```dotenv
|
||
WEBHOOK_PULL_GIT=true
|
||
```
|
||
|
||
pred reindexovaním sa vykoná:
|
||
|
||
```bash
|
||
git pull --ff-only
|
||
```
|
||
|
||
## Bezpečnosť
|
||
|
||
Vyhľadávanie podporuje API key:
|
||
|
||
```text
|
||
X-API-Key: <SEARCH_API_KEY>
|
||
```
|
||
|
||
aj Bearer autentifikáciu:
|
||
|
||
```text
|
||
Authorization: Bearer <SEARCH_API_KEY>
|
||
```
|
||
|
||
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.
|
||
|
||
Bezpečnostná vrstva zároveň kontroluje minimálnu dĺžku tajomstiev,
|
||
odlišnosť jednotlivých secretov a používa bezpečné porovnávanie
|
||
hodnôt.
|
||
|
||
## Testy
|
||
|
||
Inštalácia testovacích závislostí:
|
||
|
||
```bash
|
||
pip install -r requirements-dev.txt
|
||
```
|
||
|
||
Bežné automatizované testy:
|
||
|
||
```bash
|
||
pytest -q
|
||
```
|
||
|
||
Kontrola syntaxe najdôležitejších upravovaných modulov:
|
||
|
||
```bash
|
||
python -m py_compile \
|
||
tools/rag/rag_utils.py \
|
||
tools/rag/evaluation/evaluate_rag_answers.py \
|
||
tools/rag/evaluation/rag_runner.py \
|
||
tools/rag/evaluation/rag_metrics.py
|
||
```
|
||
|
||
Pred checkpointom je vhodné použiť aj:
|
||
|
||
```bash
|
||
git diff --check
|
||
git status
|
||
```
|
||
|
||
Pevný počet `pytest` výsledkov nie je v README uvádzaný, pretože sa
|
||
s vývojom mení. Aktuálny stav sa má vždy potvrdiť novým spustením testov
|
||
na konkrétnom commite.
|
||
|
||
## Experimentálne datasety
|
||
|
||
Pre ďalšie experimenty sú pripravené:
|
||
|
||
```text
|
||
questions_extended.json
|
||
graphrag_questions.json
|
||
robustness_questions.json
|
||
performance_queries.json
|
||
```
|
||
|
||
`graphrag_questions.json` je aktuálne určený pre vývoj GraphRAG vetvy.
|
||
Ostatné datasety zostávajú oddelené od priebežného ladenia frozen
|
||
klasického baseline.
|
||
|
||
## Najbližší postup
|
||
|
||
Klasický RAG a GraphRAG sú oddelené do samostatných komponentov v
|
||
`tools/rag/` a `tools/graphrag/`. Stabilný klasický RAG zostáva
|
||
referenčným bodom.
|
||
|
||
### 1. GraphRAG dátový model
|
||
|
||
Model je implementovaný. Rozlišuje autora dokumentu, študenta, záverečnú
|
||
prácu, projekt, tému a kľúčové slovo. Študijný program sa nedopĺňa bez
|
||
spoľahlivého zdroja.
|
||
|
||
### 2. GraphRAG evaluácia
|
||
|
||
V5.1 má zmrazený graf a úplnú historickú regresiu **320/320**.
|
||
[Finálna správa](tools/graphrag/evaluation/results/final_v5_1_2026-10-25/REPORT.md)
|
||
oddeľuje retrieval a generovanie odpovedí; pôvodné v1–v4 sa nemenia.
|
||
Pred formálnym porovnaním s klasickým RAG potrebujeme spoločnú metodiku
|
||
a ideálne otázky anotované nezávislým človekom. Nový nezávislý TEST vyžaduje
|
||
nové otázky; opakované meranie odhalených otázok je regresia.
|
||
|
||
### 3. OpenWebUI nástroje
|
||
|
||
Pripraviť samostatne inštalovateľný RAG nástroj a GraphRAG nástroj.
|
||
Každý komponent bude mať vlastný adresár, rozhranie a testy.
|
||
|
||
### 4. Hlavný agent
|
||
|
||
Pridať hlavný prompt/agenta, ktorý podľa otázky vyberie vhodný nástroj a
|
||
bude vedieť kombinovať ich výsledky.
|
||
|
||
### 5. Git MCP server
|
||
|
||
Pridať samostatný MCP server pre prácu s Git repozitárom a spúšťať ho v
|
||
Dockeri. Následne ho sprístupniť hlavnému agentovi ako ďalší nástroj.
|
||
|
||
### 6. Spojenie GraphRAG s klasickým RAG
|
||
|
||
Po stabilizovaní grafového vyhľadávania spojiť výsledky grafu s
|
||
existujúcim FTS5 + embedding vyhľadávaním a porovnať klasický RAG s
|
||
GraphRAG variantom.
|
||
|
||
### 7. Finálne experimenty
|
||
|
||
Až po stabilizovaní celého systému vykonať širšie porovnanie embedding
|
||
modelov, robustnosti, výkonu a ostatných finálnych experimentov.
|