用例(User Case)
查询分析(QueryAnalysis)
技术(Techniques)
路由(Routing)

路由

有时我们会针对不同的领域建立多个索引,并且针对不同的问题我们想要查询这些索引的不同子集。例如,假设我们有一个用于所有LangChain Python文档的向量存储索引,以及一个用于所有LangChain JS文档的索引。给定一个关于LangChain用法的问题,我们希望推断出问题所指的是哪种语言,并查询相应的文档。查询路由就是确定查询应该在哪个索引或索引子集上执行的过程。

设置

安装依赖项

%pip install -qU langchain-core langchain-openai

设置环境变量

我们将在这个示例中使用OpenAI:

import getpass
import os
 
os.environ["OPENAI_API_KEY"] = getpass.getpass()
 
# 可选的,取消下面的注释以使用LangSmith进行追踪。在这里注册:https://smith.langchain.com。
# os.environ["LANGCHAIN_TRACING_V2"] = "true"
# os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()

使用函数调用模型进行路由

使用函数调用模型对于分类非常简单,而路由实际上就是分类的过程:

from typing import Literal
 
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_openai import ChatOpenAI
 
 
class RouteQuery(BaseModel):
    """将用户查询路由到最相关的数据源。"""
 
    datasource: Literal["python_docs", "js_docs", "golang_docs"] = Field(
        ...,
        description="给定一个用户问题,选择最相关的数据源来回答他们的问题",
    )
 
 
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
structured_llm = llm.with_structured_output(RouteQuery)
 
system = """您是一个专家,负责将用户问题路由到适当的数据源。
 
根据问题所涉及的编程语言,将其路由到相应的数据源。"""
prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system),
        ("human", "{question}"),
    ]
)
 
router = prompt | structured_llm
/Users/bagatur/langchain/libs/core/langchain_core/_api/beta_decorator.py:86: LangChainBetaWarning: The function `with_structured_output` is in beta. It is actively being worked on, so the API may change.
  warn_beta(
question = """为什么下面的代码不起作用:
 
from langchain_core.prompts import ChatPromptTemplate
 
prompt = ChatPromptTemplate.from_messages(["human", "speak in {language}"])
prompt.invoke("french")
"""
router.invoke({"question": question})
RouteQuery(datasource='python_docs')
question = """为什么下面的代码不起作用:
 
 
import { ChatPromptTemplate } from "@langchain/core/prompts";
 
 
const chatPrompt = ChatPromptTemplate.fromMessages([
  ["human", "speak in {language}"],
]);
 
const formattedChatPrompt = await chatPrompt.invoke({
  input_language: "french"
});
"""
router.invoke({"question": question})
RouteQuery(datasource='js_docs')

路由到多个索引

如果我们希望查询多个索引,也可以通过更新模式来实现接受数据源的列表:

from typing import List
 
 
class RouteQuery(BaseModel):
    """将用户查询路由到最相关的数据源。"""
 
    datasources: List[Literal["python_docs", "js_docs", "golang_docs"]] = Field(
        ...,
        description="给定一个用户问题,选择最相关的数据源来回答他们的问题",
    )
 
 
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
structured_llm = llm.with_structured_output(RouteQuery)
router = prompt | structured_llm
router.invoke(
    {
        "question": "Python和JS实现的OpenAI聊天模型之间是否具有功能的平等性"
    }
)
RouteQuery(datasources=['python_docs', 'js_docs'])