DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Chat Completion Models vs OpenAI Assistants API
  • Parent Document Retrieval (PDR): Useful Technique in RAG
  • Build a Simple REST API Using Python Flask and SQLite (With Tests)
  • MCP Servers: The Technical Debt That Is Coming

Trending

  • IoT and Cybersecurity: Addressing Data Privacy and Security Challenges
  • Distributed Consensus: Paxos vs. Raft and Modern Implementations
  • Scaling Microservices With Docker and Kubernetes on Production
  • Modern Test Automation With AI (LLM) and Playwright MCP
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Optimizing Search Precision With Self-Querying Retrieval (SQR) and Langchain

Optimizing Search Precision With Self-Querying Retrieval (SQR) and Langchain

This tutorial describes the merits of SQR and how to use it with the Langchain library to improve retrieval precision and relevance within a RAG framework.

By 
Intiaz Shaik user avatar
Intiaz Shaik
·
Jul. 25, 24 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
5.2K Views

Join the DZone community and get the full member experience.

Join For Free

What Is Self-Querying Retrieval?

Self-querying retrieval (SQR) is a method ensuring that LLMs are at the core of understanding the user's intent against a document collection. Key ideas include:

  • Document representation: Word embedding provides a numerical vector for every document. This helps in fast comparison between the documents.
  • User query: The user submits a natural language query expressing their need for information.
  • LLM-driven retrieval: The query and the document representations are fed into the LLM, which then retrieves documents that maximize the user's intent.
  • Refine and repeat: The user is now able to refine his query or ask follow-up questions to narrow the search based on the retrieved documents.

Why Self-Querying Retrieval?

Traditional retrieval systems usually require complex query languages or predefined search facets. However, self-querying retrieval would provide a much more natural and user-friendly approach. Here is why:

Natural Language Queries

SQR allows the user to frame questions in natural language, making the interface in a way self-explainable and more usable. In other words, this is comparable to visiting a librarian who asks you, "What are you looking for?" Users can formulate questions in their own parlance without studying complicated query languages or specifically search facets.

Advanced Retrieval Capabilities

SQR does not apply to basic keyword searching: it supports advanced search and retrieval facilities. One can conduct content and metadata searches by author, genre, and year. This provides two layers of filtering that can obtain pretty accurate results. 

Imagine looking for a certain kind of legal document. SQR will find you documents that have the proper keywords and then further refine them by author, perhaps the judge, or even by year, like the case date.

Flexibility

SQR systems can adjust the search results about user intentions by modifying them according to further questions or inputs. This will allow the search results to be narrowed down to more appropriately fit the needs of the user.

Step-By-Step Implementation

The following are the steps to implement the naive RAG self-querying retrieval (SQR) using the Langchain library:

1. Import Libraries

We’ll import the required modules from the installed libraries to implement SQR:

Python
 
import os
from langchain.schema import Document
from langchain_openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain_openai import OpenAI
from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain.chains.query_constructor.base import AttributeInfo


These libraries and modules are essential for the subsequent steps in the process.

2. Set up the OpenAI API Key

The following code snippet retrieves your OpenAI API key from an environment variable. We’ll need a valid API key to interact with the OpenAI language model:

Python
 
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"] = ""  # Add your OpenAI API key
if OPENAI_API_KEY == "":
    raise ValueError("Please set the OPENAI_API_KEY environment variable")


3. Example Data With Metadata

Here, we define a list of documents. Each document is a Document object containing page content and metadata like title, author, year, etc:

Python
 
