LangChain OpenTutorial
  • 🦜️🔗 The LangChain Open Tutorial for Everyone
  • 01-Basic
    • Getting Started on Windows
    • 02-Getting-Started-Mac
    • OpenAI API Key Generation and Testing Guide
    • LangSmith Tracking Setup
    • Using the OpenAI API (GPT-4o Multimodal)
    • Basic Example: Prompt+Model+OutputParser
    • LCEL Interface
    • Runnable
  • 02-Prompt
    • Prompt Template
    • Few-Shot Templates
    • LangChain Hub
    • Personal Prompts for LangChain
    • Prompt Caching
  • 03-OutputParser
    • PydanticOutputParser
    • PydanticOutputParser
    • CommaSeparatedListOutputParser
    • Structured Output Parser
    • JsonOutputParser
    • PandasDataFrameOutputParser
    • DatetimeOutputParser
    • EnumOutputParser
    • Output Fixing Parser
  • 04-Model
    • Using Various LLM Models
    • Chat Models
    • Caching
    • Caching VLLM
    • Model Serialization
    • Check Token Usage
    • Google Generative AI
    • Huggingface Endpoints
    • HuggingFace Local
    • HuggingFace Pipeline
    • ChatOllama
    • GPT4ALL
    • Video Q&A LLM (Gemini)
  • 05-Memory
    • ConversationBufferMemory
    • ConversationBufferWindowMemory
    • ConversationTokenBufferMemory
    • ConversationEntityMemory
    • ConversationKGMemory
    • ConversationSummaryMemory
    • VectorStoreRetrieverMemory
    • LCEL (Remembering Conversation History): Adding Memory
    • Memory Using SQLite
    • Conversation With History
  • 06-DocumentLoader
    • Document & Document Loader
    • PDF Loader
    • WebBaseLoader
    • CSV Loader
    • Excel File Loading in LangChain
    • Microsoft Word(doc, docx) With Langchain
    • Microsoft PowerPoint
    • TXT Loader
    • JSON
    • Arxiv Loader
    • UpstageDocumentParseLoader
    • LlamaParse
    • HWP (Hangeul) Loader
  • 07-TextSplitter
    • Character Text Splitter
    • 02. RecursiveCharacterTextSplitter
    • Text Splitting Methods in NLP
    • TokenTextSplitter
    • SemanticChunker
    • Split code with Langchain
    • MarkdownHeaderTextSplitter
    • HTMLHeaderTextSplitter
    • RecursiveJsonSplitter
  • 08-Embedding
    • OpenAI Embeddings
    • CacheBackedEmbeddings
    • HuggingFace Embeddings
    • Upstage
    • Ollama Embeddings With Langchain
    • LlamaCpp Embeddings With Langchain
    • GPT4ALL
    • Multimodal Embeddings With Langchain
  • 09-VectorStore
    • Vector Stores
    • Chroma
    • Faiss
    • Pinecone
    • Qdrant
    • Elasticsearch
    • MongoDB Atlas
    • PGVector
    • Neo4j
    • Weaviate
    • Faiss
    • {VectorStore Name}
  • 10-Retriever
    • VectorStore-backed Retriever
    • Contextual Compression Retriever
    • Ensemble Retriever
    • Long Context Reorder
    • Parent Document Retriever
    • MultiQueryRetriever
    • MultiVectorRetriever
    • Self-querying
    • TimeWeightedVectorStoreRetriever
    • TimeWeightedVectorStoreRetriever
    • Kiwi BM25 Retriever
    • Ensemble Retriever with Convex Combination (CC)
  • 11-Reranker
    • Cross Encoder Reranker
    • JinaReranker
    • FlashRank Reranker
  • 12-RAG
    • Understanding the basic structure of RAG
    • RAG Basic WebBaseLoader
    • Exploring RAG in LangChain
    • RAPTOR: Recursive Abstractive Processing for Tree-Organized Retrieval
    • Conversation-With-History
    • Translation
    • Multi Modal RAG
  • 13-LangChain-Expression-Language
    • RunnablePassthrough
    • Inspect Runnables
    • RunnableLambda
    • Routing
    • Runnable Parallel
    • Configure-Runtime-Chain-Components
    • Creating Runnable objects with chain decorator
    • RunnableWithMessageHistory
    • Generator
    • Binding
    • Fallbacks
    • RunnableRetry
    • WithListeners
    • How to stream runnables
  • 14-Chains
    • Summarization
    • SQL
    • Structured Output Chain
    • StructuredDataChat
  • 15-Agent
    • Tools
    • Bind Tools
    • Tool Calling Agent
    • Tool Calling Agent with More LLM Models
    • Iteration-human-in-the-loop
    • Agentic RAG
    • CSV/Excel Analysis Agent
    • Agent-with-Toolkits-File-Management
    • Make Report Using RAG, Web searching, Image generation Agent
    • TwoAgentDebateWithTools
    • React Agent
  • 16-Evaluations
    • Generate synthetic test dataset (with RAGAS)
    • Evaluation using RAGAS
    • HF-Upload
    • LangSmith-Dataset
    • LLM-as-Judge
    • Embedding-based Evaluator(embedding_distance)
    • LangSmith Custom LLM Evaluation
    • Heuristic Evaluation
    • Compare experiment evaluations
    • Summary Evaluators
    • Groundedness Evaluation
    • Pairwise Evaluation
    • LangSmith Repeat Evaluation
    • LangSmith Online Evaluation
    • LangFuse Online Evaluation
  • 17-LangGraph
    • 01-Core-Features
      • Understanding Common Python Syntax Used in LangGraph
      • Title
      • Building a Basic Chatbot with LangGraph
      • Building an Agent with LangGraph
      • Agent with Memory
      • LangGraph Streaming Outputs
      • Human-in-the-loop
      • LangGraph Manual State Update
      • Asking Humans for Help: Customizing State in LangGraph
      • DeleteMessages
      • DeleteMessages
      • LangGraph ToolNode
      • LangGraph ToolNode
      • Branch Creation for Parallel Node Execution
      • Conversation Summaries with LangGraph
      • Conversation Summaries with LangGraph
      • LangGrpah Subgraph
      • How to transform the input and output of a subgraph
      • LangGraph Streaming Mode
      • Errors
      • A Long-Term Memory Agent
    • 02-Structures
      • LangGraph-Building-Graphs
      • Naive RAG
      • Add Groundedness Check
      • Adding a Web Search Module
      • LangGraph-Add-Query-Rewrite
      • Agentic RAG
      • Adaptive RAG
      • Multi-Agent Structures (1)
      • Multi Agent Structures (2)
    • 03-Use-Cases
      • LangGraph Agent Simulation
      • Meta Prompt Generator based on User Requirements
      • CRAG: Corrective RAG
      • Plan-and-Execute
      • Multi Agent Collaboration Network
      • Multi Agent Collaboration Network
      • Multi-Agent Supervisor
      • 08-LangGraph-Hierarchical-Multi-Agent-Teams
      • 08-LangGraph-Hierarchical-Multi-Agent-Teams
      • SQL-Agent
      • 10-LangGraph-Research-Assistant
      • LangGraph Code Assistant
      • Deploy on LangGraph Cloud
      • Tree of Thoughts (ToT)
      • Ollama Deep Researcher (Deepseek-R1)
      • Functional API
      • Reflection in LangGraph
  • 19-Cookbook
    • 01-SQL
      • TextToSQL
      • SpeechToSQL
    • 02-RecommendationSystem
      • ResumeRecommendationReview
    • 03-GraphDB
      • Movie QA System with Graph Database
      • 05-TitanicQASystem
      • Real-Time GraphRAG QA
    • 04-GraphRAG
      • Academic Search System
      • Academic QA System with GraphRAG
    • 05-AIMemoryManagementSystem
      • ConversationMemoryManagementSystem
    • 06-Multimodal
      • Multimodal RAG
      • Shopping QnA
    • 07-Agent
      • 14-MoARAG
      • CoT Based Smart Web Search
      • 16-MultiAgentShoppingMallSystem
      • Agent-Based Dynamic Slot Filling
      • Code Debugging System
      • New Employee Onboarding Chatbot
      • 20-LangGraphStudio-MultiAgent
      • Multi-Agent Scheduler System
    • 08-Serving
      • FastAPI Serving
      • Sending Requests to Remote Graph Server
      • Building a Agent API with LangServe: Integrating Currency Exchange and Trip Planning
    • 08-SyntheticDataset
      • Synthetic Dataset Generation using RAG
    • 09-Monitoring
      • Langfuse Selfhosting
