f in x
LangChain e LLM per Sviluppatori: la Pillar Guide per Costruire Applicazioni AI in Produzione
> cd .. / HUB_EDITORIALE > Visualizza in Inglese
Intelligenza Artificiale & Software

LangChain e LLM per Sviluppatori: la Pillar Guide per Costruire Applicazioni AI in Produzione

[2026-06-12] Author: Ing. Calogero Bono

Il problema: state costruendo un prototipo che non reggerà mai il traffico reale

Avete un LLM che risponde, una chiamata API che funziona in console e un entusiasmo che dura fino al primo caricamento lento di un endpoint. Poi arriva il cliente: “ma quando lo mettiamo online?”. E lì scoprite che il vostro codice Python in un notebook non sa cosa sia un load balancer, che i token costano come il caffè di una settimana e che rispondere a domande su manuali di prodotto significa costruire una pipeline RAG da zero.

Noi, di Meteora Web, ci siamo passati. E abbiamo smesso di contare i prototipi lasciati a metà. Per questo abbiamo scritto questa guida pillar: per dare a voi sviluppatori una mappa chiara del percorso che va dalla prima ChatOpenAI fino a un'app LLM pronta per il mondo reale.

Qui sotto trovate i fondamentali: LangChain, RAG, vettor database, LlamaIndex, LangSmith, embeddings, streaming, fine‑tuning, deployment e gestione dei costi. Ogni sezione finisce con qualcosa che potete mettere in produzione oggi.

LangChain fondamentali: chain, prompt template e output parser

LangChain non è un framework magico: è un layer di astrazione che trasforma chiamate API LLM in catene di operazioni componibili. Il cuore sono tre blocchi.

Prompt template: non scrivete mai stringhe in chiaro

Un prompt hard‑codato è il primo passo verso un codice fragile. I template vi permettono di separare logica e contenuto.

from langchain.prompts import PromptTemplate

template = """Sei un assistente per un negozio di abbigliamento.
Il cliente chiede: {domanda}
Rispondi in modo chiaro e professionale."""

prompt = PromptTemplate.from_template(template)
print(prompt.format(domanda="Quali sono i vostri pantaloni più venduti?"))

Perché conviene: modificate il template senza toccare codice. Gestite variabili dinamiche, traduzioni, toni diversi.

Output parser: uscite strutturate, non testo libero

Un LLM che risponde in JSON è più utile di uno che scrive paragrafi. I parser trasformano il testo in oggetti Python.

from langchain.output_parsers import CommaSeparatedListOutputParser

parser = CommaSeparatedListOutputParser()
# "rosso, verde, blu" -> ["rosso", "verde", "blu"]

Noi usiamo PydanticOutputParser per ottenere oggetti validati. Meno bug, più velocità.

Sponsored Protocol

Chain: il tubo che unisce tutto

from langchain.chains import LLMChain

chain = LLMChain(
    llm=ChatOpenAI(model="gpt-4o-mini"),
    prompt=prompt,
    output_parser=parser
)
response = chain.run(domanda="Quali sono i tre modelli più venduti?")

Azione concreta: sostituite il vostro response = client.chat(...) con una LLMChain e un parser strutturato. In 30 minuti il codice diventa manutenibile e testabile.

RAG con LangChain: recuperare documenti reali, non allucinare

Un LLM da solo non conosce i vostri dati aziendali. La Retrieval Augmented Generation risolve questo: recuperate frammenti di documenti da un database vettoriale e li iniettate nel prompt.

Il flusso RAG in 4 passi

  1. Caricate un documento (PDF, HTML, testo)
  2. Lo dividete in chunk significativi
  3. Ogni chunk viene convertito in embedding e salvato in un vector store
  4. Alla domanda, trovate i chunk più simili e li unite al prompt
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma

loader = TextLoader("manuale_prodotto.txt")
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_documents(docs)

vectorstore = Chroma.from_documents(chunks, OpenAIEmbeddings())
retriever = vectorstore.as_retriever()

Poi nella chain:

from langchain.chains import RetrievalQA

qa_chain = RetrievalQA.from_chain_type(
    llm=ChatOpenAI(model="gpt-4o-mini"),
    chain_type="stuff",
    retriever=retriever
)
response = qa_chain.run("Come si resetta il modulo WiFi?")

Attenzione: il tipo stuff funziona solo se i chunk non superano la finestra di contesto. Per documenti lunghi usate map_reduce o refine.

Azione concreta: prendete un file PDF di 10 pagine, costruite una Chroma locale e testate le risposte. Poi misurate il tempo di retrieval: sotto 1 secondo è ok. Oltre, serve ottimizzare chunk e embedding.

Vector Database: quando Chroma non basta più

