LangChain 最近发布的一个重要功能:LangGraph

LangGraph 是 LangChain 最近发布的一个重要功能,LangChain 进入多代理框架领域。通过建立在LangChain 之上,LangGraph 使开发人员可以轻松创建强大的代理运行时。

在这里插入图片描述

LangChain 使用其表达语言(LCEL)为开发人员构建定制链提供技术支持。从数据结构的角度来看,这样的链是一个有向无环图(DAG)。然而,在实践中,用户可能希望使用代理构建循环图。换句话说,代理可以根据模型推理在循环中被调用,直到任务完成。AutoGen就是支持这种机制的框架。

LangGraph专门设计以满足这类用户的需求。换句话说,开发人员可以使用它来构建类似于AutoGen的多代理LLM应用程序。

LangGraph 提供了一种称为状态机的技术,它可以驱动循环代理调用。因此,LangGraph具有三个关键元素:

  1. StateGraph(状态图)
  2. Node(节点)
  3. Edge(边缘)

技术交流&资料

技术要学会分享、交流,不建议闭门造车。一个人可以走的很快、一堆人可以走的更远。

成立了大模型技术交流群,本文完整代码、相关资料、技术交流&答疑,均可加我们的交流群获取,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友。

方式①、微信搜索公众号:机器学习社区,后台回复:加群
方式②、添加微信号:mlc2060,备注:来自CSDN + 技术交流

通俗易懂讲解大模型系列

StateGraph

StateGraph 是LangChain的一个类,表示图的数据结构并反映其状态。图的状态由将很快介绍的节点更新。

class State(TypedDict):
    input: str
    all_actions: Annotated[List[str], operator.add]

graph = StateGraph(State)

Node

图中最关键的元素之一是节点。每个LangGraph节点都有一个名称和其值,它可以是LCEL中的函数或可运行项。每个节点接收一个字典类型的数据,其结构与状态定义相同。节点返回具有相同结构的更新状态。

LangGraph定义了一个称为END的特殊节点,用于识别状态机的结束状态。

from langgraph.graph import END
graph.add_node("model", model)
graph.add_node("tools", tool_executor)

Edge

在图中,节点之间的关系通过边界定义。LangGraph定义了两种类型的边:普通边和条件边。

普通边定义了上游节点应始终调用的其他节点。

graph.add_edge("tools", "model")

条件边,使用函数(路由器)来确定下游节点。

graph.add_conditional_edge(
    "model",
    should_continue,
    {
      "end": END,
      "continue": "tools"
    }
)

如上所示,条件边需要三个元素:

  1. 上游节点:边的起点,表示转换的起始点。
  2. 路由函数:此函数根据其返回值有条件地确定应进行转换的下游节点。
  3. 状态映射:根据路由函数的返回值,此映射指定下一个目的地。它将路由函数的可能返回值与相应的下游节点相关联。

运行图
在运行图之前,有两个必要的步骤需要完成:

  1. 设置入口点,以指定图中哪个节点作为入口点
graph.set_entry_point("model")
  1. 编译
app = graph.compile()

现在,我们可以运行LangGraph应用程序如下:

app.stream(
    {
        "messages": [
            HumanMessage(content="Write a tweet about LangChain news")
        ]
    }
)

用例

这是一个示例。图包含三个节点:主管、搜索引擎和 Twitter 作者。根据需要,主管可能多次调用搜索引擎以检索所需数据,然后将数据转发给Twitter作者以撰写推文。因此,在主管和搜索引擎之间存在循环。

LangChain可以帮助开发人员轻松构建基于工具的代理,然后基于这些代理创建节点。

定义图状态

class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], operator.add]
    next: str

声明工具函数

@tool("web_search")
def web_search(query: str) -> str:
    """通过查询使用Google SERP API进行搜索"""
    search = SerpAPIWrapper()
    return search.run(query)

@tool("twitter_writer")
def write_tweet(content: str) -> str:
    """根据内容编写推文。"""
    chat = ChatOpenAI()
    messages = [
        SystemMessage(
            content="您是Twitter帐户操作员。您负责根据给定的内容撰写推文。您应遵循Twitter政策,并确保每条推文不超过140个字符。"
        ),
        HumanMessage(
            content=content
        ),
    ]
    response = chat(messages)
    return response.content

辅助函数 —— 使用工具创建代理

