Usporiadanie projektu
This commit is contained in:
parent
83be5912ed
commit
31ecefed40
@ -9,3 +9,6 @@ __pycache__/
|
||||
.coverage
|
||||
htmlcov/
|
||||
data/
|
||||
docs/
|
||||
integrations/
|
||||
**/*.md
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,6 +1,10 @@
|
||||
.env
|
||||
data/
|
||||
docs/
|
||||
integrations/
|
||||
# Documentation stays local; only the main project README is versioned.
|
||||
*.md
|
||||
!/README.md
|
||||
runtime_assets/*
|
||||
!runtime_assets/.gitkeep
|
||||
.venv/
|
||||
|
||||
@ -33,7 +33,7 @@ ARG EMBEDDING_REVISION=""
|
||||
ARG CHUNK_TOKEN_ENCODING=cl100k_base
|
||||
ARG RAG_LLM_TOKEN_ENCODING=cl100k_base
|
||||
|
||||
RUN python -m tools.runtime_assets prepare --output /opt/zp-assets \
|
||||
RUN python -m tools.runtime.runtime_assets prepare --output /opt/zp-assets \
|
||||
--model "$EMBEDDING_MODEL" --revision "$EMBEDDING_REVISION" \
|
||||
--encoding "$CHUNK_TOKEN_ENCODING" --encoding "$RAG_LLM_TOKEN_ENCODING"
|
||||
|
||||
|
||||
118
README.md
118
README.md
@ -45,7 +45,7 @@ nástroja a hlavného agenta do OpenWebUI.
|
||||
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;
|
||||
[OpenWebUI Pipe a inštalácia](integrations/openwebui/README.md),
|
||||
[OpenWebUI Pipe](tools/answers/openwebui_pipe.py), postup je nižšie v časti OpenWebUI,
|
||||
- rozšírenie RAG kontextu o začiatok rovnakej sekcie
|
||||
(`section-lead expansion`) bez globálneho zvýšenia
|
||||
`max_per_document`,
|
||||
@ -170,13 +170,13 @@ POST /webhook/gitea
|
||||
↓
|
||||
HMAC + repository + event validácia
|
||||
↓
|
||||
voliteľný git pull --ff-only
|
||||
durable synchronizačná fronta
|
||||
↓
|
||||
rebuild_index.py
|
||||
overenie vetvy + git fetch + merge --ff-only
|
||||
↓
|
||||
nový SQLite index
|
||||
nové JSON, SQLite a grafový payload v stagingu
|
||||
↓
|
||||
atomická výmena databázy
|
||||
koordinované prepnutie SQLite a Neo4j + spoločná verzia dát
|
||||
```
|
||||
|
||||
Evaluačná vetva:
|
||||
@ -210,6 +210,27 @@ zp-agent/
|
||||
│ └── security.py
|
||||
│
|
||||
├── tools/
|
||||
│ ├── answers/
|
||||
│ │ ├── answer_delivery.py
|
||||
│ │ └── openwebui_pipe.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
|
||||
@ -251,6 +272,10 @@ zp-agent/
|
||||
│ ├── test_configuration.py
|
||||
│ └── test_security.py
|
||||
│
|
||||
├── scripts/
|
||||
│ ├── start_project.sh
|
||||
│ └── verify_project.py
|
||||
│
|
||||
├── data/
|
||||
│ ├── documents.json
|
||||
│ ├── chunks.json
|
||||
@ -263,6 +288,19 @@ zp-agent/
|
||||
└── README.md
|
||||
```
|
||||
|
||||
`answers/` doručuje overené odpovede a obsahuje inštalovateľný OpenWebUI Pipe.
|
||||
`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.
|
||||
V koreňovom `tools/` zostáva iba `__init__.py`.
|
||||
|
||||
Na Gite je z dokumentácie iba tento hlavný README. 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`
|
||||
@ -595,6 +633,9 @@ ZPWIKI_KNOWN_HOSTS=/absolutna/cesta/k/known_hosts
|
||||
# Voliteľné
|
||||
EMBEDDING_MODEL=intfloat/multilingual-e5-small
|
||||
EMBEDDING_BATCH_SIZE=32
|
||||
OPENWEBUI_API_KEY=<kľúč pre generujúci školský model>
|
||||
ANSWER_MODEL=model120-fast
|
||||
ANSWER_LLM_URL=https://ui.tukekemt.xyz/api/chat/completions
|
||||
|
||||
# GraphRAG / Neo4j
|
||||
NEO4J_URI=bolt://localhost:7687
|
||||
@ -655,7 +696,7 @@ Voliteľne môžeš pred buildom pripraviť ignorované lokálne podklady a vyu
|
||||
už stiahnutý model z hostiteľa:
|
||||
|
||||
```bash
|
||||
.venv/bin/python -m tools.runtime_assets prepare
|
||||
.venv/bin/python -m tools.runtime.runtime_assets prepare
|
||||
```
|
||||
|
||||
`runtime_assets/` obsahuje veľké modelové súbory a do Gitu nepatrí; verzovaný
|
||||
@ -738,7 +779,7 @@ SQLite, Neo4j a odpovede nástrojov evidujú spoločnú verziu dát a Git revíz
|
||||
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).
|
||||
Implementácia je v [tools/sync/sync_indexes.py](tools/sync/sync_indexes.py).
|
||||
|
||||
## Publikovanie a dostupnosť nástrojov
|
||||
|
||||
@ -750,7 +791,7 @@ autorizovanom volaní; CLI používa `--include-unpublished`.
|
||||
`/health` uvádza samostatne `tools.rag`, `tools.neo4j` a `tools.graphrag`.
|
||||
Globálne `ready` vyžaduje oba vyhľadávacie nástroje; pri výpadku Neo4j
|
||||
môže klient ďalej používať RAG podľa `tools.rag.ready`.
|
||||
[Politika, migrácia a príklady](docs/publikovanie_a_dostupnost.md).
|
||||
Spoločná politika je v [tools/retrieval/publication.py](tools/retrieval/publication.py).
|
||||
|
||||
## Hybridné vyhľadávanie
|
||||
|
||||
@ -758,7 +799,8 @@ RAG aj GraphRAG používajú spoločné polia `status`, `reason`, `sources`,
|
||||
`index_version`, `complete`, `truncated` a `truncation_reasons`. Pôvodný
|
||||
RAG kontext aj grafové fakty a cesty zostávajú dostupné. Úplnosť vyhľadania
|
||||
sa odlišuje od pravdivosti odpovede; pri RAG môže byť nezaručená (`null`).
|
||||
[Výstupný kontrakt a spracovanie chýb](docs/vystupny_kontrakt.md).
|
||||
Typované polia a chyby definuje
|
||||
[tools/retrieval/retrieval_contract.py](tools/retrieval/retrieval_contract.py).
|
||||
|
||||
Vyhľadávanie kombinuje:
|
||||
|
||||
@ -924,22 +966,51 @@ 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.
|
||||
|
||||
Všetkých **591 testov** vrátane živých prešlo. V7 opravuje ignorovanie rokov
|
||||
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é.
|
||||
[Finálna správa v7](tools/graphrag/evaluation/results/final_v7_2026-10-26/REPORT.md)
|
||||
uvádza presný protokol, opravy, regresiu aj obmedzenia.
|
||||
[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.
|
||||
[Protokol a reprodukcia](tools/graphrag/evaluation/README.md).
|
||||
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.
|
||||
|
||||
## OpenWebUI
|
||||
|
||||
ZP Agent je pripojený do OpenWebUI ako OpenAPI Tool Server.
|
||||
Pripravená kontrolovaná cesta používa samostatný Pipe v
|
||||
[tools/answers/openwebui_pipe.py](tools/answers/openwebui_pipe.py).
|
||||
Administrátor v **Admin Panel → Functions → Create** vloží celý súbor,
|
||||
uloží ho napríklad ako `zp_verified` a aktivuje. Vo **Valves** nastaví:
|
||||
|
||||
| Pole | Hodnota |
|
||||
|---|---|
|
||||
| `BACKEND_URL` | Adresa API dostupná zo servera OpenWebUI, bez `/answer` |
|
||||
| `BACKEND_API_KEY` | Hodnota `SEARCH_API_KEY` backendu |
|
||||
| `DEFAULT_ENGINE` | `rag` |
|
||||
| `TIMEOUT_SECONDS` | `300` |
|
||||
|
||||
Backend používa `OPENWEBUI_API_KEY` pre generujúci model.
|
||||
`ANSWER_LLM_URL` je predvolene `https://ui.tukekemt.xyz/api/chat/completions`
|
||||
a `ANSWER_MODEL` je `model120-fast`. Základný model nesmie odkazovať na
|
||||
tento Pipe, aby nevznikla slučka. Kľúče patria do `.env` alebo Valves.
|
||||
Po aktivácii sú vo výbere dva modely: overený RAG a overený GraphRAG.
|
||||
Pipe odovzdáva poslednú otázku; kontextové odkazy na predchádzajúce správy
|
||||
zatiaľ samostatne nerozvíja.
|
||||
|
||||
Tok: **Pipe → autorizovaný `/answer` → retrieval → generovanie → kontroly
|
||||
→ renderer → priamy text v UI**. Vyžaduje `accepted_for_delivery=true`;
|
||||
odmietnutý text ani opravné pokusy sa nezobrazia. Iný model finálny text
|
||||
neprepisuje. Inštalácia na školskom serveri čaká na administrátora a
|
||||
sieťové sprístupnenie API. `localhost` vo funkcii znamená server OpenWebUI,
|
||||
nie vývojový počítač. V spoločnej Compose sieti môže byť URL
|
||||
`http://zp-agent-api:8000`.
|
||||
|
||||
Pôvodný OpenAPI Tool Server poskytuje podklady cez `/rag`.
|
||||
|
||||
OpenWebUI používa OpenAPI schému ZP Agent API a Bearer autentifikáciu
|
||||
pre vyhľadávací/RAG nástroj.
|
||||
@ -965,7 +1036,8 @@ odpoveď
|
||||
```
|
||||
|
||||
Výsledná odpoveď má byť grounded v ZP Wiki a má používať relevantný
|
||||
`source_url`.
|
||||
`source_url`. Táto pôvodná cesta s voľným následným generovaním sama
|
||||
nezaručuje kontroly doručenia pripraveného Pipe.
|
||||
|
||||
## Retrieval evaluácia
|
||||
|
||||
@ -1170,6 +1242,20 @@ Bežné automatizované testy:
|
||||
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, 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ý. Výsledky a log ostávajú lokálne v `data/`.
|
||||
|
||||
Kontrola syntaxe najdôležitejších upravovaných modulov:
|
||||
|
||||
```bash
|
||||
@ -1221,7 +1307,7 @@ spoľahlivého zdroja.
|
||||
### 2. GraphRAG evaluácia
|
||||
|
||||
V7 má zmrazený graf, DEV **1 046/1 046** a nový TEST **80/80**.
|
||||
[Finálna správa](tools/graphrag/evaluation/results/final_v7_2026-10-26/REPORT.md)
|
||||
[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
|
||||
|
||||
@ -34,9 +34,9 @@ from app.security import (
|
||||
validate_security_configuration,
|
||||
)
|
||||
from tools.rag.embedding_utils import embed_query
|
||||
from tools.retrieval_contract import error_result
|
||||
from tools.retrieval.retrieval_contract import error_result
|
||||
from tools.rag.common import DATA_DIR
|
||||
from tools.sync_jobs import SyncJobs
|
||||
from tools.sync.sync_jobs import SyncJobs
|
||||
from tools.rag.rebuild_index import rebuild_index
|
||||
|
||||
|
||||
|
||||
@ -43,11 +43,11 @@ from tools.rag.common import (
|
||||
from tools.rag.rag_utils import build_rag_context
|
||||
from tools.rag.llm_context import compact_rag_payload
|
||||
from tools.rag.search_utils import search_database
|
||||
from tools.wiki_git import expected_branch
|
||||
from tools.publication import DEFAULT_PUBLISHED_ONLY
|
||||
from tools.tool_health import tools_readiness
|
||||
from tools.retrieval_contract import RetrievalResponse, RetrievalSource, RetrievalErrorResponse
|
||||
from tools.answer_delivery import deliver_answer
|
||||
from tools.sync.wiki_git import expected_branch
|
||||
from tools.retrieval.publication import DEFAULT_PUBLISHED_ONLY
|
||||
from tools.runtime.tool_health import tools_readiness
|
||||
from tools.retrieval.retrieval_contract import RetrievalResponse, RetrievalSource, RetrievalErrorResponse
|
||||
from tools.answers.answer_delivery import deliver_answer
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
import hashlib
|
||||
import hmac
|
||||
import os
|
||||
from tools.wiki_git import expected_branch
|
||||
from tools.sync.wiki_git import expected_branch
|
||||
from typing import Any
|
||||
|
||||
from fastapi import (
|
||||
|
||||
@ -59,7 +59,7 @@ services:
|
||||
neo4j:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "python", "-m", "tools.runtime_health"]
|
||||
test: ["CMD", "python", "-m", "tools.runtime.runtime_health"]
|
||||
interval: 15s
|
||||
timeout: 10s
|
||||
retries: 12
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
# Overené odpovede v OpenWebUI
|
||||
|
||||
`verified_agent.py` je samostatná funkcia typu **Pipe**, ktorá sprístupní
|
||||
dva modely: **ZP Agent / RAG – overené** a **ZP Agent / GraphRAG – overené**.
|
||||
Vybraný model zavolá backend `/answer` a zobrazí jeho schválený text priamo.
|
||||
Ďalší jazykový model tento text neprepisuje.
|
||||
|
||||
## Inštalácia administrátorom
|
||||
|
||||
1. V OpenWebUI otvorte **Admin Panel → Functions → Create New Function**.
|
||||
2. Vložte obsah `verified_agent.py`, uložte funkciu napríklad ako `zp_verified`
|
||||
a zapnite ju. Kód funkcie vykonáva server OpenWebUI; neinštaluje ju bežný používateľ.
|
||||
3. Vo **Valves** nastavte `BACKEND_URL` na adresu API dostupnú zo servera
|
||||
OpenWebUI a `BACKEND_API_KEY` na jeho `SEARCH_API_KEY`.
|
||||
Ak sú obe služby v rovnakej Compose sieti, URL je `http://zp-agent-api:8000`.
|
||||
`localhost` v školskom OpenWebUI neoznačuje tento vývojový počítač.
|
||||
4. Backend potrebuje `OPENWEBUI_API_KEY` pre prístup ku generujúcemu modelu.
|
||||
Voliteľné `ANSWER_LLM_URL` má predvolenú hodnotu
|
||||
`https://ui.tukekemt.xyz/api/chat/completions`; `ANSWER_MODEL` je
|
||||
predvolene `model120-fast`. Vyberte základný model, ktorý nevolá tento Pipe,
|
||||
aby nevznikla slučka. Kľúče nezapisujte do zdrojového súboru ani Gitu.
|
||||
5. V chate vyberte jeden z dvoch nových modelov. Overte bežnú odpoveď,
|
||||
nedostupnosť backendu, chýbajúce podklady a neúplný výsledok.
|
||||
|
||||
Dokumentácia OpenWebUI:
|
||||
[Functions](https://docs.openwebui.com/features/extensibility/plugin/functions/),
|
||||
[Pipes](https://docs.openwebui.com/features/extensibility/plugin/functions/pipe/).
|
||||
|
||||
## Kontroly a hranice
|
||||
|
||||
- API `/answer` vyžaduje rovnakú autorizáciu ako vyhľadávanie.
|
||||
- RAG kontroluje osobu, konkrétny názov, typ a rok z toho istého záznamu
|
||||
v skutočne doručenom kontexte. Rok kategórie nenahrádza rok práce.
|
||||
Používa iba vyhľadaný text; nečíta očakávania benchmarku ani Neo4j.
|
||||
- Všeobecné odpovede môžu obsahovať doslovné citované výňatky. Ich zhoda
|
||||
so zdrojom nezaručuje, že výňatok vyčerpáva význam celej otázky.
|
||||
- GraphRAG používa kontroly typovaných faktov, väzieb, citácií a agregácií.
|
||||
- Model má najviac jeden opravný pokus podľa podkladov. Potom sa odpoveď
|
||||
odmietne. Finálny text zostavuje aplikácia z overených údajov.
|
||||
- Pipe vyžaduje `accepted_for_delivery=true` a povolený stav. Odmietnutý
|
||||
modelový text ani diagnostické pokusy sa používateľovi nevracajú.
|
||||
- Neúplnosť a verzia indexov sa prenášajú z vyhľadávania. Upozornenie na
|
||||
neúplnosť je súčasťou zobrazeného textu.
|
||||
- Pôvodný `/rag` stále poskytuje podklady. Bežný OpenAPI Tool Server
|
||||
nasledovaný ľubovoľným LLM nezabezpečuje túto kontrolovanú cestu.
|
||||
- Funkcia pracuje s poslednou otázkou; zatiaľ neprepisuje odkazy typu
|
||||
„a jeho ďalšia práca“ podľa histórie konverzácie.
|
||||
|
||||
Lokálny test integračného adaptéra a API:
|
||||
|
||||
```bash
|
||||
.venv/bin/python -m pytest -q test/test_verified_rag.py
|
||||
```
|
||||
|
||||
Test kontroluje aj HTTP payload, autorizáciu a priamy výstup oboch modelov.
|
||||
Nezastupuje inštaláciu na školskom serveri: tú musí vykonať administrátor
|
||||
a overiť sieťovú dostupnosť API zo servera OpenWebUI.
|
||||
@ -11,6 +11,6 @@ docker --context "$docker_context" info --format '{{.ServerVersion}}' >/dev/null
|
||||
"${compose[@]}" config --quiet
|
||||
"${compose[@]}" build zp-agent-api
|
||||
"${compose[@]}" up -d --wait neo4j
|
||||
"${compose[@]}" run --rm -T --no-deps zp-agent-api python -m tools.bootstrap_indexes
|
||||
"${compose[@]}" run --rm -T --no-deps zp-agent-api python -m tools.runtime.bootstrap_indexes
|
||||
"${compose[@]}" up -d --no-build --wait zp-agent-api
|
||||
"${compose[@]}" ps
|
||||
|
||||
173
scripts/verify_project.py
Normal file
173
scripts/verify_project.py
Normal file
@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verify local code, tests, databases and Docker without calling an external LLM."""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import ast
|
||||
import ipaddress
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shlex
|
||||
import socket
|
||||
import sqlite3
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import urllib.request
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def local_test_worker() -> int:
|
||||
"""Allow live local API/Neo4j tests, forbid outbound model calls."""
|
||||
os.environ.pop('OPENWEBUI_API_KEY', None)
|
||||
for line in (ROOT / '.env').read_text().splitlines():
|
||||
key, separator, value = line.partition('=')
|
||||
if separator and key in {'NEO4J_URI', 'NEO4J_USER', 'NEO4J_PASSWORD', 'NEO4J_DATABASE'}:
|
||||
values = shlex.split(value)
|
||||
if values:
|
||||
os.environ[key] = values[0]
|
||||
for key in ['RUN_NEO4J_TESTS', 'RUN_LIVE_TESTS', 'RUN_LIVE_RAG_E2E', 'HF_HUB_OFFLINE', 'TRANSFORMERS_OFFLINE']:
|
||||
os.environ[key] = '1'
|
||||
original_connect, original_connect_ex = socket.socket.connect, socket.socket.connect_ex
|
||||
original_dns = socket.getaddrinfo
|
||||
|
||||
def permitted(address):
|
||||
try:
|
||||
return address[1] in {7687, 8000} and ipaddress.ip_address(address[0]).is_loopback
|
||||
except (ValueError, TypeError, IndexError):
|
||||
return False
|
||||
|
||||
def guarded_connect(self, address):
|
||||
if self.family in {socket.AF_INET, socket.AF_INET6} and not permitted(address):
|
||||
raise RuntimeError('External network disabled during local verification')
|
||||
return original_connect(self, address)
|
||||
|
||||
def guarded_connect_ex(self, address):
|
||||
if self.family in {socket.AF_INET, socket.AF_INET6} and not permitted(address):
|
||||
raise RuntimeError('External network disabled during local verification')
|
||||
return original_connect_ex(self, address)
|
||||
|
||||
def guarded_dns(host, port, *args, **kwargs):
|
||||
if host not in {'localhost', '127.0.0.1', '::1'} or int(port) not in {7687, 8000}:
|
||||
raise RuntimeError('External DNS disabled during local verification')
|
||||
return original_dns(host, port, *args, **kwargs)
|
||||
|
||||
socket.socket.connect, socket.socket.connect_ex = guarded_connect, guarded_connect_ex
|
||||
socket.getaddrinfo = guarded_dns
|
||||
import pytest
|
||||
return pytest.main(['-q', 'test', 'tools/rag/tests', 'tools/graphrag/tests'])
|
||||
|
||||
|
||||
def verify_code() -> dict:
|
||||
files = [path for name in ['app', 'tools', 'test', 'scripts'] for path in (ROOT / name).rglob('*.py')]
|
||||
for path in files:
|
||||
text = path.read_text()
|
||||
compile(text, str(path), 'exec')
|
||||
for node in ast.walk(ast.parse(text)):
|
||||
modules = ([node.module] if isinstance(node, ast.ImportFrom) and node.module else
|
||||
[item.name for item in node.names] if isinstance(node, ast.Import) else [])
|
||||
for module in modules:
|
||||
if module.split('.')[0] in {'tools', 'app'}:
|
||||
target = ROOT.joinpath(*module.split('.'))
|
||||
if not target.with_suffix('.py').is_file() and not (target / '__init__.py').is_file():
|
||||
raise RuntimeError(f'Unresolved internal module {module} in {path.relative_to(ROOT)}')
|
||||
shells = [path for name in ['scripts', 'tools'] for path in (ROOT / name).rglob('*.sh')]
|
||||
for path in shells:
|
||||
subprocess.run(['bash', '-n', str(path)], check=True)
|
||||
return {'compiled_python_files': len(files), 'checked_shell_scripts': len(shells)}
|
||||
|
||||
|
||||
def verify_database() -> dict:
|
||||
path = ROOT / 'data/zp_index.sqlite'
|
||||
with sqlite3.connect(path.resolve().as_uri() + '?mode=ro', uri=True) as conn:
|
||||
assert conn.execute('PRAGMA quick_check').fetchone()[0] == 'ok', 'SQLite integrity failed'
|
||||
assert not conn.execute('PRAGMA foreign_key_check').fetchall(), 'SQLite foreign keys failed'
|
||||
counts = {table: conn.execute(f'SELECT count(*) FROM {table}').fetchone()[0]
|
||||
for table in ['documents', 'chunks', 'chunks_fts', 'chunk_embeddings']}
|
||||
assert counts['chunks'] == counts['chunks_fts'] and counts['chunks'] > 0, 'FTS count mismatch'
|
||||
return counts
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--docker-context', default='default')
|
||||
parser.add_argument('--git-network', action='store_true', help='Read-only probe of wiki origin over its configured SSH connection')
|
||||
parser.add_argument('--output', type=Path, default=ROOT / 'data/project_verification.json')
|
||||
parser.add_argument('--test-worker', action='store_true', help=argparse.SUPPRESS)
|
||||
args = parser.parse_args()
|
||||
os.chdir(ROOT)
|
||||
sys.path.insert(0, str(ROOT))
|
||||
if args.test_worker:
|
||||
return local_test_worker()
|
||||
report = {'checks': {}, 'external_llm_calls': False}
|
||||
args.output.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def check(name, action):
|
||||
started = time.monotonic()
|
||||
try:
|
||||
result = action()
|
||||
record = {'passed': True, 'details': result}
|
||||
except Exception as error:
|
||||
record = {'passed': False, 'error_type': type(error).__name__}
|
||||
record['seconds'] = round(time.monotonic() - started, 2)
|
||||
report['checks'][name] = record
|
||||
args.output.write_text(json.dumps(report, ensure_ascii=False, indent=2) + '\n')
|
||||
print(f'{name}: {"OK" if record["passed"] else "FAILED"}', flush=True)
|
||||
|
||||
def command(*argv):
|
||||
result = subprocess.run(argv, text=True, capture_output=True, timeout=90)
|
||||
if result.returncode:
|
||||
raise RuntimeError('Verification command failed; inspect the service locally')
|
||||
return result.stdout.strip()
|
||||
|
||||
docker = ['docker', '--context', args.docker_context]
|
||||
compose = [*docker, 'compose', '--project-directory', str(ROOT)]
|
||||
check('python_and_shell', verify_code)
|
||||
check('git_diff', lambda: command('git', 'diff', '--check'))
|
||||
check('git_integrity', lambda: command('git', 'fsck', '--connectivity-only'))
|
||||
check('compose_configuration', lambda: command(*compose, 'config', '--quiet'))
|
||||
|
||||
def health():
|
||||
with urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=15) as response:
|
||||
value = json.load(response)
|
||||
assert value['ready'] and all(tool['ready'] for tool in value['tools'].values())
|
||||
assert value['tools']['rag']['index_version'] == value['tools']['graphrag']['index_version']
|
||||
return {'ready': True, 'index_version': value['index_version'],
|
||||
'tools': {name: item['ready'] for name, item in value['tools'].items()}}
|
||||
|
||||
check('api_and_both_indexes', health)
|
||||
check('sqlite_integrity', verify_database)
|
||||
check('container_readiness', lambda: command(*compose, 'exec', '-T', 'zp-agent-api',
|
||||
'python', '-m', 'tools.runtime.runtime_health'))
|
||||
if args.git_network:
|
||||
probe = ("import os,subprocess; from tools.sync.wiki_git import expected_branch; "
|
||||
"p=subprocess.run(['git','-C',os.environ['ZPWIKI_ROOT'],'ls-remote','--exit-code',"
|
||||
"'origin','refs/heads/'+expected_branch()],capture_output=True,text=True,timeout=60); "
|
||||
"assert p.returncode==0,'Wiki origin unavailable'; print(p.stdout.strip())")
|
||||
check('wiki_git_ssh', lambda: command(*compose, 'exec', '-T', 'zp-agent-api', 'python', '-c', probe))
|
||||
|
||||
def tests():
|
||||
log = args.output.with_suffix('.pytest.log')
|
||||
environment = {**os.environ}
|
||||
environment.pop('OPENWEBUI_API_KEY', None)
|
||||
with log.open('w') as output:
|
||||
result = subprocess.run([sys.executable, str(Path(__file__).resolve()), '--test-worker'],
|
||||
env=environment, stdout=output, stderr=subprocess.STDOUT, timeout=900)
|
||||
assert result.returncode == 0, 'Regression failed; see local pytest log'
|
||||
text = log.read_text()
|
||||
counts = {name: int(value) for value, name in re.findall(r'(\d+) (passed|failed|skipped)', text)}
|
||||
assert counts.get('passed', 0) > 0 and counts.get('skipped', 0) == 0
|
||||
return {**counts, 'log': str(log), 'external_network_blocked': True}
|
||||
|
||||
check('full_local_regression', tests)
|
||||
report['passed'] = all(item['passed'] for item in report['checks'].values())
|
||||
args.output.write_text(json.dumps(report, ensure_ascii=False, indent=2) + '\n')
|
||||
print('Report: ' + str(args.output))
|
||||
return 0 if report['passed'] else 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main())
|
||||
@ -48,7 +48,7 @@ def security_environment(
|
||||
def isolated_sync_queue(monkeypatch, tmp_path):
|
||||
"""API tests never start a real index rebuild or share production job state."""
|
||||
import app.main as main
|
||||
from tools.sync_jobs import SyncJobs
|
||||
from tools.sync.sync_jobs import SyncJobs
|
||||
|
||||
class PausedJobs(SyncJobs):
|
||||
def __init__(self, data_dir, **kwargs):
|
||||
|
||||
@ -83,8 +83,9 @@ def test_runtime_requirements_contain_only_direct_dependencies() -> None:
|
||||
def test_all_application_python_files_compile() -> None:
|
||||
targets = [
|
||||
PROJECT_ROOT / "app",
|
||||
PROJECT_ROOT / "tools" / "rag",
|
||||
PROJECT_ROOT / "tools" / "graphrag",
|
||||
PROJECT_ROOT / "tools",
|
||||
PROJECT_ROOT / "test",
|
||||
PROJECT_ROOT / "scripts",
|
||||
]
|
||||
|
||||
for directory in targets:
|
||||
|
||||
@ -11,7 +11,7 @@ from tools.rag import build_sqlite_index as indexer
|
||||
from tools.rag import embedding_utils as embedding
|
||||
from tools.rag import search_core
|
||||
from tools.rag.embedding_cache import EmbeddingCache, cache_key
|
||||
from tools.text_budget import split_to_fit
|
||||
from tools.retrieval.text_budget import split_to_fit
|
||||
|
||||
|
||||
def test_unicode_split_is_lossless_and_respects_exact_counter():
|
||||
|
||||
@ -9,8 +9,8 @@ from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from tools import index_state as state
|
||||
from tools import sync_indexes as sync
|
||||
from tools.sync import index_state as state
|
||||
from tools.sync import sync_indexes as sync
|
||||
|
||||
|
||||
class Result:
|
||||
|
||||
@ -8,11 +8,11 @@ from fastapi.testclient import TestClient
|
||||
|
||||
import app.main as main
|
||||
import app.routes as routes
|
||||
import tools.tool_health as health
|
||||
import tools.runtime.tool_health as health
|
||||
import tools.rag.build_sqlite_index as indexer
|
||||
import tools.rag.search_core as search_core
|
||||
from tools.index_state import durable_json, PENDING_FILE, VERSION_FILE
|
||||
from tools.publication import PUBLICATION_POLICY_VERSION, effective_published
|
||||
from tools.sync.index_state import durable_json, PENDING_FILE, VERSION_FILE
|
||||
from tools.retrieval.publication import PUBLICATION_POLICY_VERSION, effective_published
|
||||
from tools.rag.search_utils import search_database
|
||||
from tools.rag.rag_utils import build_rag_context
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ import tools.rag.build_sqlite_index as indexer
|
||||
import tools.rag.search_core as core
|
||||
import tools.rag.search_utils as search
|
||||
from tools.rag.rag_utils import build_rag_context
|
||||
from tools.retrieval_contract import RetrievalResponse, error_result
|
||||
from tools.retrieval.retrieval_contract import RetrievalResponse, error_result
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@ -7,7 +7,7 @@ from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from tools import runtime_assets as assets
|
||||
from tools.runtime import runtime_assets as assets
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@ -9,7 +9,7 @@ import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
import app.main as main
|
||||
from tools.sync_jobs import SyncJobs
|
||||
from tools.sync.sync_jobs import SyncJobs
|
||||
from tools.rag.rebuild_index import acquire_reindex_lock
|
||||
|
||||
|
||||
|
||||
@ -172,7 +172,7 @@ def test_answer_api_checks_auth_and_does_not_expose_rejected_attempts(monkeypatc
|
||||
|
||||
|
||||
def test_graph_production_delivery_checks_renders_and_propagates_metadata(monkeypatch):
|
||||
import tools.answer_delivery as delivery
|
||||
import tools.answers.answer_delivery as delivery
|
||||
context = {'status': 'ok', 'reason': None, 'aggregation': None,
|
||||
'complete': False, 'truncated': True, 'truncation_reasons': ['result_limit'],
|
||||
'index_version': {'version': 'fixture'}, 'answer_candidates': [],
|
||||
@ -192,7 +192,7 @@ def test_graph_production_delivery_checks_renders_and_propagates_metadata(monkey
|
||||
|
||||
|
||||
def load_pipe():
|
||||
path = Path('integrations/openwebui/verified_agent.py')
|
||||
path = Path('tools/answers/openwebui_pipe.py')
|
||||
spec = importlib.util.spec_from_file_location('verified_agent_pipe', path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
@ -3,7 +3,7 @@ from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
import tools.wiki_git as wiki_git
|
||||
import tools.sync.wiki_git as wiki_git
|
||||
|
||||
|
||||
@pytest.mark.parametrize('value', ['', '../master', '-main', 'a..b', 'a b', 'a.lock', 'a/@{x', 'a//b'])
|
||||
|
||||
@ -1,112 +0,0 @@
|
||||
# Generovanie odpovedí nad zmrazeným grafom
|
||||
|
||||
Aktuálne meranie **v7** používa 46 známych DEV otázok, nový query-group TEST
|
||||
80 otázok a oddelenú historickú regresiu 320 otázok.
|
||||
Model vracia štruktúrované tvrdenia, `answer` je prázdne. Aplikácia overí
|
||||
fakty, väzby, počty a citácie a vykreslí prirodzený text deterministicky.
|
||||
Voľná próza modelu sa ako finálna odpoveď nedoručuje. Pôvodné HTTP odpovede,
|
||||
parsované aj vykreslené odpovede a každý opravný pokus sú uložené.
|
||||
|
||||
Nový TEST má prvý pokus **77/80 (96,25 %)** a finálny výsledok **80/80**;
|
||||
jednu opravu potrebovali tri otázky. Historická regresia má 319/320,
|
||||
s jedným odmietnutým nepodloženým akademickým názvom. Nejde o meranie voľnej jazykovej
|
||||
formulácie ani neznámeho korpusu. Modelový DEV má 46/46.
|
||||
[Správa v7](../graphrag/evaluation/results/final_v7_2026-10-26/REPORT.md).
|
||||
|
||||
Všetky evaluačné vstupy treba zvoliť explicitne. Nový TEST používa
|
||||
`--split test`; známa regresia `--split regression --regression-ids ...`.
|
||||
Oba potrebujú dokončený `--dev-results` s rovnakými hashmi a modelom.
|
||||
Príkazy sú v [pracovnom zázname v7](../../docs/graphrag_v7_2026-10-26_worklog.md).
|
||||
Budúci OpenWebUI agent musí dodržať `accepted_for_delivery` a odovzdať
|
||||
overený text; nekontrolované prepísanie rendererovej odpovede by tieto
|
||||
záruky obišlo. Natívny výber nástrojov ostáva ďalším blokom.
|
||||
|
||||
## Historická v6
|
||||
|
||||
Meranie **v6** je historická regresia 320 známych otázok vrátane
|
||||
42 DEV otázok. [Výsledná správa](../graphrag/evaluation/results/final_v6_2026-10-25/REPORT.md)
|
||||
uvádza samostatne prvý pokus, výsledok po jednom povolenom opravnom požiadavku,
|
||||
odmietnuté odpovede a JSON chyby. Žiadna chyba sa nevynecháva z menovateľa.
|
||||
Finálny strict výsledok je **316/320 (98,75 %)**: tri neplatné JSON/schema
|
||||
výstupy a jedno prísne odmietnutie skloňovaného mena pri správnych claims.
|
||||
|
||||
Spoločný adaptér prenáša úplnosť, orezanie, dôvody aj verziu dát. Guard používa
|
||||
iba skutočný kontext; kontroluje všetky citované URL, typy hodnôt, ich väzby
|
||||
a upozornenie pri neúplnom výpise. Môže vyžiadať najviac jednu opravu spolu
|
||||
pre formát alebo porušenie kontextu. Gold sa používa až pri hodnotení.
|
||||
Oba evaluačné grafové vstupy používajú tento istý adaptér a guard.
|
||||
|
||||
`accepted_for_delivery=false` zakazuje považovať výstup za overenú odpoveď.
|
||||
Integrácia tejto kontroly do budúceho natívneho OpenWebUI agenta je súčasťou
|
||||
bodu 4; dnešné meranie grafu dodáva kontext cez lokálny klient.
|
||||
Klasický RAG pred doručením používa `finalize_rag_answer()`: môže pridať iba
|
||||
chýbajúce upozornenie na neúplnosť, bez zmeny faktov. Zachová pôvodný text
|
||||
modelu a neobíde nepovolené URL ani tvrdenie o úplnom zozname.
|
||||
|
||||
[Podrobný postup a príkazy](../../docs/graphrag_v6_2026-10-25_worklog.md).
|
||||
Skripty `check_context_scenarios`, `check_rag_runtime`, `check_deployment`
|
||||
a `regrade_citations` oddeľujú syntetické funkčné kontroly, živý RAG smoke,
|
||||
overenie nasadenia a prepočet historických citácií od hlavnej presnosti.
|
||||
|
||||
## Historická v5.1
|
||||
|
||||
Meranie **v5.1** je historická regresia. Výsledky sú v
|
||||
[spoločnej správe](../graphrag/evaluation/results/final_v5_1_2026-10-25/REPORT.md).
|
||||
Používa 39 vopred vybraných DEV otázok (20 pôvodných a 19 historických zlyhaní)
|
||||
a 320 finálnych regresných otázok vrátane týchto 39. Nejde o nezávislý holdout.
|
||||
|
||||
Generovanie overí odtlačky kódu/promptu/dát voči kompletnému DEV. Parser prijíma
|
||||
platný typovaný JSON alebo jeden úplný JSON blok. Pri chybe formátu je povolený
|
||||
najviac jeden opravný požiadavok bez gold; pôvodné aj opravné odpovede sa ukladajú.
|
||||
Vecné zlyhanie hodnotenia neopakuje požiadavok. Report uvádza prvotnú aj konečnú
|
||||
úspešnosť a počet opráv. Natívny výber OpenWebUI nástrojov zostáva bodom 4.
|
||||
|
||||
Reprodukcia potrebuje zodpovedajúci release checkout a graf, načítanú konfiguráciu
|
||||
a nové výstupné adresáre. Najprv spustite `--split dev` s
|
||||
`--dev-ids tools/graphrag/evaluation/results/v5_1_preparation/generation_dev_ids.json`,
|
||||
`--audit tools/graphrag/evaluation/results/v5_1_preparation/source_audit.json`
|
||||
a `--freeze-manifest tools/graphrag/evaluation/frozen_v5_1.json`.
|
||||
Finálny beh používa rovnaké parametre, `--split regression` a povinné
|
||||
`--dev-results` smerujúce na tento dokončený DEV. Historické výsledky sa neprepisujú.
|
||||
|
||||
## Historický protokol v4
|
||||
|
||||
Nasledujúci text a pôvodný TEST 300 otázok opisujú v4; jej reprodukcia vyžaduje
|
||||
pôvodný kód aj graf. Týchto 300 otázok je pri ďalšom ladení historickou regresiou.
|
||||
|
||||
Tento experiment meria OpenWebUI chat API po dodaní skutočného grafového
|
||||
kontextu lokálnym skriptom. Neoveruje prehliadač ani automatický výber
|
||||
nainštalovaných nástrojov hlavným agentom. Klasický RAG sa nemení.
|
||||
|
||||
Pôvodná diagnostika použila 20 otázok. Všetkých 20 sa stalo DEV; zostávajúcich
|
||||
300 otázok zo zmrazeného grafového benchmarku tvorí nový TEST generovania.
|
||||
Predchádzajúce interné grafové meranie neposkytlo výstupy jazykového modelu.
|
||||
Žiadne očakávania, zdrojový oracle ani výsledky evaluatora sa modelu neposielajú.
|
||||
|
||||
`graph_answer_prompt.txt` určuje výstup. Kontext obsahuje iba skutočné relevantné
|
||||
fakty a zdroje, bez mien profilov vydávaných za názov akademickej práce či typu
|
||||
osoby zamieňaného za taxonomickú kategóriu. Štruktúrované tvrdenia musia spájať
|
||||
správne fakty pri tej istej osobe/práci/dokumente. Kontrolujú sa aj zdrojové
|
||||
odkazy, množiny, počty a povinné hodnoty v prirodzenom texte. Nepovinné `null`
|
||||
znamená neprítomnosť tvrdenia. Označenie diplomovej práce za dizertačnú sa odmieta.
|
||||
|
||||
Ide o prísne, ale stále pravidlové hodnotenie. Nejde o úplnú sémantickú kontrolu
|
||||
každej možnej vety. Zdrojový oracle je nezávislý od grafového buildera, nie od
|
||||
človeka, ktorý by nezávisle anotoval celý test. Osoby, korpus a šablóny sú známe.
|
||||
|
||||
Každý nový výstupný adresár obsahuje deklaráciu pred meraním, SHA kódu/promptu,
|
||||
presné DEV/TEST ID a výsledky všetkých otázok. Odpovede sa ukladajú priebežne;
|
||||
chyba ani prerušený beh sa nesmie zatajiť či premenovať na nezávislý nový TEST.
|
||||
Po odhalení TEST výsledkov patria tieto otázky pri ladení do DEV.
|
||||
|
||||
```bash
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
# Reprodukcia používa vždy nový adresár; nejde o nový nezávislý TEST.
|
||||
python -m tools.answer_evaluation.evaluate_graph_answers \
|
||||
--split test --output-dir /tmp/graphrag-answers-reproduction
|
||||
```
|
||||
|
||||
Model je `model120-fast`; presný názov modelu vrátený serverom, tokeny a pôvodné
|
||||
odpovede sú uložené vo výsledkoch. Prístupový kľúč zostáva iba v prostredí.
|
||||
@ -12,7 +12,7 @@ from tools.graphrag.graph_db import create_neo4j_driver
|
||||
from tools.graphrag.graph_search import search_graph
|
||||
from tools.graphrag.build_graphrag import graph_version
|
||||
from tools.graphrag.evaluation.reproducibility import graph_fingerprint, run_metadata, verify_freeze, sha256_file
|
||||
from tools.index_state import read_version, sqlite_version
|
||||
from tools.sync.index_state import read_version, sqlite_version
|
||||
from tools.rag.common import DB_FILE
|
||||
|
||||
|
||||
|
||||
1
tools/answers/__init__.py
Normal file
1
tools/answers/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Verified answer delivery and OpenWebUI integration."""
|
||||
@ -46,7 +46,7 @@ def deliver_answer(question: str, *, engine: str = 'rag', limit: int = 5,
|
||||
result = generate_verified_rag(question, retrieved, model)
|
||||
elif engine == 'graphrag':
|
||||
context = graph_context(search_graph(question))
|
||||
prompt = (Path(__file__).parent / 'answer_evaluation/graph_answer_prompt.txt').read_text()
|
||||
prompt = (Path(__file__).resolve().parents[1] / 'answer_evaluation/graph_answer_prompt.txt').read_text()
|
||||
generated = generate_checked_answer(question, context, prompt, model)
|
||||
if generated.get('accepted_for_delivery'):
|
||||
result = {**generated['answer'], 'accepted_for_delivery': True, 'reason': None,
|
||||
@ -13,7 +13,7 @@ from .graphrag import (
|
||||
GRAPH_SCOPE,
|
||||
build_graph_payload,
|
||||
)
|
||||
from tools.index_state import DATA_DIR, PENDING_FILE, publication_lock, read_version
|
||||
from tools.sync.index_state import DATA_DIR, PENDING_FILE, publication_lock, read_version
|
||||
|
||||
|
||||
PROJECT_ROOT = Path(
|
||||
|
||||
@ -1,136 +0,0 @@
|
||||
# GraphRAG evaluácia
|
||||
|
||||
Aktuálna verzia je **v7**, tag `graphrag-v7-frozen`.
|
||||
[Správa v7](results/final_v7_2026-10-26/REPORT.md): graf DEV 1 046/1 046,
|
||||
nový query-group TEST 80/80, model DEV 46/46, finálne odpovede TEST 80/80
|
||||
(prvý pokus 77/80). Všetkých 591 testov prešlo. Stará regresia má 319/320;
|
||||
jeden nepodložený modelový názov sa nedoručil. TEST sa neprekrýva so žiadnou odhalenou query skupinou;
|
||||
korpus, ľudia a šablóny sú známe. Dve kategórie majú len 2 a 7 nových skupín.
|
||||
|
||||
CLI vyžaduje explicitné `--questions`, `--audit`, `--freeze-manifest`
|
||||
(pri TESTe) a nový výstupný adresár. Použite `graphrag_questions_v7.json`,
|
||||
`results/v7_preparation/source_audit.json`, `frozen_v7.json`.
|
||||
Generátor `benchmark_v7` vytvára otázky jednorazovo z raw zdrojov, bez
|
||||
predikcií. Odstránil sa odhad začiatku štúdia z adresára, nie nedokumentované
|
||||
otázky z merania. [Príkazy a postup](../../../docs/graphrag_v7_2026-10-26_worklog.md).
|
||||
|
||||
## Historická v6
|
||||
|
||||
Historická verzia je **v6**, tag `graphrag-v6-frozen`.
|
||||
[Finálna správa v6](results/final_v6_2026-10-25/REPORT.md) oddeľuje grafový
|
||||
DEV 722/722, regresiu 320/320 a generované odpovede modelu.
|
||||
Generovanie má strict **316/320 (98,75 %)**; všetkých **565 testov** prešlo.
|
||||
Benchmark v6 ponecháva všetkých 1 042 otázok, ich ID a rozdelenie. Opravuje
|
||||
15 očakávaní po priamom čítaní zdrojov; generický odkaz „rešerš“ nie je názov
|
||||
akademického projektu. Všetky staršie dáta a výsledky ostávajú zachované.
|
||||
Modelový DEV má 42 známych otázok; finálna regresia obsahuje všetkých 320.
|
||||
|
||||
Použite `--questions tools/graphrag/evaluation/graphrag_questions_v6.json`,
|
||||
`--audit tools/graphrag/evaluation/results/v6_preparation/source_audit.json`
|
||||
a `--freeze-manifest tools/graphrag/evaluation/frozen_v6.json`.
|
||||
[Postup, kontroly a zdrojová vzorka](../../../docs/graphrag_v6_2026-10-25_worklog.md).
|
||||
Kontrola vzorky je AI kontrola; ľudské posúdenie je pripravené v CSV, neprebehlo.
|
||||
Ročník adresára sa pri chýbajúcom explicitnom začiatku štúdia používa ako
|
||||
náhradná konvencia, nie ako nezávislý administratívny doklad.
|
||||
|
||||
## Historická v5.1
|
||||
|
||||
Historická verzia je **v5.1**, tag `graphrag-v5.1-frozen`.
|
||||
[Finálna správa](results/final_v5_1_2026-10-25/REPORT.md) a
|
||||
[strojový súhrn](results/final_v5_1_2026-10-25/summary.json) oddeľujú
|
||||
vyhľadávanie, zdrojovú kontrolu všetkých vrátených typovaných faktov a generovanie.
|
||||
|
||||
- Graf DEV: **722/722**.
|
||||
- Graf historická regresia: **320/320**, vrátane kontroly nadbytočných faktov.
|
||||
- Generovanie: 39 vopred deklarovaných DEV a finálna regresia všetkých 320
|
||||
historických otázok. Finálny výsledok: **317/320 (99,06 %)**, bez chýb JSON
|
||||
a bez opravného požiadavku. Všetky tri zlyhania zostávajú započítané.
|
||||
- Kompletné automatizované testy: **525 passed, 4 skipped**.
|
||||
|
||||
Všetky otázky sú už známe. V5.1 je regresia, nie nový nezávislý TEST; finálna
|
||||
regresia generovania obsahuje aj 39 DEV otázok. Pôvodné gold ani výsledky sa
|
||||
nemenili. Prvá iterácia v5 (319/320) zostáva uložená a má overený zdrojový patch.
|
||||
|
||||
Reprodukcia v5.1 vyžaduje zodpovedajúci release checkout, raw wiki, JSON vstupy
|
||||
aj graf podľa manifestu. Používajte vždy nový výstupný adresár:
|
||||
|
||||
```bash
|
||||
python -m tools.graphrag.evaluation.evaluate_graphrag \
|
||||
--split test \
|
||||
--audit tools/graphrag/evaluation/results/v5_1_preparation/source_audit.json \
|
||||
--freeze-manifest tools/graphrag/evaluation/frozen_v5_1.json \
|
||||
--output-dir /tmp/graphrag-v5-1-reproduction
|
||||
```
|
||||
|
||||
Nové zmrazenie po vývoji používa kompletný DEV a `--purpose historical_regression`.
|
||||
Odtlačky zahŕňajú spoločné moduly aj efektívnu publikačnú politiku. Každý reálny
|
||||
DEV výsledok musí prejsť nezávislou kontrolou všetkých vrátených typovaných faktov.
|
||||
Pri ďalšom nezávislom experimente treba nové, vopred zdrojovo overené otázky.
|
||||
|
||||
## Historický protokol v4
|
||||
|
||||
Nasledujúce merania a príkazy opisujú pôvodnú v4. Na reprodukciu použite jej
|
||||
pôvodný checkout/graf; aktuálny kód nezodpovedá odtlačkom frozen_v4.
|
||||
|
||||
Historická zmrazená verzia je **v4**. [Finálna správa](results/final_v4_2026-10-25/REPORT.md) obsahuje protokol, výsledky a obmedzenia.
|
||||
|
||||
| Meranie grafového vyhľadávania | Správne | Úspešnosť |
|
||||
|---|---:|---:|
|
||||
| DEV/regresia v4 | 722/722 | 100,00 % |
|
||||
| Širší TEST v4 | 320/320 | 100,00 % |
|
||||
|
||||
Cieľ ≥92 % grafového vyhľadávania bol splnený v prvom finálnom behu. TEST má desať kategórií, 288 kladných a 32 záporných otázok, bez runtime chýb. Osoby aj korpus sú známe; nové sú otázky a kombinácie faktov. Logické skupiny ani normalizované otázky sa medzi DEV a TEST neprekrývajú. Výsledok neznamená všeobecnú 100 % správnosť na ľubovoľnom vstupe.
|
||||
|
||||
Generovanie odpovedí dosiahlo **281/300 (93,67 %)** na novom externom TESTe; 20 DEV otázok malo 19/20. Všetkých 19 zlyhaní vrátane 7 neplatných JSON odpovedí ostáva započítaných. Doplnkový audit všetkých vrátených grafových kontextových faktov má **319/320 (99,69 %)**; strict 320/320 neznamená pravdivosť každej nadbytočnej hodnoty. Najslabšia LLM kategória je názov + tag (21/30).
|
||||
|
||||
Samostatne sa hodnotí generovanie odpovedí cez školské OpenWebUI API po dodaní skutočného grafového kontextu. [Protokol generovania](../../answer_evaluation/README.md) oddeľuje 20 DEV a 300 nových LLM TEST výstupov. Natívny výber nástrojov hlavným agentom je ďalší blok projektu.
|
||||
|
||||
## Reprodukcia zmrazeného grafu
|
||||
|
||||
Použi zodpovedajúci kód, rovnakú pôvodnú wiki, JSON vstupy a obsah Neo4j podľa manifestu. Súkromné kľúče ostávajú v `.env`.
|
||||
|
||||
```bash
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
python -m tools.graphrag.evaluation.evaluate_graphrag \
|
||||
--split test \
|
||||
--audit tools/graphrag/evaluation/results/v4_preparation/source_audit.json \
|
||||
--freeze-manifest tools/graphrag/evaluation/frozen_v4.json \
|
||||
--output-dir /tmp/graphrag-v4-reproduction
|
||||
```
|
||||
|
||||
Existujúce finálne výstupy a manifesty sa neprepisujú. Opakované spustenie rovnakého TESTu je reprodukcia, nie nové nezávislé overenie. Ak sa podľa odhalených TEST chýb ladí ďalšia verzia, tieto otázky sú od tej chvíle DEV.
|
||||
|
||||
## Zdrojový benchmark a história
|
||||
|
||||
- `graphrag_questions.json`: pôvodných 500 otázok. V2 opravila 137 nesúladov (128 tagových predpokladov a 9 neúplných množín kategórií). Zmeny sú v `results/v2_preparation/legacy_corrections.json`.
|
||||
- V2: 509 DEV a 80 profilovo oddelených TEST otázok; finálny TEST 67/80 (83,75 %). Po odhalení sa stal regresiou.
|
||||
- V3: 589 DEV a 13 **nových** doplnkových otázok vytvorených z pôvodných dokumentov posledných dvoch neodhalených profilov. Nešlo o výber trinástich z pôvodných 500. Meranie prebehlo interným skriptom nad Neo4j bez OpenWebUI či LLM. DEV 589/589, malý TEST 13/13; obmedzené pokrytie neumožňovalo tvrdiť všeobecnú 100 % presnosť.
|
||||
- V4: 722 DEV (602 historických + 120 nových), 320 nových TEST skupín nad všetkými známymi profilmi. `source_oracle.py` číta raw Markdown oddelene od buildera. `benchmark_v4.py` nepoužíva výsledky vyhľadávania pri tvorbe očakávaní ani výbere otázok. Kontrola surových zdrojov doplnila 45 zmien/rozšírení historických väzieb názvov; záznamy a mapovanie ID sú v `results/v4_preparation/`.
|
||||
|
||||
V1–v3 ostávajú v pôvodných adresároch s manifestmi a tagmi `graphrag-v1-frozen`, `graphrag-v2-frozen`, `graphrag-v3-frozen`. Na reprodukciu treba ich pôvodný kód a graf. Percentá rôznych verzií nie sú kontrolovaným porovnaním identických otázok. Klasický RAG a jeho referenčné experimenty ostávajú samostatné.
|
||||
|
||||
## Strict a zmrazenie
|
||||
|
||||
Správne hodnoty patria tej istej osobe/práci a majú prepojené typované dôkazy. Overuje sa význam roku, názov a typ práce, relácie, kategória a autor toho istého dokumentu, zdrojové alternatívy a URL, presné množiny a počet, explicitné no-answer a neorezaný výsledok. Rozpoznaná hodnota z otázky sama nie je dôkazom. Schema3 overuje strojové vzory ciest, nie iba textový zoznam očakávaných trás.
|
||||
|
||||
Freeze vyžaduje kompletný DEV, nulové runtime chyby, platný zdrojový audit a odtlačky kódu, otázok, pôvodných súborov, JSON vstupov, grafu a parametrov. V4 explicitne deklaruje prekryv 72 profilov a nulový prekryv logických skupín. Starší režim profilovo oddeleného holdoutu zostáva zachovaný.
|
||||
|
||||
Oracle aj evaluator sú pravidlové. Priama kontrola pôvodných riadkov a stratifikovaná kontrola anotácií nie sú náhradou nezávislej ľudskej anotácie celého datasetu.
|
||||
|
||||
## Vývoj ďalšej verzie
|
||||
|
||||
Generátory historických v1–v4 neregeneruj na pôvodných miestach. Nové dáta, manifesty a merania potrebujú nové cesty/verziu. `benchmark_v4 --extra-exposed` vie vyradiť ďalšie odhalené skupiny, ale množstvo nových zdrojových prípadov je konečné a kvóty sa nesmú meniť podľa úspechu vyhľadávania.
|
||||
|
||||
```bash
|
||||
python -m tools.graphrag.evaluation.evaluate_graphrag \
|
||||
--split dev --audit tools/graphrag/evaluation/results/v4_preparation/source_audit.json \
|
||||
--output-dir /tmp/graphrag-next
|
||||
python -m tools.graphrag.evaluation.freeze_graphrag \
|
||||
--dev-results /tmp/graphrag-next/graphrag_dev.json \
|
||||
--audit tools/graphrag/evaluation/results/v4_preparation/source_audit.json \
|
||||
--output /tmp/graphrag-next/frozen.json
|
||||
```
|
||||
|
||||
Záverečná kompletná automatizovaná sada: **448 passed, 4 skipped** (vrátane nových testov generovania). Neo4j integračné testy používajú izolovaný scope a rollback. Výsledky obsahujú úplné JSON/CSV a odtlačky pre reprodukciu.
|
||||
@ -9,7 +9,7 @@ import subprocess
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from tools.publication import DEFAULT_PUBLISHED_ONLY, PUBLICATION_POLICY_VERSION
|
||||
from tools.retrieval.publication import DEFAULT_PUBLISHED_ONLY, PUBLICATION_POLICY_VERSION
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[3]
|
||||
|
||||
@ -33,14 +33,19 @@ def source_corpus_fingerprint(root: Path = ROOT) -> dict[str, Any]:
|
||||
|
||||
def content_fingerprints(questions: Path, root: Path = ROOT) -> dict[str, Any]:
|
||||
files = sorted((root / 'tools/graphrag').rglob('*.py'))
|
||||
# Shared production packages moved out of tools/. Bind their complete code
|
||||
# too, so a freeze cannot silently overlook new runtime/delivery helpers.
|
||||
for package in ('answers', 'retrieval', 'runtime', 'sync'):
|
||||
files.extend(sorted((root / 'tools' / package).rglob('*.py')))
|
||||
# requirements.txt and tools/ are present both in the checkout and image.
|
||||
files.extend(root / name for name in [
|
||||
'requirements.txt', 'tools/publication.py', 'tools/retrieval_contract.py',
|
||||
'tools/index_state.py', 'tools/rag/common.py', 'tools/sync_indexes.py',
|
||||
'requirements.txt', 'tools/retrieval/publication.py', 'tools/retrieval/retrieval_contract.py',
|
||||
'tools/sync/index_state.py', 'tools/rag/common.py', 'tools/sync/sync_indexes.py',
|
||||
'tools/rag/rag_utils.py', 'tools/answer_evaluation/context_policy.py',
|
||||
'tools/answer_evaluation/checked_generation.py', 'tools/answer_evaluation/answer_format.py',
|
||||
'tools/answer_evaluation/render_answer.py',
|
||||
'tools/rag/evaluation/rag_metrics.py', 'tools/rag/evaluation/rag_runner.py'])
|
||||
files = sorted(set(files))
|
||||
return {
|
||||
'implementation': {str(path.relative_to(root)): sha256_file(path) for path in files},
|
||||
'dataset_sha256': sha256_file(questions),
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
# Historický GraphRAG DEV beh
|
||||
|
||||
Pôvodný celý DEV beh pred dokončením evaluácie v1. Zachovaný pre históriu vývoja a analýzu chýb. Nemá obsahové odtlačky ani totožné anotačné pravidlá s novšími verziami, preto jeho skóre nemožno bez ďalšieho vydávať za priamo porovnateľný finálny benchmark. Autoritatívne merania sú v adresároch `final_*`.
|
||||
@ -1,68 +0,0 @@
|
||||
# GraphRAG: finálna evaluácia v1 — 24. 10. 2026
|
||||
|
||||
Vyhľadávanie bolo ladené na DEV, potom zmrazené pomocou `../../frozen_v1.json` a až následne vyhodnotené na celom TESTe. Po finálnom TESTe sa implementácia, evaluator, benchmark ani audit nemenili.
|
||||
|
||||
## Výsledky
|
||||
|
||||
| Beh | Strict | Úspešnosť | Runtime chyby | Priemer | Medián | p95 |
|
||||
|---|---:|---:|---:|---:|---:|---:|
|
||||
| Pôvodné vyhľadávanie, aktuálny evaluator (DEV) | 106/286 | 37.06 % | 0 | 29.99 ms | 28.12 ms | 41.82 ms |
|
||||
| Finálny DEV | 209/286 | 73.08 % | 0 | 32.79 ms | 32.21 ms | 41.83 ms |
|
||||
| Finálny TEST | 152/214 | 71.03 % | 0 | 29.58 ms | 29.33 ms | 33.78 ms |
|
||||
|
||||
Pôvodné vyhľadávanie pochádza z commitu `9f3483d`; jeho odtlačok je v `baseline_dev.json`. Porovnanie používa rovnaký benchmark, graf, parametre a aktuálny sprísnený evaluator. Historický baseline 127/286 = 44,41 % používal starší evaluator; priamo porovnateľný baseline je 106/286 = 37,06 %.
|
||||
|
||||
Latencie merajú samotné grafové vyhľadávanie. Neobsahujú tvorbu odpovede LLM, volanie OpenWebUI ani úvodný odtlačok celého grafu. Nie sú porovnateľné s približne 19 sekundami celého klasického RAG toku.
|
||||
|
||||
## Nesúlady benchmarku so zdrojmi
|
||||
|
||||
Pred TESTom vznikol statický audit všetkých 500 otázok priamo proti vstupným dokumentom, tagom a deterministickému grafovému payloadu. Audit nepoužíva výstup vyhľadávania. Pôvodný benchmark zostal od začiatku tejto úpravy nezmenený bajt po bajte. Primárne skóre vyššie zahŕňa aj všetky problémové anotácie.
|
||||
|
||||
| Zistený nesúlad | DEV | TEST |
|
||||
|---|---:|---:|
|
||||
| Očakávané kľúčové slovo nie je vo frontmatter katalógu | 66 | 46 |
|
||||
| Tag existuje, ale nie je prepojený s očakávanou osobou | 5 | 11 |
|
||||
| Presná očakávaná množina kategórií nezodpovedá aj poddokumentom | 6 | 3 |
|
||||
| Spolu otázok so zisteným nesúladom | 77 | 60 |
|
||||
|
||||
Textová zmienka o OpenWebUI alebo Elasticsearch v tele stránky sa podľa súčasného modelu nestáva uzlom `Keyword`. Rovnako sa automaticky nestotožňujú rôzne tagy alebo preklady. Vymyslenie grafového faktu na splnenie takýchto očakávaní by bolo nesprávne.
|
||||
|
||||
Doplnkové výsledky pre podmnožinu bez zistených zdrojových nesúladov:
|
||||
|
||||
| Sada | Strict | Úspešnosť |
|
||||
|---|---:|---:|
|
||||
| DEV | 209/209 | 100.00 % |
|
||||
| TEST | 152/154 | 98.70 % |
|
||||
|
||||
Toto je doplnková analýza, nie náhrada primárneho skóre ani dôkaz bezchybnosti všetkých ostatných anotácií. Pravidlá auditu a zoznam otázok boli uložené pred finálnym TESTom a overujú sa odtlačkom vo freeze manifeste.
|
||||
|
||||
## Kategórie
|
||||
|
||||
| Kategória | DEV strict | TEST strict |
|
||||
|---|---:|---:|
|
||||
| `candidate_set_aggregation` | 9/9 | 7/7 |
|
||||
| `conjunctive_disambiguation` | 2/11 | 1/9 |
|
||||
| `document_author_category_multi_hop` | 35/35 | 25/25 |
|
||||
| `person_keyword_title` | 4/42 | 3/38 |
|
||||
| `person_multiple_categories` | 15/21 | 6/9 |
|
||||
| `person_title_year` | 44/44 | 36/36 |
|
||||
| `same_academic_year_pair` | 56/56 | 42/44 |
|
||||
| `same_start_year_pair` | 28/28 | 32/32 |
|
||||
| `shared_keyword_pair` | 16/40 | 0/14 |
|
||||
|
||||
Kompletné metriky hodnôt, typovaných entít, relácií, vlastností, množín, zdrojov, kategórií, obtiažností a latencií obsahujú JSON a CSV súbory. Document recall a source recall dosiahli v oboch finálnych behoch 1,0; recall kontextových zdrojov sám osebe neznamená správnu odpoveď.
|
||||
|
||||
## Overenie a zostávajúce limity
|
||||
|
||||
- Celá testovacia sada: **359 passed, 4 skipped**. Desiatich nových Neo4j integračných prípadov sa týka skutočné vykonanie Cypher dotazov v oddelených transakciách s rollbackom.
|
||||
- Opravené sú skloňovanie názvu, otázky na spoločný rok bez číselného roku v otázke, spojenie názvu/tagu a roku/tagu pri tej istej osobe, autor/kategória pri tom istom dokumente a URL zdrojov vrátane zamietnutých kandidátov.
|
||||
- Počítanie sa vykonáva pred prezentačným limitom. Orezaný výsledok nemôže prejsť strict hodnotením.
|
||||
- Evaluator neuznáva názov ani inú hodnotu iba preto, že sa rozpoznala z otázky. Entity sa hodnotia podľa typu a pri agregácii sa kontroluje aj počet.
|
||||
- Vo finálnom TESTe ostali **g0065 a g0129**, dve formulácie otázky na spoločný rok pri rovnakej dvojici osôb. Podklady obsahujú navyše dokument Martina Jančuru; pravdepodobnou príčinou je príliš široké fuzzy rozpoznávanie mena. Detaily sú v `holdout_failures.json`. Po tomto zistení sa kód neupravoval.
|
||||
- V budúcej verzii treba túto nejednoznačnosť riešiť na samostatných vývojových prípadoch a pripraviť nový nezávislý holdout. Aktuálny TEST už nemá slúžiť ako nový nedotknutý test pre takto ladenú verziu.
|
||||
- `expected_paths` sú opisné anotácie. Strict vyhodnocuje typované fakty, relácie a vlastnosti, nie doslovnú zhodu týchto textových reťazcov s cestou.
|
||||
- Meria sa grafová retrieval vrstva, nie kvalita odpovede LLM. Otázky zdieľajú wiki a formulárové šablóny medzi DEV/TEST; výsledky nemožno vydávať za všeobecnú presnosť na ľubovoľných otázkach.
|
||||
|
||||
## Rozhodnutie o stave
|
||||
|
||||
Vývojový beh 3.3 je uzavretý pre v1, verzia 3.4 je obsahovo zmrazená, TEST 3.5 prebehol a metriky 3.6 sú uložené. Audit 3.1 odhalil 137 zdrojových nesúladov, ktoré sú explicitne zaznamenané. Finálny benchmark potrebuje novú zdrojovo overenú verziu pred formálnym porovnaním RAG a GraphRAG. Táto evaluácia ich nezakrýva úpravou otázok po TESTe.
|
||||
@ -1,11 +0,0 @@
|
||||
# GraphRAG v2 — zmrazené meranie 25. 10. 2026
|
||||
|
||||
- DEV: **509/509 (100 %)**, TEST: **67/80 (83,75 %)**, runtime chyby: 0.
|
||||
- Celá testovacia sada: 426 passed, 4 skipped; vrátane 10 skutočných Neo4j rollback testov.
|
||||
- Pôvodných 500 otázok je odteraz iba DEV/regresia. 128 chybných predpokladov o tagoch má overenú no-answer anotáciu a 9 otázok má opravené úplné kategórie.
|
||||
- Nový TEST má 80 prípadov z 24 profilov bez prekryvu s DEV. Tagy, autori, korpus a rodiny šablón sú spoločné; nejde o dôkaz všeobecnej presnosti.
|
||||
- Všetky zdroje boli anotované nezávislým parserom pôvodného Markdownu. Fakty sa hodnotia ako prepojené typované dôkazy vrátane správneho významu roku a platných alternatív zdrojov.
|
||||
- 13 TEST zlyhaní je zachovaných v `holdout_failures.json`: formulácia tagu pred osobami a meno s číslicou. Verzia v2 sa po meraní neupravuje. Ak sa podľa zistení ďalej vyvíja, tieto otázky prechádzajú do DEV a nová verzia potrebuje nový holdout.
|
||||
- Latencia je iba čas grafového vyhľadávania, bez LLM/OpenWebUI. Podrobné metriky a odtlačky obsahujú JSON/CSV a `../../frozen_v2.json`.
|
||||
|
||||
Historické v1 (152/214) a v2 (67/80) majú rozdielne datasety/evaluatory; samotný rozdiel percent nemožno vydávať za kontrolovaný experiment zlepšenia.
|
||||
@ -1,64 +0,0 @@
|
||||
# GraphRAG: finálna opravená verzia v3 — 25. 10. 2026
|
||||
|
||||
Upravovalo sa grafové vyhľadávanie a jeho evaluácia. Klasický RAG backend, SQLite index a jeho zmrazené odpovede zostali zachované.
|
||||
|
||||
## Výsledky a ich význam
|
||||
|
||||
| Meranie | Strict | Úspešnosť | Runtime chyby | Priemer | Medián | p95 |
|
||||
|---|---:|---:|---:|---:|---:|---:|
|
||||
| DEV/regresia v3 | 589/589 | 100.00 % | 0 | 41.53 ms | 40.42 ms | 56.27 ms |
|
||||
| Doplnkový nový TEST v3 | 13/13 | 100.00 % | 0 | 54.83 ms | 43.19 ms | 109.37 ms |
|
||||
| Širší nezávislý TEST v2 pred finálnymi opravami | 67/80 | 83.75 % | 0 | 46.29 ms | 37.56 ms | 54.18 ms |
|
||||
|
||||
**13/13 nie je dôkaz 100 % správnosti celého programu.** Posledný holdout používa len dva zvyšné doteraz nepoužité profily. Obsahuje kategórie, autora dokumentu, začiatok štúdia, nulový počet a negatívne prípady. Nemá reprezentatívne pokrytie všetkých deviatich kladných reasoning kategórií. Najširšie nezávislé meranie v tejto iterácii je stále zaznamenané v2 67/80; po zistení chýb sa tieto otázky stali DEV/regresiou.
|
||||
|
||||
Všetky pôvodné prípady ostali zachované: DEV v3 obsahuje celý súbor 589 už vystavených otázok z v2 vrátane negatívnych otázok a nulového počtu. Nedochádza k vynechávaniu neúspešných prípadov. Starý TEST sa po oprave nevydáva za nový nezávislý TEST. Latencie merajú samotné grafové vyhľadávanie, bez LLM a OpenWebUI.
|
||||
|
||||
## Opravy benchmarku a referenčných údajov
|
||||
|
||||
- Pôvodný súbor 500 otázok a výsledky v1 zostali nezmenené; pôvodný v1 je reprodukovateľný z tagu `classic-rag-e5-small-frozen` pre RAG a `graphrag-v1-frozen` pre grafovú verziu.
|
||||
- 128 otázok malo nepodložený predpoklad o doslovnom frontmatter tagu. Ich opravená anotácia vyžaduje explicitné `no_answer`, dôvod a neprítomnosť kladného vymysleného faktu. Audit sám nepripočítava úspech; hodnotí sa skutočný výsledok vyhľadávania.
|
||||
- 9 otázok má opravenú presnú množinu kategórií vrátane poddokumentov.
|
||||
- Oracle číta pôvodné Markdown súbory, YAML metadata, akademické nadpisy a označené názvy. Nepoužíva GraphRAG builder ani výsledky retrievalu ako zdroj odpovedí. Proveniencia obsahuje cesty, SHA-256, zdrojové riadky a základ určenia roku.
|
||||
- Pri v2 sa odhalila ďalšia chyba anotácie: názov pod `Bakalársky projekt 2020` sa nesmie premeniť na názov záverečnej práce 2021 len podľa kategórie `bp2021`. Opravené je rozlíšenie projektu a práce v oboch nezávislých parseroch. Záznam všetkých 24 zmien/rozšírení väzieb, vrátane štyroch nových opráv kladného predpokladu na záporný, je v `../v3_preparation/source_adjudications.json`.
|
||||
- Zdrojové validátory hlásia 0 zostávajúcich nesúladov. Ide o pravidlovú kontrolu s dohľadateľným zdrojom, nie záruku bezchybnej ľudskej anotácie celého korpusu.
|
||||
|
||||
## Vyhľadávanie a evaluator
|
||||
|
||||
Celé mená sa porovnávajú v súvislom poradí s kontrolovaným skloňovaním. Presná zhoda má prednosť; neznáme celé aj jednoslovné meno alebo neznámy kandidát nezruší obmedzenie na osoby. Rovnomenné profily vedú k `ambiguous`. Rola autora dokumentu sa rozlišuje od opisovaného študenta.
|
||||
|
||||
Tag sa číta ako celý požadovaný výraz vrátane formulácie pred menami. Neznámy viacslovný tag sa neskracuje na známy prefix. Výsledky majú stav, dôvod, kontrolované entity a dôkazy zamietnutia.
|
||||
|
||||
Evaluator skladá typovaný graf dôkazov z konkrétnych ciest a kontraktov pripravených Cypher dotazov. Kontroluje osobu, konkrétnu prácu, hodnotu jej roku/názvu, správnu reláciu, kategóriu a autora toho istého dokumentu, presnú množinu a počet. Odmieta zmiešanie rôznych osôb/prác a protichodných vlastností rovnakého uzla. Začiatok štúdia sa neráta ako rok práce. Štruktúrované vzory ciest sú skutočne overované. Alternatívne dokumenty dokazujúce rovnaký fakt sa hodnotia ako alternatívy a kontroluje sa URL konkrétneho dôkazu.
|
||||
|
||||
Builder navyše rozpoznáva `Vedecký projekt` a `Bakalársky projekt`; akademický rozsah `2023/24` sa rozlišuje podľa jeho rokov a podporujúcej kategórie. Graf bol pred obnovou zálohovaný.
|
||||
|
||||
## Testy a zmrazenie
|
||||
|
||||
Celý projekt: **430 passed, 4 skipped**, vrátane desiatich skutočných Neo4j prípadov v izolovaných rollback transakciách. Nové testy cielia aj úmyselne nesprávne výsledky a záporné prípady, nie iba kladné ukážky.
|
||||
|
||||
Pred TESTom v3 bol celý DEV úspešný a vznikol `../../frozen_v3.json`. Manifest overuje kód, dataset, pôvodný Markdown, JSON vstupy, graf, audit a parametre. Kontroluje nulový prekryv profilov DEV/TEST. Existujúce manifesty a finálne výsledky sú chránené pred prepísaním. Po TESTe v3 sa Python kód ani dataset nemenili.
|
||||
|
||||
| Kategória | DEV v3 strict | TEST v3 strict |
|
||||
|---|---:|---:|
|
||||
| `candidate_set_aggregation` | 25/25 | 1/1 |
|
||||
| `conjunctive_disambiguation` | 28/28 | nepokryté |
|
||||
| `document_author_category_multi_hop` | 68/68 | 2/2 |
|
||||
| `negative_lookup` | 16/16 | 6/6 |
|
||||
| `person_keyword_title` | 88/88 | nepokryté |
|
||||
| `person_multiple_categories` | 38/38 | 2/2 |
|
||||
| `person_title_year` | 88/88 | nepokryté |
|
||||
| `same_academic_year_pair` | 108/108 | nepokryté |
|
||||
| `same_start_year_pair` | 68/68 | nepokryté |
|
||||
| `shared_keyword_pair` | 62/62 | nepokryté |
|
||||
| `person_start_year` | samostatné jednotkové pokrytie | 2/2 |
|
||||
|
||||
## Zostávajúce obmedzenia
|
||||
|
||||
- Na silný všeobecný odhad presnosti treba ďalší nezávislý súbor otázok/dát od človeka alebo nový korpus. Opakované dolaďovanie na už odhalenom TESTe by z neho urobilo DEV.
|
||||
- Riešenie používa pravidlá pre slovenské formulácie a kontrolované skloňovanie; nepokrýva ľubovoľné preklepy a všetky možné otázky.
|
||||
- Pri nejednoznačných rovnomenných profiloch sa bezpečne odmieta výber. Všeobecné počítanie iných domén a univerzálny prienik pre ľubovoľný počet ľudí nie sú týmto benchmarkom garantované.
|
||||
- Ide o retrieval vrstvu. GraphRAG ešte nie je kompletný OpenWebUI agent a toto meranie nehodnotí kvalitu odpovedí LLM.
|
||||
- V1, v2 a v3 majú rôzne benchmarky a prísnosť evaluatora. Ich percentá nemožno bez kontrolovaného experimentu priamo odčítať ako zlepšenie modelu.
|
||||
|
||||
Zadané chyby bodu 3 sú opravené a meranie aktuálnej verzie uzavreté s uvedenými limitmi. Nasleduje integrácia nástroja a neskôr reprezentatívne porovnanie RAG/GraphRAG.
|
||||
@ -1,123 +0,0 @@
|
||||
# GraphRAG v4 — širšia evaluácia, 25. 10. 2026
|
||||
|
||||
Finálne generované odpovede cez OpenWebUI API: **281/300 = 93,67 %**, cieľ ≥92 % splnený. Grafové vyhľadávanie splnilo očakávania v **320/320** otázkach; doplnková kontrola všetkých kontextových faktov má **319/320 (99,69 %)**. DEV/regresia grafu **722/722**. Ide o správnosť podľa deklarovaných kritérií benchmarku; nie o univerzálnu pravdivosť ľubovoľnej odpovede.
|
||||
|
||||
## Korpus a protokol
|
||||
|
||||
Zdroj: používateľom zadaný repozitár `jp170na/zpwiki`, predvolená vetva `master`, commit `3e892a1d49e9bce118cd03478ce15e01c2bebb4e`. Lokálny checkout bol overený cez `git ls-remote --symref origin HEAD`. Korpus má 114 README dokumentov a 72 osôb. Indexové JSON a klasický RAG sa nemenili.
|
||||
|
||||
Nový TEST má **320 nových otázok / logických skupín**, 288 kladných a 32 záporných prípadov. Samostatný DEV má 602 historicky odhalených otázok a 120 nových prípadov. Všetky otázky boli pripravené z pôvodného Markdownu bez načítania výstupov vyhľadávania. Používajú sa formulácie otázok v niekoľkých variantoch. Výber je deterministický, seed 20261025, kvóty sú určené v generátore.
|
||||
|
||||
Všetkých 72 profilov už bolo odhalených v predchádzajúcich verziách. Preto je v4 **holdout nových otázok a kombinácií faktov nad známym korpusom**, nie experiment s novými osobami. DEV/TEST majú nulový prekryv normalizovaných logických skupín a otázok; profily, slovník a rodiny šablón sa prekrývajú. Freeze tento rozdiel výslovne uvádza a kontroluje. Starší režim profilovo oddeleného holdoutu ostáva prísny.
|
||||
|
||||
## Zdrojové očakávania
|
||||
|
||||
- Pôvodných 137 nesúladov ostáva zdokumentovaných v historickom audite a opravných záznamoch v2/v3. V4 nevydáva chybný predpoklad otázky za nájdený pozitívny fakt.
|
||||
- Pred prvým TESTom v4 prebehla ďalšia kontrola názvov: pokyny, organizačné poznámky, odkazy na repozitár a súvisiace práce sa nesmú stať názvom. Výslovný názov má prednosť pred všeobecnou témou. Názov môže byť v Markdown odkaze. Projekt sa rozlišuje od záverečnej práce.
|
||||
- Pri školskom roku sa použije explicitný nadpis, rozsah sa rozbalí. Kategória môže vybrať rok v rámci rozsahu, ale nesmie ho prepísať na nesúvisiaci rok; `Vedecký projekt 2022/23` s `vp2021` má rok 2023.
|
||||
- V4 eviduje 45 zmien alebo rozšírení historických väzieb oproti v3. Originálne súbory v1–v3 sa neprepisujú. `question_lineage.json` mapuje pôvodné ID na v4 regresiu.
|
||||
- Audit má **0 zdrojových nesúladov**. Priama kontrola 616 zdrojových dôkazových záznamov TESTu overila SHA, hodnoty frontmatter a riadky názvov. Navyše sa kontrolovali názvy a surové ukážky v stratifikovanej 20-otázkovej vzorke. Záznam je v `../v4_preparation/source_review.json`.
|
||||
- Oracle číta pôvodný Markdown oddelene od grafového buildera; zostáva pravidlový. Toto nie je úplná nezávislá ľudská anotácia všetkých 320 otázok. Rok práce je rok doložený nadpisom/metadátami akademického záznamu, nie automaticky rok obhajoby či vydania.
|
||||
|
||||
## Čo sa skutočne vyhodnocuje
|
||||
|
||||
Strict kontroluje hodnoty pri správnej osobe a konkrétnej práci, rozdiel year/start_year, názvy a typy, prepojené grafové dôkazy, kategóriu a autora toho istého dokumentu, skutočné zdrojové URL, presné množiny, počty a nenájdené prípady. Neúplný alebo orezaný výsledok neuspeje. Výstupy aj s prípadnými chybami zostávajú v menovateli.
|
||||
|
||||
Opravy v4 cielili DEV a pôvodné dokumenty. DEV pred kontrolou zdrojov mal 716/722, priebežný DEV po rozšírení anotácií 709/722, konečný DEV 722/722. Až potom vznikol `../../frozen_v4.json` a spustil sa jediný finálny grafový TEST. Po jeho odhalení sa grafový Python kód ani benchmark nemenili.
|
||||
|
||||
| Meranie | Správne | Úspešnosť | Runtime chyby | Priemer | Medián | p95 |
|
||||
|---|---:|---:|---:|---:|---:|---:|
|
||||
| Graf DEV v4 | 722/722 | 100,00 % | 0 | 42,12 ms | 40,65 ms | 54,14 ms |
|
||||
| Graf TEST v4 | 320/320 | 100,00 % | 0 | 43,01 ms | 42,94 ms | 50,86 ms |
|
||||
|
||||
| Kategória grafového TESTu | Správne | Úspešnosť |
|
||||
|---|---:|---:|
|
||||
| Spoločné kľúčové slovo | 40/40 | 100 % |
|
||||
| Spoločné roky práce | 40/40 | 100 % |
|
||||
| Spoločný začiatok štúdia | 32/32 | 100 % |
|
||||
| Názov a rok práce | 24/24 | 100 % |
|
||||
| Názov a kľúčové slovo | 32/32 | 100 % |
|
||||
| Osoba, kategória a autor dokumentu | 24/24 | 100 % |
|
||||
| Úplná množina kategórií | 24/24 | 100 % |
|
||||
| Výber a počet kandidátov | 32/32 | 100 % |
|
||||
| Tag a rok pri tej istej osobe | 40/40 | 100 % |
|
||||
| Nenájdené údaje/osoby | 32/32 | 100 % |
|
||||
|
||||
Graf má 447 uzlov a 879 vzťahov. Pred zmenou bol uložený snapshot aj archív projektu v `/tmp/zp-agent-graphrag-v4-backup-20261025T013116Z/`. Záverečná kompletná automatizovaná sada: **448 passed, 4 skipped** vrátane Neo4j integračných rollback testov a nových testov LLM hodnotenia.
|
||||
|
||||
## Historické merania ostávajú zachované
|
||||
|
||||
| Verzia | TEST | Význam |
|
||||
|---|---:|---|
|
||||
| v1 | 152/214 (71,03 %) | Pôvodný benchmark s neskôr zistenými nesúladmi |
|
||||
| v2 | 67/80 (83,75 %) | Profilovo oddelený širší TEST pred poslednými opravami |
|
||||
| v3 | 13/13 (100 %) | Malý doplnkový TEST na posledných dvoch nových profiloch |
|
||||
| v4 | 320/320 (100 %) | Nové otázky/logické skupiny nad všetkými známymi profilmi |
|
||||
|
||||
Verzie majú odlišné otázky, anotácie a pravidlá; percentá nie sú kontrolovaným priamym porovnaním rovnakého testu. Historické klasické RAG DEV/TEST, retrieval baseline a podklady pre diplomovku zostávajú zachované.
|
||||
|
||||
## Reprodukcia grafového merania
|
||||
|
||||
```bash
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
python -m tools.graphrag.evaluation.evaluate_graphrag \
|
||||
--split test \
|
||||
--audit tools/graphrag/evaluation/results/v4_preparation/source_audit.json \
|
||||
--freeze-manifest tools/graphrag/evaluation/frozen_v4.json \
|
||||
--output-dir /tmp/graphrag-v4-reproduction
|
||||
```
|
||||
|
||||
Treba zodpovedajúci kód, pôvodnú wiki, JSON vstupy a graf podľa manifestu. Pre opakovanie sa vyžaduje nový adresár. Reprodukcia nie je ďalší nezávislý TEST. Ak sa podľa v4 TESTu bude ďalej ladiť, jeho otázky sa stanú DEV a treba nový testovací protokol.
|
||||
|
||||
## Finálne odpovede modelu cez OpenWebUI
|
||||
|
||||
Na používateľovu otázku o spôsobe testovania sa interné meranie doplnilo skutočným externým generovaním. Prvých 20 otázok sa najprv použilo na diagnostiku (pôvodné hodnotenie 16/20). Potom zostali výhradne DEV. Samostatné opätovné hodnotenie pod rovnakými finálnymi kritériami má 15/20; pôvodný súbor sa neprepisuje. Spresnil sa význam polí a odstránila sa zámena profilových/úložiskových metadát s akademickými faktami. Nepovinné null sa pri hodnotení nepovažuje za pozitívne tvrdenie. Na týchto istých DEV otázkach nový prompt dosiahol 19/20.
|
||||
|
||||
Zostávajúcich **300 otázok** tvorí nový TEST generovania. Ich grafové výsledky sa už predtým merali, ale odpovede tohto modelu na tieto otázky neboli pred ladením generovania pozorované. Pred prvou TEST odpoveďou sa uložili presné ID, model, temperature=0, tri súbežné požiadavky, SHA promptu/adaptéra/HTTP klienta a odkaz na zmrazený graf. Počas ani po tomto TESTe sa prompt či hodnotenie neladili. Vyhodnotilo sa všetkých 300 vrátane zlyhaní; prvý finálny beh splnil cieľ.
|
||||
|
||||
| Meranie generovania | Správne | Strict úspešnosť | Chyba spracovania |
|
||||
|---|---:|---:|---:|
|
||||
| DEV, 20 už odhalených otázok | 19/20 | 95,00 % | 0 |
|
||||
| TEST, 300 nových LLM výstupov | **281/300** | **93,67 %** | 7 |
|
||||
|
||||
Model ID je `model120-fast`, server vrátil `Qwen3.5-122B-A10B-Q4_K_M`. Priemerná latencia externého požiadavku bola 7,62 s, medián 7,58 s, p95 11,52 s pri troch súbežných požiadavkách. JSON aj CSV obsahujú všetky výsledky; surové odpovede, tokeny a kontrolné príznaky zostali uložené. `../answers_v4_test_2026-10-25/frozen_answers.json` deklaruje protokol a `answers_test.json` je úplné meranie.
|
||||
|
||||
| Kategória LLM TESTu | Správne | Strict úspešnosť |
|
||||
|---|---:|---:|
|
||||
| Spoločné kľúčové slovo | 38/38 | 100.00 % |
|
||||
| Spoločné roky práce | 37/38 | 97.37 % |
|
||||
| Spoločný začiatok štúdia | 29/30 | 96.67 % |
|
||||
| Názov a rok práce | 21/22 | 95.45 % |
|
||||
| Názov a kľúčové slovo | 21/30 | 70.00 % |
|
||||
| Osoba, kategória a autor dokumentu | 20/22 | 90.91 % |
|
||||
| Úplná množina kategórií | 21/22 | 95.45 % |
|
||||
| Výber a počet kandidátov | 27/30 | 90.00 % |
|
||||
| Tag a rok pri tej istej osobe | 37/38 | 97.37 % |
|
||||
| Nenájdené údaje/osoby | 30/30 | 100.00 % |
|
||||
|
||||
Devätnásť zlyhaní sa výlučne rozdelilo takto: **7 neplatných JSON výstupov**, **6 chýbajúcich alebo rozdelených väzieb**, **3 chýbajúce povinné hodnoty v prirodzenom texte** a **3 nepodporené tvrdenia alebo zamenené osoby**. Všetky zostali v menovateli. Pri neplatnom JSON server odpovedal, nešlo o transportný výpadok. Časť vecne správnych odpovedí stratila strict bod pre formát alebo pre neúplný predpísaný výstup; výsledok preto nie je percentom výlučne faktických nepravdivých viet. Príklady sú v `../answers_v4_test_2026-10-25/failures.json`.
|
||||
|
||||
Najslabšia kategória je názov + tag (21/30). Napríklad tag z dcérskeho dokumentu patrí podľa benchmarku tej istej osobe, ale model niekedy požaduje neprávom ten istý dokument ako pri názve práce. Niekedy uvedie správny tag a názov v dvoch claims namiesto požadovanej spojenej väzby. Pri autorovi dokumentu sa v dvoch prípadoch správny autor v texte omylom stal aj person v štruktúrovanom tvrdení. Zaznamenané obmedzenia zostávajú predmetom ďalšieho vývoja; 93,67 % nie je zárukou bezchybného agenta.
|
||||
|
||||
## Doplnková kontrola všetkých vrátených grafových faktov
|
||||
|
||||
Po meraní sa navyše porovnali všetky normalizované grafové fakty použité v 320 kontextoch s pôvodným zdrojovým oracle, vrátane nadbytočných hodnôt. V **319/320 kontextoch (99,69 %)** boli všetky takto kontrolované fakty zdrojovo podporené. V `wide-080` splnenie požadovaných očakávaní prešlo, ale graf navyše vrátil pri Dominikovi Nagyovi rok 2021, ktorý oracle nepotvrdzuje. Tento nadbytočný údaj sa dostal aj do odpovede modelu a LLM hodnotenie ho správne odmietlo.
|
||||
|
||||
Preto **320/320 strict retrieval neznamená 100 % pravdivosť každej nadbytočnej grafovej hodnoty**. Pôvodný strict skóruje splnenie očakávaných otázok a dôkazov; doplnková kontrola odhaľuje aj túto zvyšnú odchýlku. Obe čísla sú uložené bez prepísania pôvodných výsledkov. Táto doplnková metrika je post-hoc audit, nie náhrada primárneho predregistrovaného výsledku ani ďalší TEST.
|
||||
|
||||
## Stav bodu 3 a praktické hranice
|
||||
|
||||
| Podbod | Stav v4 |
|
||||
|---|---|
|
||||
| 3.1 Audit a benchmark | Uzavretý pre deklarovaný korpus: 320 nových TEST skupín, 722 DEV, opravy a zdrojové dôkazy uložené. |
|
||||
| 3.2 Evaluator | Funkčný, typované a spojené dôkazy, roly/roky/počty/zdroje, negatívne regresie; LLM skóruje aj predpísaný formát a úplnosť. |
|
||||
| 3.3 DEV ladenie | Ukončené pred TEST: graf 722/722, generovanie 19/20. |
|
||||
| 3.4 Zmrazenie | Odtlačky grafu/kódu/dát/otázok/auditu a osobitne promptu/generovania uložené pred TESTom. |
|
||||
| 3.5 Finálny TEST | Celých 320 grafových otázok a 300 externých LLM odpovedí; všetky zlyhania započítané. |
|
||||
| 3.6 Metriky a vyhodnotenie | JSON, CSV, rozpis kategórií, chýb a historických experimentov uložený; cieľ ≥92 % splnený. |
|
||||
|
||||
Bod 3 je uzavretý **pre túto verziu a deklarovaný protokol**, s uvedenými chybami a hranicami. Neznamená to dokončenie celého projektu ani všeobecnú 100 % správnosť kódu. Nasleduje bod 4: samostatne inštalovateľné nástroje a natívna integrácia/hodnotenie hlavného OpenWebUI agenta.
|
||||
|
||||
Externý beh používa školské chat API s kontextom dodaným lokálnym skriptom; netestuje prehliadač ani autonómny výber nainštalovaného grafového nástroja. Hodnotí štruktúrované zdrojovo podporené tvrdenia, povinné textové hodnoty a citácie; nie ľubovoľnú sémantiku každej vety. Modelové váhy na externom serveri nie sú lokálne zmrazené a budúca reprodukcia nemusí vrátiť tie isté texty ani pri temperature=0. Uložené pôvodné odpovede umožňujú audit merania.
|
||||
@ -1,123 +0,0 @@
|
||||
# GraphRAG v5.1 — uzavretie bodu 3, 25. 10. 2026
|
||||
|
||||
Finálna regresia grafového vyhľadávania má **320/320**, vrátane zdrojovej
|
||||
kontroly všetkých vrátených typovaných faktov. DEV má **722/722**.
|
||||
Finálne generovanie dosiahlo **317/320 — 99.06 %**.
|
||||
Cieľ ≥92 % je **splnený**.
|
||||
|
||||
Ide o **historickú regresiu**, nie o nový nezávislý TEST. Žiadne nové otázky
|
||||
neboli potrebné pre kontrolu opráv; pôvodné otázky, gold ani výsledky v1–v4
|
||||
sa nemenili. Zistenia sa nesmú vydávať za univerzálnu pravdivosť odpovedí.
|
||||
|
||||
## Protokol a dátové rozdelenie
|
||||
|
||||
Používa sa pôvodný v4 benchmark: 722 DEV a 320 historických TEST otázok,
|
||||
v desiatich kategóriách, z toho 288 kladných a 32 záporných. Všetky otázky,
|
||||
osoby aj šablóny boli odhalené pred touto verziou. Zdrojom je raw Markdown
|
||||
repozitára `jp170na/zpwiki`, commit `3e892a1d49e9bce118cd03478ce15e01c2bebb4e`.
|
||||
|
||||
DEV generovania má 39 vopred deklarovaných otázok: pôvodných 20 DEV a 19
|
||||
historických zlyhaní modelu. Finálna regresia zahŕňa všetkých 320 otázok
|
||||
vrátane týchto 39; prekryv je uvedený v `frozen_answers.json`. Výber sa nemenil
|
||||
podľa úspechu aktuálneho finálneho behu a všetky zlyhania ostávajú v menovateli.
|
||||
|
||||
## Opravy a história iterácií
|
||||
|
||||
1. Organizačná príprava na projekt nevytvára akademický záznam ani rok práce.
|
||||
`wide-080` teraz vracia iba zdrojovo doložené spoločné akademické roky.
|
||||
2. Označenie návrhu zadania bez explicitného názvu nepreukazuje názov práce.
|
||||
Prvý prísny DEV mal 719/722 pre tri nadbytočné názvy pri Martinovi Šarišskom;
|
||||
nasledovala oprava parsera bez zmeny benchmarkových očakávaní.
|
||||
3. Prvá zmrazená v5 mala regresiu 319/320. Pri `wide-275` parser považoval vetu
|
||||
o odporúčanom čase konzultácie za názov projektu na hranici chunku.
|
||||
V5.1 také organizačné vety odmieta. V5 a jej 38/39 DEV generovania ostávajú
|
||||
archivované; overený patch umožňuje rekonštrukciu prvej iterácie.
|
||||
4. Evaluator kontroluje `complete=false` aj nezávisle od `truncated`, všetky
|
||||
vrátené typované fakty, vlastnosť–hodnotu pri správnej práci/osobe/dokumente,
|
||||
druh práce, metadata, URL aj jednotlivé a spoločné roky.
|
||||
5. Prompt vysvetľuje, že tag aj akademický názov môžu pochádzať z odlišných
|
||||
dokumentov tej istej osoby. Požadovaná spojená väzba sa uvádza v jednej claim.
|
||||
6. JSON sa kontroluje typovanou schémou. Jediný celý JSON blok sa môže vybrať
|
||||
z Markdown ohraničenia bez prepisovania hodnôt. Pri chybe formátu je povolený
|
||||
najviac jeden opravný požiadavok, s rovnakou otázkou a kontextom, bez gold.
|
||||
Vecná chyba hodnotenia nespúšťa opravný pokus.
|
||||
|
||||
Po finálnom zmrazení v5.1 sa kód, prompt ani gold podľa finálneho merania
|
||||
nemenili. Správa otvorene uvádza zostávajúce zlyhania.
|
||||
|
||||
## Výsledky
|
||||
|
||||
| Meranie | Správne | Strict úspešnosť |
|
||||
|---|---:|---:|
|
||||
| Graf DEV | 722/722 | 100,00 % |
|
||||
| Graf historická regresia | 320/320 | 100,00 % |
|
||||
| Zdrojovo podporené typované fakty, regresné výstupy | 320/320 | 100,00 % |
|
||||
| LLM DEV | 38/39 | 97.44 % |
|
||||
| LLM finálna regresia bez opravného požiadavku | 317/320 | 99.06 % |
|
||||
| LLM finálna regresia po deklarovanom spracovaní | 317/320 | 99.06 % |
|
||||
|
||||
Bez opravného požiadavku znamená po konzervatívnom parsovaní, prípadne po
|
||||
vybratí jediného úplného JSON bloku. Takto normalizovaných prvých výstupov:
|
||||
**0**. Opravný požiadavok na formát sa použil
|
||||
pri **0** otázkach. Finálne chyby spracovania alebo
|
||||
transportu: **0**. Pôvodné odpovede a všetky opravné pokusy sú uložené.
|
||||
|
||||
| Kategória LLM regresie | Správne | Strict úspešnosť |
|
||||
|---|---:|---:|
|
||||
| Výber a počet kandidátov | 32/32 | 100.00 % |
|
||||
| Tag a rok pri tej istej osobe | 40/40 | 100.00 % |
|
||||
| Osoba, kategória a autor dokumentu | 24/24 | 100.00 % |
|
||||
| Nenájdené údaje/osoby | 32/32 | 100.00 % |
|
||||
| Názov a kľúčové slovo | 30/32 | 93.75 % |
|
||||
| Úplná množina kategórií | 24/24 | 100.00 % |
|
||||
| Názov a rok práce | 23/24 | 95.83 % |
|
||||
| Spoločné roky práce | 40/40 | 100.00 % |
|
||||
| Spoločný začiatok štúdia | 32/32 | 100.00 % |
|
||||
| Spoločné kľúčové slovo | 40/40 | 100.00 % |
|
||||
|
||||
Zostávajúce zlyhania: `{'unsupported_claim': 1, 'answerability': 2}`. Úplné odpovede a kontrolné príznaky sú
|
||||
v `../answers_v5_1_regression_2026-10-25/answers_regression.json`, tabuľka v CSV
|
||||
a zoznam zlyhaní v `failures.json`. Prípadné vecne správne, ale neúplne
|
||||
štruktúrované odpovede strácajú strict bod; nejde o percento nepravdivých viet.
|
||||
|
||||
## Porovnanie s historickou v4
|
||||
|
||||
V4 grafový strict TEST mal 320/320, ale doplnková kontrola všetkých kontextových
|
||||
faktov 319/320. V5.1 má 320/320 aj v prísnejšej kontrole typovaných faktov.
|
||||
V4 generovanie malo 281/300 (93,67 %). Na rovnakých 300 otázkach má aktuálna
|
||||
historická regresia **297/300 — 99.00 %**.
|
||||
V5.1 navyše uvádza celkový 320-otázkový výsledok vyššie. Ide o opisné
|
||||
porovnanie: zmenili sa kritériá, prompt, spracovanie JSON aj rozdelenie DEV.
|
||||
|
||||
## Zmrazenie, reprodukcia a nasadenie
|
||||
|
||||
Grafový manifest je `../../frozen_v5_1.json`; označenie release je
|
||||
`graphrag-v5.1-frozen`. Zahŕňa odtlačky grafového kódu, spoločných modulov,
|
||||
requirements, publikačnej politiky, raw wiki, vstupných JSON a obsahu grafu.
|
||||
Manifest generovania viaže prompt, formátovanie, HTTP klienta, dokončený DEV
|
||||
a presný zoznam všetkých vyhodnotených ID. Pri meraní bol pracovný kód ešte
|
||||
pred release commitom; obsahové odtlačky určujú meraný kód, na checkout použite
|
||||
release tag, nie iba rodičovský `git_head` uložený v metadátach.
|
||||
|
||||
Aktuálny graf má 446 uzlov/877 vzťahov; vstupy majú 114 dokumentov/887 chunkov.
|
||||
Publikačná politika zahŕňa chýbajúce `published` a vylučuje explicitné false.
|
||||
Koordinovaná synchronizácia a oddelené readiness stavy zostávajú zachované.
|
||||
Automatizovaná sada: **525 passed, 4 skipped**. Overenie nasadeného obrazu
|
||||
a opravených prípadov je v `deployment_check.json`; presné verzie hostiteľského
|
||||
a kontajnerového prostredia aj identifikátor obrazu sú v `runtime_versions.json`.
|
||||
|
||||
Reprodukcia používa vždy nové adresáre. Existujúce finálne výsledky a manifesty
|
||||
sa neprepisujú. Presné príkazy sú v `docs/graphrag_v5_2026-10-25_worklog.md`.
|
||||
|
||||
## Obmedzenia a ďalší blok
|
||||
|
||||
Zdrojové overenie je nezávislé od grafového buildera, ale pravidlové; nenahrádza
|
||||
nezávislú ľudskú anotáciu všetkých otázok. Hodnotenie kontroluje typované tvrdenia,
|
||||
väzby, zdroje a povinné hodnoty v texte, nie sémantiku každej možnej vety.
|
||||
Výsledky nad známym korpusom a šablónami nemerajú všeobecnú generalizáciu.
|
||||
Modelové váhy riadi externý poskytovateľ; reprodukcia nemusí vrátiť rovnaké texty.
|
||||
|
||||
Tento release uzatvára dohodnuté podbody 3.1–3.6 pre uvedený regresný protokol.
|
||||
Nasledujú samostatne dohodnuté prierezové úpravy vrátane odovzdania všetkých
|
||||
spoločných polí kontraktu do LLM kontextu. Natívny výber a inštalácia nástrojov
|
||||
OpenWebUI hlavným agentom patrí do bodu 4 a tento experiment ho nehodnotí.
|
||||
@ -1,24 +0,0 @@
|
||||
# Prvá iterácia v5 — zachovaná diagnostická regresia
|
||||
|
||||
Tento adresár zachováva prvý zmrazený beh sprísneného hodnotenia. **Finálnou
|
||||
verziou je nasledujúca v5.1**, nie tento diagnostický výsledok. Všetky otázky
|
||||
boli historicky odhalené; nejde o nový nezávislý TEST.
|
||||
|
||||
- DEV: 722/722; všetky vrátené typované fakty prešli zdrojovou kontrolou.
|
||||
- Regresia pôvodného TESTu: 319/320; požadované fakty boli nájdené vo všetkých
|
||||
otázkach, ale `wide-275` navyše obsahoval nepravdivý názov projektu.
|
||||
- Konkrétny chybný názov bol „Odporúčaný čas konzultácie je piatok.“ Parser
|
||||
ho prevzal z organizačnej vety na hranici chunku. Nasledujúca verzia ho
|
||||
odmieta podľa všeobecného pravidla pre organizačné poznámky.
|
||||
- DEV generovania: 38/39, bez neplatných JSON odpovedí; `wide-145` mal správne
|
||||
fakty rozdelené do dvoch claims namiesto požadovanej spojenej väzby.
|
||||
|
||||
Výsledky sa neprepisujú. V5.1 je ďalšia vývojová iterácia nad rovnakou
|
||||
historickou regresiou. Po finálnom zmrazení v5.1 sa podľa jej výsledkov neladí.
|
||||
|
||||
Odtlačky prvej iterácie sú v `../../frozen_v5.json`. Na rekonštrukciu jej kódu
|
||||
z finálneho release checkoutu slúži
|
||||
[`candidate1_from_final.patch`](../v5_preparation/candidate1_from_final.patch).
|
||||
Rekonštruované súbory boli porovnané so SHA v pôvodnom manifeste; osobitne
|
||||
sa overil aj odtlačok pôvodného promptu pre LLM. Patch používajte v izolovanom
|
||||
checkoute; na reprodukciu grafu treba jeho zodpovedajúcu obnovu.
|
||||
@ -1,139 +0,0 @@
|
||||
# GraphRAG v6 — finálne kontroly bodu 3
|
||||
|
||||
Grafový DEV má **722/722** a historická regresia **320/320**, vrátane nezávislej
|
||||
zdrojovej kontroly všetkých vrátených typovaných faktov. Generované odpovede
|
||||
majú strict **316/320 — 98,75 %**. Cieľ ≥92 % je splnený.
|
||||
|
||||
Ide o **historickú regresiu**, nie nový nezávislý TEST. Všetky otázky sú známe;
|
||||
42 DEV otázok je zahrnutých aj vo finálnych 320. Nejde o všeobecnú pravdivosť
|
||||
agenta ani o meranie natívneho výberu OpenWebUI nástrojov.
|
||||
|
||||
## Výsledky
|
||||
|
||||
| Meranie | Výsledok | Úspešnosť |
|
||||
|---|---:|---:|
|
||||
| Graf DEV | 722/722 | 100,00 % |
|
||||
| Graf regresia | 320/320 | 100,00 % |
|
||||
| Zdrojovo podporené typované fakty v grafových regresných výstupoch | 320/320 | 100,00 % |
|
||||
| LLM DEV | 40/42 | 95,24 % |
|
||||
| LLM regresia — prvý pokus | 316/320 | 98,75 % |
|
||||
| LLM regresia — po deklarovaných kontrolách/opravách | 316/320 | 98,75 % |
|
||||
| Parseovateľné odpovede so zdrojovo podporenými štruktúrovanými tvrdeniami | 317/320 | 99,06 % |
|
||||
| Syntetické živé funkčné scenáre, mimo benchmarku | 9/9 | 100,00 % |
|
||||
| Automatizované testy vrátane všetkých živých testov | 565 | všetky prešli |
|
||||
|
||||
Tri otázky použili jediný povolený opravný požiadavok pre neplatný JSON;
|
||||
ani druhá odpoveď neprešla schémou. Opravný pokus vyvolaný porušením
|
||||
kontextu sa v tejto finálnej regresii nepoužil. Žiadne prvé JSON odpovede
|
||||
nepotrebovali odbaľovanie Markdown bloku. Všetky pokusy sú uložené.
|
||||
|
||||
| Kategória generovania | Strict správne | Úspešnosť |
|
||||
|---|---:|---:|
|
||||
| `candidate_set_aggregation` | 32/32 | 100.00 % |
|
||||
| `conjunctive_disambiguation` | 40/40 | 100.00 % |
|
||||
| `document_author_category_multi_hop` | 23/24 | 95.83 % |
|
||||
| `negative_lookup` | 32/32 | 100.00 % |
|
||||
| `person_keyword_title` | 31/32 | 96.88 % |
|
||||
| `person_multiple_categories` | 24/24 | 100.00 % |
|
||||
| `person_title_year` | 23/24 | 95.83 % |
|
||||
| `same_academic_year_pair` | 40/40 | 100.00 % |
|
||||
| `same_start_year_pair` | 31/32 | 96.88 % |
|
||||
| `shared_keyword_pair` | 40/40 | 100.00 % |
|
||||
|
||||
## Štyri strict zlyhania
|
||||
|
||||
- `wide-104`: text obsahuje skloňované „Martina NaN1“, protokol vyžaduje
|
||||
pôvodné „Martin NaN1“. Štruktúrované väzby a zdroje prešli; ide o
|
||||
konzervatívne odmietnutie povrchového tvaru mena. Neoznačujeme ho za
|
||||
fakticky nesprávny rok. Zmrazený primárny strict výsledok nemeníme.
|
||||
- `wide-119`, `wide-143`, `wide-176`: dva neplatné JSON/schema výstupy.
|
||||
`accepted_for_delivery=false`; odpovede neprešli na doručenie. Bez
|
||||
parseovateľného výstupu sa správnosť tvrdení nedá spoľahlivo vyhodnotiť.
|
||||
|
||||
Úplné zlyhania aj kontexty sú v
|
||||
[failures.json](../answers_v6_regression_2026-10-25/failures.json).
|
||||
Kód ani prompt grafového generovania sa podľa tohto finálneho výsledku neladil.
|
||||
|
||||
## Zdrojový benchmark
|
||||
|
||||
V6 zachováva 1 042 otázok a všetky ID, formulácie, kategórie a rozdelenie.
|
||||
Priame čítanie odhalilo generické linkové označenia „rešerš“, ktoré sa
|
||||
nesprávne vydávali za akademický názov. Opravených je 15 očakávaní; štyri
|
||||
regresné otázky `wide-116`, `wide-142`, `wide-145`, `wide-165` ostali v
|
||||
menovateli a očakávajú `no_answer`. Regresia má 284 pozitívnych a 36
|
||||
negatívnych očakávaní. Pôvodná v4 má 288/32 a zostáva nezmenená.
|
||||
Zdrojový audit všetkých 1 042 aktuálnych otázok má **0 nesúladov**.
|
||||
|
||||
Nezávislé priame čítanie vzorky 34 otázok vykonala **AI** oddelene od
|
||||
retrievera: 31 podporených, dve opravené a jedna podmienená ročníkom
|
||||
adresára. Pri `wide-112` Tomáš Kuchárik nemá explicitne uvedený začiatok
|
||||
štúdia; používa sa zavedený fallback `students/2016`. Ide o konvenciu,
|
||||
ktorú má človek potvrdiť pred výkladom ako administratívny fakt.
|
||||
[Hárok pre človeka](../v6_preparation/source_review.csv) je pripravený;
|
||||
**ľudské posúdenie neprebehlo**.
|
||||
|
||||
## Kontext, citácie a RAG
|
||||
|
||||
Kontext obsahuje úplnosť, orezanie, dôvody a verziu dát. Model má jasné pokyny
|
||||
pre neúplné výsledky a presný agregovaný počet s orezanými dôkazmi. Guard
|
||||
kontroluje URL v zozname aj v texte oproti zdrojom konkrétneho dotazu,
|
||||
štruktúrované hodnoty a spojenie názvu/roku s tagom cez tú istú osobu.
|
||||
Nepoužíva gold. Najviac jeden spoločný opravný požiadavok rieši formát
|
||||
alebo porušenie kontextu; oracle vstupuje až do následného hodnotenia.
|
||||
|
||||
Prepočet 56 archivovaných súborov skontroloval 6 044 uložených odpovedí,
|
||||
vrátane opakovaných experimentov. Našiel päť výskytov nepovolenej URL;
|
||||
nejde o 6 044 nezávislých otázok. Historický finálny RAG DEV ostáva
|
||||
624/629, finálny RAG TEST po prísnej kontrole URL má **506/519 — 97,50 %**,
|
||||
pôvodné skóre bolo 507/519. Súbory ani pôvodné metriky sa neprepisovali.
|
||||
Pri `q0892` navyše uvedená `http://skner.tukekemt.xyz` v Markdowne reálne
|
||||
existuje, ale nie je medzi archivovanými `source_url`; prísne odmietnutie
|
||||
odkazu nie je dôkazom nepravdivosti tej adresy. [Celý prepočet](../v6_preparation/citation_regrade.json).
|
||||
|
||||
Živá RAG vzorka piatich vopred zvolených otázok mala 5/5 správnych faktov
|
||||
aj citácií, ale 5/5 vynechaných upozornení. Vrstva `finalize_rag_answer()`
|
||||
preto vie pridať iba pravdivé upozornenie, bez zmeny faktov; uchová
|
||||
`model_answer`, pôvodné dôvody a príznak `display_notice_added`. Neobíde
|
||||
neznámu citáciu ani nepodložené tvrdenie o úplnom zozname. Prehratie tých
|
||||
istých uložených výstupov má 5/5 prijateľných odpovedí. **Nie je to nové
|
||||
meranie modelu ani odhad jeho presnosti z piatich prípadov.**
|
||||
|
||||
## História a porovnateľnosť
|
||||
|
||||
| Verzia | Grafové meranie | Generovanie |
|
||||
|---|---|---|
|
||||
| v4 | TEST 320/320; dodatočné faktové overenie 319/320 | nový LLM TEST 281/300 |
|
||||
| v5.1 | historická regresia 320/320 so všetkými typovanými faktami | regresia 317/320 |
|
||||
| v6 | historická regresia 320/320 so všetkými typovanými faktami | strict regresia 316/320 |
|
||||
|
||||
V6 opravuje 15 gold očakávaní a pridáva kontroly; rozdiel percent nie je
|
||||
kontrolovaný odhad zlepšenia/zhoršenia modelu. Všetky v1–v5.1 výstupy,
|
||||
klasický RAG, retrieval baseline aj vybrané experimenty ostávajú zachované.
|
||||
Prvý v6 DEV kandidát 41/42 je uložený; po oprave odmietnutého spojenia tagu
|
||||
a roku bol finálny DEV 40/42 s dvomi JSON chybami. Všetky iterácie sú
|
||||
priznané a žiadne chybné otázky sa nevyberali z finálneho merania.
|
||||
|
||||
## Nasadenie a ďalší bod
|
||||
|
||||
Nasadené Docker API, SQLite a Neo4j používajú spoločnú verziu
|
||||
`10b78a8e70744e2792ffe4cf11d45571`, wiki Git
|
||||
`3e892a1d49e9bce118cd03478ce15e01c2bebb4e`.
|
||||
Graf má 446 uzlov a 877 vzťahov; index 114 dokumentov a 887 chunkov.
|
||||
Predvolene je viditeľných 113 dokumentov: 16 bez published sa zahrnie,
|
||||
jediný explicitný published=false sa vylúči. Kontrola porovnáva
|
||||
normalizované Neo4j hodnoty s pôvodnými JSON metadátami.
|
||||
|
||||
[Overenie hostiteľa](deployment_check_host.json) a
|
||||
[overenie v Docker obraze](deployment_check_docker.json) kontrolujú odtlačky,
|
||||
pripravenosť RAG/Neo4j/GraphRAG, skutočné RAG API, grafové pozitívne aj
|
||||
negatívne dotazy a spoločnú verziu. `frozen_v6.json` fixuje graf,
|
||||
`frozen_answers.json` parametre generovania a `frozen_release_v6.json`
|
||||
všetky runtime moduly vrátane samostatnej RAG prezentačnej vrstvy.
|
||||
|
||||
Bod 4 pridá samostatne inštalovateľné OpenWebUI nástroje a hlavného agenta.
|
||||
Musí používať existujúce guardy a rešpektovať odmietnutie doručenia aj
|
||||
úplnosť zdrojov. Natívny výber a kombinovanie nástrojov sa v dnešnom
|
||||
320-otázkovom grafovom meraní netestovali. Pre nový nezávislý odhad treba
|
||||
nové vopred overené otázky; ľudská kontrola pripraveného hárka je odporúčaná.
|
||||
|
||||
[Príkazy a presné zmeny](../../../../../docs/graphrag_v6_2026-10-25_worklog.md).
|
||||
@ -1,147 +0,0 @@
|
||||
# GraphRAG v7 — uzavretie bodu 3, 26. 10. 2026
|
||||
|
||||
Nový query-group TEST dosiahol **80/80** pri grafovom vyhľadávaní aj pri
|
||||
finálnych odpovediach. Na prvý pokus modelu prešlo **77/80 — 96,25 %**;
|
||||
tri otázky prešli po jednom povolenom opravnom požiadavku. Cieľ ≥92 % je splnený
|
||||
už pri prvom pokuse aj pri finálnej pipeline. Celá sada má **591 úspešných
|
||||
testov, bez preskočenia**.
|
||||
|
||||
**Bod 3 je technicky uzavretý pre podporované typy dotazov a tento korpus.**
|
||||
Hodnotí sa modelový výber štruktúrovaných tvrdení, kontrola zdrojov a
|
||||
renderer; nie ľubovoľná voľná próza LLM ani natívne OpenWebUI smerovanie.
|
||||
100 % na 80 otázkach nie je zárukou všeobecnej pravdivosti.
|
||||
|
||||
## Výsledky
|
||||
|
||||
| Meranie | Správne | Úspešnosť |
|
||||
|---|---:|---:|
|
||||
| Graf DEV vrátane známych regresií | 1 046/1 046 | 100,00 % |
|
||||
| Graf nový query-group TEST | 80/80 | 100,00 % |
|
||||
| Graf historická podmnožina v DEV | 320/320 | 100,00 % |
|
||||
| Model + renderer DEV, finálne | 46/46 | 100,00 % |
|
||||
| Nový TEST, prvý pokus modelu + renderer | 77/80 | 96,25 % |
|
||||
| Nový TEST, po jednej povolenej oprave | 80/80 | 100,00 % |
|
||||
| Historická regresia, prvý pokus | 310/320 | 96.88 % |
|
||||
| Historická regresia, finálne | 319/320 | 99.69 % |
|
||||
| Živé syntetické funkčné scenáre mimo benchmarku | 9/9 | 100,00 % |
|
||||
|
||||
Modelový DEV mal prvý pokus 45/46 a jednu úspešnú opravu formátu.
|
||||
V novom TESTe potreboval `fresh7-054` opravu schémy a `fresh7-058`,
|
||||
`fresh7-059` odstránenie nepodloženého počtu pri neagregačnej otázke.
|
||||
Opravu vyvolal iba formát alebo skutočný kontext; gold ani následné
|
||||
skóre sa pri rozhodovaní o opakovaní nepoužívajú.
|
||||
Finálna historická regresia má **0 chýb spracovania**,
|
||||
**10 opravných požiadavkov**
|
||||
(z toho formát 3, kontext 7).
|
||||
Všetky odpovede, pôvodné pokusy a prípadné zlyhania ostávajú v menovateli.
|
||||
|
||||
Zostávajúci prípad `wide-285`: po chybe schémy model vložil názov dcérskeho
|
||||
dokumentu PYTORCH - LSTM TUTORIÁL ako akademický názov k roku 2019.
|
||||
Taká väzba nie je v akademických faktoch doložená; guard ju odmietol
|
||||
(`unsupported_academic_binding`, `accepted_for_delivery=false`).
|
||||
Odpoveď sa nedoručila. Povolený opravný pokus už bol vyčerpaný.
|
||||
[Úplný záznam](../answers_v7_regression_2026-10-26/failures.json).
|
||||
|
||||
| Kategória nového TESTu | Finálne správne | Úspešnosť |
|
||||
|---|---:|---:|
|
||||
| `candidate_set_aggregation` | 7/7 | 100.00 % |
|
||||
| `conjunctive_disambiguation` | 6/6 | 100.00 % |
|
||||
| `document_author_category_multi_hop` | 2/2 | 100.00 % |
|
||||
| `negative_lookup` | 8/8 | 100.00 % |
|
||||
| `person_keyword_title` | 10/10 | 100.00 % |
|
||||
| `person_multiple_categories` | 7/7 | 100.00 % |
|
||||
| `person_title_year` | 10/10 | 100.00 % |
|
||||
| `same_academic_year_pair` | 10/10 | 100.00 % |
|
||||
| `same_start_year_pair` | 10/10 | 100.00 % |
|
||||
| `shared_keyword_pair` | 10/10 | 100.00 % |
|
||||
|
||||
## Uzavreté podbody
|
||||
|
||||
| Podbod | Konkrétny výsledok |
|
||||
|---|---|
|
||||
| 3.1 Benchmark a zdroje | 1 126 zdrojovo skontrolovaných otázok; 10 opravených očakávaní po odstránení odhadu štúdia z adresára. Nová vzorka 20 otázok priamo skontrolovaná z Markdownov. |
|
||||
| 3.2 Evaluator a doručenie | Rozpory v úplnosti, nepodložené počty/roky, chýbajúce claims/citácie a HTML/referenčné odkazy majú regresné testy. Finálny text vzniká iba z overených tvrdení. |
|
||||
| 3.3 DEV | Kompletný grafový DEV 1 046/1 046, modelový DEV 46/46; staré prípady `wide-104`, `wide-119`, `wide-143`, `wide-176` prešli na prvý pokus aj v novej regresii. |
|
||||
| 3.4 Zmrazenie | `frozen_v7.json`, deklarácie generovania a `frozen_release_v7.json`; explicitné CLI vstupy, odtlačky rendereru aj spoločných modulov. |
|
||||
| 3.5 Finálne overenie | Nový TEST 80 skupín bez DEV prekryvu, jednorazovo po zmrazení; samostatná historická regresia 320 otázok a kontrola Dockeru. |
|
||||
| 3.6 Metriky a správa | Oddelené prvotné a finálne odpovede, vyhľadávanie a modelová pipeline, nový TEST a regresia. V1–v6 ostávajú zachované. |
|
||||
|
||||
## Opravené chyby
|
||||
|
||||
- Rok 1999 sa už nevynechá: dotaz na Jána Holpa nevracia práce z 2019/2021.
|
||||
Aj ostatné štvormiestne roky sa aplikujú ako obmedzenie. Nepodporovaný
|
||||
číselný zápis po „roku“ sa explicitne odmieta.
|
||||
- Veta „Výpis je neúplný“ neospravedlňuje iné kladné tvrdenie o úplnom zozname.
|
||||
Pravdivé popretie úplnosti je povolené.
|
||||
- Prirodzený text sa skladá deterministicky z validovaných claims/count a URL.
|
||||
Pri regrade neočakávanej voľnej prózy dopísaný rok 2099 neprejde.
|
||||
Zostávajúci číselný filter nie je univerzálny sémantický analyzátor;
|
||||
používateľovi sa preto nedoručuje nekontrolovaný voľný text modelu.
|
||||
- Počet bez úplnej agregácie sa odmietne. Pozitívne faktové odpovede vyžadujú
|
||||
tvrdenia a citácie, vrátane zdrojov jednotlivých atribútov. Count=0 v úplnej
|
||||
prázdnej agregácii je povolený.
|
||||
- Kontrolujú sa aj referenčné Markdown a HTML odkazy, relatívne URL, entity
|
||||
a korektné URL so zátvorkami. Nepovolené odkazy sa neobchádzajú upozornením.
|
||||
- Začiatok štúdia je iba explicitne uvedený údaj. Graf eviduje pôvod a istotu,
|
||||
chýbajúca hodnota ostáva neznáma; `wide-112` už nevyžaduje odhadovaný rok
|
||||
Tomáša Kuchárika. Cohort nie je administratívny fakt o nástupe na štúdium.
|
||||
- Skloňované meno sa v texte rozpoznáva obmedzenými príponami pri zachovaní
|
||||
presnej štruktúrovanej identity. Canonical renderer používa pôvodné meno.
|
||||
- Dataset, audit, manifest a DEV ID sa pri evaluácii vyberajú explicitne;
|
||||
spúšťanie už potichu nevyberá v4.
|
||||
|
||||
## Nezávislosť a pôvod očakávaní
|
||||
|
||||
Všetkých 1 042 v6 otázok je odhalených a v7 ich označuje ako DEV. Štyri
|
||||
nové auditové rokové regresie dopĺňajú počet na 1 046. Historických 320
|
||||
sa vyhodnocuje z tejto množiny samostatne. Je to **regresia**, nie nový TEST.
|
||||
|
||||
Nový TEST má 80 kombinácií, 72 kladných a 8 záporných. Seed 20261026,
|
||||
kvóty a ID vznikli z raw Markdownov pred čítaním predikcií. Normalizované
|
||||
query skupiny ani formulácie sa s DEV neprekrývajú. Po zmrazení sa podľa
|
||||
TESTu nemenil kód, prompt, gold ani výber otázok. Korpus, osoby a rodiny
|
||||
šablón sú známe; nejde o unseen-profile experiment.
|
||||
|
||||
Priama AI kontrola 20 otázok pokrýva všetkých desať kategórií.
|
||||
[Zdrojový hárok](../v7_preparation/source_review.csv) a
|
||||
[výňatky](../v7_preparation/source_review_packet.json) sú uložené.
|
||||
**Ľudská anotácia neprebehla.** Neistá adresárová konvencia bola odstránená,
|
||||
nie potvrdená bez dôkazu. Autor–kategória má iba dve nové skupiny a výpis
|
||||
kategórií sedem; nemožno tvrdiť rovnakú štatistickú silu každej kategórie.
|
||||
|
||||
## Regresia a zachované referencie
|
||||
|
||||
V6 mala strict 316/320. V7 mení gold pri 10 známych otázkach (sedem z
|
||||
historických 320) a používa štruktúrovaný modelový výstup s rendererom.
|
||||
Rozdiel percent nie je izolovaný odhad zlepšenia samotného LLM.
|
||||
Všetky pôvodné baseline, otázky, finálne JSON/CSV a v1–v6 výsledky sa zachovávajú.
|
||||
|
||||
Prepočet citácií 56 archivovaných súborov má 6 044 odpovedí a päť výskytov
|
||||
URL mimo podkladov, rovnako ako v6. Ide o prekrývajúce sa experimenty.
|
||||
Klasický RAG sa novým modelovým TESTom nemeral. Prehratie piatich uložených
|
||||
RAG odpovedí cez kontrolu upozornenia opäť prešlo 5/5; to nie je nová
|
||||
presnosť modelu. Je to regresia prezentačnej vrstvy.
|
||||
|
||||
## Nasadenie a reprodukcia
|
||||
|
||||
Súbory, SQLite a Neo4j sú po koordinovanom `/sync` na spoločnej generácii
|
||||
`33ea0794472c416e97c84371a2a6cdf8`; wiki Git je
|
||||
`3e892a1d49e9bce118cd03478ce15e01c2bebb4e`. Index má 114 dokumentov a 887
|
||||
chunkov, graf 446 uzlov a 877 vzťahov. Explicitné published=false sa skryje,
|
||||
16 chýbajúcich hodnôt sa zahrnie; viditeľných je 113 dokumentov.
|
||||
|
||||
[Hostiteľské overenie](deployment_check_host.json) a
|
||||
[overenie Dockeru](deployment_check_docker.json) potvrdzujú dostupnosť,
|
||||
spoločnú generáciu, normalizované publikovanie a runtime odtlačky.
|
||||
Modelové výstupy obsahujú celý skutočný grafový kontext a verziu dát.
|
||||
|
||||
[Príkazy a zmeny](../../../../../docs/graphrag_v7_2026-10-26_worklog.md).
|
||||
Reprodukcia používa nový výstupný adresár a príslušný release checkout.
|
||||
Git HEAD v metadátach merania je východiskový commit pred finálnym commitom;
|
||||
konkrétny meraný kód určujú obsahové SHA. Model `model120-fast` je vzdialená
|
||||
služba; parametre a odpovede sú uložené, váhy prevádzkuje poskytovateľ.
|
||||
|
||||
Ďalším blokom sú natívne nástroje a hlavný agent v OpenWebUI. Musia rešpektovať
|
||||
odmietnutie doručenia a odovzdať overený text; voľné prepísanie rendererového
|
||||
textu bez kontrol by uvedené vlastnosti obišlo. Toto smerovanie sa v bode 3
|
||||
nemeralo a je súčasťou bodu 4.
|
||||
@ -5,9 +5,9 @@ import json
|
||||
import re
|
||||
import unicodedata
|
||||
from typing import Any, Iterable
|
||||
from tools.publication import DEFAULT_PUBLISHED_ONLY, PUBLICATION_POLICY_VERSION
|
||||
from tools.retrieval.publication import DEFAULT_PUBLISHED_ONLY, PUBLICATION_POLICY_VERSION
|
||||
from .publication import public_query
|
||||
from tools.retrieval_contract import result_fields, source_references, error_result
|
||||
from tools.retrieval.retrieval_contract import result_fields, source_references, error_result
|
||||
|
||||
|
||||
GRAPH_SCOPE = "zpwiki"
|
||||
@ -2653,7 +2653,7 @@ def search_graph(
|
||||
get_neo4j_settings,
|
||||
)
|
||||
|
||||
from tools.index_state import DATA_DIR, IndexUnavailableError, index_snapshot
|
||||
from tools.sync.index_state import DATA_DIR, IndexUnavailableError, index_snapshot
|
||||
from .build_graphrag import graph_version
|
||||
settings = (
|
||||
get_neo4j_settings()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from tools.publication import effective_published
|
||||
from tools.retrieval.publication import effective_published
|
||||
|
||||
import re
|
||||
import unicodedata
|
||||
|
||||
@ -100,7 +100,7 @@ def test_comparison_checks_individual_years_as_well_as_shared_year(evidence):
|
||||
def test_freeze_includes_shared_modules_and_effective_publication_policy():
|
||||
questions=Path('tools/graphrag/evaluation/graphrag_questions_v4.json')
|
||||
fp=content_fingerprints(questions)
|
||||
assert {'tools/publication.py','tools/retrieval_contract.py','tools/index_state.py'} <= fp['implementation'].keys()
|
||||
assert {'tools/retrieval/publication.py','tools/retrieval/retrieval_contract.py','tools/sync/index_state.py'} <= fp['implementation'].keys()
|
||||
assert fp['retrieval_policy']['published_only'] is True
|
||||
assert fp['retrieval_policy']['academic_preparation_is_work'] is False
|
||||
|
||||
|
||||
@ -102,7 +102,7 @@ def test_shared_keyword_does_not_include_private_person(graph):
|
||||
|
||||
|
||||
def test_graph_contract_distinguishes_exact_count_from_trimmed_evidence(graph):
|
||||
from tools.retrieval_contract import RetrievalResponse
|
||||
from tools.retrieval.retrieval_contract import RetrievalResponse
|
||||
tx, _ = graph
|
||||
result = gs.search_graph_with_session(tx, 'Koľko osôb má prácu v roku 2024?', limit=1)
|
||||
RetrievalResponse.model_validate(result)
|
||||
|
||||
@ -23,8 +23,8 @@ from tools.rag.common import (
|
||||
load_zpwiki_page,
|
||||
write_json,
|
||||
)
|
||||
from tools.text_budget import split_to_fit
|
||||
from tools.runtime_assets import configure_tokenizer
|
||||
from tools.retrieval.text_budget import split_to_fit
|
||||
from tools.runtime.runtime_assets import configure_tokenizer
|
||||
|
||||
configure_tokenizer()
|
||||
|
||||
|
||||
@ -7,8 +7,8 @@ from functools import lru_cache
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
from tools.text_budget import split_to_fit
|
||||
from tools.runtime_assets import local_model
|
||||
from tools.retrieval.text_budget import split_to_fit
|
||||
from tools.runtime.runtime_assets import local_model
|
||||
|
||||
|
||||
DEFAULT_EMBEDDING_MODEL = (
|
||||
|
||||
@ -6,7 +6,7 @@ import json
|
||||
import os
|
||||
|
||||
from tools.rag.build_chunks import TokenCounter
|
||||
from tools.text_budget import split_to_fit
|
||||
from tools.retrieval.text_budget import split_to_fit
|
||||
|
||||
SOURCE_FIELDS = ('source_id', 'title', 'author', 'document_path', 'source_url', 'published',
|
||||
'categories', 'tags', 'section')
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from tools.publication import DEFAULT_PUBLISHED_ONLY
|
||||
from tools.retrieval.publication import DEFAULT_PUBLISHED_ONLY
|
||||
|
||||
import json
|
||||
import re
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from tools.publication import DEFAULT_PUBLISHED_ONLY
|
||||
from tools.retrieval.publication import DEFAULT_PUBLISHED_ONLY
|
||||
|
||||
import json
|
||||
import re
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from tools.publication import DEFAULT_PUBLISHED_ONLY
|
||||
from tools.retrieval_contract import result_fields
|
||||
from tools.retrieval.publication import DEFAULT_PUBLISHED_ONLY
|
||||
from tools.retrieval.retrieval_contract import result_fields
|
||||
|
||||
import inspect
|
||||
import json
|
||||
import sqlite3
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from tools.index_state import rag_snapshot
|
||||
from tools.sync.index_state import rag_snapshot
|
||||
|
||||
from tools.rag.rag_document_expansion import (
|
||||
expand_results_with_exact_document_section,
|
||||
|
||||
@ -21,7 +21,7 @@ if str(PROJECT_ROOT) not in sys.path:
|
||||
|
||||
|
||||
from tools.rag.common import DATA_DIR, ZPWIKI_ROOT
|
||||
from tools.wiki_git import update_wiki
|
||||
from tools.sync.wiki_git import update_wiki
|
||||
|
||||
|
||||
REINDEX_LOCK_FILE = DATA_DIR / ".reindex.lock"
|
||||
@ -122,7 +122,7 @@ def rebuild_index(
|
||||
progress('git_pull')
|
||||
git_pull(root)
|
||||
|
||||
from tools.sync_indexes import synchronize_indexes
|
||||
from tools.sync.sync_indexes import synchronize_indexes
|
||||
if progress:
|
||||
progress('building_indexes')
|
||||
result = synchronize_indexes(root, target, progress=progress)
|
||||
|
||||
@ -16,7 +16,7 @@ if str(PROJECT_ROOT) not in sys.path:
|
||||
|
||||
from tools.rag.common import DB_FILE
|
||||
from tools.rag.search_utils import search_database
|
||||
from tools.retrieval_contract import error_result
|
||||
from tools.retrieval.retrieval_contract import error_result
|
||||
|
||||
|
||||
def print_results(
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from tools.publication import DEFAULT_PUBLISHED_ONLY
|
||||
from tools.retrieval.publication import DEFAULT_PUBLISHED_ONLY
|
||||
|
||||
import sqlite3
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from tools.index_state import rag_snapshot
|
||||
from tools.retrieval_contract import result_fields, source_references
|
||||
from tools.sync.index_state import rag_snapshot
|
||||
from tools.retrieval.retrieval_contract import result_fields, source_references
|
||||
|
||||
# Tieto importy sú zámerne verejné.
|
||||
# Zachovávajú spätnú kompatibilitu pre testy
|
||||
|
||||
@ -7,7 +7,7 @@ from pathlib import Path
|
||||
import pytest
|
||||
|
||||
import tools.rag.rebuild_index as rebuild
|
||||
import tools.wiki_git as wiki_git
|
||||
import tools.sync.wiki_git as wiki_git
|
||||
|
||||
|
||||
def hold_lock(lock_path: str, ready, release) -> None:
|
||||
@ -57,7 +57,7 @@ def test_rebuild_runs_pipeline_in_correct_order(
|
||||
"git_pull",
|
||||
lambda root: calls.append("git_pull"),
|
||||
)
|
||||
import tools.sync_indexes as sync
|
||||
import tools.sync.sync_indexes as sync
|
||||
monkeypatch.setattr(sync, 'synchronize_indexes', lambda wiki, data:
|
||||
calls.append('sqlite_and_neo4j') or {'documents_scanned': 1, 'chunks_created': 1,
|
||||
'counts': {'fts_chunks': 1}, 'index_version': {'version': 'both'}})
|
||||
@ -75,7 +75,7 @@ def test_rebuild_runs_pipeline_in_correct_order(
|
||||
|
||||
|
||||
def test_rebuild_pulls_and_locks_the_requested_snapshot_paths(tmp_path, monkeypatch):
|
||||
import tools.sync_indexes as sync
|
||||
import tools.sync.sync_indexes as sync
|
||||
wiki = tmp_path / 'alternate-wiki'
|
||||
data = tmp_path / 'alternate-data'
|
||||
seen = []
|
||||
|
||||
1
tools/retrieval/__init__.py
Normal file
1
tools/retrieval/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Shared retrieval contracts, publication policy and text budgets."""
|
||||
1
tools/runtime/__init__.py
Normal file
1
tools/runtime/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Model assets, startup and service readiness."""
|
||||
@ -6,9 +6,9 @@ from app.security import validate_security_configuration
|
||||
from tools.rag.common import DATA_DIR, DB_FILE, ZPWIKI_ROOT
|
||||
from tools.rag.embedding_utils import embed_query
|
||||
from tools.rag.rebuild_index import rebuild_index
|
||||
from tools.runtime_assets import asset_root, verify
|
||||
from tools.sync_indexes import git_revision, source_files
|
||||
from tools.tool_health import tools_readiness
|
||||
from tools.runtime.runtime_assets import asset_root, verify
|
||||
from tools.sync.sync_indexes import git_revision, source_files
|
||||
from tools.runtime.tool_health import tools_readiness
|
||||
|
||||
|
||||
def main():
|
||||
@ -13,7 +13,7 @@ from pathlib import Path
|
||||
|
||||
DEFAULT_MODEL = 'intfloat/multilingual-e5-small'
|
||||
DEFAULT_REVISION = '614241f622f53c4eeff9890bdc4f31cfecc418b3'
|
||||
DEFAULT_ROOT = Path(__file__).resolve().parents[1] / 'runtime_assets'
|
||||
DEFAULT_ROOT = Path(__file__).resolve().parents[2] / 'runtime_assets'
|
||||
|
||||
|
||||
def asset_root() -> Path:
|
||||
@ -24,7 +24,7 @@ def manifest(root: Path | None = None) -> dict | None:
|
||||
path = (root or asset_root()) / 'manifest.json'
|
||||
if not path.exists():
|
||||
if os.getenv('ZP_ASSETS_REQUIRED') == '1':
|
||||
raise RuntimeError('Chýbajú runtime assets; zostavte image alebo spustite python -m tools.runtime_assets prepare.')
|
||||
raise RuntimeError('Chýbajú runtime assets; zostavte image alebo spustite python -m tools.runtime.runtime_assets prepare.')
|
||||
return None
|
||||
return json.loads(path.read_text())
|
||||
|
||||
@ -74,7 +74,7 @@ def denied(*args, **kwargs): raise RuntimeError('Network access during offline a
|
||||
socket.socket.connect = denied
|
||||
socket.socket.connect_ex = denied
|
||||
socket.getaddrinfo = denied
|
||||
from tools.runtime_assets import configure_tokenizer, manifest, local_model
|
||||
from tools.runtime.runtime_assets import configure_tokenizer, manifest, local_model
|
||||
configure_tokenizer()
|
||||
import tiktoken
|
||||
for encoding in manifest()['encodings']:
|
||||
@ -10,8 +10,8 @@ from neo4j import Query
|
||||
|
||||
from tools.graphrag.graph_db import create_neo4j_driver, get_neo4j_settings
|
||||
from tools.graphrag.graphrag import GRAPH_SCOPE
|
||||
from tools.index_state import IndexUnavailableError, index_snapshot, sqlite_version
|
||||
from tools.publication import PUBLICATION_POLICY_VERSION
|
||||
from tools.sync.index_state import IndexUnavailableError, index_snapshot, sqlite_version
|
||||
from tools.retrieval.publication import PUBLICATION_POLICY_VERSION
|
||||
from tools.rag.search_core import verify_search_schema, embedding_index_info
|
||||
|
||||
PROBE_TIMEOUT_SECONDS = 2.0
|
||||
1
tools/sync/__init__.py
Normal file
1
tools/sync/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Git synchronization, durable jobs and coherent index publication."""
|
||||
@ -19,13 +19,13 @@ from contextlib import closing
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
from tools.index_state import (PENDING_FILE, VERSION_FILE, durable_json, fsync_directory,
|
||||
from tools.sync.index_state import (PENDING_FILE, VERSION_FILE, durable_json, fsync_directory,
|
||||
publication_lock, sqlite_version)
|
||||
from tools.rag.scan_zpwiki import scan_pages
|
||||
from tools.rag.build_chunks import build_chunks
|
||||
from tools.rag.build_sqlite_index import build_database
|
||||
from tools.rag.embedding_utils import embedding_model_name
|
||||
from tools.publication import PUBLICATION_POLICY_VERSION
|
||||
from tools.retrieval.publication import PUBLICATION_POLICY_VERSION
|
||||
from tools.graphrag.graphrag import build_graph_payload
|
||||
from tools.graphrag.graph_db import create_neo4j_driver, get_neo4j_settings
|
||||
from tools.graphrag.build_graphrag import (create_constraints, graph_version,
|
||||
Loading…
Reference in New Issue
Block a user