Chroma è perfetto per prototipi e progetti small. Ma se avete milioni di documenti o richiedete latenza sotto i 50 ms, dovrete salire di livello.

  • Chroma: leggero, open source, ideale per sviluppo e demo. Si installa con pip e salva i dati su disco.
  • Pinecone: serverless, indici automatici, gestito. Pagate per throughput e storage. Ottimo quando non volete amministrare un server.
  • Weaviate: containerizzato, ibrido vettoriale + lessicale, scalabile orizzontalmente. Per chi ha esigenze enterprise e un team DevOps.
# Esempio con Weaviate (client v3)
import weaviate

client = weaviate.Client("http://localhost:8080")
client.schema.create_class({
    "class": "Prodotto",
    "properties": [
        {"name": "nome", "dataType": ["string"]},
        {"name": "descrizione", "dataType": ["text"]}
    ]
})

Quando passare da Chroma: quando il vostro dataset supera 100k chunk oppure quando la concorrenza supera 10 richieste al secondo. Noi lo abbiamo fatto per una piattaforma di e‑commerce con 500k prodotti: Weaviate in cluster Docker ha tenuto senza problemi.

Sponsored Protocol

LlamaIndex: un data framework pensato per i knowledge worker

LlamaIndex (ex GPT Index) è alternativa o complemento a LangChain. Mentre LangChain è generico e incentrato sulle chain, LlamaIndex è specializzato nella gestione dei dati: indicizzare, indicizzare, indicizzare.

Vantaggi concreti:

  • connettori nativi per oltre 100 formati (Google Drive, Notion, SQL, Slack)
  • gestione automatica degli chunk e della gerarchia documentale
  • supporto a indici vettoriali, alberi di keyword e indici sintetici per riassunti
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query("Quali sono i punti salienti del bilancio 2025?")

Noi lo usiamo quando il cliente ha dati eterogenei (fatture, email, manuali) e vuole un’unica interfaccia di domanda. La curva di apprendimento è dolce, ma attenti: la personalizzazione delle query è meno flessibile di LangChain.

LangSmith: debuggare e monitorare le vostre app LLM

Quando un LLM in produzione risponde male, dovete sapere perché. LangSmith è la piattaforma di osservabilità di LangChain: registra ogni run, mostra i prompt generati, i token spesi, i tempi di risposta.

Noi lo usiamo per:

  • tracciare regressioni dopo un cambio di modello
  • confrontare risposte di GPT‑4 vs GPT‑4o‑mini su un dataset di test
  • trovare allucinazioni analizzando i chunk recuperati

Setup minimo: export LANGCHAIN_API_KEY=... LANGCHAIN_TRACING_V2=true. Poi ogni chain viene tracciata automaticamente. Costo: quasi zero (free tier generoso).

Sponsored Protocol

Azione concreta: attivate il tracing sulla vostra RAG chain e lanciate 20 query di test. Guardate il dashboard: il tempo di retrieval è sotto controllo? I chunk sono pertinenti? Se vedete chunk irrilevanti, cambiate il text splitter o il modello di embedding.

Embeddings: la base della ricerca semantica

Gli embeddings sono vettori numerici che rappresentano il significato di un testo. Più due testi sono simili, più i loro vettori sono vicini (cosine similarity).

Come scegliere il modello di embedding?

  • OpenAI Embeddings (text‑embedding‑3‑small/large): ottimi per qualità e semplicità, ma hanno un costo per token e i dati passano su server esterni.
  • Sentence‑Transformers (locali): installazione con pip install sentence-transformers. Gratis, veloci con GPU, privacy totale.
  • BGE‑M3 (multilingua): se i vostri documenti sono in italiano, funziona meglio di modelli solo inglesi.
from sentence_transformers import SentenceTransformer

model = SentenceTransformer("BAAI/bge-m3")
embedding = model.encode("Il modem non si connette").tolist()

Errore comune: usare embedding di modello diverso tra indicizzazione e query. Il vector store non capisce la differenza di spazio latente. State sempre sullo stesso modello.

Streaming delle risposte LLM: l’UX che fa la differenza

Un utente non aspetta 10 secondi per una risposta completa. Lo streaming manda i token man mano che vengono generati: l’utente vede la risposta mentre nasce. Con FastAPI e LangChain è lineare.

from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler

llm = ChatOpenAI(
    model="gpt-4o-mini",
    streaming=True,
    callbacks=[StreamingStdOutCallbackHandler()]
)

Per integrarlo in un’app web con FastAPI: usate StreamingResponse e un callback personalizzato che scrive su un generatore.

from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from langchain.callbacks.base import BaseCallbackHandler

class StreamHandler(BaseCallbackHandler):
    def __init__(self): self.queue = []
    def on_llm_new_token(self, token, **kwargs):
        self.queue.append(token)

app = FastAPI()

@app.post("/chat")
async def chat(prompt: str):
    handler = StreamHandler()
    chain = LLMChain(
        llm=ChatOpenAI(streaming=True, callbacks=[handler]),
        prompt=prompt_template
    )
    chain.run(prompt)
    async def generate():
        for token in handler.queue:
            yield token
    return StreamingResponse(generate(), media_type="text/plain")

