langgraph实现 handsoff between agents 模式 (1)

官网示例代码

from typing_extensions import Literal
from langchain_core.messages import ToolMessage
from langchain_core.tools import tool
from langgraph.graph import MessagesState, StateGraph, START
from langgraph.types import Command
from langchain_openai import ChatOpenAImodel = ChatOpenAI(temperature=0,model="GLM-4-PLUS",openai_api_key="your api key",openai_api_base="https://open.bigmodel.cn/api/paas/v4/"
)@tool
def transfer_to_multiplication_expert():"""Ask multiplication agent for help."""# This tool is not returning anything: we're just using it# as a way for LLM to signal that it needs to hand off to another agent# (See the paragraph above)return@tool
def transfer_to_addition_expert():"""Ask addition agent for help."""returndef addition_expert(state: MessagesState,
) -> Command[Literal["multiplication_expert", "__end__"]]:system_prompt = ("You are an addition expert, you can ask the multiplication expert for help with multiplication. ""Always do your portion of calculation before the handoff.")messages = [{"role": "system", "content": system_prompt}] + state["messages"]ai_msg = model.bind_tools([transfer_to_multiplication_expert]).invoke(messages)# If there are tool calls, the LLM needs to hand off to another agentif len(ai_msg.tool_calls) > 0:tool_call_id = ai_msg.tool_calls[-1]["id"]# NOTE: it's important to insert a tool message here because LLM providers are expecting# all AI messages to be followed by a corresponding tool result messagetool_msg = {"role": "tool","content": "Successfully transferred","tool_call_id": tool_call_id,}return Command(goto="multiplication_expert", update={"messages": [ai_msg, tool_msg]})# If the expert has an answer, return it directly to the userreturn {"messages": [ai_msg]}def multiplication_expert(state: MessagesState,
) -> Command[Literal["addition_expert", "__end__"]]:system_prompt = ("You are a multiplication expert, you can ask an addition expert for help with addition. ""Always do your portion of calculation before the handoff.")messages = [{"role": "system", "content": system_prompt}] + state["messages"]ai_msg = model.bind_tools([transfer_to_addition_expert]).invoke(messages)if len(ai_msg.tool_calls) > 0:tool_call_id = ai_msg.tool_calls[-1]["id"]tool_msg = {"role": "tool","content": "Successfully transferred","tool_call_id": tool_call_id,}return Command(goto="addition_expert", update={"messages": [ai_msg, tool_msg]})return {"messages": [ai_msg]}
builder = StateGraph(MessagesState)
builder.add_node("addition_expert", addition_expert)
builder.add_node("multiplication_expert", multiplication_expert)
# we'll always start with the addition expert
builder.add_edge(START, "addition_expert")
graph = builder.compile()
builder = StateGraph(MessagesState)
builder.add_node("addition_expert", addition_expert)
builder.add_node("multiplication_expert", multiplication_expert)
# we'll always start with the addition expert
builder.add_edge(START, "addition_expert")
graph = builder.compile()
from IPython.display import Image, displaydisplay(Image(graph.get_graph().draw_mermaid_png()))

在这里插入图片描述

