Utilizzare SelfQueryRetriever con LangChain per interrogare un database vettoriale
LangChain è ben noto per orchestrare le interazioni con i large language models (LLM). Recentemente, LangChain ha introdotto un modo per eseguire il self-querying, consentendo loro di interrogare la “chain” o i moduli stessi utilizzando una query di input dell’utente. Questo post ti mostrerà come eseguire il self-query su Milvus, il vector database più popolare al mondo. Interpretando una query dell’utente, il sistema può perfezionare le ricerche all’interno dei vector store, migliorando i risultati di retrieval. Puoi trovare il codice per questo esempio su CoLab qui.
Impostiamo il self-querying su Milvus con LangChain. Questo processo consiste in quattro passaggi logici.
Impostare le basi di LangChain e Milvus.
Ottenere o creare i dati necessari.
Informare il modello sul formato dei dati previsto.
Dimostrare il self-querying e spiegare come funziona.
Introduzione al Self-Querying
Il self-querying è una tecnica potente utilizzata nell’elaborazione del linguaggio naturale (NLP) e nell’information retrieval. Consente a un sistema di interrogare se stesso utilizzando una query di input dell’utente, permettendo risultati più accurati e pertinenti. Nel contesto di LangChain, il self-querying viene utilizzato per recuperare informazioni da un vector store, che è un database che memorizza vettori che rappresentano documenti o punti dati. Il self-query retriever è un componente chiave del framework LangChain, consentendo la creazione di query e retrieval complessi utilizzando il linguaggio naturale.
Sfruttando il self-querying, LangChain può scomporre la query di un utente in un formato strutturato che il vector store può comprendere. Questo processo garantisce che i documenti recuperati siano altamente pertinenti alla query dell’utente, rendendo più facile trovare le informazioni di cui ha bisogno. Che tu stia costruendo un modello di IA conversazionale o un motore di ricerca, il self-querying può migliorare significativamente l’accuratezza e la pertinenza dei tuoi risultati.
Configurazione di LangChain e Milvus
Il primo passo è configurare le librerie necessarie. Puoi installare le librerie richieste usando pip install openai langchain milvus python-dotenv. Se hai seguito i miei tutorial precedenti, conosci già python-dotenv, la mia libreria preferita per gestire le variabili d’ambiente. Usiamo la libreria OpenAI con LangChain per accedere a GPT e utilizziamo Milvus come nostro vector store.
Una volta connessa la chiave API di OpenAI, importa i moduli LangChain necessari. Abbiamo bisogno dei seguenti sei moduli:
Document: Un tipo di dato LangChain per l’archiviazione dei dati.OpenAIeOpenAIEmbeddings: Due funzionalità per accedere a OpenAI e ai suoi embeddings.Milvus: Un modulo per accedere a Milvus da LangChain.SelfQueryRetriever: Un modulo retriever.AttributeInfo: Un modulo che definisce la nostra struttura dati per LangChain.
Dopo aver importato i moduli, impostiamo la variabile embeddings sulla funzione predefinita di OpenAI Embeddings. Il passaggio finale nel processo di configurazione è utilizzare la libreria milvus per avviare un’istanza di Milvus Lite nel nostro notebook.
Ora, diamo un’occhiata ai dati.
import os
from dotenv import load_dotenv
load_dotenv()
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
from langchain.schema import Document
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Milvus
from langchain.llms import OpenAI
from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain.chains.query_constructor.base import AttributeInfo
embeddings = OpenAIEmbeddings()
from milvus import default_server
default_server.start()
Raccogliamo alcuni dati. Puoi effettuare lo scraping dei tuoi dati, usare i dati forniti così come sono, oppure usarli come modello per creare i tuoi dati. Ho preparato un elenco di documenti sui film per questo esempio, tra cui Jurassic Park, Toy Story, Finding Nemo, The Unbearable Weight of Massive Talent, Lord of War e Ghost Rider. Anche se non includo i titoli nei nostri dati, voglio che tu sappia a quali film si riferiscono.
Memorizzo ciascuno di questi film come oggetto LangChain Document. Contiene una chiave page_content corrispondente a una stringa, in questo caso la descrizione del film. Include anche metadati, come l’anno, la valutazione e il genere del film.
docs = [
# jurassic park
Document(page_content="A bunch of scientists bring back dinosaurs and mayhem breaks loose",
metadata={"year": 1993, "rating": 7.7, "genre": "action"}),
# toy story
Document(page_content="Toys come alive and have a blast doing so",
metadata={"year": 1995, "genre": "animated", "rating": 9.3 }),
# finding nemo
Document(page_content="A dad teams up with a mentally disabled partner to break into a dentist\'s office to save his son.",
metadata={"year": 2003, "genre": "animated", "rating": 8.2 }),
# unbearable weight of massive talent
Document(page_content="Nicholas Cage plays Nicholas Cage in this movie about Nicholas Cage.",
metadata={"year": 2022, "genre": "comedy", "rating": 7.0 }),
# lord of war
Document(page_content="Nicholas Cage sells guns until he has enough money to marry his favorite model. Then he sells more guns.",
metadata={"year": 2005, "genre": "comedy", "rating": 7.6 }),
# ghost rider
Document(page_content="Nicholas Cage loses his skin and sets his skull on fire. Then he rides a motorcycle.",
metadata={"year": 2007, "genre": "action", "rating": 5.3 }),
]
Definizione dei metadati self-query e del self query retriever per LangChain e Milvus
Abbiamo completato i primi due passaggi del puzzle, e ora è il momento del terzo.
Per prima cosa, configuriamo il nostro database vettoriale per l’ingestione. Possiamo usare l’implementazione LangChain Milvus per importare i nostri documenti e creare un database vettoriale basato sui documenti esistenti. Questo passaggio è anche il punto in cui entra in gioco la funzione di embedding, usando la variabile embeddings che abbiamo creato in precedenza. L’istruzione di confronto tiene conto dei formati e delle linee guida specifici necessari per creare condizioni di filtro che guidano i processi di recupero dei dati.
Il parametro connection_args è l’unico parametro richiesto per connettersi a Milvus. In questo tutorial, uso anche il parametro collection_name per assegnare un nome alla collection in cui archiviamo i nostri dati. Ogni collection in Milvus deve avere un nome. Per impostazione predefinita, LangChain usa LangChainCollection.
vector_store = Milvus.from_documents(
docs,
embedding=embeddings,
connection_args={"host": "localhost", "port": default_server.listen_port},
collection_name="movies"
)
Successivamente, definiamo le informazioni sui metadati usando la funzionalità AttributeInfo in modo che LangChain sappia cosa aspettarsi. Questa sezione creerà un elenco di informazioni sugli attributi per i dati. Specificheremo il nome, la descrizione e il tipo di dato di ciascun attributo. È qui che un’istruzione di condizione logica diventa parte integrante della formulazione di confronti e operazioni logiche all’interno del processo di costruzione della query.
metadata_field_info = [
AttributeInfo(
name="genre",
description="The genre of the movie",
type="string",
),
AttributeInfo(
name="year",
description="The year the movie was released",
type="integer",
),
AttributeInfo(
name="rating",
description="A 1-10 rating for the movie",
type="float"
),
]
Gli ultimi due elementi descrivono il documento, inizializzano l’LLM e definiscono il Self-Query Retriever. Definiamo il self-query retriever chiamando il suo metodo ‘from_llm’. Dobbiamo usare questo metodo per collegare l’LLM, il vector store, la descrizione del contenuto del documento e le informazioni sui campi dei metadati. In questo esempio, impostiamo anche ‘verbose = True’ per abilitare l’output dettagliato per questo self-query retriever. La stringa della query dovrebbe includere solo testo rilevante corrispondente ai contenuti del documento, assicurando che eventuali condizioni nei filtri siano distintamente separate e non incluse nella stringa della query stessa.
document_content_description = "Brief summary of a movie"
llm = OpenAI(temperature=0)
retriever = SelfQueryRetriever.from_llm(
llm, vector_store, document_content_description, metadata_field_info, verbose=True
)
Risultati del self-querying
Abbiamo completato la configurazione del self-query retriever. Ora vediamo come funziona in azione. In questo esempio, ho usato tre descrizioni di film relative a Nicholas Cage. Quindi, la domanda che poniamo è: quali sono alcuni film su Nicholas Cage?
# This example only specifies a relevant query
retriever.get_relevant_documents("What are some movies about Nicholas Cage?")
Dovremmo ottenere un output come quello qui sotto.
langchain-query-vector-database.png
Impostando verbose=True, possiamo visualizzare la query, il filtro e il limite. L’LLM converte la nostra query da “What are some movies about Nicholas Cage?” a “Nicholas Cage.” Osservando i risultati, possiamo notare che i primi tre risultati sono tutti film con Nicholas Cage. Tuttavia, il quarto risultato, Finding Nemo, è irrilevante a causa del parametro impostato per recuperare quattro risultati.
Si spera che la panoramica del codice abbia chiarito il concetto di self-querying su un database vettoriale. Sul sito web di LangChain, LangChain descrive il self-querying come un metodo che consente a un LLM di interrogare se stesso usando il vector store sottostante. In altre parole, LangChain sta sviluppando una semplice app di retrieval augmented generation (RAG) nel framework CVP che include una funzione di self-querying.
In questo tutorial, abbiamo esplorato la funzionalità di self-query di LangChain usando Milvus come vector store sottostante. Il self-querying ti consente di creare una semplice app RAG combinando un LLM e un database vettoriale. L’LLM scompone la query in linguaggio naturale in una stringa, poi vettorializzata per l’interrogazione.
Nel nostro esempio, abbiamo generato alcuni dati di esempio relativi ai film. Un modo per espandere questo esempio è raccogliere i tuoi dati. Quando definisci il self-query retriever, ricorda di fornire le descrizioni sia per il vector store sia per i metadati.
Per iniziare e sperimentare con la funzionalità di self-query di LangChain, consulta il notebook colab.
Interrogare il Vector Store con istruzioni di operazioni logiche
Quando si interroga il vector store, le istruzioni di operazioni logiche vengono usate per specificare condizioni per filtrare i documenti. Un’istruzione di operazione logica assume la forma op(statement1, statement2, …), dove op è un operatore logico come AND, OR o NOT. Ogni istruzione può essere un’istruzione di confronto, che assume la forma comp(attr, val), dove comp è un comparatore come EQ, LT o GT, e attr e val sono rispettivamente l’attributo e il valore confrontati.
Ad esempio, un’istruzione di operazione logica potrebbe apparire così: AND(EQ(language, “English”), GT(rating, 4)). Questa istruzione filtrerebbe i documenti che hanno un attributo language uguale a “English” e un attributo rating maggiore di 4. Usando le istruzioni di operazioni logiche, puoi creare query complesse che combinano più condizioni, consentendo un filtraggio più preciso dei documenti nel vector store.
Gestire la query dell’utente
Quando un utente inserisce una query, il self-query retriever utilizza un costruttore di query per generare una query strutturata. La query strutturata viene quindi tradotta in query per il vector store, che vengono eseguite sul vector store per recuperare documenti pertinenti. Il costruttore di query utilizza un prompt e un parser di output per generare la query strutturata, che cattura i filtri specificati dall’utente.
Ad esempio, se un utente inserisce la query “Find movies with a rating greater than 4 and a runtime less than 2 hours”, il costruttore di query potrebbe generare una query strutturata come questa: AND(GT(rating, 4), LT(runtime, 120)). Questa query strutturata verrebbe quindi tradotta in query per il vector store ed eseguita sul vector store per recuperare documenti pertinenti. Gestendo la query dell’utente in questo modo, il self-query retriever garantisce che i risultati siano adattati ai requisiti specifici dell’utente.
Best practice e conclusione
Quando si utilizza il self-query retriever, è importante seguire le best practice per garantire risultati accurati e pertinenti. Ecco alcuni suggerimenti:
Usa un linguaggio specifico e conciso quando inserisci le query.
Usa istruzioni di operazione logica per specificare le condizioni per filtrare i documenti.
Usa istruzioni di confronto per confrontare attributi e valori.
Usa il comparatore EQ per specificare corrispondenze esatte.
Usa i comparatori LT e GT per specificare query di intervallo.
Usa gli operatori logici AND e OR per combinare le condizioni.
In conclusione, il self-query retriever è uno strumento potente per creare modelli di IA conversazionale in grado di recuperare ed elaborare informazioni da varie fonti. Utilizzando istruzioni di operazione logica e istruzioni di confronto, gli utenti possono specificare query complesse e recuperare documenti pertinenti da un vector store. Seguendo le best practice e utilizzando efficacemente il self-query retriever, gli sviluppatori possono creare modelli di IA più accurati e pertinenti, in grado di gestire un’ampia gamma di query degli utenti.
Continua a leggere

Zilliz Cloud Update: Tiered Storage, Business Critical Plan, Cross-Region Backup, and Pricing Changes
This release offers a rebuilt tiered storage with lower costs, a new Business Critical plan for enhanced security, and pricing updates, among other features.

Zilliz Named "Highest Performer" and "Easiest to Use" in G2's Summer 2025 Grid® Report for Vector Databases
Zilliz shines in G2's Summer 2025 Grid® Report as both "Highest Performer" and "Easiest to Use," solving the performance-usability dilemma.

Why Not All VectorDBs Are Agent-Ready
Explore why choosing the right vector database is critical for scaling AI agents, and why traditional solutions fall short in production.