Powered by GitBook
On this page
  • Overview
  • Table of Contents
  • References
  • Environment Setup
  • Sample Data
  • SelfQueryRetriever
  • Query Constructor Chain
  • Structured Query Translator
  1. 10-Retriever

Self-querying

PreviousMultiVectorRetrieverNextTimeWeightedVectorStoreRetriever

Last updated 28 days ago

  • Author:

  • Peer Review:

  • Proofread :

  • This is a part of

Overview

SelfQueryRetriever is a retriever equipped with the capability to generate and resolve queries autonomously.

SelfQueryRetriever converts the natural language input provided by the user into a structured query using a query-constructing LLM chain . This structured query is then used to retrieve documents from the vector store .

Through this process, SelfQueryRetriever goes beyond merely comparing the user's input query with the content of stored documents semantically, and extracts filters on the metadata from the user's query and executes those filters to retrieve relevant documents.

The list of self-querying retrievers supported by LangChain can be found .

Table of Contents

References


Environment Setup

[Note]

  • langchain-opentutorial is a package that provides a set of easy-to-use environment setup, useful functions and utilities for tutorials.

%%capture --no-stderr
%pip install langchain-opentutorial
    [notice] A new release of pip is available: 24.1 -> 24.3.1
    [notice] To update, run: python.exe -m pip install --upgrade pip