from langchain_core.messages import convert_to_messagesdef pretty_print_messages(update):if isinstance(update, tuple):ns, update = update# skip parent graph updates in the printoutsif len(ns) == 0:returngraph_id = ns[-1].split(":")[0]print(f"Update from subgraph {graph_id}:")print("\n")for node_name, node_update in update.items():print(f"Update from node {node_name}:")print("\n")for m in convert_to_messages(node_update["messages"]):m.pretty_print()print("\n")
for chunk in graph.stream({"messages": [("user", "what's (3 + 5) * 12")]},
):pretty_print_messages(chunk)
Update from node addition_expert:==================================[1m Ai Message [0m==================================
Tool Calls:transfer_to_multiplication_expert (call_-9024512232541698720)Call ID: call_-9024512232541698720Args:
=================================[1m Tool Message [0m=================================Successfully transferredUpdate from node multiplication_expert:==================================[1m Ai Message [0m==================================The result of \((3 + 5) \times 12\) is \(96\).

代码解释

这段代码实现了一个基于状态图(StateGraph)的简单对话系统,该系统利用两个“专家”节点(加法专家和乘法专家)来处理用户的问题。每个专家节点都由一个函数表示,并且可以根据需要将任务传递给另一个专家。代码的主要部分如下:

  1. 模型和工具定义

    • 使用ChatOpenAI模型作为对话系统的底层语言模型。
    • 定义了两个工具函数transfer_to_multiplication_experttransfer_to_addition_expert,这些工具函数用于在专家之间传递控制权。
  2. 专家函数

    • addition_expert函数处理加法相关的查询,并可以在需要时通过transfer_to_multiplication_expert工具将任务传递给乘法专家。
    • multiplication_expert函数处理乘法相关的查询,并可以在需要时通过transfer_to_addition_expert工具将任务传递给加法专家。
  3. 状态图构建

    • 使用StateGraph构建了一个对话流程图,其中包括加法专家和乘法专家两个节点。
    • 设置对话的起始节点为加法专家。
  4. 状态图的可视化

    • 使用graph.get_graph().draw_mermaid_png()方法生成了状态图的图像表示,并通过IPython.display模块显示这个图像。
  5. 对话处理和输出

    • 定义了pretty_print_messages函数,用于格式化和打印对话中的消息。
    • 使用graph.stream方法开始对话流程,并通过pretty_print_messages函数显示对话的输出。

这段代码的主要功能是创建一个能够处理加法和乘法查询的对话系统。用户提出的问题首先由加法专家处理,如果问题涉及到乘法运算,加法专家会将问题传递给乘法专家。乘法专家完成计算后,将结果返回给用户。这个系统展示了如何使用状态图和专家节点来构建一个能够处理特定领域任务的对话系统。

类似例子

from typing import Literal@tool
def transfer_to_english_expert():"""向英文专家请求帮助。"""return@tool
def transfer_to_chinese_expert():"""向中文专家请求帮助。"""returndef chinese_expert(state: MessagesState,
) -> Command[Literal["english_expert", "__end__"]]:system_prompt = ("你只讲中文,遇到英文问题,向英文专家请求帮助")messages = [{"role": "system", "content": system_prompt}] + state["messages"]ai_msg = model.bind_tools([transfer_to_english_expert]).invoke(messages)if len(ai_msg.tool_calls) > 0:tool_call_id = ai_msg.tool_calls[-1]["id"]tool_msg = {"role": "tool","content": "成功移交至英文专家","tool_call_id": tool_call_id,}return Command(goto="english_expert", update={"messages": [ai_msg, tool_msg]})return {"messages": [ai_msg]}def english_expert(state: MessagesState,
) -> Command[Literal["chinese_expert", "__end__"]]:system_prompt = ("You are an English expert. You only speak in English. ")messages = [{"role": "system", "content": system_prompt}] + state["messages"]ai_msg = model.bind_tools([transfer_to_chinese_expert]).invoke(messages)if len(ai_msg.tool_calls) > 0:tool_call_id = ai_msg.tool_calls[-1]["id"]tool_msg = {"role": "tool","content": "Successfully transferred to Chinese expert","tool_call_id": tool_call_id,}return Command(goto="chinese_expert", update={"messages": [ai_msg, tool_msg]})return {"messages": [ai_msg]}builder = StateGraph(MessagesState)
builder.add_node("chinese_expert", chinese_expert)
builder.add_node("english_expert", english_expert)
builder.add_edge(START, "chinese_expert")
graph = builder.compile()from IPython.display import Image, displaydisplay(Image(graph.get_graph().draw_mermaid_png()))

在这里插入图片描述

for chunk in graph.stream({"messages": [("user", "what's deepseek?")]},
):pretty_print_messages(chunk)
Update from node chinese_expert:==================================[1m Ai Message [0m==================================
Tool Calls:transfer_to_english_expert (call_-9024511682785680250)Call ID: call_-9024511682785680250Args:
=================================[1m Tool Message [0m=================================成功移交至英文专家Update from node english_expert:==================================[1m Ai Message [0m==================================DeepSeek is a term that might refer to a variety of concepts depending on the context. Here are a few possible interpretations:1. **Search Engine Technology**: It could be a metaphorical or branded name for a search engine or a search algorithm designed to delve deeply into data sources to retrieve highly relevant information.2. **Philosophical or Psychological Concept**: In a more abstract sense, it might refer to the act of seeking deep understanding or truth, often used in philosophical or psychological discussions.3. **Business or Product Name**: It could be the name of a company, product, or service that specializes in in-depth research, analytics, or data mining.4. **Technical Term in a Specific Field**: In certain scientific or technical fields, "deepseek" might be a term used to describe a particular method or process.Without more context, it's challenging to provide a definitive answer. If you have a specific context or industry in mind, please provide more details for a more accurate explanation.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/10574.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis代金卷(优惠卷)秒杀案例-单应用版

优惠卷表:优惠卷基本信息,优惠金额,使用规则 包含普通优惠卷和特价优惠卷(秒杀卷) 优惠卷的库存表:优惠卷的库存,开始抢购时间,结束抢购时间.只有特价优惠卷(秒杀卷)才需要填写这些信息 优惠卷订单表 卷的表里已经有一条普通优惠卷记录 下面首先新增一条秒杀优惠卷记录 { &quo…

观察者模式和订阅发布模式的关系

有人把观察者模式等同于发布订阅模式,也有人认为这两种模式存在差异,本质上就是调度的方法不同。 发布订阅模式: 观察者模式: 相比较,发布订阅将发布者和观察者之间解耦。(发布订阅有调度中心处理)

Ethflow Round 1 (Codeforces Round 1001, Div. 1 + Div. 2)(A,B,C,E1)

题目链接:Dashboard - Ethflow Round 1 (Codeforces Round 1001, Div. 1 Div. 2) - Codeforces A. String 思路 可以发现最小反转次数就是把每个1单独反转为0就行,即统计1的个数 代码 void solve(){string s;cin>>s;int sum0;for(int i0;i&l…

FreeRTOS从入门到精通 第十五章(事件标志组)

参考教程:【正点原子】手把手教你学FreeRTOS实时系统_哔哩哔哩_bilibili 一、事件标志组简介 1、概述 (1)事件标志位是一个“位”,用来表示事件是否发生。 (2)事件标志组是一组事件标志位的集合&#x…

Leetcode:541

1,题目 2,思路 用List集合来装字符串其中每k个为一个元素单位我们根据题目意思就可以明白list中偶数位需要反转reverse,奇数保持原样再全部拼接一块最后return tostring 3,代码 import java.util.ArrayList; import java.util.…

C语言指针专题四 -- 多级指针

目录 1. 多级指针的核心原理 1. 多级指针的定义 2. 内存结构示意图 3. 多级指针的用途 2. 编程实例 实例1:二级指针操作(修改一级指针的值) 实例2:动态二维数组(二级指针) 实例3:三级指…

Linux运维之Linux的安装和配置

目录 Linux的基本概念: 1.为什么要使用Linux? 2.什么是Linux? Linux的安装和配置: 1.下载Linux的虚拟机和镜像文件: 1.1下载虚拟机 1.2下载镜像文件 2.在虚拟机或者物理机中安装Linux操作系统 3.配置虚拟机的…

第一个3D程序!

运行效果 CPP #include <iostream> #include <fstream> #include <string> #include <cmath>#include <GL/glew.h> #include <GLFW/glfw3.h> #include <glm/glm.hpp> #include <glm/gtc/type_ptr.hpp> #include <glm/gtc/…

deepseek+vscode自动化测试脚本生成

近几日Deepseek大火,我这里也尝试了一下,确实很强。而目前vscode的AI toolkit插件也已经集成了deepseek R1,这里就介绍下在vscode中利用deepseek帮助我们完成自动化测试脚本的实践分享 安装AI ToolKit并启用Deepseek 微软官方提供了一个针对AI辅助的插件,也就是 AI Toolk…

简要介绍C++中的 max 和 min 函数以及返回值

简要介绍C中的 max 和 min 函数 在C中&#xff0c;std::max 和 std::min 是标准库 <algorithm> 中提供的函数&#xff0c;用于比较两个或多个值并返回最大值或最小值。这些函数非常强大且灵活&#xff0c;支持多种数据类型&#xff08;如整数、浮点数、字符串等&#xff…

【MyDB】4-VersionManager 之 3-死锁及超时检测

【MyDB】4-VersionManager 之 3-死锁及超时检测 死锁及超时检测案例背景LockTable锁请求与等待管理 addvm调用addputIntoList&#xff0c;isInList&#xff0c;removeFromList 死锁检测 hasDeadLock方法资源释放与重分配 参考资料 死锁及超时检测 本章涉及代码&#xff1a;top/…

Elasticsearch:如何搜索含有复合词的语言

作者&#xff1a;来自 Elastic Peter Straer 复合词在文本分析和标记过程中给搜索引擎带来挑战&#xff0c;因为它们会掩盖词语成分之间的有意义的联系。连字分解器标记过滤器等工具可以通过解构复合词来帮助解决这些问题。 德语以其长复合词而闻名&#xff1a;Rindfleischetik…

服务器虚拟化实战:架构、技术与最佳实践

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 服务器虚拟化是现代 IT 基础设施的重要组成部分&#xff0c;通过虚拟化技术可以提高服务器资源利用率、降低硬件成本&am…

【LLM】Ollama框架入门指北

note Ollama是一个开源框架&#xff0c;专门设计用于在本地运行大型语言模型。它的主要特点是将模型权重、配置和数据捆绑到一个包中&#xff0c;从而优化了设置和配置细节&#xff0c;包括GPU使用情况&#xff0c;简化了在本地运行大型模型的过程。Ollama提供了对模型量化的支…

Linux系统:Ubuntu替换镜像源具体方法;

在Linux系统更新下载软件时&#xff0c;如遇因镜像源问题下载失败时&#xff0c;我们就需要替换系统原有镜像源&#xff0c;那么&#xff0c;此时&#xff0c;你是否还在百度四处搜索可以用的镜像源地址&#xff0c;然后反复去测试源地址的正确性呢&#xff0c;下面介绍一个亲测…

使用vhd虚拟磁盘安装两个win10系统

使用vhd虚拟磁盘安装两个win10系统 前言vhd虚拟磁盘技术简介准备工具开始动手实践1.winX选择磁盘管理2.选择“操作”--“创建VHD”3.自定义一个位置&#xff0c;输入虚拟磁盘大小4.右键初始化磁盘5.选择GPT分区表格式6.右键新建简单卷7.给卷起个名字&#xff0c;用于区分8.打开…

HTML(快速入门)

欢迎大家来到我的博客~欢迎大家对我的博客提出指导&#xff0c;有错误的地方会改进的哦~点击这里了解更多内容 目录 一、前言二、HTML基础2.1 什么是HTML?2.2 认识HTML标签2.2.1 HTML标签当中的基本结构2.2.2 标签层次结构 2.3 HTML常见标签2.3.1 标题标签2.3.2 段落标签2.3.3…

d3.js: Relation Graph

d3.js Tags d3/d3 GitHub D3 by Observable | The JavaScript library for bespoke data visualization 下载或 <!-- 引入 D3.js 库 --> <script src"https://d3js.org/d3.v7.min.js"></script> <!-- 引入 D3.js 库 --> <…

Oracle Primavera P6自动进行进度计算

前言 在P6 Professional 有一个自动计划计算的选项&#xff0c;很多人不了解该设置如何使用&#xff0c;以及什么时候该启动这项配置。 详情 P6 Professional 默认为非自动进度计算。启用自动选项后&#xff0c;可以快速查看调度更改的效果。 ​ ​ 如图所示&#xff0c;当你…

反射、枚举以及lambda表达式

一.反射 1.概念&#xff1a;Java的反射&#xff08;reflection&#xff09;机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性&#xff0c;既然能拿到那么&am…