System Design GenAI: Fondamenti e Architetture per Applicazioni in Produzione
Stai cercando di integrare un LLM nella tua applicazione e ti chiedi se fare RAG, fine-tuning o semplicemente migliorare i prompt? Non sei il solo: secondo un'analisi di 2024, il 73% dei deployment GenAI in enterprise fallisce entro sei mesi, principalmente per scelte architetturali sbagliate nelle fasi iniziali di progettazione. Il problema non e il modello: e che molti team scelgono la tecnologia prima di capire il problema.
Questa guida ti fornisce un framework decisionale pratico per progettare sistemi GenAI in produzione, coprendo le architetture fondamentali - RAG, fine-tuning, prompt engineering - e i criteri per scegliere l'approccio giusto in base al tuo caso d'uso specifico.
Cosa Imparerai
- Le tre architetture fondamentali: RAG, fine-tuning e prompt engineering
- Framework decisionale: quando usare ciascun approccio
- Architetture di sistema per applicazioni GenAI in produzione
- Stack tecnologico 2026: LangChain, LlamaIndex, vLLM
- Pattern comuni e anti-pattern da evitare
- Metriche di qualita per valutare un sistema RAG
Il Problema del 73%: Perche i Deployment GenAI Falliscono
Prima di entrare nelle architetture, e cruciale capire perche cosi tanti progetti falliscono. Le cause principali identificate nelle post-mortem di deployment enterprise sono:
- Hallucination non gestita: il modello genera risposte plausibili ma false, e nessun sistema di validazione e stato implementato
- Latenza inaccettabile: p99 oltre i 3-5 secondi su query che l'utente si aspetta veloci
- Costi esplosivi: nessun calcolo del costo per query prima del go-live, poi il budget viene bruciato in settimane
- Knowledge cutoff non gestito: il modello non conosce dati recenti o privati dell'azienda
- Mancanza di tracciabilita: impossibile sapere su quali documenti si basa una risposta (critico in contesti regolamentati)
Ogni architettura che esamineremo affronta alcuni di questi problemi meglio di altri. Conoscere i trade-off ti permette di progettare sistemi robusti fin dall'inizio.
Le Tre Architetture Fondamentali
1. Prompt Engineering
Il punto di partenza per qualsiasi sistema GenAI: strutturare il prompt per guidare il modello verso l'output desiderato. Tecniche chiave nel 2026:
- Few-shot prompting: fornire esempi input-output nel prompt
- Chain-of-thought (CoT): chiedere al modello di ragionare step-by-step prima di rispondere
- System prompt: definire il comportamento e il contesto del modello
- Structured output: forzare l'output in formato JSON o XML per parsing affidabile
# Esempio: prompt engineering con structured output
import json
from openai import OpenAI
client = OpenAI()
def analyze_ticket(ticket_text: str) -> dict:
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": """Sei un sistema di triage per ticket di supporto.
Analizza il ticket e restituisci JSON con:
- priority: "high" | "medium" | "low"
- category: "bug" | "feature" | "question"
- sentiment: "frustrated" | "neutral" | "positive"
- estimated_resolution_hours: numero intero"""
},
{
"role": "user",
"content": f"Ticket: {ticket_text}"
}
],
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
# Uso
result = analyze_ticket("Il mio account e bloccato da ieri, non riesco ad accedere!")
# {"priority": "high", "category": "bug", "sentiment": "frustrated", ...}
Quando usarlo: casi semplici e ben definiti, prototipazione rapida, quando non hai dati privati da integrare e il modello base gia conosce il dominio.
Limiti: non funziona con dati recenti o proprietari, hallucination su fatti specifici, costo proporzionale alla lunghezza del contesto.
2. RAG - Retrieval-Augmented Generation
RAG risolve il problema del knowledge cutoff e dei dati privati: invece di affidarsi solo alla conoscenza del modello, recupera documenti rilevanti da un database e li inserisce nel contesto prima della generazione.
L'architettura base di un sistema RAG ha quattro fasi:
- Indexing: i documenti vengono suddivisi in chunk, convertiti in vettori embedding e salvati in un vector database
- Retrieval: la query dell'utente viene convertita nello stesso spazio embedding e si recuperano i chunk piu simili
- Augmentation: i chunk recuperati vengono inseriti nel prompt come contesto
- Generation: il LLM genera la risposta basandosi sul contesto fornito
# RAG minimo funzionante con LangChain e Qdrant
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_qdrant import QdrantVectorStore
from langchain.chains import RetrievalQA
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 1. Carica e chunka i documenti
loader = PyPDFLoader("manuale_prodotto.pdf")
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=64
)
chunks = splitter.split_documents(docs)
# 2. Crea il vector store
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = QdrantVectorStore.from_documents(
documents=chunks,
embedding=embeddings,
url="http://localhost:6333",
collection_name="manuale_prodotto"
)
# 3. Crea la chain RAG
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
rag_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
return_source_documents=True
)
# 4. Query
result = rag_chain.invoke({"query": "Come configuro le notifiche email?"})
print(result["result"])
# La risposta cita i documenti recuperati, non inventa
Quando usarlo: knowledge base aziendale, documentazione tecnica, FAQ, qualsiasi caso dove la risposta deve basarsi su documenti specifici e tracciabili.
Limiti: qualita dipendente dalla qualita del retrieval, latenza aggiuntiva, overhead di infrastruttura.
3. Fine-tuning
Il fine-tuning adatta il comportamento del modello attraverso addestramento aggiuntivo su dati specifici del dominio. Nel 2026, il paradigma dominante e il Parameter-Efficient Fine-tuning (PEFT) con tecniche come LoRA e QLoRA che permettono di addestrare su hardware consumer.
# Fine-tuning con LoRA usando transformers e PEFT
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig, get_peft_model, TaskType
import torch
model_name = "meta-llama/Llama-3.1-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16,
device_map="auto"
)
# Configurazione LoRA: adatta solo il 0.1% dei parametri
lora_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
r=16, # rank della matrice di adattamento
lora_alpha=32, # scaling factor
lora_dropout=0.1,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj"]
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# trainable params: 6,815,744 || all params: 8,037,191,680
# trainable%: 0.0848%
Quando usarlo: quando hai migliaia di esempi di addestramento, serve un formato di output molto specifico e consistente, o vuoi ridurre la lunghezza del prompt eliminando esempi few-shot.
Anti-pattern critico: non fare fine-tuning per iniettare conoscenza fattuale (date, numeri, fatti specifici). Il modello "memorizza" senza comprensione e hallucinera comunque. Per la conoscenza usa RAG.
Il Framework Decisionale
La domanda piu importante non e "quale tecnologia usare" ma "qual e il mio problema reale". Questo decision tree copre il 90% dei casi d'uso:
Hai dati privati o recenti che il modello non conosce?
SI --> Considera RAG come base
NO --> Prompt engineering puo essere sufficiente
Il tuo knowledge base e aggiornato frequentemente?
SI --> RAG (indicizza i nuovi documenti, non ri-addestra)
NO --> Fine-tuning puo essere considerato
Hai 1000+ esempi di coppie input-output di alta qualita?
SI --> Fine-tuning e un'opzione valida
NO --> Stai nei limiti di RAG + few-shot
Hai bisogno di tracciabilita (citare le fonti)?
SI --> RAG obbligatorio
NO --> Piu flessibilita
Latenza critica (sotto 500ms)?
SI --> Fine-tuning (elimina retrieval overhead) o caching aggressivo
NO --> RAG funziona bene
Conclusione tipica 2026:
Start with RAG + prompt engineering
Add fine-tuning solo se RAG non raggiunge qualita richiesta
Architettura di Sistema per Produzione
Un sistema GenAI production-grade va ben oltre il semplice "LLM + vector database". I componenti necessari per un deployment serio:
# Stack minimo per RAG in produzione (Docker Compose)
services:
api:
image: your-genai-api:latest
environment:
OPENAI_API_KEY: ${OPENAI_API_KEY}
QDRANT_URL: http://qdrant:6333
REDIS_URL: redis://redis:6379
depends_on:
- qdrant
- redis
qdrant:
image: qdrant/qdrant:v1.9.0
volumes:
- qdrant_storage:/qdrant/storage
ports:
- "6333:6333"
redis:
image: redis:7-alpine
# Semantic cache: evita LLM calls per query simili
volumes:
- redis_data:/data
prometheus:
image: prom/prometheus:latest
# Monitora: latency p50/p95/p99, costo per query, quality score
grafana:
image: grafana/grafana:latest
# Dashboard: LLM performance, retrieval quality, cost tracking
I componenti critici che separano un prototipo da un sistema in produzione:
- Semantic caching (Redis + libreria come GPTCache): riduce i costi del 30-60% per applicazioni con query simili ricorrenti
- Observability: traccia ogni chiamata LLM con latenza, tokens usati, costo e quality score - senza questi dati non puoi ottimizzare
- Fallback strategy: cosa succede quando OpenAI e down? Hai un modello locale come backup?
- Rate limiting e quota management: proteggi il tuo budget dalle query anomale
- PII detection: prima di mandare dati al LLM, rileva e oscura dati personali sensibili
Lo Stack Tecnologico del 2026
L'ecosistema GenAI si e stabilizzato intorno a pochi player dominanti:
Stack Consigliato 2026
- Orchestrazione: LangChain v0.3+ o LlamaIndex v0.10+ per pipeline RAG complesse; LangGraph per workflow agentici
- Vector Database: Qdrant (self-hosted, eccellente performance), pgvector (gia in PostgreSQL, sotto 1M vettori), Pinecone (managed, latenza garantita)
- Inference: vLLM o TensorRT-LLM per modelli open source self-hosted; OpenAI/Anthropic per API cloud
- Embeddings: text-embedding-3-small di OpenAI (1536 dim, $0.02/1M token) o all-MiniLM-L6-v2 per self-hosting gratuito
- Observability: LangSmith, Weights & Biases Weave, o Phoenix per tracing delle chain
- Evaluation: RAGAS per metriche RAG automatizzate (faithfulness, answer relevancy, context recall)
Metriche di Qualita per Sistemi RAG
Come sapere se il tuo sistema RAG funziona bene? Il framework RAGAS definisce metriche misurabili:
# Valutazione automatica con RAGAS
from ragas import evaluate
from ragas.metrics import (
faithfulness, # la risposta e supportata dai documenti recuperati?
answer_relevancy, # la risposta risponde alla domanda?
context_recall, # i documenti recuperati contengono le info necessarie?
context_precision # i documenti recuperati sono tutti rilevanti?
)
from datasets import Dataset
# Dataset di test (ground truth necessario)
test_data = {
"question": ["Come configuro l'autenticazione 2FA?"],
"answer": ["Per configurare 2FA, vai in Impostazioni > Sicurezza..."],
"contexts": [["Documentazione 2FA: ...", "Guida sicurezza: ..."]],
"ground_truth": ["La 2FA si configura tramite l'app mobile nelle impostazioni sicurezza"]
}
dataset = Dataset.from_dict(test_data)
result = evaluate(dataset, metrics=[
faithfulness,
answer_relevancy,
context_recall,
context_precision
])
print(result)
# faithfulness: 0.95 (la risposta non inventa)
# answer_relevancy: 0.88 (la risposta e pertinente)
# context_recall: 0.82 (i doc recuperati coprono la risposta)
# context_precision: 0.91 (i doc recuperati sono rilevanti)
Target realistici per un sistema in produzione: faithfulness > 0.85 (critico: sotto questo soglia le hallucinations sono frequenti), answer_relevancy > 0.80, context_recall > 0.75.
Anti-pattern da Evitare
- Chunk size fisso per tutti i documenti: documenti strutturati (FAQ, API docs) richiedono chunking diverso da testo narrativo
- Solo retrieval semantico: fallisce su termini tecnici esatti; usa hybrid search (BM25 + semantico)
- Nessun reranking: i top-k vettori non sono necessariamente i piu utili; un cross-encoder migliora la precision del 15-20%
- RAG senza evaluation continua: la qualita si degrada quando i documenti cambiano; monitora faithfulness in produzione
- Fine-tuning come prima scelta: e costoso e lento; RAG e quasi sempre la mossa giusta per iniziare
Conclusioni e Next Steps
Il sistema design per applicazioni GenAI richiede scelte architetturali che vanno ben oltre la selezione del modello. La regola pratica del 2026: inizia sempre con RAG + prompt engineering, misura la qualita con RAGAS, e aggiungi fine-tuning solo se il gap di qualita persiste dopo l'ottimizzazione del retrieval.
Nei prossimi articoli di questa serie esploreremo ogni componente in dettaglio: la selezione del vector database giusto, le strategie di chunking, l'hybrid search e l'architettura agentica con LangGraph.

Commenti
Caricamento commenti...
Accedi per commentare