python机器人Agent编程——多Agent框架的底层逻辑(上)

news2024/11/17 15:26:57

目录

  • 一、前言
  • 二、两个核心概念
    • 2.1 Routines
      • (1)清晰的Prompt
      • (2)工具调用json schema自动生成
      • (3)解析模型的toolcall指令
      • (4)单Agent的循环决策与输出
  • PS.扩展阅读
    • ps1.六自由度机器人相关文章资源
    • ps2.四轴机器相关文章资源
    • ps3.移动小车相关文章资源
    • ps3.wifi小车控制相关文章资源

一、前言

现在大语言模型中的第一性原理:Scaling laws正在失效的论调四起,大模型大有迎来瓶颈期的感觉。然而,世界在AI领域都在较劲,虚虚实实,不可信其有也不可信其无。但是有个方向是一致的,那就是多Agent的路线。无论是AI头部企业OpenAI、Google、Facbook、Microsoft还是业界大佬Andrew FeiFeiLi、Michael Winikoff等都对多Agent技术路线作了充分的肯定。本文是对阅读Ilan Bigio的《Orchestrating Agents: Routines and Handoffs》的回炉理解和分享,其文章平实未有半点修饰,基础阐述了多Agent协作的底层算法逻辑。而OpenAI推出的教育框架Swarm就是源于此Idea.
在这里插入图片描述

二、两个核心概念

多Agent协作Idea引入了概念: routineshandoffs,通过基于这两个概念的python代码实现,完成了多个智能体间的转移、协作和完整的用户交互。

2.1 Routines

这个词通过体会,可以理解为简单的机械的任务列表。通过向LLM描述一些比较清晰的,简单的先后任务Prompt,和提供完成这些任务表所需的function或者tools,实现单个Agent完成某项“技能”的能力。这里的核心要点主要有两个:

(1)清晰的Prompt

需要向LLM提供一个较为明确,没有歧义容易操作的system的Promt描述,这个相当于对一个社会上的普通人,雇用后,对其进行业务的培训,让他/她明白这个岗位的职责和操作步骤,使其成为一个公司的特定岗位的业务员。

system_message = (
    "You are a customer support agent for ACME Inc."
    "Always answer in a sentence or less."
    "Follow the following routine with the user:"
    "1. First, ask probing questions and understand the user's problem deeper.\n"
    " - unless the user has already provided a reason.\n"
    "2. Propose a fix (make one up).\n"
    "3. ONLY if not satesfied, offer a refund.\n"
    "4. If accepted, search for the ID and then execute refund."
    ""
)

(2)工具调用json schema自动生成

LLM现在都支持外部的tool/函数调用了,而且很多都是遵循OpenAi的规范格式,就是json schema格式,可以认为是大模型的结构化输出通讯协议的一种。

大模型JSON Schema格式是一种用于描述和验证JSON数据结构的规范。它定义了JSON数据中各个元素的类型、格式、约束和关系,确保了数据的一致性和可靠性。在软件开发、API设计以及数据交换过程中,JSON Schema发挥着重要作用(来自网络的定义,不知道说些什么)
“协议”的格式如下:

