dp-zp-agent/README.md

1122 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 v4 s 320 novými TEST otázkami 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).
## Hybridné vyhľadávanie
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": false,
"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": false,
"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 v4: DEV/regresia **722/722**, širší TEST
**320/320**, bez runtime chýb. TEST pokrýva desať kategórií, 288 kladných
a 32 záporných otázok. Nové otázky a kombinácie faktov sú oddelené od DEV;
zdrojových 72 profilov aj rodiny formulácií sú známe. Nejde o záruku
100 % správnosti na ľubovoľných otázkach. Historické v2 **67/80** a v3
**13/13** ostávajú zachované. Pôvodných 137 nesúladov má zdrojové opravy;
v4 dopĺňa kontrolu názvov oproti pôvodnému Markdownu. Generovanie odpovedí
cez OpenWebUI API sa meria zvlášť od grafového retrievalu a od natívneho
výberu nástrojov agentom.
Finálny nový TEST generovaných odpovedí cez OpenWebUI API: **281/300 (93,67 %)**.
Doplnkový audit všetkých grafových kontextových faktov: **319/320 (99,69 %)**;
strict retrieval 320/320 meria splnenie požadovaných očakávaní.
Podrobné výsledky, obmedzenia a reprodukcia sú v
[GraphRAG evaluácii](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
V4 má zmrazený benchmark a širší TEST **320/320**. [Finálna správa](tools/graphrag/evaluation/results/final_v4_2026-10-25/REPORT.md)
oddeľuje výsledky grafového retrievalu a generovania odpovedí modelom.
Historické v1–v3 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.
Vystavené TEST otázky sú pri ďalšom ladení iba regresiou.
### 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.