# Install required packages
from langchain_opentutorial import package

package.install(
    [
        "langsmith",
        "langchain",
        "langchain_core",
        "langchain_openai",
        "langchain_chroma",
        "langchain_community",
    ],
    verbose=False,
    upgrade=False,
)
from dotenv import load_dotenv

load_dotenv(override=True)
True
# Set environment variables
from langchain_opentutorial import set_env

set_env(
    {
        # "OPENAI_API_KEY": "",
        # "LANGCHAIN_API_KEY": "",
        "LANGCHAIN_TRACING_V2": "true",
        "LANGCHAIN_ENDPOINT": "https://api.smith.langchain.com",
        "LANGCHAIN_PROJECT": "Self-querying",
    }
)
Environment variables have been set successfully.
%pip install lark
Requirement already satisfied: lark in c:\users\hyj89\appdata\local\pypoetry\cache\virtualenvs\langchain-kr-arohchi8-py3.11\lib\site-packages (1.2.2)
    Note: you may need to restart the kernel to use updated packages.
[notice] A new release of pip is available: 24.1 -> 24.3.1
[notice] To update, run: python.exe -m pip install --upgrade pip

Sample Data

Let's build a vector store that enables similarity search based on the descriptions and metadata of some cosmetic products.

from langchain_chroma import Chroma
from langchain_core.documents import Document
from langchain_openai import OpenAIEmbeddings

# Generate sample data with the descriptions and metadata of cosmetic products.
docs = [
    Document(
        page_content="A hyaluronic acid serum packed with moisture, delivering hydration deep into the skin.",
        metadata={"year": 2024, "category": "Skincare", "user_rating": 4.7},
    ),
    Document(
        page_content="A matte-finish foundation with 24-hour wear, covering pores and providing a natural skin appearance.",
        metadata={"year": 2023, "category": "Makeup", "user_rating": 4.5},
    ),
    Document(
        page_content="A hypoallergenic cleansing oil made with plant-based ingredients, gently removes makeup and impurities.",
        metadata={"year": 2023, "category": "Cleansers", "user_rating": 4.8},
    ),
    Document(
        page_content="A brightening cream with vitamin C, brightens dull skin tones for a radiant complexion.",
        metadata={"year": 2023, "category": "Skincare", "user_rating": 4.6},
    ),
    Document(
        page_content="A long-lasting lipstick with vivid color payoff and a moisturizing texture for all-day comfort.",
        metadata={"year": 2024, "category": "Makeup", "user_rating": 4.4},
    ),
    Document(
        page_content="A tone-up sunscreen with SPF50+/PA++++, offering high UV protection and keeping the skin safe.",
        metadata={"year": 2024, "category": "Sunscreen", "user_rating": 4.9},
    ),
]

