1705 lines
65 KiB
Markdown
1705 lines
65 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. Táto vetva pripravuje backend pre Claude Skills a autentizovaný MCP konektor.
|
||
|
||
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 v7 s novým TESTom 80 kombinácií a 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. Aktuálna integrácia pre Claude je opísaná nižšie; historické merania zostávajú zachované.
|
||
|
||
## 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ď,
|
||
- autorizovaný `/answer` s kontrolou faktických väzieb, citácií a úplnosti,
|
||
najviac jednou opravou a zostavením finálneho textu z overených údajov;
|
||
klienti Claude používajú túto istú kontrolovanú cestu,
|
||
- 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,
|
||
- konfigurovateľné povolené CORS originy,
|
||
- bezpečnostné HTTP hlavičky,
|
||
- dva Claude Skills a MCP nástroje pre webový Claude, Desktop a Code,
|
||
- 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
|
||
↓
|
||
Claude Skills / MCP konektor
|
||
↓
|
||
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. Obe vyhľadávania sú samostatne dostupné cez API a MCP nástroje pre Claude.
|
||
|
||
Synchronizačná vetva:
|
||
|
||
```text
|
||
Gitea push
|
||
↓
|
||
POST /webhook/gitea
|
||
↓
|
||
HMAC + repository + event validácia
|
||
↓
|
||
durable synchronizačná fronta
|
||
↓
|
||
overenie vetvy + git fetch + merge --ff-only
|
||
↓
|
||
nové JSON, SQLite a grafový payload v stagingu
|
||
↓
|
||
koordinované prepnutie SQLite a Neo4j + spoločná verzia dát
|
||
```
|
||
|
||
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/
|
||
│ ├── answers/
|
||
│ │ ├── answer_delivery.py
|
||
│ │ └── model_client.py
|
||
│ ├── answer_evaluation/
|
||
│ │ ├── checked_generation.py
|
||
│ │ ├── context_policy.py
|
||
│ │ └── evaluate_graph_answers.py
|
||
│ ├── retrieval/
|
||
│ │ ├── publication.py
|
||
│ │ ├── retrieval_contract.py
|
||
│ │ └── text_budget.py
|
||
│ ├── runtime/
|
||
│ │ ├── runtime_assets.py
|
||
│ │ ├── runtime_health.py
|
||
│ │ ├── tool_health.py
|
||
│ │ └── bootstrap_indexes.py
|
||
│ ├── sync/
|
||
│ │ ├── index_state.py
|
||
│ │ ├── sync_indexes.py
|
||
│ │ ├── sync_jobs.py
|
||
│ │ └── wiki_git.py
|
||
│ ├── 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
|
||
│
|
||
├── packages/
|
||
│ └── claude/
|
||
│ ├── client.py
|
||
│ ├── mcp_server.py
|
||
│ ├── rag/SKILL.md
|
||
│ ├── graphrag/SKILL.md
|
||
│ └── dist/
|
||
│
|
||
├── scripts/
|
||
│ ├── start_project.sh
|
||
│ ├── compose.sh
|
||
│ ├── build_claude_packages.py
|
||
│ └── verify_project.py
|
||
│
|
||
├── data/
|
||
│ ├── documents.json
|
||
│ ├── chunks.json
|
||
│ └── zp_index.sqlite
|
||
│
|
||
├── deployment/
|
||
│ ├── Dockerfile
|
||
│ ├── docker-compose.yml
|
||
│ ├── requirements.txt
|
||
│ └── requirements-dev.txt
|
||
└── README.md
|
||
```
|
||
|
||
`answers/` doručuje overené odpovede a oddeľuje poskytovateľa generujúceho modelu.
|
||
`answer_evaluation/` obsahuje kontrolu odpovedí, renderer a evaluačné klienty.
|
||
`retrieval/` zdieľa dátový kontrakt, publikačnú politiku a delenie podľa rozpočtu.
|
||
`runtime/` pripravuje model/tokenizér a kontroluje štart a dostupnosť služieb.
|
||
`sync/` spravuje Git, frontu a spoločné publikovanie SQLite/Neo4j indexov.
|
||
`packages/claude/` obsahuje skills, spoločného HTTP klienta a MCP most.
|
||
Samostatné ZIPy v `packages/claude/dist/` obsahujú klienta a nepotrebujú importovať backend.
|
||
V koreňovom `tools/` zostáva iba `__init__.py`.
|
||
|
||
Na Gite je hlavný README a povinné vstupné súbory `SKILL.md`. Vedľajšie návody,
|
||
pracovné záznamy a textové správy ostávajú lokálne a sú ignorované.
|
||
JSON/CSV výsledky a pôvodné experimentálne manifesty zostávajú zachované.
|
||
Historické zmrazené merania sa reprodukujú v ich pôvodnom Git checkoute;
|
||
presun modulov nemení ich uložené odtlačky ani výsledky.
|
||
|
||
### `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=jp170na/zpwiki
|
||
EXPECTED_GITEA_BRANCH=master
|
||
WEBHOOK_PULL_GIT=true
|
||
ZPWIKI_SSH_KEY=/absolutna/cesta/k/ssh_klucu
|
||
ZPWIKI_KNOWN_HOSTS=/absolutna/cesta/k/known_hosts
|
||
|
||
# Voliteľné
|
||
EMBEDDING_MODEL=intfloat/multilingual-e5-small
|
||
EMBEDDING_BATCH_SIZE=32
|
||
# Generovanie overenej odpovede: zvoľ jedného poskytovateľa a presný model.
|
||
ANSWER_PROVIDER=anthropic
|
||
ANTHROPIC_API_KEY=<kľúč Anthropic API; predplatné chatu tento kľúč nenahrádza>
|
||
ANSWER_MODEL=<presný identifikátor dostupného Claude modelu>
|
||
ANSWER_MAX_TOKENS=4096
|
||
# Pre anthropic je predvolená URL https://api.anthropic.com/v1/messages.
|
||
# Alternatíva: ANSWER_PROVIDER=openai_compatible, ANSWER_API_KEY, ANSWER_LLM_URL.
|
||
|
||
# Webový MCP konektor (samostatný kľúč, nikdy SEARCH_API_KEY):
|
||
ZP_MCP_ACCESS_TOKEN=<ďalšia náhodná hodnota s minimálne 32 znakmi>
|
||
ZP_MCP_PUBLIC_URL=https://mcp.example.com/mcp
|
||
ZP_MCP_AUTH_MODE=oauth
|
||
ZP_MCP_LOGIN_PASSWORD=<samostatný náhodný prihlasovací kód, minimálne 32 znakov>
|
||
|
||
# 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
|
||
|
||
Potrebný je dostupný Docker Engine, natívny Linux Compose v2 a Buildx.
|
||
Vo WSL používaj kontext, ku ktorému sa Linux klient vie pripojiť; Windows
|
||
kontext s `npipe` tu nie je náhradou Linux socketu. Overenie:
|
||
|
||
```bash
|
||
docker --context default info
|
||
docker compose version
|
||
docker buildx version
|
||
```
|
||
|
||
Po vytvorení `.env`, klonu `../zpwiki` a SSH konfigurácie spusti:
|
||
|
||
```bash
|
||
./scripts/start_project.sh
|
||
```
|
||
|
||
Dockerfile, Compose a oba zoznamy závislostí sú v `deployment/`.
|
||
`.env`, `.gitignore` a `.dockerignore` zostávajú v koreni projektu.
|
||
Príkazy Compose spúšťaj cez `./scripts/compose.sh`, napríklad
|
||
`./scripts/compose.sh ps`. Obal nastavuje absolútne cesty, koreň build
|
||
kontextu a pôvodný názov projektu `zp-agent`, takže sa nemenia dátové volume.
|
||
Funguje aj pri spustení cez absolútnu cestu z iného pracovného priečinka.
|
||
|
||
Skript štandardne používa kontext `default`, nemení globálny Docker kontext
|
||
a spravuje iba projekt `zp-agent`. Iný cieľ nastav cez `ZP_DOCKER_CONTEXT`.
|
||
Zostaví image, počká na zdravý Neo4j, overí existujúce indexy a podľa
|
||
potreby ich koordinovane vytvorí. Až potom spustí API a počká na readiness.
|
||
Pri opakovanom spustení ponechá konzistentné a aktuálne indexy.
|
||
|
||
Model aj tokenizér sú súčasťou image v `/opt/zp-assets`. Bežný štart
|
||
nevyžaduje internet ani existujúcu používateľskú Hugging Face/tiktoken cache.
|
||
Prvý build potrebuje balíky a modelové súbory; build overuje aj načítanie
|
||
pripravených assets so zakázanou sieťou. Prázdny HF cache volume neskrýva
|
||
model pribalený v image. Git pripojenie je samostatná sieťová operácia;
|
||
príznaky offline zakazujú sťahovanie modelu, nie synchronizáciu wiki.
|
||
|
||
Voliteľne môžeš pred buildom pripraviť ignorované lokálne podklady a využiť
|
||
už stiahnutý model z hostiteľa:
|
||
|
||
```bash
|
||
.venv/bin/python -m tools.runtime.runtime_assets prepare
|
||
```
|
||
|
||
`runtime_assets/` obsahuje veľké modelové súbory a do Gitu nepatrí; verzovaný
|
||
je iba prázdny adresár pre čistý build. Bez pripravených lokálnych podkladov
|
||
si ich Docker build vytvorí sám. Súbory majú manifest so SHA-256 a model je
|
||
pripnutý na konkrétny commit. Iný model/revízia vyžaduje nový build s
|
||
`EMBEDDING_MODEL`/`EMBEDDING_REVISION` a zodpovedajúce pripravené assets.
|
||
API pri nesúlade neprejde potichu na sťahovanie iného modelu.
|
||
|
||
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
|
||
./scripts/compose.sh logs -f zp-agent-api
|
||
```
|
||
|
||
Zastavenie:
|
||
|
||
```bash
|
||
./scripts/compose.sh down
|
||
```
|
||
|
||
Hugging Face cache volume zostáva persistentné; predvolený embeddingový
|
||
model a tokenizér však štartujú priamo z overených súborov v image.
|
||
|
||
Neo4j je spustené ako samostatná služba v rovnakom Docker Compose
|
||
prostredí. Stav služieb je možné skontrolovať:
|
||
|
||
```bash
|
||
./scripts/compose.sh ps
|
||
```
|
||
|
||
Neo4j Browser je lokálne dostupný na:
|
||
|
||
```text
|
||
http://127.0.0.1:7474/browser/
|
||
```
|
||
|
||
Kontrola spojenia z API kontajnera:
|
||
|
||
```bash
|
||
./scripts/compose.sh 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
|
||
./scripts/compose.sh 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:
|
||
Implementácia je v [tools/sync/sync_indexes.py](tools/sync/sync_indexes.py).
|
||
|
||
## 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`.
|
||
Spoločná politika je v [tools/retrieval/publication.py](tools/retrieval/publication.py).
|
||
|
||
## 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`).
|
||
Typované polia a chyby definuje
|
||
[tools/retrieval/retrieval_contract.py](tools/retrieval/retrieval_contract.py).
|
||
|
||
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
|
||
./scripts/compose.sh 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
|
||
./scripts/compose.sh 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.
|
||
|
||
Zmrazená evaluácia GraphRAG **v7** má DEV **1 046/1 046** a nový TEST
|
||
**80/80** pre grafové vyhľadávanie aj finálne odpovede. Modelový DEV má
|
||
**46/46**; pri novom TESTe prešlo na prvý pokus **77/80 (96,25 %)**,
|
||
po jednej povolenej oprave **80/80 (100 %)**. Prirodzený text sa skladá
|
||
z overených štruktúrovaných tvrdení. Sú to nové kombinácie nad známym
|
||
korpusom a šablónami, nie neznáme osoby ani ľudsky anotovaný benchmark.
|
||
Samostatná historická regresia má **319/320 (99,69 %)**; nepodložená
|
||
odpoveď v zostávajúcom prípade bola odmietnutá pred doručením.
|
||
|
||
Pri zmrazení v7 prešli vtedajšie testy vrátane živých. V7 opravuje ignorovanie rokov
|
||
mimo 20xx, kontrolu rozporných tvrdení o úplnosti, počtov, povinných tvrdení
|
||
a citácií vrátane referenčného Markdownu a HTML. Začiatok štúdia vyžaduje
|
||
explicitný zdroj, neodvodzuje sa z adresára; opravilo sa 10 očakávaní.
|
||
Všetky v1–v6 merania ostávajú zachované.
|
||
[Uložené výsledky v7](tools/graphrag/evaluation/results/final_v7_2026-10-26/summary.json)
|
||
obsahujú metriky; historické manifesty a raw odpovede ostávajú pri meraniach.
|
||
|
||
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.
|
||
V7 benchmark nie je nezávisle anotovaný človekom. Nové ladenie na známych
|
||
otázkach sa označuje ako regresia, nie ako nový nezávislý TEST.
|
||
|
||
Otázky typu „Aké práce má Ján Holp a v ktorých rokoch?“ vracajú jednotlivé
|
||
práce aj projekty s názvom, typom a rokom. Záznamy bez samostatného názvu
|
||
sa zachovajú a odpoveď uvedie, že názov v zdroji chýba. Dva projekty z rovnakého
|
||
roku sa nezlučujú. Kontrola pred doručením vyžaduje pokrytie všetkých dodaných
|
||
záznamov vrátane ich vzájomných väzieb a zdrojov; samotný zoznam rokov nestačí.
|
||
Otázka pýtajúca sa iba na roky naďalej vracia iba roky. Táto neskoršia oprava
|
||
nemení historické výsledky ani manifest v7; ich skóre sa neprenáša na novú verziu.
|
||
|
||
## Claude Skills a webový MCP konektor
|
||
|
||
Táto vetva `claude-tools` zachováva spoločný RAG/GraphRAG backend,
|
||
Docker, synchronizáciu, kontroly aj historické experimenty. Zdrojové Tools,
|
||
Pipe a builder určené výhradne pre OpenWebUI sú odstránené. Zmienky o školskom
|
||
OpenWebUI v starších výsledkoch a evaluačných klientoch sú historická metodika,
|
||
nie požiadavka na inštaláciu do jeho administrácie.
|
||
|
||
Tok pre webový Claude:
|
||
|
||
```text
|
||
Claude + dva Skills
|
||
-> HTTPS /mcp + OAuth s PKCE (lokálna diagnostika môže používať token)
|
||
-> zpwiki_rag / zpwiki_graphrag / zpwiki_health
|
||
-> súkromný backend /answer alebo /health
|
||
-> SQLite / Neo4j -> zvolený generujúci model -> kontroly -> overený text
|
||
```
|
||
|
||
Skill riadi výber nástroja a interpretáciu výstupu. MCP poskytuje vykonateľné
|
||
nástroje a bezpečne drží backendový kľúč na serveri. Do ZIPu nepatria wiki dáta,
|
||
databázy, modelové váhy, `.env` ani API kľúče. Samotné nahratie ZIPu backend
|
||
nespustí ani nesprístupní localhost internetu.
|
||
|
||
### Balíky a ich zostavenie
|
||
|
||
```bash
|
||
.venv/bin/python scripts/build_claude_packages.py
|
||
```
|
||
|
||
Verziované a deterministicky zostavené sú:
|
||
|
||
- `packages/claude/dist/zpwiki-rag.zip`: text, technológie, individuálne fakty,
|
||
- `packages/claude/dist/zpwiki-graphrag.zip`: väzby, spoločné témy, roky a počty,
|
||
- `packages/claude/dist/packages.json`: SHA-256 archívov.
|
||
|
||
Každý ZIP má koreňový priečinok s `SKILL.md`, `scripts/query.py`,
|
||
`scripts/client.py` a manifestom vnútorných súborov. Funguje po samostatnom
|
||
rozbalení, bez importov z tohto repozitára. Pri zmene klienta alebo skillu
|
||
zopakuj builder a commitni aktualizované ZIPy aj manifest.
|
||
|
||
### Webový Claude: postup nasadenia
|
||
|
||
1. Na hostiteľovi priprav Docker a existujúci backend podľa tohto README.
|
||
Over `/health`, dostupnosť oboch indexov a ich spoločnú verziu.
|
||
2. Pre `/answer` nastav poskytovateľa modelu v `.env`. `ANSWER_PROVIDER=anthropic`
|
||
používa `ANTHROPIC_API_KEY` alebo `ANSWER_API_KEY`, explicitný `ANSWER_MODEL`
|
||
a Messages API. Adaptér oddeľuje system prompt a odmieta orezané odpovede.
|
||
`openai_compatible` používa `ANSWER_API_KEY`, `ANSWER_LLM_URL`, `ANSWER_MODEL`.
|
||
Historické `OPENWEBUI_API_KEY` zostáva podporované pre reprodukciu starých
|
||
experimentov. Použitie Claude ako rozhrania samo osebe nemení poskytovateľa.
|
||
3. Vygeneruj oddelený `ZP_MCP_ACCESS_TOKEN` aj `ZP_MCP_LOGIN_PASSWORD` cez
|
||
dva príkazy `openssl rand -hex 32`. Nastav `ZP_MCP_AUTH_MODE=oauth` a
|
||
`ZP_MCP_PUBLIC_URL=https://<tvoja-doména>/mcp`. Prvý token slúži lokálnej
|
||
diagnostike; druhý kód zadáva vlastník projektu na prihlasovacej stránke.
|
||
Kľúče zostávajú v ignorovanom `.env`. Nesmú byť rovnaké ani zhodné s backendovým kľúčom.
|
||
4. Spusti MCP profil. Backend a Neo4j zostávajú rovnaké:
|
||
|
||
```bash
|
||
scripts/compose.sh --profile claude up -d --build
|
||
```
|
||
|
||
5. Priprav DNS a dôveryhodné HTTPS. `deployment/claude.Caddyfile` je príklad
|
||
reverzného proxy na tom istom hostiteľovi: zmeň doménu a proxy smeruj na
|
||
`127.0.0.1:8001`. MCP je na hostiteľovi zámerne dostupné iba cez loopback.
|
||
Proxy musí zachovať cestu `/mcp`, Host a Authorization a dovoliť dlhšie
|
||
požiadavky. Doména musí byť dostupná z infraštruktúry Anthropic, nie iba z VPN.
|
||
6. V Claude otvor **Customize > Connectors > Add custom connector**, zadaj
|
||
meno `ZP Agent` a HTTPS adresu `/mcp`. Vyber **Sign in now** a
|
||
**Streamable HTTP**. Ak sa zobrazuje výber OAuth klienta, použi
|
||
**Register automatically**. OAuth client ID a client secret nechaj prázdne:
|
||
server podporuje Dynamic Client Registration (DCR), nepotrebuje vlastné
|
||
hlavičky ani administrátorskú OAuth aplikáciu. Pri pripojení sa otvorí stránka
|
||
ZP Agenta; vlož hodnotu `ZP_MCP_LOGIN_PASSWORD` zo svojho lokálneho `.env`
|
||
do poľa **Prístupový kód ZP Agenta** a povoľ prístup. Nie je to heslo účtu Claude.
|
||
Kód nepatrí do chatu ani do polí OAuth client secret. Po potvrdení sa prehliadač
|
||
vráti na `https://claude.ai/api/mcp/auth_callback` a Claude dostane obmedzené tokeny.
|
||
7. V **Customize > Skills** nahraj oba ZIPy a zapni ich. Podľa účtu musí byť
|
||
zapnuté aj Code execution and file creation. V organizácii môžu konektory
|
||
vyžadovať zásah vlastníka; nejde o oprávnenia OpenWebUI.
|
||
8. V novom chate zapni konektor, over `zpwiki_health` (indexy, nie kredit generujúceho API), jednu otázku cez každý
|
||
nástroj, neexistujúcu osobu a neexistujúci rok. Skontroluj aj výsledný text
|
||
Claude: zachovanie citácií a upozornenia na neúplnosť. Schválený backendový
|
||
text má Claude prezentovať bezo zmien, ale skill túto vlastnosť UI nevynucuje.
|
||
|
||
Bez reálnej domény, HTTPS a nastavenia konektora v používateľovom účte môžeme
|
||
preukázať lokálnu funkčnosť balíkov, protokolu a backendu; nie hotové webové
|
||
nasadenie. Prvé reálne volania odošlú otázku a výsledok do Claude. Výsledky
|
||
pôvodných modelov nie sú odhadom presnosti novej konfigurácie.
|
||
|
||
Oficiálne návody: [Skills](https://support.claude.com/en/articles/12512180-use-skills-in-claude),
|
||
[vzdialené konektory a Request headers](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp).
|
||
|
||
### OAuth a uchovávanie prihlásení
|
||
|
||
Používa sa OAuth Authorization Code so S256 PKCE, presným Claude callbackom,
|
||
viazaním tokenu na konkrétnu adresu `/mcp`, rozsahom `zpwiki:read` a voliteľným
|
||
`offline_access`. Discovery a registrácia sú verejné; samotné MCP a `/health`
|
||
sú chránené. Prístupový token platí najviac hodinu, refresh grant 30 dní.
|
||
Obnova rotuje tokeny; opätovné použitie starého refresh tokenu odvolá celý grant.
|
||
Kódy sú jednorazové, platné dve minúty. Prihlásenie vyžaduje súhlas a chráni
|
||
ho Secure/HttpOnly/SameSite cookie, CSRF, obmedzenie pokusov a veľkosti požiadaviek.
|
||
|
||
Toto je prihlásenie jedným projektovým kódom pre vlastníka a poverených ľudí,
|
||
nie univerzitné SSO ani správa samostatných používateľských účtov. Vlastník môže
|
||
kód odovzdať profesorovi mimo chatu. Zmena prihlasovacieho kódu, statického tokenu
|
||
alebo verejnej adresy pri obnove kontajnera zneplatní predchádzajúce OAuth prihlásenia.
|
||
|
||
Klienti a granty prežijú reštart kontajnera v pomenovanom Docker volume
|
||
`claude-oauth`, v súbore `/var/lib/zp-oauth/oauth.sqlite` s oprávneniami 0600.
|
||
Prístupové a refresh tokeny aj autorizačné kódy sa ukladajú pod SHA-256 odtlačkami.
|
||
Databáza ani prihlasovacie kódy nepatria do ZIPov alebo na Git. Voliteľný režim
|
||
`ZP_MCP_AUTH_MODE=bearer` zachováva predchádzajúce pripájanie pomocou
|
||
`Authorization: Bearer <ZP_MCP_ACCESS_TOKEN>`, ak účet Claude sprístupňuje beta
|
||
funkciu Request headers. Predvolený Compose profil používa OAuth.
|
||
|
||
Oficiálne požiadavky: [autentizácia konektorov Claude](https://claude.com/docs/connectors/building/authentication).
|
||
|
||
### Lokálny klient a voliteľný Desktop / Claude Code
|
||
|
||
Pre skripty nastav `ZP_AGENT_URL` a `ZP_AGENT_API_KEY`, alebo si skopíruj
|
||
`packages/claude/config.example.json` mimo repozitára, doplň skutočné hodnoty,
|
||
nastav oprávnenia `chmod 600` a do `ZP_AGENT_CONFIG` ulož iba cestu k súboru.
|
||
Konfigurácia nemá byť súčasťou skillu ani správy modelu. HTTP je povolené iba
|
||
pre loopback; `ZP_AGENT_ALLOW_HTTP=1` je výslovná výnimka pre súkromnú Docker sieť.
|
||
|
||
```bash
|
||
python packages/claude/rag/scripts/query.py --health
|
||
python packages/claude/rag/scripts/query.py "Aký je názov diplomovej práce osoby Ján Holp?"
|
||
python packages/claude/graphrag/scripts/query.py "Práce Jána Holpa v roku 1999?" --mode retrieve
|
||
```
|
||
|
||
Predvolené `--mode answer` poskytuje iba prijatú overenú odpoveď a nikdy
|
||
neodhalí `attempts`, odmietnutý text alebo diagnostiku. `--mode retrieve`
|
||
nevolá generujúci model, vráti podklady a explicitne označí potrebu následnej
|
||
kontroly finálneho textu. `--health` kontroluje nástroje bez generovania.
|
||
URL presmerovania sa nesledujú, chyby neobsahujú tajomstvá a odpoveď je limitovaná.
|
||
|
||
Pravidlá odpovedania dostane Claude pri inicializácii konektora a v Skills;
|
||
výsledky nástrojov neobsahujú pole `presentation_instructions`. Pravidlá určujú
|
||
použiť aktuálnu odpoveď bez dodatočných dohadov, zachovať
|
||
upozornenie na neúplnosť, nezamieňať autora dokumentu s autorom práce a pri
|
||
`no_answer` iba oznámiť nedostatok podkladov. Rozdiely oproti starším odpovediam
|
||
sa nevysvetľujú odhadom; verzia dát neoznačuje verziu programu.
|
||
Tieto pokyny ovplyvňujú správanie Claude, jeho finálny text však náš backend
|
||
nemôže programovo vynútiť. Po aktualizácii už nahratých Skills nahraď ich
|
||
novými ZIPmi z `packages/claude/dist/` (verzia 1.5.0) a over správanie v novom chate.
|
||
|
||
### Nahratie Skills do webového Claude
|
||
|
||
1. Zapni Code execution and file creation (v novom rozložení Create and edit files)
|
||
v Settings > Capabilities, ak ešte nie je zapnuté.
|
||
2. Otvor Customize > Skills, potom + > Create skill > Upload a skill.
|
||
3. Nahraj samostatne `packages/claude/dist/zpwiki-rag.zip` a `zpwiki-graphrag.zip`.
|
||
ZIPy už obsahujú správny koreňový priečinok a netreba ich rozbaľovať.
|
||
4. Zapni Skills s názvami `rag` a `graphrag`. Staršie Skills `zpwiki-rag` a
|
||
`zpwiki-graphrag`, ak si ich už nahral, vypni alebo odstráň, aby sa neprekrývali.
|
||
5. V novom chate zapni existujúci konektor ZP AGENT. Napíš `/`, vyber príslušný
|
||
Skill z ponuky a dopíš otázku, napríklad `/rag Aký je názov diplomovej práce
|
||
Jána Holpa?` alebo `/graphrag Aké práce má Ján Holp a v ktorých rokoch?`.
|
||
Ak ponuka Skills v tvojej verzii rozhrania nie je dostupná, výslovne požiadaj
|
||
„Použi skill rag: ...“ alebo „Použi skill graphrag: ...“.
|
||
|
||
Nahratie a zapnutie sa vykonáva v používateľovom účte; zostavenie ZIPov ani
|
||
nasadenie MCP túto časť nevykoná automaticky. Oficiálny postup:
|
||
https://support.claude.com/en/articles/12512180-use-skills-in-claude
|
||
|
||
Lokálny MCP most používa oficiálne SDK:
|
||
|
||
```bash
|
||
.venv/bin/python -m pip install -r deployment/requirements-claude.txt
|
||
ZP_AGENT_CONFIG=/sukromna/cesta/zp-agent.json .venv/bin/python packages/claude/mcp_server.py
|
||
```
|
||
|
||
Pre Desktop uprav absolútne cesty v `packages/claude/claude_desktop_config.example.json`
|
||
a jeho položku `mcpServers.zpwiki` pridaj k existujúcej konfigurácii bez jej prepisovania.
|
||
Pre Claude Code môžeš nainštalovať rozbalené ZIPy do `.claude/skills/` a používať
|
||
ich klienty priamo. Lokálny stdio most sa do webového Claude nepridáva; web používa
|
||
vyššie opísanú HTTPS službu.
|
||
|
||
### Kontroly balíkov
|
||
|
||
```bash
|
||
PYTHONDONTWRITEBYTECODE=1 .venv/bin/python -m pytest -q -p no:cacheprovider test/test_claude_packages.py
|
||
PYTHONDONTWRITEBYTECODE=1 .venv/bin/python scripts/check_claude_oauth.py
|
||
PYTHONDONTWRITEBYTECODE=1 .venv/bin/python scripts/verify_project.py --no-save --git-network
|
||
```
|
||
|
||
Testy pokrývajú samostatné rozbalenie ZIPov, deterministické SHA-256,
|
||
HTTP komunikáciu a autorizáciu backendu, odmietnutý výstup, metadáta úplnosti,
|
||
MCP stdio aj autentizovaný HTTP protokol, zlý token a kontrolu hostiteľa,
|
||
OAuth discovery, prihlásenie, PKCE, CSRF, presmerovania, scope a resource,
|
||
jednorazové kódy, expiráciu, rotáciu, opakovanie a odvolanie tokenov.
|
||
`check_claude_oauth.py` overí skutočnú verejnú adresu z `.env`: discovery, DCR,
|
||
prihlásenie, PKCE, odmietnutie opakovania kódu, MCP, spoločnú verziu indexov,
|
||
obnovu aj odvolanie tokenov. Kódy neukladá do reportu ani nevypisuje; testovací
|
||
grant po skončení odvolá. Finálny redirect na účet Claude nenasleduje a nevolá LLM.
|
||
Voliteľné `--browser firefox` alebo `--browser chromium` odošle prihlasovací formulár
|
||
skutočným prehliadačom s čerstvým profilom (vyžaduje Playwright a jeho browser).
|
||
Tento režim nekonštruuje hlavičku Origin ručne a zachytí aj rozdiel medzi HTTP
|
||
klientom a HTML formulárom. Prehliadač má sieť povolenú iba na MCP server; test zachytí pokus o návrat
|
||
na Claude bez odoslania požiadavky do účtu.
|
||
Prihlasovacia stránka používa `Referrer-Policy: same-origin`: zachová pôvod vlastného
|
||
formulára a neposiela referrer pri návrate na Claude. Ostatné odpovede používajú
|
||
`no-referrer`; kontrola pôvodu aj CSRF zostávajú zapnuté. CSP povoľuje formuláru
|
||
iba vlastný server a presne registrovanú callback adresu Claude, aby prehliadač
|
||
neblokoval legitímne presmerovanie po prihlásení.
|
||
Adaptér Anthropic je testovaný s lokálne nasimulovanými odpoveďami; bez API kľúča
|
||
sa nevykonáva platené volanie Anthropic. Verejné HTTPS a samotný účet Claude
|
||
sa overia až pri skutočnom pripojení.
|
||
|
||
## 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ý.
|
||
|
||
## Tokenové limity, segmenty a embeddingová cache
|
||
|
||
Chunkovanie dodrží `CHUNK_MAX_TOKENS` aj pri dlhom slove, riadku kódu,
|
||
tabuľke alebo nadpise. Posledné delenie zachová Unicode znaky a obsah;
|
||
celá cesta nadpisov zostáva v metadátach.
|
||
|
||
Finálny embeddingový vstup obsahuje názov, autora, tagy, kategórie, obsah
|
||
aj prefix `passage: `. Jeho veľkosť sa meria skutočným tokenizérom modelu
|
||
vrátane špeciálnych tokenov. Nadlimitný vstup sa bez straty obsahu rozdelí
|
||
na segmenty. Pôvodný chunk, FTS a graf ostávajú zachované. Vektorové
|
||
vyhľadávanie vyberá najlepšiu zhodu segmentu a každý chunk vráti iba raz.
|
||
Encoder nadlimitný nesegmentovaný vstup odmietne namiesto tichého orezania.
|
||
|
||
`data/embedding_cache.sqlite` uchováva vektory podľa presného vstupu a
|
||
odtlačku váh, tokenizéra a konfigurácie modelu. Pri zmene relevantných
|
||
metadát alebo modelu sa vektor prepočíta. Kontrolný súčet zachytí poškodený
|
||
záznam cache. Prvé vytvorenie novej cache prepočíta všetko; ďalšia obnova
|
||
nezmenených vstupov použije cache. Výsledok synchronizácie obsahuje
|
||
`embedding_segments`, `embedding_computed` a `embedding_reused`; počet
|
||
`embedding_chunks` stále označuje počet pokrytých pôvodných chunkov.
|
||
Cache je obnoviteľná optimalizácia; jej odstránenie pri zastavenej
|
||
synchronizácii vyvolá nový výpočet, nezmení aktívne indexy.
|
||
|
||
`POST /rag` predvolene vracia dôkazy iba raz v `context` a stručné citačné
|
||
metadáta v `sources`. Diagnostické expanzie a ich texty sa vrátia len pri
|
||
explicitnom `include_diagnostics: true`, oddelene v `diagnostics`.
|
||
RAG evaluačný klient diagnostiku pred odoslaním modelu vždy odstráni.
|
||
|
||
`RAG_LLM_MAX_TOKENS` (predvolene 12000) obmedzuje celý JSON podkladu
|
||
vrátane kontextu, pokynov, zdrojov a verzie dát. Nie je to rozpočet celej
|
||
konverzácie ani výstupu modelu. `RAG_LLM_TOKEN_ENCODING` má predvolene
|
||
`cl100k_base`; ide o explicitný odhad, nie presný tokenizér všetkých
|
||
vzdialených modelov. Výstup `context_budget` uvádza použitý tokenizér,
|
||
limit a skutočný počet podľa tohto odhadu. Pri orezaní nástroj nastaví
|
||
`complete=false`, `truncated=true` a dôvod `llm_context_budget`.
|
||
|
||
## Manuálna synchronizácia a stav úloh
|
||
|
||
`POST /sync` uloží požiadavku do persistentnej fronty a ihneď vráti HTTP 202.
|
||
Indexovanie prebieha na pozadí; prijatie požiadavky ešte neznamená dokončenie.
|
||
|
||
```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": true}'
|
||
```
|
||
|
||
Odpoveď obsahuje `job_id` a `status_url`, napríklad `/sync/jobs/<job_id>`.
|
||
Stav načítaj rovnakým `SYNC_API_KEY`:
|
||
|
||
```bash
|
||
curl http://127.0.0.1:8000/sync/jobs/<job_id> -H "X-API-Key: $SYNC_API_KEY"
|
||
curl http://127.0.0.1:8000/sync/status -H "X-API-Key: $SYNC_API_KEY"
|
||
```
|
||
|
||
Úloha má stav `queued`, `running`, `succeeded` alebo `failed`. Pole `phase`
|
||
rozlišuje čakanie na zámok, Git, budovanie a publikovanie indexov. Úspešná
|
||
úloha obsahuje v `result` počty, trvanie a spoločnú verziu SQLite a Neo4j.
|
||
Prehľad obsahuje aktívne úlohy, posledný úspech a posledné zlyhanie.
|
||
|
||
Fronta `data/sync_jobs.sqlite` prežije reštart. Procesový zámok povoľuje
|
||
iba jedného pracovníka; rozpracovaná úloha sa po páde zopakuje. Push prijatý
|
||
po začiatku obnovy vytvorí následnú úlohu. Ďalšie čakajúce požiadavky sa
|
||
zlúčia, pričom požiadavka na stiahnutie z Gitu sa zachová. Konflikt s CLI
|
||
obnovou spôsobí čakanie, nie stratu požiadavky. Bežná chyba sa skúsi najviac
|
||
trikrát; následne zostane viditeľný stav `failed` a možno poslať nový `/sync`.
|
||
CLI `python -m tools.rag.rebuild_index --pull` zostáva synchronný.
|
||
|
||
## Gitea webhook a prístup ku Gitu
|
||
|
||
Endpoint `POST /webhook/gitea` overuje HMAC-SHA256 nad pôvodným telom,
|
||
veľkosť payloadu, udalosť `push`, repozitár a konkrétnu vetvu z `ref`:
|
||
|
||
```dotenv
|
||
EXPECTED_GITEA_REPOSITORY=jp170na/zpwiki
|
||
EXPECTED_GITEA_BRANCH=master
|
||
WEBHOOK_PULL_GIT=true
|
||
```
|
||
|
||
Push inej vetvy a zmazanie vetvy sa ignorujú bez obnovy. `X-Gitea-Delivery`
|
||
zabraňuje opakovanému zaradeniu rovnakého doručenia. Platný push vráti HTTP
|
||
202 s odkazom na stav úlohy; nečaká na dokončenie indexovania.
|
||
|
||
Git aktualizácia overí zhodu `origin` s očakávaným repozitárom, aktívnu
|
||
vetvu a neprítomnosť lokálnych zmien vrátane nesledovaných súborov. Potom vykoná:
|
||
|
||
```bash
|
||
git fetch --no-tags --no-recurse-submodules origin refs/heads/master:refs/remotes/origin/master
|
||
git merge --ff-only refs/remotes/origin/master
|
||
```
|
||
|
||
Cieľom je aktuálna verzia nakonfigurovanej vetvy; oneskorený webhook
|
||
neprepína wiki naspäť na starší commit. Odlišná história sa automaticky
|
||
neprepisuje. Pri chybe Gitu zostávajú predchádzajúce indexy zachované.
|
||
|
||
Pre tento wiki server treba SSH. V `.env` nastav absolútne hostiteľské cesty
|
||
`ZPWIKI_SSH_KEY` a `ZPWIKI_KNOWN_HOSTS`. Compose pripája iba tieto dva súbory
|
||
na čítanie do `/run/secrets/`; kľúč sa nekopíruje do image ani repozitára.
|
||
Použi kľúč s prístupom k wiki, ideálne deploy kľúč iba na čítanie, a vopred
|
||
over záznam servera v `known_hosts`. SSH používa `BatchMode` a povinné
|
||
striktné overenie servera; pri chybe si interaktívne nepýta heslo.
|
||
|
||
Na Gitea nastav push webhook na verejne dosiahnuteľnú adresu
|
||
`https://<adresa-api>/webhook/gitea` s rovnakým `WEBHOOK_SECRET`. Lokálna
|
||
adresa `127.0.0.1` nie je zo vzdialeného Gitea servera dosiahnuteľná.
|
||
|
||
## 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 deployment/requirements-dev.txt
|
||
```
|
||
|
||
Bežné automatizované testy:
|
||
|
||
```bash
|
||
pytest -q
|
||
```
|
||
|
||
Kompletná lokálna kontrola s bežiacim projektom a `.env`:
|
||
|
||
```bash
|
||
.venv/bin/python scripts/verify_project.py --git-network
|
||
```
|
||
|
||
Skript skompiluje všetky Python súbory v aplikácii, nástrojoch, balíkoch, testoch
|
||
a skriptoch, overí interné importy a syntax shell skriptov, Git,
|
||
Compose, API, spoločnú verziu indexov, integritu SQLite a kompletnú
|
||
regresiu vrátane lokálneho Neo4j. Prepínač `--git-network` navyše iba
|
||
načíta hlavičku nastavenej wiki vetvy cez existujúce SSH pripojenie.
|
||
Počas pytestu sú externé spojenia zablokované a kľúč generujúceho modelu
|
||
odstránený. HTTP transport testy povoľujú iba svoj dočasný loopback port.
|
||
Výsledky ostávajú lokálne v `data/reports/verification/` a pytest logy
|
||
v `data/logs/verification/`. Každé spustenie má vlastný časový identifikátor;
|
||
existujúci report sa neprepisuje. Skript počká najviac 90 sekúnd na
|
||
pripravenosť API po štarte Dockera (`--wait-ready-seconds`).
|
||
|
||
### Reporty, logy a uchovávanie
|
||
|
||
Prevádzkové indexy `documents.json`, `chunks.json`, `index_version.json`,
|
||
SQLite databázy a zámky ostávajú priamo v `data/`. Reporty sa zapisujú
|
||
do `data/reports/<oblasť>/`, logy do `data/logs/`. Výstupy inštalovateľných
|
||
Claude skills sú verziované v `packages/claude/dist/`; dočasné testovacie balíky sa vytvárajú mimo projektu.
|
||
|
||
Päť najnovších dokončených kontrol projektu zostáva v aktívnom priečinku;
|
||
staršie kontroly aj ich logy sa presunú do `archive/verification/`.
|
||
Neúspešná dokončená kontrola sa tiež uchová. Rozpracované reporty sa
|
||
automaticky nearchivujú. Staršie pôvodné výstupy sú v `archive/legacy/`.
|
||
Súbory sa nemažú a ich obsah sa nemení; `data/reports/migrations/`
|
||
obsahuje záznam pôvodnej a novej cesty spolu s SHA-256. Replay klienti
|
||
vedia cez tento záznam načítať aj presunutý vstup.
|
||
|
||
```bash
|
||
.venv/bin/python scripts/manage_reports.py # náhľad presunov
|
||
.venv/bin/python scripts/manage_reports.py --apply # presun, bez mazania
|
||
```
|
||
|
||
Formálne evaluačné výsledky v `tools/*/evaluation/results/`, baseline,
|
||
GraphRAG verzie a podklady pre diplomovku sa týmto uchovávaním nemenia.
|
||
RAG merania, audity a modelové odpovede v `reports/` sa automaticky
|
||
nemažú ani nerotujú; uchovávajú sa kvôli reprodukcii. Celé `data/` zostáva
|
||
ignorované Gitom. Parametre `--output` kontrolných skriptov sú voliteľné;
|
||
staré ploché cesty `data/nazov.json` sa presmerujú do príslušnej oblasti.
|
||
|
||
### Širšie overenie kontrolovaného RAG
|
||
|
||
`complete`, `truncated` a `truncation_reasons` zostávajú technickým opisom
|
||
vyhľadávania. Overená odpoveď navyše obsahuje `answer_coverage` so scope, status,
|
||
warnings a limitations. Status `supported` znamená doložené tvrdenia/výňatky,
|
||
nie úplné prehľadanie korpusu. Bežný výber kandidátov a zdrojov preto nepridáva
|
||
automatické upozornenie k názvu, roku alebo krátkemu opisu. Obmedzený zoznam
|
||
záznamov a orezané citované zadanie dostanú konkrétne upozornenie. Pri nenájdenej
|
||
informácii sa zachová opatrné tvrdenie o dostupných podkladoch. Žiadny limit sa
|
||
kvôli tomu nezvyšuje ani sa neprepisuje na `complete=true`.
|
||
|
||
Stručný opis zachová všetky dostupné hlavné body zadania; pevný limit dvoch bodov
|
||
sa na ne nevzťahuje. Zásobník úloh a história stretnutí nenahrádzajú hlavné zadanie.
|
||
Bez explicitného zadania sa použije obmedzený výber opisných podkladov. Model
|
||
vyberá `evidence_ids` z dodaných kandidátov a aplikácia dosadí ich presné texty
|
||
a zdroje. Neznámy identifikátor, chýbajúci hlavný bod alebo nesprávne citácie
|
||
neprejdú kontrolou. Všetky podklady podliehajú spoločnému tokenovému rozpočtu;
|
||
jeho skutočné obmedzenie dostane konkrétne upozornenie aj pri stručnom opise.
|
||
Rok v obsahovej otázke môže byť iba filtrom; výpis roku sa vyžaduje osobitne.
|
||
Grafový nástroj pri otázkach na textové zadanie, problémy alebo experimenty
|
||
odporučí `/rag`, pretože samotné uzly a vzťahy tieto textové dôkazy neobsahujú.
|
||
|
||
Finálne formulovanie je oddelené v `tools/answer_evaluation/presentation.py`.
|
||
Overené názvy a roky sa zobrazujú vo vetách, práce v číslovanom zozname.
|
||
Rok práce sa nevydáva za dátum jej začatia alebo dokončenia. Pri opise sa
|
||
známe rozkazovacie formulácie zadania menia na pomenovania cieľov, napríklad
|
||
„Vypracujte prehľad“ na „Vypracovanie prehľadu“. Ide o obmedzené gramatické
|
||
pravidlá po kontrole doslovného dôkazu, nie o voľné dopĺňanie faktov modelom.
|
||
Neznámy opis, podmienky, negácie a údaje o dosiahnutom stave zostávajú zachované.
|
||
|
||
Známe gramatické úpravy sa uplatňujú iba na text mimo URL, kódu a HTML značiek.
|
||
Citované výňatky v dôkazoch sa nemenia. Konektor posiela aktuálnu otázku bez
|
||
parafrázy; môže odstrániť iba úvodný príkaz `/rag` alebo `/graphrag`. Odpoveď
|
||
z `/answer` nesie aj `query` a `engine`; klient odmietne nezhodu s požiadavkou.
|
||
Skills a inicializačné pokyny MCP vyžadujú porovnať otázku aj s aktuálnou správou
|
||
používateľa. Výber otázky samotným Claude zostáva potrebné overiť v jeho rozhraní.
|
||
Pri názve a roku práce model dostáva typované fakty a stručné zdroje. RAG tvrdenia
|
||
nepoužívajú grafové `record_id` ani `work_label`; každé tvrdenie musí mať doloženú
|
||
wiki URL. Označenie zdroja ako `S1` nenahrádza citáciu.
|
||
|
||
Obsahové otázky podporujú presný nadpis práce v úvodzovkách, číslo projektu,
|
||
nečíslovaný projekt, vylúčenie konkrétneho čísla aj otázku na oba projekty.
|
||
Každá práca si zachová vlastné dôkazy a pokrytie požadovaných aspektov.
|
||
Odpoveď „obe“ vyžaduje doplnenie pôvodnej otázky z predchádzajúceho spresnenia
|
||
v Claude; stateless backend si konverzáciu nedomýšľa. Nadpisy úloh na ďalšie
|
||
stretnutie označujú plán. Otázka na skutočne používané metódy vyberá záznamy
|
||
o používaní alebo implementácii, nie samotné pokyny na štúdium či návrh.
|
||
|
||
Pri obsahovom porovnaní viacerých študentov sa pre každého načíta požadovaný typ
|
||
práce z rovnakého SQLite snapshotu; všetky podklady naďalej podliehajú spoločnému
|
||
tokenovému rozpočtu. Zadanie a zaznamenaný stav sa kontrolujú a zobrazujú oddelene.
|
||
Chýbajúce výsledky sa oznámia, neodvodzujú sa z cieľov. Grafová otázka na roky,
|
||
v ktorých majú práce „obaja“, používa prienik rokov a prikladá doložené typy a názvy
|
||
prác z týchto rokov; nezobrazuje namiesto odpovede všetky individuálne roky.
|
||
|
||
`rag_preparation.py` vie pomenované profily dohľadať v SQLite aj mimo prvých
|
||
výsledkov a pri viacerých možných prácach vyžiada typ alebo rok. Obsahové
|
||
porovnanie je obmedzené na štyri osoby naraz. `question_intent.py` rozlišuje
|
||
požadované problémy, metódy, experimenty, ciele a výsledky. `content_selection.py`
|
||
vyberá doslovné, typovo a osobne viazané podklady, odstraňuje opakovania a
|
||
uprednostňuje vecné výsledky pred administratívnymi poznámkami. Model dostane
|
||
len tieto kandidátske výňatky; ich skutočný JSON podlieha tokenovému rozpočtu.
|
||
Chýbajúce časti sa označia jednotlivo, aj keď sú ostatné časti zodpovedateľné.
|
||
Pri limite kontextu sa nestratí informácia, ktoré osoby používateľ požadoval.
|
||
|
||
Výňatky nesú interný `passage_id`, osobu, pôvodné označenie práce a rok. Kontrola
|
||
odmietne zamenený identifikátor a pri rovnakom texte pod rôznymi prácami vyžaduje
|
||
jednoznačné priradenie. Číslo projektu odlišuje aj dva projekty rovnakého typu
|
||
a roku. Zadanie, plánované úlohy, priebežný stav a zaznamenané výsledky sa
|
||
zobrazujú oddelene; negatívny výsledok zostáva výsledkom. Administratívna poznámka
|
||
nenahrádza technický výsledok. Porovnávané osoby si delia kontextový rozpočet,
|
||
aby dlhý prvý profil nevytlačil ostatné. Skrátenie rešpektuje celé odseky a položky
|
||
zoznamu vrátane ich výhrad; pri stručnom opise má zachovanie podmienky prednosť
|
||
pred orientačným limitom dĺžky.
|
||
|
||
Krátke porovnanie zobrazuje rovnaké oblasti vedľa seba v tabuľke; dlhé výňatky,
|
||
kód a odkazy zostávajú v samostatných sekciách bez úpravy ich obsahu. Prázdne
|
||
pomocné sekcie sa nevypisujú a chýbajúce oblasti sa konkrétne pomenujú pri danej
|
||
osobe. Spoločné vlastnosti sa uvádzajú najprv súhrnne a potom s doloženými
|
||
osobami a zdrojmi. Stručnejšie formulácie nemenia rok práce na dátum jej
|
||
začatia alebo dokončenia a ciele neprezentujú ako dosiahnuté výsledky.
|
||
|
||
Rozpoznané, ale nepodporované operátory (napríklad interval rokov, vylučovanie
|
||
alebo minimálny počet) vedú k `ambiguous` a konkrétnemu spresneniu. Rok práce
|
||
sa nepoužije ako dôkaz dátumu jej začatia či obhajoby. Chybové odpovede odlišujú
|
||
nedostupné vyhľadávanie, nedostupný model, vyťaženie a zamietnutý neoverený text;
|
||
raw výstupy odmietnutého modelu sa štandardnému klientovi neposkytujú.
|
||
|
||
Grafový filter tagu sa uplatňuje aj pri otázkach na neurčených študentov a
|
||
konkrétny typ/rok práce: všetky podmienky musí spĺňať tá istá osoba. Spojenie
|
||
„tag RAG a zároveň diplomový projekt“ nepatrí do názvu tagu. Úvodzovky umožňujú
|
||
zachovať viacslovný tag aj so spojkou „a“. Pri názve práce konkrétnej osoby sa
|
||
zachovajú aj záznamy bez názvu; odpoveď uvedie známy typ a rok a chýbajúci názov.
|
||
Spoločné tagy sa zobrazujú súhrnne, s dôkazmi pre každú požadovanú osobu.
|
||
Rozpoznané podmienky na počet vrátane slovných čísloviek („aspoň tri“) vyžadujú
|
||
spresnenie; prahové filtrovanie zatiaľ nie je implementované. Predikcia dokončenia
|
||
práce sa výslovne odlišuje od vyhľadania práce evidovanej v určitom roku.
|
||
|
||
Otázky na obsah, zadanie, ciele alebo metódy práce používajú textové výňatky
|
||
z príslušnej akademickej sekcie, nie iba metadáta o názve a roku. Výňatok musí
|
||
patriť požadovanej osobe, typu práce a prípadne roku. Názov, rok ani samotný
|
||
nadpis zadania nenahrádzajú opis. Kombinovaná otázka na názov/rok aj obsah
|
||
vyžaduje overené štruktúrované údaje aj priradené doslovné výňatky. Ak opis
|
||
v skutočne dodaných podkladoch chýba, odpoveď ho nesmie domýšľať.
|
||
|
||
`tools/rag/evaluation/json_files/verified_rag_regression.json` obsahuje
|
||
vopred vybraných 80 známych otázok z deviatich kategórií, vrátane 10
|
||
neodpovedateľných otázok a 52 otázok s typovanými očakávaniami.
|
||
Je to regresná vzorka; jej úspešnosť nie je nový nezávislý odhad presnosti.
|
||
Očakávania overuje oddelený oracle priamo z pôvodných Markdownov.
|
||
Zdrojové cesty, odtlačky a pôvod akademického roku sú uložené pri otázkach.
|
||
Ľudská anotácia sa tým nenahrádza. Dve otázky na Dária Lindvaia používajú
|
||
rok z kategórie `dp2021`; kontrolovaná cesta taký rok nepovažuje za
|
||
explicitný dôkaz roku práce. Táto neistota je uvedená v datasete.
|
||
|
||
```bash
|
||
# Len lokálne vyhľadávanie a kontrola podkladov, bez generujúceho modelu:
|
||
.venv/bin/python -m tools.answer_evaluation.evaluate_verified_rag --mode retrieve
|
||
|
||
# Úmyselné chybné odpovede na uložených skutočných kontextoch, bez LLM:
|
||
.venv/bin/python -m tools.answer_evaluation.check_verified_rag_guards --input <report.json>
|
||
|
||
# Skutočné generovanie cez /answer: vyžaduje nakonfigurovaný model a povolené
|
||
# odoslanie otázok aj wiki podkladov tomuto poskytovateľovi:
|
||
.venv/bin/python -m tools.answer_evaluation.evaluate_verified_rag --mode deliver
|
||
|
||
# Opätovné vyhodnotenie uložených odpovedí bez nového generovania:
|
||
.venv/bin/python -m tools.answer_evaluation.evaluate_verified_rag --mode replay --input <report.json>
|
||
```
|
||
|
||
Aj evaluačný runner podporuje `--no-save`; v tomto režime otázky a odpovede
|
||
spracuje v pamäti a vypíše skóre bez zápisu reportu či deklarácie.
|
||
Kontrolovaná cesta používa pri všeobecných otázkach iba doslovné výňatky
|
||
bez nežiadaných akademických tvrdení. Referenčný odkaz v citovanom texte
|
||
sa prijme iba vtedy, keď je doložený tým istým dodaným zdrojom; položky
|
||
`source_urls` naďalej označujú pôvodné wiki zdroje.
|
||
|
||
Runner posiela na backend iba otázku a parametre; očakávané odpovede model
|
||
nedostane. Vyhodnocuje finálny stav, prijatie odpovede, citácie, úplné
|
||
väzby osoba–práca–typ–rok a pokrytie očakávaných údajov vo výňatkoch.
|
||
Nesprávne „nenájdené“, blokované odpovede a technické zlyhania sú vedené
|
||
samostatne a zostávajú v menovateli. Doslovná citácia sama osebe nedokazuje
|
||
relevantnosť. Automatická kontrola pokrytia známych údajov nenahrádza
|
||
ľudské posúdenie významu všeobecných odpovedí.
|
||
|
||
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
|
||
|
||
V7 má zmrazený graf, DEV **1 046/1 046** a nový TEST **80/80**.
|
||
[Finálne metriky](tools/graphrag/evaluation/results/final_v7_2026-10-26/summary.json)
|
||
oddeľuje nový TEST od historickej regresie a vyhľadávanie od modelu
|
||
s kontrolami a rendererom; pôvodné v1–v6 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. Claude Skills a nástroje
|
||
|
||
Skills a lokálne overiteľný autentizovaný MCP most sú v `packages/claude/`.
|
||
Pre web zostáva pripraviť verejnú HTTPS adresu, token v nastaveniach konektora,
|
||
nahrať ZIPy a overiť reálne správanie Claude podľa návodu vyššie.
|
||
|
||
### 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.
|