{
  "type": "function",
  "function": {
    "name": "sample_function",#工具名称
    "description": "This is my docstring. Call this function when you want.",#工具描述
    "parameters": {#工具行参数描述
      "type": "object",
      "properties": {
        "param_1": {#第1个参数
          "type": "string"
        },
        "param_2": {#第2个参数
          "type": "string"
        },
        "the_third_one": {#第3个参数
          "type": "integer"
        },
        "some_optional": {#可选参数
          "type": "string"
        }
      },
      "required": [
        "param_1",
        "param_2",
        "the_third_one"
      ] {#必须传入的参数
    }
  }
}

其实就是对应的一个python的普通的funciton:

def sample_function(param_1, param_2, the_third_one: int, some_optional="John Doe"):
    """
    This is my docstring. Call this function when you want.
    """
    print("Hello, world")

区别与需要手动定义这个JSON Schema,可以用一个python函数自动生成实现JSON Schema,这个也是用到了swarm框架里了:

import inspect
#实现一个自动JSON Schema生成
def function_to_schema(func) -> dict:
    type_map = {
        str: "string",
        int: "integer",
        float: "number",
        bool: "boolean",
        list: "array",
        dict: "object",
        type(None): "null",
    }

    try:
        signature = inspect.signature(func)
    except ValueError as e:
        raise ValueError(
            f"Failed to get signature for function {func.__name__}: {str(e)}"
        )

    parameters = {}
    for param in signature.parameters.values():
        try:
            param_type = type_map.get(param.annotation, "string")
        except KeyError as e:
            raise KeyError(
                f"Unknown type annotation {param.annotation} for parameter {param.name}: {str(e)}"
            )
        parameters[param.name] = {"type": param_type}

    required = [
        param.name
        for param in signature.parameters.values()
        if param.default == inspect._empty
    ]

    return {
        "type": "function",
        "function": {
            "name": func.__name__,
            "description": (func.__doc__ or "").strip(),
            "parameters": {
                "type": "object",
                "properties": parameters,
                "required": required,
            },
        },
    }

以上的自动生成函数适合任何一个普通函数:

def add(a:int,b:int,isadd=True):
    """
    this funciton is used to do add method when isadd is true or minuse method when isadd is false return the result
    """
    if isadd:
        return a+b
    else:
        return a-b

schema =  function_to_schema(add)
print(json.dumps(schema, indent=2))

打印结果如下:
在这里插入图片描述
有了以上两个法宝后就可以轻松实现agent的外部函数调用了:

# -*- coding: utf-8 -*-
"""
Created on Fri Nov 15 16:47:17 2024

@author: 18268
"""

import inspect
import json

def function_to_schema(func) -> dict:
    type_map = {
        str: "string",
        int: "integer",
        float: "number",
        bool: "boolean",
        list: "array",
        dict: "object",
        type(None): "null",
    }

    try:
        signature = inspect.signature(func)
    except ValueError as e:
        raise ValueError(
            f"Failed to get signature for function {func.__name__}: {str(e)}"
        )

    parameters = {}
    for param in signature.parameters.values():
        try:
            param_type = type_map.get(param.annotation, "string")
        except KeyError as e:
            raise KeyError(
                f"Unknown type annotation {param.annotation} for parameter {param.name}: {str(e)}"
            )
        parameters[param.name] = {"type": param_type}

    required = [
        param.name
        for param in signature.parameters.values()
        if param.default == inspect._empty
    ]

    return {
        "type": "function",
        "function": {
            "name": func.__name__,
            "description": (func.__doc__ or "").strip(),
            "parameters": {
                "type": "object",
                "properties": parameters,
                "required": required,
            },
        },
    }

def add(a:int,b:int,isadd=True):
    """
    this funciton is used to do add method when isadd is true or minuse method when isadd is false return the result
    """
    if isadd:
        return a+b
    else:
        return a-b

schema =  function_to_schema(add)
print(json.dumps(schema, indent=2))

from openai import OpenAI
# 定义模型  
MODEL = "llama3.2:latest"  
ollama_client = OpenAI(
    base_url = 'http://localhost:11434/v1',
    api_key='None', # required, but unused
)
messages = []

tools = [add]
tool_schemas = [function_to_schema(tool) for tool in tools]

response = ollama_client.chat.completions.create(
            model=MODEL,
            messages=[{"role": "user", "content": "1加1等于几"}],
            tools=tool_schemas,
        )
message = response.choices[0].message

print(message.tool_calls[0].function)

最后模型根据用户输入"1加1等于几",会去查找工具的tool_schemas,并自主决定了调用add这个工具,输出如下:
在这里插入图片描述
这个是openai自定义的一个type:openai.types.chat.chat_completion_message_tool_call.Function

(3)解析模型的toolcall指令

这个就是当模型认为要调用工具时,会吐出要调用的某个函数的信息:
在这里插入图片描述

,包含一个function属性及对应名字和参数。接下来就是根据它,去调用实体的函数:

tools=[add]
tools_map = {tool.__name__: tool for tool in tools}#这里搞了一个tools_map,用于存多个funciton的名字

def execute_tool_call(tool_call, tools_map):
	#根据openai的LLM返回格式,调用相应函数
    name = tool_call.function.name
    args = json.loads(tool_call.function.arguments)

    print(f"Assistant: {name}({args})")

    # call corresponding function with provided arguments
    return tools_map[name](**args)
execute_tool_call(message.tool_calls[0], tools_map)

如下调用了add函数,执行并输出了结果。
在这里插入图片描述

(4)单Agent的循环决策与输出

以上实现了LLM自动调用工具库的function,如果需要多个工具库的调用,还需要做一个while循环,首先需要将前一个工具执行输出结果输入给LLM,然后再让LLM对照routines的任务表判断,是否还要继续调用其它工具,直到它认为可以输出结果返给user为止:


def run_full_turn(system_message, tools, messages):

    num_init_messages = len(messages)
    messages = messages.copy()

    while True:

        # turn python functions into tools and save a reverse map
        tool_schemas = [function_to_schema(tool) for tool in tools]
        tools_map = {tool.__name__: tool for tool in tools}

        # === 1. get openai completion ===
        
        
        response = ollama_client.chat.completions.create(
                    model=MODEL,#或者qwen2.5等本地模型
                    messages=[{"role": "system", "content": system_message}] + messages,
                    tools=tool_schemas or None,
                )
        
      
        message = response.choices[0].message
        messages.append(message)

        if message.content:  # print assistant response
            print("Assistant:", message.content)

        if not message.tool_calls:  # if finished handling tool calls, break
            break

        # === 2. handle tool calls ===

        for tool_call in message.tool_calls:
            result = execute_tool_call(tool_call, tools_map)

            result_message = {
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": result,
            }
            print("result_message:",result_message)
            messages.append(result_message)

    # ==== 3. return new messages =====
    return messages[num_init_messages:]

PS.扩展阅读

————————————————————————————————————————

对于python机器人编程感兴趣的小伙伴,可以进入如下链接阅读相关咨询

ps1.六自由度机器人相关文章资源

(1) 对六自由度机械臂的运动控制及python实现(附源码)
在这里插入图片描述

(2) N轴机械臂的MDH正向建模,及python算法
在这里插入图片描述

ps2.四轴机器相关文章资源

(1) 文章:python机器人编程——用python实现一个写字机器人
在这里插入图片描述

在这里插入图片描述

(2)python机器人实战——0到1创建一个自动是色块机器人项目-CSDN直播

(3)博文《我从0开始搭建了一个色块自动抓取机器人,并实现了大模型的接入和语音控制-(上基础篇)》的vrep基础环境
(3)博文《我从0开始搭建了一个色块自动抓取机器人,并实现了大模型的接入和语音控制-(上基础篇)》的vrep基础环境
(4)实现了语音输入+大模型指令解析+机器视觉+机械臂流程打通
在这里插入图片描述
在这里插入图片描述

ps3.移动小车相关文章资源

(1)python做了一个极简的栅格地图行走机器人,到底能干啥?[第五弹]——解锁蒙特卡洛定位功能-CSDN博客
(2) 对应python资源:源码地址
在这里插入图片描述
在这里插入图片描述

(3)python机器人编程——差速AGV机器、基于视觉和预测控制的循迹、自动行驶(上篇)_agv编程-CSDN博客
(4)python机器人编程——差速AGV机器、基于视觉和预测控制的循迹、自动行驶(下篇)_agv路线规划原则python-CSDN博客
对应python及仿真环境资源:源码链接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ps3.wifi小车控制相关文章资源

web端配套资源源代码已经上传(竖屏版),下载地址
仿真配套资源已经上传:下载地址
web端配套资源源代码已经上传(横屏版),下载地址

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【大语言模型】ACL2024论文-14 任务:不可能的语言模型

【大语言模型】ACL2024论文-14 任务:不可能的语言模型 目录 文章目录 【大语言模型】ACL2024论文-14 任务:不可能的语言模型目录摘要研究背景问题与挑战如何解决创新点算法模型实验效果重要数据与结论推荐阅读指数和推荐理由 后记 任务:不可能…

redis linux 安装

下载解压 https://download.redis.io/releases/ tar -zvxf ----redis-7.4.1编译 进入目录下 # redis 依赖c yum install gcc-cmake可能会有问题,所以记得换源# 安装到 /usr/local/redis make PREFIX/usr/local/redis installcd src ./redis-serverredis.confi…

计算机毕业设计Hadoop+大模型空气质量预测 空气质量可视化 空气质量分析 空气质量爬虫 Spark 机器学习 深度学习 Django 大模型

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

云原生之运维监控实践-使用Telegraf、Prometheus与Grafana实现对InfluxDB服务的监测

背景 如果你要为应用程序构建规范或用户故事,那么务必先把应用程序每个组件的监控指标考虑进来,千万不要等到项目结束或部署之前再做这件事情。——《Prometheus监控实战》 去年写了一篇在Docker环境下部署若依微服务ruoyi-cloud项目的文章,当…

HTML+CSS+JavaScript

一、HTML 1、什么是HTML HTML(Hyper Text Markup Language)也叫超文本标记语言,什么意思呢? 超文本:普通文本语言没有什么特殊功能,而超文本,是表示一种比文本语言功能更强大的语言&#xff0c…

Dropout 和 BatchNorm 在训练和验证中的差异

文章目录 1. Dropout1.1 作用1.2 训练和验证的差异1.3 示例 2. Batch Normalization (BatchNorm)2.1 作用2.2 训练和验证时的差异2.3 示例 3. 总结4. 实际使用建议 在神经网络中,Dropout 和 Batch Normalization (BatchNorm) 是常见的层,其行为在 训练阶…

SQL Server 查询设置 - LIKE/DISTINCT/HAVING/排序

目录 背景 一、LIKE - 模糊查询 1. 通配符 % 2. 占位符 _ 3. 指定集合 [] 3.1 表示否定 ^ 3.2 表示范围 - 4. 否定 NOT 二、DISTINCT - 去重查询 三、HAVING - 过滤查询 四、小的查询设置 1. ASC|DESC - 排序 2. TOP - 限制 3. 子查询 4. not in - 取补集&…

【算法速刷(10/100)】LeetCode —— 23. 合并 K 个升序链表

按照最朴素的方法,每轮都对所给列表进行一次遍历,O(n)的复杂度获得值最小的节点,并将其上的链表指针后移一位,一旦为空则剔除数组。数组为空时结束循环。 这样写时间复杂度较高,因为涉及到枚举最小值节点,数…

【C语言】四种方法交换两个数(免费复制)

方法一&#xff1a; 通过中间变量t直接交换。 #include<stdio.h> //方法一 int main() {int a,b,t;printf("请输入a和b的值&#xff1a;\n");scanf("%d %d",&a,&b);printf("交换前&#xff1a;a%d,b%d\n",a,b);ta;ab;bt;printf…

WebSocket简易聊天室实现(有详细解释)

完整代码 Arata08/online-chat-demo 服务端: 1.编写配置类&#xff0c;扫描有 ServerEndpoint 注解的 Bean import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.s…

数据分析——Python绘制实时的动态折线图

最近在做视觉应用开发&#xff0c;有个需求需要实时获取当前识别到的位姿点位是否有突变&#xff0c;从而确认是否是视觉算法的问题&#xff0c;发现Python的Matplotlib进行绘制比较方便。 目录 1.数据绘制2.绘制实时的动态折线图3.保存实时数据到CSV文件中 import matplotlib.…

i春秋-Hash

练习平台地址 竞赛中心 题目描述 题目内容 啥也没有就一个标签跳转 点击后的确发生了跳转 观察到url中有key和hash两个值&#xff0c;猜测hash是key的hash 查看源代码发现确实是 $hashmd5($sign.$key);the length of $sign is 8 解密得到$sign应该为kkkkkk01 构造122的hash i…

举例理解LSM-Tree,LSM-Tree和B+Tree的比较

写操作 write1&#xff1a;WAL 把操作同步到磁盘中WAL做备份&#xff08;追加写、性能极高&#xff09; write2&#xff1a;Memtable 完成WAL后将(k,v)数据写入内存中的Memtable&#xff0c;Memtable的数据结构一般是跳表或者红黑树 内存内采用这种数据结构一方面支持内存…

论文PDF页面无法下载PDF

问题&#xff1a;通常在下载学术论文时&#xff0c;网页命名是PDF页面&#xff0c;但是无法下载PDF&#xff0c;下载的是html网页 解决&#xff1a; mac&#xff1a;按F12打开开发者界面 然后点击源代码/来源选项 然后打开下图所在位置&#xff0c;鼠标右键复制链接&#xff…

ORA-01092 ORA-14695 ORA-38301

文章目录 前言一、MAX_STRING_SIZE--12C 新特性扩展数据类型 varchar2(32767)二、恢复操作1.尝试恢复MAX_STRING_SIZE参数为默认值2.在upgrade模式下执行utl32k.sql 前言 今天客户发来一个内部测试库数据库启动截图报错&#xff0c;描述是“上午出现服务卡顿&#xff0c;然后重…

ElasticSearch学习笔记二:使用Java客户端

一、前言 在上一篇文章中&#xff0c;我们对ES有了最基本的认识&#xff0c;本着实用为主的原则&#xff0c;我们先不学很深的东西&#xff0c;今天打算先学习一下ES的Java客户端如何使用。 二、创建项目 1、普通Maven项目 1、创建一个Maven项目 2、Pom文件 <dependenc…

[Linux]多线程详解

多线程 1.线程的概念和理解1.1线程的优点1.2线程的缺点1.3线程的设计1.4线程 VS 进程 2.线程控制2.1线程等待2.2 线程终止2.3 线程分离 3.线程互斥3.1背景3.2抢票代码演示3.3保护公共资源&#xff08;加锁&#xff09;3.3.1创建锁/销毁锁3.3.2申请锁/尝试申请锁/解锁 3.4解决抢…

替换OpenTSDB和HBase,宝武集团使用IoTDB助力钢铁设备智能运维

时序数据库 IoTDB 应用于宝武集团全基地钢铁时序数据管理&#xff0c;激活数据资产&#xff0c;赋能大型设备智能运维。 1. 背景概述 宝武装备智能科技有限公司&#xff08;以下简称&#xff1a;宝武智维&#xff09;是中国宝武设备智能运维专业化平台公司&#xff0c;30 余年始…

VSCode+ESP-IDF开发ESP32-S3-DevKitC-1(1)开发环境搭建

VSCodeESP-IDF开发ESP32-S3-DevKitC-1&#xff08;1&#xff09;开发环境搭建 1.开发环境搭建&#xff08;安装ESP-IDF&#xff09;2.开发环境搭建&#xff08;安装VS Code&#xff09;3.开发环境搭建&#xff08;VSCode中安装ESP-IDF插件及配置&#xff09; 1.开发环境搭建&am…

Ubuntu24 上安装搜狗输入法

link 首先在终端中依次输入以下代码 sudo apt update sudo apt install fcitx 找到语言支持 在终端中依次输入 sudo cp /usr/share/applications/fcitx.desktop /etc/xdg/autostart/ sudo apt purge ibus 进入网页 搜狗输入法linux-首页​ shurufa.sogou.com/linux 找到刚才下…