# Build a vector store
vectorstore = Chroma.from_documents(
    docs, OpenAIEmbeddings(model="text-embedding-3-small")
)

SelfQueryRetriever

To instantiate the retriever , you need to define metadata fields and a brief description of the document contents in advance using the AttributeInfo class.

In this example, the metadata for cosmetic products is defined as follows:

  • category : String type, represents the category of the cosmetic product and takes one of the following values: ['Skincare', 'Makeup', 'Cleansers', 'Sunscreen'].

  • year : Integer type, represents the year the cosmetic product was released.

  • user_rating : Float type, represents the user rating in the range of 1 to 5.

from langchain.chains.query_constructor.schema import AttributeInfo

# Generate metadata field
metadata_field_info = [
    AttributeInfo(
        name="category",
        description="The category of the cosmetic product. One of ['Skincare', 'Makeup', 'Cleansers', 'Sunscreen']",
        type="string",
    ),
    AttributeInfo(
        name="year",
        description="The year the cosmetic product was released",
        type="integer",
    ),
    AttributeInfo(
        name="user_rating",
        description="A user rating for the cosmetic product, ranging from 1 to 5",
        type="float",
    ),
]

Create retriever object with SelfQueryRetriever.from_llm method.

  • llm: Large language model

  • vectorstore: Vector store

  • document_contents: Description of the contents of the documents

  • metadata_field_info: Metadata field information

from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain_openai import ChatOpenAI

# Define the LLM to use
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

# Create SelfQueryRetriever
retriever = SelfQueryRetriever.from_llm(
    llm=llm,
    vectorstore=vectorstore,
    document_contents="Brief summary of a cosmetic product",
    metadata_field_info=metadata_field_info,
)

Now, let's test this SelfQueryRetriever with some example queries.

# Self-query retrieval
retriever.invoke("Please recommend products with a rating of 4.8 or higher.")
[Document(metadata={'category': 'Cleansers', 'user_rating': 4.8, 'year': 2023}, page_content='A hypoallergenic cleansing oil made with plant-based ingredients, gently removes makeup and impurities.'),
     Document(metadata={'category': 'Sunscreen', 'user_rating': 4.9, 'year': 2024}, page_content='A tone-up sunscreen with SPF50+/PA++++, offering high UV protection and keeping the skin safe.')]
# Self-query retrieval
retriever.invoke("Please recommend products released in 2023.")
[Document(metadata={'category': 'Cleansers', 'user_rating': 4.8, 'year': 2023}, page_content='A hypoallergenic cleansing oil made with plant-based ingredients, gently removes makeup and impurities.'),
     Document(metadata={'category': 'Skincare', 'user_rating': 4.6, 'year': 2023}, page_content='A brightening cream with vitamin C, brightens dull skin tones for a radiant complexion.'),
     Document(metadata={'category': 'Makeup', 'user_rating': 4.5, 'year': 2023}, page_content='A matte-finish foundation with 24-hour wear, covering pores and providing a natural skin appearance.')]
# Self-query retrieval
retriever.invoke("Please recommend products in the Sunscreen category.")
[Document(metadata={'category': 'Sunscreen', 'user_rating': 4.9, 'year': 2024}, page_content='A tone-up sunscreen with SPF50+/PA++++, offering high UV protection and keeping the skin safe.')]

SelfQueryRetriever can also be used to retrieve items with two or more conditions.

# Self-query retrieval
retriever.invoke(
    "Please recommend products in the 'Makeup' category with a rating of 4.5 or higher."
)
[Document(metadata={'category': 'Makeup', 'user_rating': 4.5, 'year': 2023}, page_content='A matte-finish foundation with 24-hour wear, covering pores and providing a natural skin appearance.')]

You can also specify the number of documents to retrieve using the argument k when using SelfQueryRetriever .

This can be done by passing enable_limit=True to the constructor.

retriever = SelfQueryRetriever.from_llm(
    llm=llm,
    vectorstore=vectorstore,
    document_contents="Brief summary of a cosmetic product",
    metadata_field_info=metadata_field_info,
    enable_limit=True,  # Enable to limit the search result.
    search_kwargs={"k": 2},  # Limit the number of retrieved documents to 2.
)