Azione concreta: aggiungete streaming al vostro chatbot locale. Misurate la latenza percepita: se il primo token arriva entro 500 ms, l’utente resta. Se no, ottimizzate la rete o cambiate modello.

Sponsored Protocol

Fine‑tuning LLM: quando serve e quando no

Il fine‑tuning non è per tutti. Serve quando avete dati strutturati in coppie input‑output e volete specializzare il modello su un dominio stretto (es. linguaggio medico, contratti legali).

Ma attenti:

  • il fine‑tuning non corregge allucinazioni su fatti assenti nel training set
  • costa: addestramento su GPU + hosting del modello
  • richiede migliaia di esempi di qualità

Quando invece non serve: se potete raggiungere lo stesso risultato con prompt engineering + RAG. Il 90% dei casi si risolve senza fine‑tuning.

Se decidete di provarlo, usate Unsloth o Axolotl per QLoRA – riducono la memoria GPU del 70%.

# Con Unsloth
from unsloth import FastLanguageModel
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="unsloth/llama-3-8b-bnb-4bit",
    max_seq_length=2048,
    dtype=None,
    load_in_4bit=True,
)

Regola empirica: se il vostro dataset ha meno di 500 esempi, non fatelo. Usate RAG. Se ne avete 5000+, valutate il fine‑tuning con QLoRA su un modello piccolo (7B).

Deployment di app AI: Gradio, Streamlit e FastAPI

Il prototipo funziona in locale. Ora va messo online. Tre strade.

  • Gradio: perfetto per demo e prototipi veloci. Con poche righe avete un’interfaccia web con slider, chat, file upload.
  • Streamlit: più flessibile, ideale per dashboard AI con visualizzazioni. Noi lo usiamo per tool interni di analisi documentale.
  • FastAPI: l’unica scelta per API di produzione. Gestisce CORS, rate limiting, autenticazione. Combinate con Docker e un reverse proxy (Nginx/Caddy).
# FastAPI endpoint RAG
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Query(BaseModel):
    text: str

@app.post("/rag")
async def rag_endpoint(query: Query):
    result = qa_chain.run(query.text)
    return {"response": result}

Noi di Meteora Web abbiamo costruito una piattaforma proprietaria di gestione social con Laravel/Livewire, ma per i servizi AI usiamo FastAPI in container Docker su server Linux. Perché? Controllo totale e nessun canone a vita. Lo stesso stack che usiamo per i nostri clienti.

Sponsored Protocol

Costi LLM: come ottimizzare token e budget API

Un progetto che spende 200 € al mese in API OpenAI può diventare 2000 € se non si controllano i token. Ecco le nostre leve.

  • Cache delle risposte: se la stessa domanda viene ripetuta, non chiamate l’API. Usate Redis o un dizionario in‑memory per query già viste.
  • Modelli più piccoli: GPT‑4o‑mini costa 0.15 $/M input token vs 2.5 $/M di GPT‑4o. Per il 90% delle applicazioni la qualità è sufficiente.
  • Chunk ottimizzati: se ogni RAG vi restituisce 4000 token di contesto, il costo si moltiplica. Provate chunk da 500 token.
  • Embedding batch: fate embedding di centinaia di documenti in un’unica chiamata API invece che una alla volta.

Strumenti di monitoraggio: LangSmith traccia i token, ma potete anche loggare su un database e calcolare il costo a sessione utente. Noi lo facciamo in ogni progetto: il report mensile mostra costo / domanda. Se supera 0.01 €, interveniamo.

In sintesi — cosa fare adesso

  1. Costruite una RAG locale con Chroma e un manuale PDF. Non ci vuole un pomeriggio.
  2. Aggiungete streaming al vostro endpoint e testate la UX dal browser.
  3. Attivate LangSmith tracing su una chain esistente. Scoprirete cose che non sapevate.
  4. Calcolate il costo per query con il vostro modello attuale. Se supera 0.005 €, iniziate a ottimizzare.
  5. Scegliete lo stack di deployment: per API pubbliche, FastAPI + Docker. Per demo clienti, Gradio su una VPS.

Non fermatevi al prototipo. Il divario tra demo e produzione si colma con queste pratiche. Noi lo facciamo tutti i giorni per aziende in Sicilia e in tutta Italia. E se volete un confronto tecnico, contattateci.

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere Informatico, co-fondatore di Meteora Web. Esperto in architetture software, sicurezza informatica e sviluppo sistemi scalabili.
[ Read Full Dossier ]

> METEORA_WEB // WEB AGENCY

Costruiamo la presenza digitale che la tua azienda merita.

Siti web, social, pubblicità online, e-commerce e hosting performante: ingegnerizzati con metodo da ingegneri informatici a Sciacca, per tutta Italia.

> MW_JOURNAL

> READ_ALL()