引言
在构建复杂的机器学习应用时,能够在不同任务间智能地进行路由至关重要。路由不仅能够给模型交互带来结构和一致性,还能根据状态和上下文信息优化模型调用。本篇文章将探讨如何在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---