There are 3 products released in 2023, but by setting the value of k to 2, only 2 products are retrieved.

# Self-query retrieval
retriever.invoke("Please recommend products released in 2023.")
[Document(metadata={'category': 'Cleansers', 'user_rating': 4.8, 'year': 2023}, page_content='A hypoallergenic cleansing oil made with plant-based ingredients, gently removes makeup and impurities.'),
     Document(metadata={'category': 'Skincare', 'user_rating': 4.6, 'year': 2023}, page_content='A brightening cream with vitamin C, brightens dull skin tones for a radiant complexion.')]

However, you can also limit the number of search results by directly specifying the number of search results in the query without explicitly specifying search_kwargs in the code.

retriever = SelfQueryRetriever.from_llm(
    llm=llm,
    vectorstore=vectorstore,
    document_contents="Brief summary of a cosmetic product",
    metadata_field_info=metadata_field_info,
    enable_limit=True,  # Enable to limit the search result.
)

# Self-query retrieval
retriever.invoke("Please recommend one product released in 2023.")
[Document(metadata={'category': 'Cleansers', 'user_rating': 4.8, 'year': 2023}, page_content='A hypoallergenic cleansing oil made with plant-based ingredients, gently removes makeup and impurities.')]
# Self-query retrieval
retriever.invoke("Please recommend 2 products released in 2023.")
[Document(metadata={'category': 'Cleansers', 'user_rating': 4.8, 'year': 2023}, page_content='A hypoallergenic cleansing oil made with plant-based ingredients, gently removes makeup and impurities.'),
     Document(metadata={'category': 'Skincare', 'user_rating': 4.6, 'year': 2023}, page_content='A brightening cream with vitamin C, brightens dull skin tones for a radiant complexion.')]

Query Constructor Chain

To see what happens internally and to have more custom control, we can construct a retriever from scratch.

First, we need to create a query_constructor chain that generates structured queries. Here, we use the get_query_constructor_prompt function to retrieve the prompt that helps constructing queries.

from langchain.chains.query_constructor.base import (
    StructuredQueryOutputParser,
    get_query_constructor_prompt,
)

# Retrieve the query constructor prompt using the document content description and metadata field information.
prompt = get_query_constructor_prompt(
    "Brief summary of a cosmetic product",  # Document content description
    metadata_field_info,  # Metadata field information
)

# Create StructuredQueryOutputParser
output_parser = StructuredQueryOutputParser.from_components()

# Create query_constructor chain
query_constructor = prompt | llm | output_parser

To check the content of the prompt, use the prompt.format method to pass the string "dummy question" to the query parameter and print the result.

