551 lines
12 KiB
Markdown
551 lines
12 KiB
Markdown
# dp-zp-agent
|
|
|
|
Agent pre manažment záverečných prác nad repozitárom `zpwiki`.
|
|
|
|
Projekt rieši základnú časť systému pre vyhľadávanie v Markdown súboroch zo školského repozitára záverečných prác. Cieľom je vytvoriť samostatnú službu, ktorá vie indexovať obsah `zpwiki`, vyhľadávať v ňom a neskôr sa napojí na OpenWebUI, RAG, znalostný graf a GraphRAG.
|
|
|
|
Aktuálne je implementovaný prototyp, ktorý vie načítať Markdown dokumenty, spracovať ich metadata, rozdeliť ich na menšie časti, uložiť ich do SQLite databázy a sprístupniť vyhľadávanie cez FastAPI.
|
|
|
|
## Aktuálny stav
|
|
|
|
Zatiaľ je implementované:
|
|
|
|
1. načítanie Markdown súborov z repozitára `zpwiki`,
|
|
2. extrakcia metadát z YAML front matter,
|
|
3. spracovanie položiek `taxonomy`, hlavne kategórie, tagy a autor,
|
|
4. rozdelenie dokumentov na menšie textové chunky,
|
|
5. vytvorenie SQLite indexu,
|
|
6. jednoduché skórovacie fulltextové vyhľadávanie nad chunkmi,
|
|
7. rozlíšenie režimu vyhľadávania:
|
|
1. `person` pre mená osôb, napríklad `jan ptak`,
|
|
2. `topic` pre tematické dopyty, napríklad `rag agent` alebo `knowledge graph`,
|
|
8. FastAPI backend,
|
|
9. endpoint `GET /health`,
|
|
10. endpoint `POST /search`,
|
|
11. endpoint `POST /sync` pre manuálne spustenie reindexovania,
|
|
12. endpoint `POST /webhook/gitea` pre prijatie webhooku z Gitea,
|
|
13. overenie webhooku pomocou jednoduchého tokenu alebo HMAC podpisu,
|
|
14. automatická Swagger dokumentácia API,
|
|
15. Dockerfile a `docker-compose.yml`,
|
|
16. spustenie celého riešenia cez Docker,
|
|
17. volume mount pre priečinok `data`,
|
|
18. volume mount pre repozitár `zpwiki`.
|
|
|
|
## Overený stav testovania
|
|
|
|
Pri testovaní cez Docker bolo overené:
|
|
|
|
1. FastAPI kontajner sa spustí,
|
|
2. endpoint `/health` vracia `200 OK`,
|
|
3. endpoint `/search` vracia `200 OK`,
|
|
4. endpoint `/sync` spustí reindexovanie a vracia `200 OK`,
|
|
5. endpoint `/webhook/gitea` prijme platný webhook a spustí reindexovanie,
|
|
6. Docker kontajner vidí repozitár `zpwiki` cez cestu `/zpwiki`,
|
|
7. systém načítal 114 dokumentov,
|
|
8. systém vytvoril 955 chunkov,
|
|
9. SQLite index bol vytvorený v `/app/data/zp_index.sqlite`.
|
|
|
|
## Štruktúra projektu
|
|
|
|
```text
|
|
dp-zp-agent/
|
|
├── app/
|
|
│ ├── __init__.py
|
|
│ └── main.py
|
|
├── scripts/
|
|
│ ├── __init__.py
|
|
│ ├── common.py
|
|
│ ├── scan_zpwiki.py
|
|
│ ├── build_chunks.py
|
|
│ ├── build_sqlite_index.py
|
|
│ ├── rebuild_index.py
|
|
│ ├── search_db.py
|
|
│ └── search_utils.py
|
|
├── data/
|
|
├── Dockerfile
|
|
├── docker-compose.yml
|
|
├── requirements.txt
|
|
├── .gitignore
|
|
└── README.md
|
|
```
|
|
|
|
Súbor `scripts/search_chunks.py` bol odstránený, pretože jeho funkcionalita bola duplicitná voči súboru `scripts/build_chunks.py`.
|
|
|
|
## Popis hlavných súborov
|
|
|
|
### `app/main.py`
|
|
|
|
Obsahuje FastAPI aplikáciu a API endpointy:
|
|
|
|
1. `GET /health`,
|
|
2. `POST /search`,
|
|
3. `POST /sync`,
|
|
4. `POST /webhook/gitea`.
|
|
|
|
### `scripts/common.py`
|
|
|
|
Obsahuje spoločné konštanty a pomocné funkcie:
|
|
|
|
1. cesty k projektu,
|
|
2. cesta k `zpwiki`,
|
|
3. cesta k dátovým súborom,
|
|
4. čítanie a zápis JSON,
|
|
5. spracovanie YAML metadát,
|
|
6. normalizácia tagov a kategórií.
|
|
|
|
### `scripts/scan_zpwiki.py`
|
|
|
|
Prejde Markdown súbory v `zpwiki`, načíta metadata a uloží základné informácie do súboru:
|
|
|
|
```text
|
|
data/documents.json
|
|
```
|
|
|
|
### `scripts/build_chunks.py`
|
|
|
|
Rozdelí obsah Markdown dokumentov na menšie textové chunky a uloží ich do súboru:
|
|
|
|
```text
|
|
data/chunks.json
|
|
```
|
|
|
|
### `scripts/build_sqlite_index.py`
|
|
|
|
Vytvorí SQLite databázu:
|
|
|
|
```text
|
|
data/zp_index.sqlite
|
|
```
|
|
|
|
Do databázy uloží dokumenty, chunky, tagy a kategórie.
|
|
|
|
### `scripts/rebuild_index.py`
|
|
|
|
Spustí celý proces naraz:
|
|
|
|
1. načítanie dokumentov,
|
|
2. vytvorenie chunkov,
|
|
3. vytvorenie SQLite indexu.
|
|
|
|
Voliteľne vie pred reindexovaním spustiť aj `git pull`.
|
|
|
|
### `scripts/search_utils.py`
|
|
|
|
Obsahuje spoločnú logiku vyhľadávania:
|
|
|
|
1. normalizácia textu,
|
|
2. tokenizácia,
|
|
3. rozlíšenie režimu `person` a `topic`,
|
|
4. skórovanie výsledkov,
|
|
5. vyhľadávanie v SQLite databáze.
|
|
|
|
### `scripts/search_db.py`
|
|
|
|
Slúži na testovanie vyhľadávania z terminálu.
|
|
|
|
## Príprava prostredia
|
|
|
|
Projekt očakáva, že vedľa neho existuje naklonovaný repozitár `zpwiki`.
|
|
|
|
Odporúčaná štruktúra:
|
|
|
|
```text
|
|
~/DP/
|
|
├── zpwiki/
|
|
└── zp-agent/
|
|
```
|
|
|
|
## Lokálne spustenie bez Dockeru
|
|
|
|
Vytvorenie a aktivácia Python prostredia:
|
|
|
|
```bash
|
|
python3 -m venv .venv
|
|
source .venv/bin/activate
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
Vygenerovanie dát a indexu:
|
|
|
|
```bash
|
|
python scripts/rebuild_index.py
|
|
```
|
|
|
|
Alternatívne sa dá proces spustiť po krokoch:
|
|
|
|
```bash
|
|
python scripts/scan_zpwiki.py
|
|
python scripts/build_chunks.py
|
|
python scripts/build_sqlite_index.py
|
|
```
|
|
|
|
Testovanie vyhľadávania v termináli:
|
|
|
|
```bash
|
|
python scripts/search_db.py "jan ptak"
|
|
python scripts/search_db.py "rag agent"
|
|
python scripts/search_db.py "knowledge graph"
|
|
```
|
|
|
|
Spustenie API lokálne:
|
|
|
|
```bash
|
|
uvicorn app.main:app --reload
|
|
```
|
|
|
|
Health check:
|
|
|
|
```bash
|
|
curl http://127.0.0.1:8000/health
|
|
```
|
|
|
|
Vyhľadávanie cez API:
|
|
|
|
```bash
|
|
curl -X POST http://127.0.0.1:8000/search \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"query":"jan ptak","limit":5}'
|
|
```
|
|
|
|
## Spustenie cez Docker
|
|
|
|
Projekt je možné spustiť cez Docker Compose. Kontajner používa volume mount pre priečinok `data` a pre repozitár `zpwiki`.
|
|
|
|
Build Docker image:
|
|
|
|
```bash
|
|
docker compose build --no-cache
|
|
```
|
|
|
|
Spustenie kontajnera:
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
Zobrazenie logov:
|
|
|
|
```bash
|
|
docker compose logs -f zp-agent-api
|
|
```
|
|
|
|
Zastavenie kontajnera:
|
|
|
|
```bash
|
|
docker compose down
|
|
```
|
|
|
|
## Reindexovanie cez Docker
|
|
|
|
Celý proces indexovania je možné spustiť priamo v Docker kontajneri:
|
|
|
|
```bash
|
|
docker compose run --rm zp-agent-api python scripts/rebuild_index.py
|
|
```
|
|
|
|
Tento príkaz vykoná:
|
|
|
|
1. načítanie Markdown dokumentov,
|
|
2. extrakciu metadát,
|
|
3. rozdelenie dokumentov na chunky,
|
|
4. vytvorenie SQLite indexu.
|
|
|
|
Po úspešnom behu vzniknú v priečinku `data` súbory:
|
|
|
|
```text
|
|
documents.json
|
|
chunks.json
|
|
zp_index.sqlite
|
|
```
|
|
|
|
Kontrola dát:
|
|
|
|
```bash
|
|
ls -lh data
|
|
```
|
|
|
|
## Testovanie vyhľadávania cez Docker
|
|
|
|
```bash
|
|
docker compose run --rm zp-agent-api python scripts/search_db.py "rag agent"
|
|
```
|
|
|
|
```bash
|
|
docker compose run --rm zp-agent-api python scripts/search_db.py "jan ptak"
|
|
```
|
|
|
|
## Testovanie API cez Docker
|
|
|
|
Health check:
|
|
|
|
```bash
|
|
curl http://127.0.0.1:8000/health
|
|
```
|
|
|
|
Vyhľadávanie:
|
|
|
|
```bash
|
|
curl -X POST http://127.0.0.1:8000/search \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"query":"rag agent","limit":5}'
|
|
```
|
|
|
|
Manuálne reindexovanie cez API:
|
|
|
|
```bash
|
|
curl -X POST http://127.0.0.1:8000/sync \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"pull_git":false}'
|
|
```
|
|
|
|
## Swagger UI
|
|
|
|
FastAPI automaticky generuje Swagger dokumentáciu API.
|
|
|
|
Po spustení servera je dostupná na adrese:
|
|
|
|
```text
|
|
http://127.0.0.1:8000/docs
|
|
```
|
|
|
|
V Swagger UI je možné testovať endpointy:
|
|
|
|
1. `/health`,
|
|
2. `/search`,
|
|
3. `/sync`,
|
|
4. `/webhook/gitea`.
|
|
|
|
## Webhook pre Gitea
|
|
|
|
Aplikácia obsahuje endpoint:
|
|
|
|
```text
|
|
POST /webhook/gitea
|
|
```
|
|
|
|
Webhook slúži na spustenie reindexovania po zmene v repozitári.
|
|
|
|
Endpoint podporuje dva spôsoby overenia:
|
|
|
|
1. jednoduchý token cez header `X-Gitea-Token`,
|
|
2. HMAC podpis cez header `X-Gitea-Signature`.
|
|
|
|
Hodnota tajného kľúča sa nastavuje cez environment premennú:
|
|
|
|
```text
|
|
WEBHOOK_SECRET
|
|
```
|
|
|
|
V `docker-compose.yml` je počas vývoja nastavené:
|
|
|
|
```text
|
|
WEBHOOK_SECRET=dev-secret
|
|
```
|
|
|
|
### Test webhooku cez token
|
|
|
|
```bash
|
|
curl -X POST http://127.0.0.1:8000/webhook/gitea \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-Gitea-Event: push" \
|
|
-H "X-Gitea-Token: dev-secret" \
|
|
-d '{"repository":{"full_name":"KEMT/zpwiki"}}'
|
|
```
|
|
|
|
### Test webhooku cez HMAC podpis
|
|
|
|
```bash
|
|
BODY='{"repository":{"full_name":"KEMT/zpwiki"}}'
|
|
|
|
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "dev-secret" -hex | sed 's/^.* //')
|
|
|
|
curl -X POST http://127.0.0.1:8000/webhook/gitea \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-Gitea-Event: push" \
|
|
-H "X-Gitea-Signature: sha256=$SIG" \
|
|
--data-raw "$BODY"
|
|
```
|
|
|
|
### Test neplatného tokenu
|
|
|
|
Pri neplatnom tokene má endpoint vrátiť `401 Unauthorized`.
|
|
|
|
```bash
|
|
curl -i -X POST http://127.0.0.1:8000/webhook/gitea \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-Gitea-Event: push" \
|
|
-H "X-Gitea-Token: zly-token" \
|
|
-d '{"repository":{"full_name":"KEMT/zpwiki"}}'
|
|
```
|
|
|
|
## Kompletný test cez Docker
|
|
|
|
```bash
|
|
cd ~/DP/zp-agent
|
|
|
|
docker compose down
|
|
docker compose build --no-cache
|
|
|
|
docker compose run --rm zp-agent-api ls /zpwiki/pages | head
|
|
|
|
docker compose run --rm zp-agent-api python scripts/rebuild_index.py
|
|
|
|
ls -lh data
|
|
|
|
docker compose run --rm zp-agent-api python scripts/search_db.py "rag agent"
|
|
|
|
docker compose up -d
|
|
|
|
curl http://127.0.0.1:8000/health
|
|
|
|
curl -X POST http://127.0.0.1:8000/search \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"query":"rag agent","limit":5}'
|
|
|
|
curl -X POST http://127.0.0.1:8000/sync \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"pull_git":false}'
|
|
```
|
|
|
|
## Čo ešte treba dorobiť
|
|
|
|
### 1. OpenWebUI integrácia
|
|
|
|
Treba napojiť API na OpenWebUI.
|
|
|
|
Možné riešenia:
|
|
|
|
1. OpenAPI tool server,
|
|
2. OpenWebUI tool,
|
|
3. OpenWebUI pipeline,
|
|
4. vlastný agent, ktorý bude volať endpoint `/search`.
|
|
|
|
Cieľ je, aby používateľ mohol v OpenWebUI položiť otázku a agent použil vyhľadávanie nad `zpwiki`.
|
|
|
|
### 2. Embeddingy a vektorové vyhľadávanie
|
|
|
|
Aktuálne vyhľadávanie je fulltextové a skórovacie. Ďalší krok je pridať embeddingy.
|
|
|
|
Treba dorobiť:
|
|
|
|
1. výber embedding modelu,
|
|
2. generovanie embeddingov pre chunky,
|
|
3. uloženie embeddingov,
|
|
4. vektorové vyhľadávanie,
|
|
5. porovnanie fulltextového a vektorového vyhľadávania.
|
|
|
|
Možné databázy:
|
|
|
|
1. PostgreSQL plus pgvector,
|
|
2. Qdrant,
|
|
3. ChromaDB,
|
|
4. FAISS ako jednoduchý lokálny prototyp.
|
|
|
|
### 3. RAG odpovede s citáciami
|
|
|
|
Treba doplniť generovanie odpovede pomocou jazykového modelu.
|
|
|
|
Postup:
|
|
|
|
1. používateľ položí otázku,
|
|
2. systém nájde relevantné chunky,
|
|
3. chunkom priradí zdrojové URL,
|
|
4. jazykový model vytvorí odpoveď iba z nájdeného kontextu,
|
|
5. odpoveď obsahuje odkazy na zdrojové stránky.
|
|
|
|
Cieľ je, aby agent nehalucinoval a vedel ukázať, z ktorých dokumentov odpovedal.
|
|
|
|
### 4. Znalostný graf
|
|
|
|
Treba vytvoriť štruktúrovaný graf nad dátami zo `zpwiki`.
|
|
|
|
Základné entity:
|
|
|
|
1. `Student`,
|
|
2. `Thesis`,
|
|
3. `Tag`,
|
|
4. `Category`,
|
|
5. `Author`,
|
|
6. `Year`.
|
|
|
|
Základné vzťahy:
|
|
|
|
1. študent má prácu,
|
|
2. práca má tag,
|
|
3. práca patrí do kategórie,
|
|
4. autor vedie alebo spravuje prácu,
|
|
5. práca je podobná inej práci,
|
|
6. práca patrí do roka alebo obdobia.
|
|
|
|
### 5. GraphRAG
|
|
|
|
Treba prepojiť RAG a znalostný graf.
|
|
|
|
GraphRAG časť má umožniť:
|
|
|
|
1. vyhľadávanie podľa vzťahov,
|
|
2. vysvetlenie, prečo sa našli konkrétne práce,
|
|
3. odporúčanie podobných tém,
|
|
4. analýzu tém podľa tagov, rokov a kategórií,
|
|
5. kombináciu textového, vektorového a grafového vyhľadávania.
|
|
|
|
### 6. Čiastočné reindexovanie
|
|
|
|
Aktuálne endpoint `/sync` a webhook spúšťajú celé reindexovanie. Neskôr treba doplniť efektívnejší spôsob synchronizácie.
|
|
|
|
Plánované časti:
|
|
|
|
1. zistenie aktuálneho commitu,
|
|
2. detekcia zmenených Markdown súborov,
|
|
3. reindexovanie iba zmenených dokumentov,
|
|
4. uloženie stavu synchronizácie do databázy,
|
|
5. logovanie výsledku synchronizácie.
|
|
|
|
### 7. Vyhodnotenie systému
|
|
|
|
Treba pripraviť testovaciu sadu otázok a porovnať viacero prístupov.
|
|
|
|
Porovnať treba minimálne:
|
|
|
|
1. jednoduché fulltextové vyhľadávanie,
|
|
2. vektorové vyhľadávanie,
|
|
3. RAG,
|
|
4. GraphRAG.
|
|
|
|
Príklady testovacích otázok:
|
|
|
|
1. `Nájdi práce o RAG.`
|
|
2. `Nájdi práce podobné téme Agent pre manažment záverečných prác.`
|
|
3. `Ktoré práce používajú znalostný graf?`
|
|
4. `Kto riešil chatbot alebo agenta?`
|
|
5. `Aké témy patria do kategórie dp2027?`
|
|
6. `Zhrň práce súvisiace s NLP.`
|
|
|
|
Sledované vlastnosti:
|
|
|
|
1. relevantnosť výsledkov,
|
|
2. správnosť odpovede,
|
|
3. správnosť citácií,
|
|
4. počet halucinácií,
|
|
5. čas odpovede,
|
|
6. čas reindexovania po zmene v Gite.
|
|
|
|
### 8. Dokumentácia do diplomovej práce
|
|
|
|
Treba priebežne písať:
|
|
|
|
1. čo je RAG,
|
|
2. čo je generatívny model,
|
|
3. čo je znalostný graf,
|
|
4. čo je GraphRAG,
|
|
5. ako funguje `zpwiki`,
|
|
6. návrh architektúry systému,
|
|
7. návrh databázy a indexu,
|
|
8. návrh webhook synchronizácie,
|
|
9. návrh integrácie s OpenWebUI,
|
|
10. popis experimentov a vyhodnotenia.
|
|
|
|
## Najbližší praktický krok
|
|
|
|
Najbližšie treba pokračovať integráciou s OpenWebUI a prípravou RAG odpovedí s citáciami. Potom bude možné porovnať jednoduché fulltextové vyhľadávanie s RAG a neskôr s GraphRAG.
|