docs = [
    Document(
        page_content="A complex, layered narrative exploring themes of identity and belonging",
        metadata={"title":"The Namesake", "author": "Jhumpa Lahiri", "year": 2003, "genre": "Fiction", "rating": 4.5, "language":"English", "country":"USA", "ISBN": "0618485228", "publisher": "Mariner Books"},
    ),
    Document(
        page_content="A luxurious, heartfelt novel with themes of love and loss set against a historical backdrop",
        metadata={"title":"The Nightingale", "author": "Kristin Hannah", "year": 2015, "genre": "Historical Fiction", "rating": 4.8, "language":"English", "country":"France", "ISBN": "0312577222", "publisher": "St. Martin's Press"},
    ),
    Document(
        page_content="A full-bodied epic with rich characters and a sprawling plot",
        metadata={"title":"War and Peace", "author": "Leo Tolstoy", "year": 1869, "genre": "Historical Fiction", "rating": 4.7, "language":"Russian", "country":"Russia", "ISBN": "0199232768", "publisher": "Oxford University Press"},
    ),
    Document(
        page_content="An elegant, balanced narrative with intricate character development and subtle themes",
        metadata={"title":"Pride and Prejudice", "author": "Jane Austen", "year": 1813, "genre": "Romance", "rating": 4.6, "language":"English", "country":"UK", "ISBN": "0141439513", "publisher": "Penguin Classics"},
    ),
    Document(
        page_content="A highly regarded novel with deep themes and a nuanced exploration of human nature",
        metadata={"title":"To Kill a Mockingbird", "author": "Harper Lee", "year": 1960, "genre": "Fiction", "rating": 4.9, "language":"English", "country":"USA", "ISBN": "0061120081", "publisher": "Harper Perennial Modern Classics"},
    ),
    Document(
        page_content="A crisp, engaging story with vibrant characters and a compelling plot",
        metadata={"title":"The Alchemist", "author": "Paulo Coelho", "year": 1988, "genre": "Adventure", "rating": 4.4, "language":"Portuguese", "country":"Brazil", "ISBN": "0061122416", "publisher": "HarperOne"},
    ),
    Document(
        page_content="A rich, complex narrative set in a dystopian future with strong thematic elements",
        metadata={"title":"1984", "author": "George Orwell", "year": 1949, "genre": "Dystopian", "rating": 4.7, "language":"English", "country":"UK", "ISBN": "0451524934", "publisher": "Signet Classics"},
    ),
    Document(
        page_content="An intense, gripping story with dark themes and intricate plot twists",
        metadata={"title":"Gone Girl", "author": "Gillian Flynn", "year": 2012, "genre": "Thriller", "rating": 4.3, "language":"English", "country":"USA", "ISBN": "0307588378", "publisher": "Crown Publishing Group"},
    ),
    Document(
        page_content="An exotic, enchanting tale with rich descriptions and an intricate plot",
        metadata={"title":"One Hundred Years of Solitude", "author": "Gabriel García Márquez", "year": 1967, "genre": "Magical Realism", "rating": 4.8, "language":"Spanish", "country":"Colombia", "ISBN": "0060883286", "publisher": "Harper Perennial Modern Classics"},
    ),
    # ... (add more book documents as needed)
] 


4. Define the Embedding Function

Create an instance of OpenAIEmbeddings which converts document text into numerical representations suitable for retrieval:

Python
 
embeddings = OpenAIEmbeddings()


5. Initialize Vector Store

Now that we have document embeddings, let’s create a vector store using the Chroma library. This store will hold the document embeddings for efficient retrieval:

Python
 
vectorstore = Chroma.from_documents(docs, embeddings)


6. Create LLM and Retriever

Here, we’ll establish communication with the OpenAI LLM and create the core component for SQR — the retriever object:

Python
 
metadata_field_info = [
    AttributeInfo(
        name="title",
        description="The title of the book",
        type="string or list[string]",
    ),
    AttributeInfo(
        name="author",
        description="The author of the book",
        type="string or list[string]",
    ),
    AttributeInfo(
        name="year",
        description="The year the book was published",
        type="integer",
    ),
    AttributeInfo(
        name="genre",
        description="The genre of the book",
        type="string or list[string]",
    ),
    AttributeInfo(
        name="rating",
        description="The rating of the book (1-5 scale)",
        type="float",
    ),
    AttributeInfo(
        name="language",
        description="The language the book is written in",
        type="string",
    ),
    AttributeInfo(
        name="country",
        description="The country the author is from",
        type="string",
    ),
]

document_content_description = "Brief description of the book"

llm = OpenAI(temperature=0)

retriever = SelfQueryRetriever.from_llm(
    llm,
    vectorstore,
    document_content_description,
    metadata_field_info,
    verbose=True
)


7. Example Queries

Finally, we can explore various SQR queries you can use with the retriever object to interact with your document collection:

Python
 
# Basic query
retriever.invoke("What are some highly rated historical fiction books")

# Query with filtering
retriever.invoke("I want a book with deep themes and a rating above 4.5")

# Query with composite filter
retriever.invoke("I want a book with complex characters and a gripping plot")

# Query with country filter
retriever.invoke("What books come from the USA?")

# Query with year range and theme filter
retriever.invoke("What's a book published after 2003 but before 2015 with deep themes and a high rating")

# Retrieval with limiting
retriever = SelfQueryRetriever.from_llm(
    llm,
    vectorstore,
    document_content_description,
    metadata_field_info,
    enable_limit=True,
    verbose=True
)
retriever.invoke("What are two books that have a rating above 4.8")

retriever.invoke("What are two books that come from USA or UK")


This way we can effectively use SQR to perform detailed and specific book searches.

Conclusion

The self-query retriever significantly improves the precision and relevance of what is retrieved within a Retrieval-Augmented Generation framework. SQR supports dynamic and context-aware querying that personalizes retrieval in accordance with certain needs, hence improving the quality of the responses generated. In other words, with SQR, RAG models will be better placed to provide accurate and contextually relevant information, therefore improving overall performance and the user experience.

API SQR Python (language) Natural Language Engineering large language model

Opinions expressed by DZone contributors are their own.

Related

  • Chat Completion Models vs OpenAI Assistants API
  • Parent Document Retrieval (PDR): Useful Technique in RAG
  • Build a Simple REST API Using Python Flask and SQLite (With Tests)
  • MCP Servers: The Technical Debt That Is Coming

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!