Introduzione: RAG e Vector Database per un Chatbot Intelligente
Per rendere il chatbot di sergigiuseppe.it realmente intelligente e contestualizzato, ho implementato un sistema di Retrieval-Augmented Generation (RAG) basato su embedding di documenti. Questo approccio permette al chatbot di rispondere attingendo da una knowledge base aggiornata dei miei progetti, esperienze e competenze professionali.
In questo articolo tecnico condivido l'architettura completa del workflow di embedding implementato con n8n, Google Gemini Embeddings, e PostgreSQL con pgvector su Neon Database.
Stack Tecnologico Utilizzato
Per realizzare questo sistema ho scelto tecnologie open source e servizi cloud con tier gratuiti generosi:
- n8n: Piattaforma di workflow automation per orchestrare l'intero processo
- Google Gemini API: Per generare embeddings (text-embedding-004, 768 dimensioni)
- Neon Database: PostgreSQL serverless con supporto pgvector per vector search
- Docker: Per containerizzazione e deployment consistente
Architettura del Workflow di Embedding
Il workflow si compone di diverse fasi che gestiscono l'upload, l'estrazione, il chunking e il salvataggio vettoriale dei documenti.
Screenshot del workflow n8n implementato per l'elaborazione e l'embedding dei documenti
Fase 1: Ricezione Documenti via Webhook
Il punto di ingresso è un webhook endpoint che accetta file tramite richieste POST:
POST /webhook/document-upload
Content-Type: multipart/form-data
Il webhook è configurato per ricevere documenti in formato:
- PDF (esperienze, progetti, CV)
- TXT (descrizioni tecniche)
- Markdown (documentazione)
Fase 2: Validazione e Routing del File Type
Ho implementato una logica condizionale con nodi If per gestire diversi formati:
If file is PDF:
- Controlla il mime type:
application/pdf - Route verso extractor PDF specifico
If file is Text:
- Controlla il mime type:
text/plainotext/markdown - Route verso extractor testuale
Questa validazione garantisce che solo file supportati vengano processati, mentre altri formati vengono bloccati dal nodo Stop and Error.
Fase 3: Estrazione del Contenuto
Due nodi Extract from File gestiscono l'estrazione:
- Extract from File (PDF): Utilizza librerie di parsing PDF per estrarre testo strutturato
- Extract from File1 (TXT): Legge direttamente il contenuto testuale
Entrambi producono output binario che viene passato alla fase successiva.
Fase 4: Chunking Semantico con Default Data Loader
Il nodo Default Data Loader è configurato per:
Type of Data: Binary
Data Format: Automatically Detect by Mime Type
Text Splitting: Recursive Character Text Splitter
Chunk Size: 1000 caratteri
Chunk Overlap: 200 caratteri
Il Recursive Character Text Splitter divide il testo rispettando la struttura semantica (paragrafi, sezioni) invece di tagliare arbitrariamente. L'overlap del 20% preserva il contesto tra chunk adiacenti.
Fase 5: Generazione Embeddings con Google Gemini
Il nodo Embeddings Google Gemini trasforma ogni chunk testuale in vettori numerici:
Configurazione:
- Model:
text-embedding-004 - Output dimensions:
768 - Batch processing: Automatico
Google Gemini è stato scelto per:
- Tier gratuito generoso (1.500 richieste/giorno)
- Qualità embeddings eccellente
- Dimensioni vettore ottimali (768 vs 1536 di OpenAI)
Fase 6: Storage in PostgreSQL con pgvector
Il nodo Postgres PGVector Store salva i chunk embeddati nel database Neon:
Schema tabella documents:
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
content TEXT NOT NULL,
embedding VECTOR(768),
metadata JSONB
);
Configurazione:
- Operation Mode: Insert Documents
- Table Name: documents
- Embedding Batch Size: 200
Ottimizzazioni Implementate
Performance
- Chunk Size Ottimizzato: 1.000 caratteri bilancia contesto e precisione nel retrieval
- Batch Processing: Gli embeddings vengono processati in batch per ridurre chiamate API
- Connection Pooling: Neon gestisce automaticamente il pooling delle connessioni PostgreSQL
Gestione RAM su Railway
Dato che n8n gira su Railway free tier (500MB RAM), ho implementato:
N8N_CONCURRENCY_PRODUCTION_LIMIT=1
EXECUTIONS_DATA_PRUNE=true
EXECUTIONS_DATA_MAX_AGE=168
Questo limita le esecuzioni concorrenti ed elimina dati vecchi per liberare memoria.
Error Handling
Il nodo Stop and Error blocca file non supportati con messaggio chiaro, evitando elaborazioni fallite.
Risultati e Metriche
Dopo l'implementazione:
- Tempo medio elaborazione: 2-3 secondi per documento PDF (5-10 pagine)
- Chunk generati: Media 15-20 per documento
- Costo: $0 (tier gratuiti Google Gemini + Neon)
- Accuracy retrieval: >90% su query tecniche specifiche
Conclusioni
Implementare un sistema di embedding professionale richiede attenzione all'architettura, ma strumenti come n8n semplificano enormemente l'orchestrazione. La combinazione di Google Gemini (embeddings gratuiti), Neon (PostgreSQL serverless), e n8n (workflow automation) permette di creare soluzioni RAG production-ready con costi minimi.

