# Repo Agent & QA — LLM Proxy • OpenWebUI Tools • Agent Repo/QA Een compacte, productierijpe stack om (1) chat/LLM-verzoeken af te handelen, (2) OpenWebUI-compatibele tools (STT/TTS/Retrieval) aan te bieden, en (3) een **Repo Agent** te draaien die **kandidaten zoekt, diffs genereert** (dry-run) en — na akkoord — **schrijft & pusht** op een nieuwe branch. Inclusief **Repo-QA** (vraag-antwoord over je codebase met padverwijzingen), **Laravel-bewuste heuristiek**, **hybride retrieval** (Meili/BM25 + embeddings/Chroma), **slim chunking**, **niet-destructieve guards** en een **lichte graaf-boost** (route ⇄ controller ⇄ view ⇄ lang). > Dockerfile inbegrepen (Python 3.11-slim), met o.a. `faster-whisper`, `piper` TTS, Meili/Chroma-clients, `gitpython`, `sentence-transformers`, `rank-bm25`. --- ## Inhoudsopgave * [Architectuur in 3 onderdelen](#architectuur-in-3-onderdelen) * [Belangrijkste features](#belangrijkste-features) * [Snel starten](#snel-starten) * [Docker (aanbevolen)](#docker-aanbevolen) * [Zonder Docker (dev)](#zonder-docker-dev) * [Configuratie (ENV)](#configuratie-env) * [Endpoints](#endpoints) * [Hoe het werkt (flow prompt → diffs/qa)](#hoe-het-werkt-flow-prompt--diffsqa) * [Retrieval & indexing](#retrieval--indexing) * [Chunking & contextbudget](#chunking--contextbudget) * [Laravel-bewust + lichte graaf-boost](#laravel-bewust--lichte-graaf-boost) * [Veiligheid: diff-guard & apply](#veiligheid-diff-guard--apply) * [Troubleshooting](#troubleshooting) * [Roadmap (suggesties)](#roadmap-suggesties) * [Licentie](#licentie) --- ## Architectuur in 3 onderdelen | Onderdeel | Doel | Taken | Bestanden in deze repo | | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | | **LLM Proxy** | Dunne HTTP-laag voor chat/LLM + (optioneel) tool-calls; OpenWebUI-vriendelijk. | `/chat` endpoint, promptverrijking, streaming; kan tools/agent aanroepen. | `app.py` (routes) | | **OpenWebUI-compatible Tools** | Kleine helper-endpoints die je rechtstreeks vanuit OpenWebUI of de proxy kunt aanroepen. | STT (faster-whisper), TTS (piper), retrieval (Meili/BM25/Chroma), PDF/afbeelding utils. | `app.py` (tool-routes), helpers in `queue_helper.py` | | **Agent Repo & Repo QA** | “De smid”: zoekt relevante files, bouwt context, **maakt diffs** (dry-run), en kan **apply & push** doen op nieuwe branch. QA over repo. | Kandidaten zoeken, slim chunken, LLM-editplannen, diff-guards, branch & push. Repo-QA antwoord met padbronnen. | **`agent_repo.py`**, `smart_rag.py`, `windowing_utils.py`, `queue_helper.py` | **Mijn advies (prod vs dev):** * **Prod:** scheid *LLM Proxy + Tools* (publiek) van *Agent Repo/QA* (afschermen; heeft Gitea-rechten). * **Dev:** alles in één Uvicorn-app (zoals in deze Dockerfile) is prima. --- ## Belangrijkste features * **Hybride retrieval**: Meili/BM25 (file-niveau **harde signalen**) + Chroma/embeddings (chunk-niveau **semantiek**). * **Laravel-bewuste heuristiek**: routes scannen, controller ↔ view ↔ lang keys, FormRequests/Policies. * **Slim chunken**: taalspecifiek (PHP/Blade/JS/MD), functie/section-grenzen; overlap; contextbudget. * **Lichte graaf-boost**: route ⇄ controller ⇄ view ⇄ lang relaties wegen mee in ranking. * **Niet-destructieve patches**: diff-guard op deletieratio; kleine, anker-gebaseerde edits; sanity-checks. * **Repo-QA**: compacte, bronverwijzende antwoorden (“Bronnen: padnamen”). * **OpenWebUI-tools**: STT (faster-whisper), TTS (piper), retrieval als losse endpoints. * **Dry-run → Apply**: eerst diffs tonen; na *“Akkoord apply”* nieuwe branch + push. --- ## Snel starten ### Docker (aanbevolen) **Dockerfile (samenvatting)** ```dockerfile FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN apt-get update && apt-get -y install git curl ffmpeg libcairo2 libpango-1.0-0 libgdk-pixbuf2.0-0 apt-utils RUN pip install --upgrade pip RUN pip install --no-cache-dir -r requirements.txt RUN pip install PyPDF2 python-multipart gitpython chromadb httpx meilisearch pandas openpyxl python-pptx faster-whisper==1.0.0 cairosvg sentence-transformers rank-bm25 # piper TTS RUN apt-get update && apt-get install -y --no-install-recommends wget ca-certificates libstdc++6 libatomic1 \ && rm -rf /var/lib/apt/lists/* \ && mkdir -p /opt/piper \ && set -eux; URL="https://github.com/rhasspy/piper/releases/download/2023.11.14-2/piper_linux_x86_64.tar.gz"; \ wget -O /tmp/piper.tgz "$URL"; tar -xzf /tmp/piper.tgz -C /opt/piper --strip-components=1; \ ln -sf /opt/piper/piper /usr/local/bin/piper; rm -f /tmp/piper.tgz COPY app.py . COPY queue_helper.py . COPY agent_repo.py . COPY windowing_utils.py . COPY smart_rag.py . EXPOSE 8080 CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"] ``` **Build & run** ```bash # 1) Build docker build -t repo-agent:latest . # 2) Run (met voorbeeld-ENV; pas aan op jouw omgeving) docker run --rm -p 8080:8080 \ -e MEILI_URL=http://host.docker.internal:7700 \ -e MEILI_MASTER_KEY=your_meili_key \ -e GITEA_URL=http://host.docker.internal:3000 \ -e GITEA_TOKEN=your_gitea_token \ -e REPO_AGENT_SMART=1 \ -e AGENT_DESTRUCTIVE_RATIO=0.25 \ -e RAG_GRAPH_ENABLE=1 \ repo-agent:latest ``` > **Tip:** start MeiliSearch naast deze container (of gebruik bestaande). Chroma is optioneel; zonder Chroma valt retrieval semantisch terug op BM25/Meili. ### Zonder Docker (dev) ```bash python -m venv .venv && source .venv/bin/activate pip install -r requirements.txt pip install PyPDF2 python-multipart gitpython chromadb httpx meilisearch pandas openpyxl python-pptx faster-whisper==1.0.0 cairosvg sentence-transformers rank-bm25 uvicorn app:app --host 0.0.0.0 --port 8080 --reload ``` --- ## Configuratie (ENV) | Variabele | Betekenis | Default / Opmerking | | ---------------------------------------------- | --------------------------------------------------------- | ---------------------------- | | `MEILI_URL`, `MEILI_MASTER_KEY` | MeiliSearch voor file-retrieval & (optioneel) indexing. | Aanbevolen. | | `REPO_AGENT_SMART` | Schakel intent-/expansie + hybride retrieval in de agent. | `1` (aan) | | `GITEA_URL`, `GITEA_TOKEN` | Nodig voor private repos en **apply/push**. | Sterk aanbevolen voor Agent. | | `AGENT_DEFAULT_BRANCH` | Basisbranch om op te clonen/indexeren. | `main` (fallback `master`) | | `AGENT_DESTRUCTIVE_RATIO` | Max. deletieratio vóór blokkeren (0–1). | `0.25` (voorbeeld) | | `RAG_GRAPH_ENABLE` | **Lichte graaf-boost** op ranking inschakelen. | **`1` (aan)** | | `RAG_EMB_WEIGHT` | Gewicht embeddings t.o.v. lexicaal signaal. | `0.6` typisch | | `RAG_PER_QUERY_K`, `RAG_N_RESULTS` | Recall parameters hybrid retrieval. | 30 / 18 (voorbeeld) | | `RAG_NEIGHBORS` | Laravel “buren” (routes→controllers→views). | `1` (aan) | | `LLM_PRIORS_ENABLE`, `LLM_PRIORS_K` | LLM-gebaseerde pad-prior suggesties. | `1` / `12` | | `LARAVEL_PRIORS_K` | Max #Laravel priors vóór RAG. | `8` | | `CHUNK_CHARS_LARAVEL`, `CHUNK_OVERLAP_LARAVEL` | Chunkgrootte/overlap voor Laravel-stacks. | 1800 / 300 | | `CHUNK_CHARS_DEFAULT`, `CHUNK_OVERLAP_DEFAULT` | Idem voor generieke stacks. | 2600 / 350 | | `AGENT_QA_CTX_BUDGET_TOKENS` | Tokenbudget voor Repo-QA context. | 6000 | | `QA_MIN_PER_SNIPPET`, `QA_MAX_PER_SNIPPET` | Contextdistributie per snippet. | 180 / 900 | | `QA_KEEP_TOP_K` | Max snippets na trimming. | 8 | > **NB**: Veel van bovenstaande komen rechtstreeks terug in `agent_repo.py` (zie env-reads aldaar). Waarden hierboven zijn “goede defaults”. --- ## Endpoints > Endpoints staan in `app.py`. Onderstaande is het **standaardpatroon** in deze setup. ### 1) LLM Proxy * `POST /chat` — voer een chat uit (optioneel met tool-calls) Voorbeeld: ```bash curl -X POST http://localhost:8080/chat \ -H "Content-Type: application/json" \ -d '{"messages":[{"role":"user","content":"Geef een korte samenvatting van de meldingenmodule."}]}' ``` ### 2) OpenWebUI-compatible Tools * `POST /tools/stt` — audio → tekst (faster-whisper) * `POST /tools/tts` — tekst → audio (piper) * `POST /tools/retrieve` — retrieval (Meili/BM25 + embeddings) Voorbeeld: ```bash curl -X POST http://localhost:8080/tools/retrieve \ -H "Content-Type: application/json" \ -d '{"query":"waar staat het wachtwoordbeleid?", "k": 12}' ``` ### 3) Agent Repo & Repo QA * `POST /agent/dryrun` — **genereer diffs**, geen writes * `POST /agent/apply` — **schrijf & push** (na akkoord) * `POST /qa/ask` — Repo-QA met paden als bronnen Voorbeelden: ```bash # Dry-run diffs curl -X POST http://localhost:8080/agent/dryrun \ -H "Content-Type: application/json" \ -d '{"repo":"owner/project","user_goal":"Vervang \"Versturen\" → \"Verzenden\" in meldingen-create"}' # Apply (na akkoord) curl -X POST http://localhost:8080/agent/apply \ -H "Content-Type: application/json" \ -d '{"repo":"owner/project","confirm":"Akkoord apply"}' # Repo-QA curl -X POST http://localhost:8080/qa/ask \ -H "Content-Type: application/json" \ -d '{"repo":"owner/project","question":"Waar wordt de storing-aanmaak afgehandeld?"}' ``` --- ## Hoe het werkt (flow prompt → diffs/qa) **Samengevatte pipeline (Agent Repo):** 1. **Prompt binnen** → intent & scope (optioneel refine; NL/EN synonyms). 2. **Repo selecteren** → clone/update op basisbranch; meelifall-cache. 3. **Candidate discovery (hybride)** * **Meili/BM25 (file-niveau, hard signal)**: top-N files. * **LLM-priors + Laravel-heuristiek**: routes, controllers, views, lang-keys. * **Chroma/embeddings (chunk-niveau, zacht signaal)**. * **Lichte graaf-boost**: route ⇄ controller ⇄ view ⇄ lang. 4. **Slim chunken**: functie/section-grenzen; overlap; metadata (path, class/method, blade-section, start/end). 5. **Contextbouw (RAG)**: top-chunks + korte file/dir-summaries → compact context. 6. **Patchvoorstel per bestand** * **Veilige literal-replaces** (UI-labels) → minimaal. * **LLM edit-plan** met regex/insert/replace-operaties (max 4 stappen). * **Volledige rewrite (guarded)** als laatste redmiddel. 7. **Diff-guard & checks**: deletieratio drempel; syntaxis/parse waar mogelijk. 8. **Resultaat**: toon diffs + “waarom geselecteerd”; **Akkoord apply** → branch + push. **Repo-QA:** * Zelfde discovery/ctx, maar i.p.v. diffs levert QA een **kort antwoord + bronpaden**. --- ## Retrieval & indexing * **MeiliSearch**: snelle file-retriever. Gebruik `name/path/summary/content` als searchable; boost bekende paden (`routes/**`, `resources/views/**`, `app/Http/Controllers/**`) bij route/view/vertaling-taken. * **BM25 fallback**: aanwezig als Meili niet beschikbaar is. * **Chroma (optioneel)**: embeddings per **chunk** met metadata (`path`, `lang`, `class`, `function`, `route`, `blade_section`, `start/end`). Wordt gebruikt als **zachte** rankingbron naast Meili. **Reranking (vuistregel)** `FinalScore(file) = 0.55 * Meili + 0.35 * Embeddings + 0.10 * Heuristiek + PathBoost + Recency` --- ## Chunking & contextbudget * **Taalspecifiek**: * PHP → class/method/closure; docblocks mee. * Blade → `@section`, componenten, top-level HTML-blokken. * JS/TS → function/module-grenzen. * MD/Tekst → alinea’s; headers intact. * **Budget**: context trimmer verdeelt tokens over snippets (`QA_MIN/MAX_PER_SNIPPET`, `QA_KEEP_TOP_K`), deduplication, novelty-score en overlap. --- ## Laravel-bewust & lichte graaf-boost * **Route-mapping**: scan `routes/web.php`/`api.php` → `Controller@method`. * **View & lang-koppeling**: `return view('foo.bar')` → `resources/views/foo/bar.blade.php`; `__('key')`, `@lang('key')` → `resources/lang/**`. * **Neighbors**: controller → view(s), route → controller, view → partials/layouts (dichtbij). * **Graph-boost (aan)**: deze relaties wegen mee in ranking (standaard **aan** via `RAG_GRAPH_ENABLE=1`). **Tree + samenvattingen** * Projecttree krijgt **korte omschrijvingen per dir/file** (README’s, docblocks, eerste regels) zodat de LLM **snapt welke lagen** er zijn. Deze summaries worden hergebruikt in retrieval en prompt-context. --- ## Veiligheid: diff-guard & apply * **Destructiviteits-guard**: schat deletieratio met `difflib.ndiff`; blokkeer als `> AGENT_DESTRUCTIVE_RATIO` (files < ~6 regels worden soepeler behandeld). * **Editstrategie (minimaal eerst)**: 1. gerichte literal-replaces (quotes, fallbacks), 2. scoped HTML/Blade vervanging, 3. LLM edit-plan (max 4 bewerkingen), 4. guarded rewrite. * **Apply**: alleen na “Akkoord apply” → nieuwe branch `task/-YYYYMMDD-HHMMSS` → **push** (Gitea token vereist). --- ## Troubleshooting * **Geen kandidaten gevonden** → specificeer een route, bestand of label-tekst; controleer Meili/Chroma beschikbaarheid. * **Apply faalt** → check `GITEA_URL`/`GITEA_TOKEN` en repo-rechten; branch bestaat al? * **STT/TTS werkt niet** → controleer `ffmpeg` in container en piper/faster-whisper install (zitten in Dockerfile). * **Lage precisie** → verhoog `RAG_PER_QUERY_K` en `RAG_N_RESULTS`, zet `RAG_GRAPH_ENABLE=1`, gebruik `LLM_PRIORS_ENABLE=1`. --- ## Roadmap (suggesties) * **AST-chunking voor PHP** (nikic/php-parser) voor nog scherpere grenzen. * **Cross-encoder reranker** (klein model) bovenop cosine. * **Blade compile-check** (sanity) en `php -l` op changed files. * **Auto test-suggesties** bij diffs. * **Meer tools** (PDF tabel-extractie, image-OCR) als OpenWebUI-endpoints. --- ## Licentie Kies een licentie (MIT/Apache-2.0/GPL-3.0). Voeg `LICENSE` toe aan de repo. --- ### Bestandsoverzicht ``` app.py # Uvicorn/FastAPI app; /chat, tools, agent/qa routes agent_repo.py # Repo Agent & Repo QA: retrieval, chunking, diffs, apply smart_rag.py # Intent/expansie, hybride retrieval helpers windowing_utils.py # Chunking & contextbudget utils queue_helper.py # Hulpfuncties voor taken/IO Dockerfile # Container build (Python 3.11-slim, piper, faster-whisper, Meili/Chroma clients) requirements.txt # Basis Python dependencies ```