从MultiPromptChain到LangGraph:高效迁移的最佳实践

119 阅读3分钟

引言

在使用大型语言模型(LLM)时,如何高效路由输入查询至适当的提示非常关键。传统的MultiPromptChain方法虽然能实现这一功能,但在支持聊天模型常见特性,如消息角色和工具调用方面存在局限。本文将通过对比MultiPromptChainLangGraph,详细讲解如何迁移并利用LangGraph的优势,提升系统灵活性和扩展功能。

主要内容

MultiPromptChain 的局限

MultiPromptChain通过指令LLM选择合适的提示并生成响应,虽然简单直接,但无法支持消息角色和工具调用等聊天模型功能。这限制了开发者在复杂应用场景中的能力。

LangGraph 的优势

通过LangGraph,我们能获得更强大的功能支持:

  • 支持聊天提示模板:可包含系统消息和用户角色。
  • 支持工具调用:允许在路由步骤中调用工具。
  • 支持流式输出:在每个步骤和输出令牌上都可进行流式处理。

代码示例

下面的示例展示了如何使用LangGraph实现与MultiPromptChain类似的功能,使用langchain-openai >= 0.1.20版本。

%pip install -qU langchain-core langchain-openai langgraph

import os
from getpass import getpass
from langchain_openai import ChatOpenAI
from langgraph.graph import END, START, StateGraph
from typing_extensions import TypedDict
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableConfig

os.environ["OPENAI_API_KEY"] = getpass()

llm = ChatOpenAI(model="gpt-4o-mini")

# 定义要路由的提示
prompt_1 = ChatPromptTemplate.from_messages(
    [
        ("system", "You are an expert on animals."),
        ("human", "{input}"),
    ]
)
prompt_2 = ChatPromptTemplate.from_messages(
    [
        ("system", "You are an expert on vegetables."),
        ("human", "{input}"),
    ]
)

chain_1 = prompt_1 | llm | StrOutputParser()
chain_2 = prompt_2 | llm | StrOutputParser()

route_system = "Route the user's query to either the animal or vegetable expert."
route_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", route_system),
        ("human", "{input}"),
    ]
)

class RouteQuery(TypedDict):
    destination: Literal["animal", "vegetable"]

route_chain = route_prompt | llm.with_structured_output(RouteQuery)

class State(TypedDict):
    query: str
    destination: RouteQuery
    answer: str

async def route_query(state: State, config: RunnableConfig):
    destination = await route_chain.ainvoke(state["query"], config)
    return {"destination": destination}

async def prompt_1(state: State, config: RunnableConfig):
    return {"answer": await chain_1.ainvoke(state["query"], config)}

async def prompt_2(state: State, config: RunnableConfig):
    return {"answer": await chain_2.ainvoke(state["query"], config)}

def select_node(state: State) -> Literal["prompt_1", "prompt_2"]:
    if state["destination"] == "animal":
        return "prompt_1"
    else:
        return "prompt_2"

graph = StateGraph(State)
graph.add_node("route_query", route_query)
graph.add_node("prompt_1", prompt_1)
graph.add_node("prompt_2", prompt_2)

graph.add_edge(START, "route_query")
graph.add_conditional_edges("route_query", select_node)
graph.add_edge("prompt_1", END)
graph.add_edge("prompt_2", END)
app = graph.compile()

state = await app.ainvoke({"query": "what color are carrots"})
print(state["destination"])
print(state["answer"])

# 使用API代理服务提高访问稳定性

该代码展示了如何使用LangGraph实现查询的路由和响应生成,与MultiPromptChain进行功能对比。

常见问题和解决方案

  • 网络限制:某些地区在访问API时可能受限,建议使用API代理服务以提高访问稳定性。
  • 错误消息或异常:确保环境变量OPENAI_API_KEY正确设置,并验证所用库版本是否兼容。

总结和进一步学习资源

通过迁移到LangGraph,我们不仅可以更好地利用LLM的功能,还可以灵活地扩展系统逻辑。推荐学习以下资源以进一步掌握相关技巧:

参考资料

  1. LangChain 文档: langchain.com/docs
  2. LangGraph 官方文档: langgraph-docs.com

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

---END---