# Print prompt
print(prompt.format(query="dummy question"))
Your goal is to structure the user's query to match the request schema provided below.
    
    << Structured Request Schema >>
    When responding use a markdown code snippet with a JSON object formatted in the following schema:
    
    ```json
    {
        "query": string \ text string to compare to document contents
        "filter": string \ logical condition statement for filtering documents
    }
    ```
    
    The query string should contain only text that is expected to match the contents of documents. Any conditions in the filter should not be mentioned in the query as well.
    
    A logical condition statement is composed of one or more comparison and logical operation statements.
    
    A comparison statement takes the form: `comp(attr, val)`:
    - `comp` (eq | ne | gt | gte | lt | lte | contain | like | in | nin): comparator
    - `attr` (string):  name of attribute to apply the comparison to
    - `val` (string): is the comparison value
    
    A logical operation statement takes the form `op(statement1, statement2, ...)`:
    - `op` (and | or | not): logical operator
    - `statement1`, `statement2`, ... (comparison statements or logical operation statements): one or more statements to apply the operation to
    
    Make sure that you only use the comparators and logical operators listed above and no others.
    Make sure that filters only refer to attributes that exist in the data source.
    Make sure that filters only use the attributed names with its function names if there are functions applied on them.
    Make sure that filters only use format `YYYY-MM-DD` when handling date data typed values.
    Make sure that filters take into account the descriptions of attributes and only make comparisons that are feasible given the type of data being stored.
    Make sure that filters are only used as needed. If there are no filters that should be applied return "NO_FILTER" for the filter value.
    
    << Example 1. >>
    Data Source:
    ```json
    {
        "content": "Lyrics of a song",
        "attributes": {
            "artist": {
                "type": "string",
                "description": "Name of the song artist"
            },
            "length": {
                "type": "integer",
                "description": "Length of the song in seconds"
            },
            "genre": {
                "type": "string",
                "description": "The song genre, one of "pop", "rock" or "rap""
            }
        }
    }
    ```
    
    User Query:
    What are songs by Taylor Swift or Katy Perry about teenage romance under 3 minutes long in the dance pop genre
    
    Structured Request:
    ```json
    {
        "query": "teenager love",
        "filter": "and(or(eq(\"artist\", \"Taylor Swift\"), eq(\"artist\", \"Katy Perry\")), lt(\"length\", 180), eq(\"genre\", \"pop\"))"
    }
    ```
    
    
    << Example 2. >>
    Data Source:
    ```json
    {
        "content": "Lyrics of a song",
        "attributes": {
            "artist": {
                "type": "string",
                "description": "Name of the song artist"
            },
            "length": {
                "type": "integer",
                "description": "Length of the song in seconds"
            },
            "genre": {
                "type": "string",
                "description": "The song genre, one of "pop", "rock" or "rap""
            }
        }
    }
    ```
    
    User Query:
    What are songs that were not published on Spotify
    
    Structured Request:
    ```json
    {
        "query": "",
        "filter": "NO_FILTER"
    }
    ```
    
    
    << Example 3. >>
    Data Source:
    ```json
    {
        "content": "Brief summary of a cosmetic product",
        "attributes": {
        "category": {
            "description": "The category of the cosmetic product. One of ['Skincare', 'Makeup', 'Cleansers', 'Sunscreen']",
            "type": "string"
        },
        "year": {
            "description": "The year the cosmetic product was released",
            "type": "integer"
        },
        "user_rating": {
            "description": "A user rating for the cosmetic product, ranging from 1 to 5",
            "type": "float"
        }
    }
    }
    ```
    
    User Query:
    dummy question
    
    Structured Request:
    

Call the query_constructor.invoke method to process the given query.

query_output = query_constructor.invoke(
    {
        # Call the query constructor to generate a query.
        "query": "Please recommend skincare products released in 2023 with a rating of 4.5 or higher."
    }
)
# Print query
query_output.filter.arguments
[Comparison(comparator=, attribute='category', value='Skincare'),
     Comparison(comparator=, attribute='year', value=2023),
     Comparison(comparator=, attribute='user_rating', value=4.5)]

The core component of a SelfQueryRetriever is the query constructor . To build an effective retrieval system, it is essential to ensure that the query constructor is well defined.

To achieve this, you need to adjust the prompt, examples within the prompt, and attribute descriptions .

Structured Query Translator

You can also create a structured query using the structured query translator .

Structured query translator converts a query into metadata filters compatible with the syntax of the vector store with StructuredQuery object.

from langchain.retrievers.self_query.chroma import ChromaTranslator

retriever = SelfQueryRetriever(
    query_constructor=query_constructor,  # The query_constructor chain created in the previous step.
    vectorstore=vectorstore,  # Specify the VectorStore
    structured_query_translator=ChromaTranslator(),  # Query translator
)

Use the retriever.invoke method to generate an answer for the given question.

retriever.invoke(
    "Please recommend skincare products released in 2023 with a rating of 4.5 or higher."
)
[Document(metadata={'category': 'Skincare', 'user_rating': 4.7, 'year': 2024}, page_content='A hyaluronic acid serum packed with moisture, delivering hydration deep into the skin.'),
     Document(metadata={'category': 'Skincare', 'user_rating': 4.6, 'year': 2023}, page_content='A brightening cream with vitamin C, brightens dull skin tones for a radiant complexion.')]

Set up the environment. You may refer to for more details.

You can checkout the for more details.

LangChain Documentation: Self-querying retrievers
LangChain cookbook: Building hotel room search with self-querying retrieval
Environment Setup
langchain-opentutorial
Hye-yoon Jeong
Juni Lee
LangChain Open Tutorial
here
Overview
Environment Setup
Sample Data
SelfQueryRetriever
Query Constructor Chain