[深入掌握LangChain中的智能路由技术:实现动态交互]

104 阅读3分钟

引言

在构建复杂的机器学习应用时,能够在不同任务间智能地进行路由至关重要。路由不仅能够给模型交互带来结构和一致性,还能根据状态和上下文信息优化模型调用。本篇文章将探讨如何在LangChain框架中实现智能路由,通过条件返回可运行对象和语义相似性路由,帮助您掌握这些技能。

主要内容

1. 什么是路由?

路由是指在一个多步骤处理流程中,通过将前一步的输出定义为下一步的输入,从而实现非确定性链式调用。它可以使模型与用户的交互更加结构化和一致化。

2. 路由的两种实现方式

  • 条件返回可运行对象(推荐):使用RunnableLambda根据条件返回相应的子链。
  • 使用RunnableBranch(旧方法):通过定义条件和对应的可运行对象来实现路由。

3. 使用条件返回可运行对象

在这个方法中,我们将创建一个链用于识别问题所属的主题,然后根据主题选择相应的处理子链。

设置分类链

from langchain_anthropic import ChatAnthropic
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate

chain = (
    PromptTemplate.from_template(
        """Given the user question below, classify it as either being about `LangChain`, `Anthropic`, or `Other`.

Do not respond with more than one word.

<question>
{question}
</question>

Classification:"""
    )
    | ChatAnthropic(model_name="claude-3-haiku-20240307")  # 使用API代理服务提高访问稳定性
    | StrOutputParser()
)
chain.invoke({"question": "how do I call Anthropic?"})

创建并路由到子链

def route(info):
    if "anthropic" in info["topic"].lower():
        return anthropic_chain
    elif "langchain" in info["topic"].lower():
        return langchain_chain
    else:
        return general_chain

from langchain_core.runnables import RunnableLambda

full_chain = {"topic": chain, "question": lambda x: x["question"]} | RunnableLambda(route)
full_chain.invoke({"question": "how do I use Anthropic?"})

4. 使用RunnableBranch

虽然可以使用RunnableBranch实现类似的功能,但它不提供任何RunnableLambda无法实现的优势,因此我们推荐使用自定义函数。

from langchain_core.runnables import RunnableBranch

branch = RunnableBranch(
    (lambda x: "anthropic" in x["topic"].lower(), anthropic_chain),
    (lambda x: "langchain" in x["topic"].lower(), langchain_chain),
    general_chain,
)
full_chain = {"topic": chain, "question": lambda x: x["question"]} | branch
full_chain.invoke({"question": "how do I use Anthropic?"})

5. 通过语义相似性进行路由

通过使用嵌入技术,可以根据查询的语义相似性选择最相关的提示。

from langchain_community.utils.math import cosine_similarity
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_openai import OpenAIEmbeddings

physics_template = """You are a very smart physics professor. ...
{query}"""

math_template = """You are a very good mathematician. ...
{query}"""

embeddings = OpenAIEmbeddings()
prompt_templates = [physics_template, math_template]
prompt_embeddings = embeddings.embed_documents(prompt_templates)

def prompt_router(input):
    query_embedding = embeddings.embed_query(input["query"])
    similarity = cosine_similarity([query_embedding], prompt_embeddings)[0]
    most_similar = prompt_templates[similarity.argmax()]
    print("Using MATH" if most_similar == math_template else "Using PHYSICS")
    return PromptTemplate.from_template(most_similar)

chain = (
    {"query": RunnablePassthrough()}
    | RunnableLambda(prompt_router)
    | ChatAnthropic(model="claude-3-haiku-20240307") # 使用API代理服务提高访问稳定性
    | StrOutputParser()
)

print(chain.invoke("What's a black hole"))
print(chain.invoke("What's a path integral"))

常见问题和解决方案

  • 网络限制问题: 在某些地区访问API可能不稳定,建议使用API代理服务来提高访问的可靠性。
  • 语义相似性计算精度: 确保嵌入模型的选择和距离度量方法符合您的特定应用需求。

总结和进一步学习资源

智能路由技术在复杂应用中起着关键作用。通过掌握这些技能,您可以创建动态交互式应用,并以此为基础继续拓展LangChain的其他特性。建议查看LangChain的官方文档和其他实用指南,以深入了解可运行对象的更多高级用法。

参考资料

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