Overview
RAG Chatbot
Componente Angular <wuic-rag-chatbot> che permette di interrogare il codebase
WUIC in linguaggio naturale, con due modalita' operative: retrieval pure
(top-K snippet del codice) e RAG + LLM (risposta generata da Claude usando
i top-K come contesto). Degrada automaticamente in retrieval-only se la API
key Claude non e' configurata sul server.
Architettura
Stack a 3 layer, tutti gia' deployati nel progetto:
- Layer 1 — Server Python FastAPI
rag_server.pysu127.0.0.1:8765,
carica al boot l'indice ibrido BM25 + bge-m3 + LoRA cross-encoder Phase C
da c:/src/Wuic/codebase_embeddings/.
- Layer 2 — Bridge C#
RagControllerin KonvergenceCore (/api/Rag/Query,
/api/Rag/Chat, /api/Rag/Health, /api/Rag/Reload), proxy autenticato
via cookie k-user.
- Layer 3 — Componente Angular standalone
<wuic-rag-chatbot>esportato
da wuic-framework-lib.
Vedi anche la skill operativa skills/rag-chatbot-creation/SKILL.md per il
playbook end-to-end di creazione/manutenzione del componente, e
skills/rag-rebuild-pipeline/SKILL.md per il rebuild dell'indice/LoRA.
Contesto pagina e retrieval dinamico dei metadata
Quando l'utente chatta da una pagina dell'app, il componente inietta nel prompt
un contesto pagina minimale: solo la route/pagina corrente (es. cities/list,
cities/edit, designer). NON inlinea l'elenco colonne, l'identita' SQL o i
dettagli dei lookup — inlinearli gonfiava ogni richiesta a prescindere dal prompt
e saturava il context window.
I dettagli mancanti vengono recuperati on-demand dal modello tramite il tool
non-terminale request_metadata_detail, risolto lato backend da
RagController.ResolveMetadataDetail (l'engine non ha accesso al DB metadata). Il
modello chiama il tool, riceve il risultato come tool_result e SOLO DOPO emette
il propose_* con i nomi reali. Il loop multi-turn e' gestito dall'engine (max 3
turni di retrieval).
detail supportati:
detail | Ritorna | Quando |
|---|---|---|
columns | identita' SQL (schema/tabella + full qualifier) e l'elenco colonne reali (nome, tipo, lookup, required, pk, nome SQL) | servono i nomi reali delle colonne di una route |
lookup_columns | join_alias, value_field, text_field, related_route, related_columns[] di una colonna lookupByID | si compone uno snippet SQL su un lookup |
Convenzione alias di join (lookup): la query autogenerata WUIC joina la tabella
correlata di una colonna lookupByID con alias <column>_<entity> (es. la colonna
StateProvinceID lookup verso stateprovinces ha alias StateProvinceID_stateprovinces).
Negli snippet SQL i campi della tabella correlata si referenziano come
[<join_alias>].[<col>], es. [StateProvinceID_stateprovinces].[StateProvinceName].
Il valore esatto dell'alias va sempre ottenuto via
request_metadata_detail{detail:'lookup_columns'}, mai dedotto a mano.
Il meccanismo e' estendibile: nuovi detail (es. physical_columns, related_routes,
enum_values) si aggiungono nel resolver senza toccare il componente Angular ne'
gonfiare il contesto.
Modalita'
mode input | Comportamento |
|---|---|
auto (default) | Usa chat se il backend espone Claude API key, altrimenti retrieval |
chat | Forza RAG + LLM. Se la API key manca, il backend ritorna mode=retrieval-only con warning visibile |
retrieval | Forza retrieval-only, salta la chiamata LLM (utile per ridurre costi) |
Inputs
| Input | Tipo | Default | Descrizione |
|---|---|---|---|
title | string | 'Assistente codebase WUIC' | Etichetta header |
mode | 'auto' | 'chat' | 'retrieval' | 'auto' | Modalita' operativa |
topK | number | 5 | Numero di chunk da retrieve dal RAG |
showSources | boolean | true | Mostra/nasconde i source chip nei messaggi assistant |
maxHistory | number | 20 | Numero massimo di turn mantenuti in memoria |
placeholder | string | 'Chiedi qualcosa...' | Placeholder dell'input |
model | string | 'claude-haiku-4-5-20251001' | Modello Claude per la modalita' chat |
chatHeight | string | '420px' | Altezza fissa area chat |
showClearButton | boolean | true | Mostra bottone "Svuota cronologia" |
Outputs
| Output | Payload | Descrizione |
|---|---|---|
resultSelected | RagSource | Click su un source chip; il componente tenta anche un deep-link vscode://file/... |
errorOccurred | {message, details?} | Errori HTTP non recuperabili |
turnAdded | RagChatbotTurn | Emette dopo ogni turn (user o assistant) aggiunto alla history |
Esempio d'uso
Standalone import nel componente parent:
- selector HTML:
<wuic-rag-chatbot mode="auto" [topK]="5" (resultSelected)="onSrc($event)"></wuic-rag-chatbot> - import TypeScript:
import { WuicRagChatbotComponent, RagSource } from 'wuic-framework-lib'; - aggiungere
WuicRagChatbotComponentagliimportsdel componente standalone parent.
Per una pagina demo completa con aside debug e gestione eventi, vedi
WuicTest/wwwroot/src/app/component/rag-chatbot-demo-page/.
Auth
Tutte le chiamate HTTP partono con withCredentials: true e il bridge C#
applica gli stessi check di autenticazione degli altri controller WUIC
(cookie di sessione k-user, regola 10 di AGENTS). Mai esporre il server
Python 127.0.0.1:8765 direttamente al browser: deve sempre essere proxiato
dal C#.
Service WuicRagService
API tipizzata sopra RagController, esportata da wuic-framework-lib.
Tre metodi principali:
query(text, {topK, useLora}) -> Observable<RagQueryResponse>chat(text, history, {topK, model}) -> Observable<RagChatResponse>health() -> Observable<RagHealthResponse>reload() -> Observable<{status, ...}>(post rebuild RAG)
Varianti *Async ritornano Promise via firstValueFrom().
Tutte le interfacce RagSource, RagQueryResponse, RagChatResponse,
RagHealthResponse, RagChatTurn sono esportate.
Modello Claude
Default: claude-haiku-4-5-20251001 (veloce, italiano nativo, ~$0.001 per
query da 5 chunk). Override possibile via input [model] del componente
oppure passando options.model al metodo chat() del service.
System prompt usato server-side:
> Sei un assistente esperto del codebase WUIC. Rispondi alla domanda dell'utente
> usando ESCLUSIVAMENTE il contesto fornito. Se la risposta non e' nel contesto,
> rispondi 'Non ho trovato informazioni sufficienti nel codebase per rispondere.'
> Cita sempre i file rilevanti tra parentesi quadre nel formato
> [file.ext::SimboloOpzionale]. Rispondi in italiano salvo richiesta esplicita
> di un'altra lingua. Non inventare API o nomi di metodi: se non sono nel
> contesto, dillo esplicitamente.
Fallback automatico
Quando il backend rileva una di queste condizioni, il response include
mode: 'retrieval-only' + warning + sources:
ANTHROPIC_API_KEYnon settata sul server Python- chiamata Claude fallita (errore HTTP, rate limit, modello sconosciuto, ecc.)
Il componente Angular interpreta response.mode === 'retrieval-only' e mostra
nel turn assistant un summary testuale dei top-K chunk + il banner warning,
cosi' l'utente vede comunque dei risultati utili.
Prerequisiti runtime
- Server Python
rag_server.pyattivo su127.0.0.1:8765(vedi skill
rag-chatbot-creation per il setup NSSM in produzione)
- KonvergenceCore in esecuzione (espone
/api/Rag/...) - Login con cookie
k-userdi sessione valido - (Opzionale)
ANTHROPIC_API_KEYenv var sul server Python per modalita' chat
Avvio (primo utilizzo)
Se accedendo alla route rag-chatbot dal menu vedi il banner
"Server RAG non raggiungibile" con stato RAG offline, significa che il
server Python non e' in ascolto.
Prerequisiti: Python 3.12 (winget install Python.Python.3.12)
Setup e avvio con rag-setup.ps1
Lo script rag-setup.ps1 automatizza la creazione del venv e l'installazione
delle dipendenze. Funziona sia dal repository sorgente che da un pacchetto
ZIP di deploy (i file RAG sono inclusi in entrambi).
# Setup (una sola volta) — crea venv, installa torch + dipendenze
pwsh scripts/rag-setup.ps1
# Per GPU CUDA (opzionale, piu' veloce)
pwsh scripts/rag-setup.ps1 -CudaVersion 12.1
# Avvio serverIl cold start richiede ~13 secondi (caricamento indice + LoRA). Una volta
che il log mostra Uvicorn running on http://127.0.0.1:8765, ricarica la
pagina nel browser: il banner scompare e il chatbot passa in modalita'
operativa.
Per produzione (Windows service persistente) vedi la skill
skills/rag-chatbot-deploy/SKILL.md.
Hot-reload post rebuild RAG
Dopo aver rigenerato l'indice/LoRA con la skill rag-rebuild-pipeline, basta
chiamare:
POST /api/Rag/Reload(via WuicRagService.reload())- oppure restartare il servizio Python
per ricaricare il nuovo indice senza downtime applicativo.
Test
I test del service e del componente sono in:
projects/wuic-framework-lib/src/lib/service/wuic-rag.service.spec.ts(14 test)projects/wuic-framework-lib/src/lib/component/rag-chatbot/rag-chatbot.component.spec.ts(18 test)
Eseguibili con npm run test:unit:wuic-lib (vitest, runner di default del lib
post-migrazione karma->vitest).
Riferimenti
- Skill creazione:
skills/rag-chatbot-creation/SKILL.md - Skill rebuild RAG:
skills/rag-rebuild-pipeline/SKILL.md - Server Python:
c:/src/Wuic/codebase_embeddings/rag_server.py - Bridge C#:
c:/src/Wuic/KonvergenceCore/Controllers/RagController.cs - Service Angular:
projects/wuic-framework-lib/src/lib/service/wuic-rag.service.ts - Componente:
projects/wuic-framework-lib/src/lib/component/rag-chatbot/rag-chatbot.component.ts - Demo page:
c:/src/Wuic/WuicTest/wwwroot/src/app/component/rag-chatbot-demo-page/