def create_agent(llm: ChatOpenAI, tools: list, system_prompt: str):
    prompt = ChatPromptTemplate.from_messages(
        [
            (
                "system",
                system_prompt,
            ),
            MessagesPlaceholder(variable_name="messages"),
            MessagesPlaceholder(variable_name="agent_scratchpad"),
        ]
    )
    agent = create_openai_tools_agent(llm, tools, prompt)
    executor = AgentExecutor(agent=agent, tools=tools)
    return executor

辅助函数 —— 使用代理创建节点

def agent_node(state, agent, name):
    result = agent.invoke(state)
    return {"messages": [HumanMessage(content=result["output"], name=name)]}

创建主管节点

members = ["Search_Engine", "Twitter_Writer"]
system_prompt = (
    "您是一名主管,负责管理以下工作者之间的对话:{members}。给定以下用户请求,使用下一步操作进行回复。每个工作者将执行一个任务,并回复其结果和状态。完成后,使用FINISH进行回复。"
)
options = ["FINISH"] + members
function_def = {
    "name": "route",
    "description": "选择下一个角色。",
    "parameters": {
        "title": "routeSchema",
        "type": "object",
        "properties": {
            "next": {
                "title": "Next",
                "anyOf": [
                    {"enum": options},
                ],
            }
        },
        "required": ["next"],
    },
}
prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system_prompt),
        MessagesPlaceholder(variable_name="messages"),
        (
            "system",
            "根据以上对话,下一个应该采取行动的人是谁?还是我们应该结束?选择一个:{options}",
        ),
    ]
).partial(options=str(options), members=", ".join(members))
supervisor_chain = (
    prompt
    | llm.bind_functions(functions=[function_def], function_call="route")
    | JsonOutputFunctionsParser()
)

创建节点和边缘

search_engine_agent = create_agent(llm, [web_search], "您是一个网络搜索引擎。")
search_engine_node = functools.partial(agent_node, agent=search_engine_agent, name="Search_Engine")
twitter_operator_agent = create_agent(llm, [write_tweet], "您负责根据给定的内容撰写推文。")
twitter_operator_node = functools.partial(agent_node, agent=twitter_operator_agent, name="Twitter_Writer")
workflow = StateGraph(AgentState)
workflow.add_node("Search_Engine", search_engine_node)
workflow.add_node("Twitter_Writer", twitter_operator_node)
workflow.add_node("supervisor", supervisor_chain)
for member in members:
    workflow.add_edge(member, "supervisor")
conditional_map = {k: k for k in members}
conditional_map["FINISH"] = END
workflow.add_conditional_edges("supervisor", lambda x: x["next"], conditional_map)

编译

workflow.set_entry_point("supervisor")
graph = workflow.compile()

现在我们可以使用此图执行任务。让我们要求它搜索LangChain新闻并撰写一条推文:

for s in graph.stream(
    {
        "messages": [
            HumanMessage(content="Write a tweet about LangChain news")
        ]
    }
):
    if "__end__" not in s:
        print(s)
        print("----")

参考文献

  • https://ai.gopubby.com/langgraph-absolute-beginners-guide-cd4a05336312
  • https://github.com/sugarforever/LangChain-Tutorials/blob/main/langgraph_nodes_edges.ipynb
  • 27
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据您提供的引用内容,Langchain-Chatchat在执行过程中出现了JSONDecodeError: Expecting value: line 1 column 1 (char 0)的错误。要解决这个问题,可以尝试以下两种方法: 方法一:在encoding.py的data.decode函数后面加上一个ignore属性。这样做可以忽略解码过程中可能出现的错误,并继续进行安装。 方法二:如果您是在conda创建的虚拟环境中操作,可以在conda的安装目录下找到类似的encoding.py文件。例如,如果conda安装在D盘,可以找到D:\Anaconda\envs\langchain\Lib\site-packages\pip\_internal\utils\encoding.py。同样地,在encoding.py的data.decode函数后面加上一个ignore属性。 希望以上方法能够帮助您解决Langchain-Chatchat中的JSONDecodeError问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [windows环境下的langchain-ChatGLM的本地部署](https://blog.csdn.net/muwpq/article/details/131270390)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [langchain-chatglm(v0.2.0)使用更新说明-项目更名为Langchain-Chatchat](https://blog.csdn.net/weixin_42232045/article/details/132271595)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值