MetaGPT中的单智能体Action

news/2024/12/17 5:00:45/

目录

    • 单智能体 单Action
    • 单智能体 多Action
    • 参考链接

单智能体 单Action

定义一个名为SimpleCoder的角色,这个角色可以执行一个名为SimpleWriteCode的动作。这个动作的目的是生成一个Python函数的代码,该函数能够完成给定的任务,并提供两个可运行的测试用例。代码使用了metagpt库中的Action和Role类,以及日志记录功能。

下面是代码的逐行解释:

**1.导入所需的模块:**re用于正则表达式,asyncio用于异步编程,以及metagpt库中的Action、Role、Message和logger。

2.定义一个名为SimpleWriteCode的类: 继承自Action。这个类的作用是生成Python函数代码。

  • PROMPT_TEMPLATE是一个字符串模板,用于生成提示用户编写代码的字符串。 name是这个动作的名称。
  • run方法是一个异步方法,它接受一个指令字符串,生成一个提示,然后调用_aask方法(这个方法在代码中没有定义,可能是metagpt库的一部分)来获取用户输入的代码。
  • parse_code是一个静态方法,用于从用户输入中提取Python代码。它使用正则表达式来查找被python包围的代码块。

3.定义一个名为SimpleCoder的类: 继承自Role。这个类的作用是使用SimpleWriteCode动作。

  • 在__init__方法中,它设置了可以执行的动作列表,这里只有一个SimpleWriteCode。
  • _act方法是一个异步方法,它获取最近的消息,使用SimpleWriteCode动作生成代码,然后创建一个新的Message对象并返回。

4.定义一个名为main的异步函数: 创建了一个SimpleCoder实例,设置了一个任务(在这个例子中是“write a function that calculates the sum of a list”),然后运行这个角色并记录结果。

import re
import asyncio
from metagpt.actions import Action
from metagpt.roles import Role
from metagpt.schema import Message
from metagpt.logs import loggerclass SimpleWriteCode(Action):PROMPT_TEMPLATE:str = """Write a python function that can {instruction} and provide two runnable test cases.Return ```python your_code_here ```with NO other texts,your code:"""name: str = "SimpleWriteCode"async def run(self, instruction: str):prompt = self.PROMPT_TEMPLATE.format(instruction=instruction)rsp = await self._aask(prompt)code_text = SimpleWriteCode.parse_code(rsp)return code_text@staticmethoddef parse_code(rsp):pattern = r'```python(.*)```'match = re.search(pattern, rsp, re.DOTALL)code_text = match.group(1) if match else rspreturn code_textclass SimpleCoder(Role):def __init__(self, **kwargs):super().__init__(**kwargs)self.set_actions([SimpleWriteCode])async def _act(self) -> Message:logger.info(f"{self._setting}: ready to {self.rc.todo}")todo = self.rc.todo  # todo will be SimpleWriteCode()msg = self.get_memories(k=1)[0]  # find the most recent messagescode_text = await todo.run(msg.content)msg = Message(content=code_text, role=self.profile,cause_by=type(todo))return msgasync def main():msg = "write a function that calculates the sum of a list"role = SimpleCoder()logger.info(msg)result = await role.run(msg)logger.info(result)await main()

输出:

2024-12-11 16:21:31.726 | INFO     | __main__:main:51 - write a function that calculates the sum of a list
2024-12-11 16:21:31.728 | INFO     | __main__:_act:37 - <property object at 0x000001DAC56A5260>(): ready to SimpleWriteCode```python
def generate_sum_function():def sum_of_list(lst):return sum(lst)return sum_of_list# Test cases
sum_function = generate_sum_function()# Test case 1
assert sum_function([1, 2, 3, 4, 5]) == 15
print("Test case 1 passed.")# Test case 2
assert sum_function([-1, 0, 1, 2, -3]) == -1
print("Test case 2 passed2024-12-11 16:21:36.636 | WARNING  | metagpt.utils.cost_manager:update_cost:49 - Model GLM-4 not found in TOKEN_COSTS.
2024-12-11 16:21:36.637 | INFO     | __main__:main:53 - : 
def generate_sum_function():def sum_of_list(lst):return sum(lst)return sum_of_list# Test cases
sum_function = generate_sum_function()# Test case 1
assert sum_function([1, 2, 3, 4, 5]) == 15
print("Test case 1 passed.")# Test case 2
assert sum_function([-1, 0, 1, 2, -3]) == -1
print("Test case 2 passed.").")
```

另一个问题测试

async def main():msg = "solve th problem: 3x+11*2/3 =6"role = SimpleCoder()logger.info(msg)result = await role.run(msg)logger.info(result)await main()

输出

2024-12-11 16:28:46.157 | INFO     | __main__:main:4 - solve th problem: 3x+11*2/3 =6
2024-12-11 16:28:46.158 | INFO     | __main__:_act:37 - <property object at 0x000001DAC56A5260>(): ready to SimpleWriteCode```python
def solve_linear_equation():# Constants in the equation: 3x + 11 * 2/3 = 6a = 3b = 22/3c = -6# Calculate x using the formula: x = (c - b) / ax = (c - b) / areturn x# Test cases
test_case_1 = solve_linear_equation()
test_case_2 = solve_linear_equation()# The following line is just to prevent syntax error, remove it when pasting into a Python environment
# python your_code_here
```Please note that when pasting this into a Python environment, you should remove the last line starting with `# python`. The test cases are simply calling the function twice to show that it can be run multiple times. The actual result should be the same each time the function is called.2024-12-11 16:28:57.476 | WARNING  | metagpt.utils.cost_manager:update_cost:49 - Model GLM-4 not found in TOKEN_COSTS.
2024-12-11 16:28:57.477 | INFO     | __main__:main:6 - : 
def solve_linear_equation():# Constants in the equation: 3x + 11 * 2/3 = 6a = 3b = 22/3c = -6# Calculate x using the formula: x = (c - b) / ax = (c - b) / areturn x# Test cases
test_case_1 = solve_linear_equation()
test_case_2 = solve_linear_equation()# The following line is just to prevent syntax error, remove it when pasting into a Python environment
# python your_code_here

单智能体 多Action

定义一个名为Programmer的角色,它能够执行三个动作:优化需求(RequirementsOpt)、编写代码(CodeWrite)和运行代码(CodeRun)。这个角色的目的是自动化地处理编程任务,从理解需求到编写和测试代码。下面是对代码的详细解释:

导入模块

  • re:正则表达式模块,用于文本匹配。
  • asyncio:异步编程模块,用于定义和运行异步任务。
  • subprocess:用于执行外部命令和程序。
  • metagpt库中的Action、Role、Message和logger。

CodeWrite 类

  • 这是一个Action类,用于根据给定的需求编写Python函数。
  • PROMPT_TEMPLATE:一个字符串模板,用于生成提示用户编写代码的字符串。
  • run方法:接受需求字符串,生成提示,调用_aask方法获取代码,然后解析代码。
  • parse_code静态方法:从响应中提取Python代码。

RequirementsOpt 类

  • 另一个Action类,用于优化和明确需求。
  • PROMPT_TEMPLATE:一个字符串模板,用于生成需求优化的提示。
  • run方法:接受原始需求,生成优化需求的提示,调用_aask方法获取优化后的需求。

CodeRun 类

  • 用于运行Python代码。
  • run方法:使用subprocess模块执行Python代码,并返回输出结果或错误信息。

Programmer 类

  • 定义了一个名为Programmer的角色,继承自Role。
  • 初始化时,设置了三个动作:RequirementsOpt、CodeWrite和CodeRun,并设置为顺序执行模式。
  • _act方法:定义了角色的行动逻辑,包括获取用户输入、执行动作、构造消息对象并返回结果。

main 函数

  • 定义了一个异步函数main,用于运行Programmer角色。
  • 实例化Programmer角色,设置一个具体的需求,记录日志信息,运行角色并记录结果。
  • 代码执行 使用await main()启动异步任务。

代码逻辑

  • 需求优化:首先,Programmer角色会优化用户提供的需求,使其更加明确和全面。
  • 代码编写:然后,根据优化后的需求,编写相应的Python代码。
  • 代码运行:最后,运行编写的代码,并返回结果。
import re
import asyncio
import subprocess
from metagpt.actions import Action
from metagpt.roles import Role
from metagpt.schema import Message
from metagpt.logs import logger# 代码撰写Action
class CodeWrite(Action):PROMPT_TEMPLATE: str = """根据以下需求,编写一个能够实现{requirements}的Python函数。返回的格式为:```python\n你的代码\n```,请不要包含其他的文本。```python# your code here```"""name: str = "CodeWriter"async def run(self, requirements: str):prompt = self.PROMPT_TEMPLATE.format(requirements=requirements)rsp = await self._aask(prompt)code_text = CodeWrite.parse_code(rsp)return code_text@staticmethoddef parse_code(rsp):  # 从模型生成中字符串匹配提取生成的代码pattern = r"```python(.*?)```"  # 使用非贪婪匹配match = re.search(pattern, rsp, re.DOTALL)code_text = match.group(1) if match else rspreturn code_text# 需求优化Action
class RequirementsOpt(Action):PROMPT_TEMPLATE: str = """你要遵守的规范有:1.简要说明 (Brief Description)简要介绍该用例的作用和目的。2.事件流 (Flow of Event)包括基本流和备选流,事件流应该表示出所有的场景。3.用例场景 (Use-Case Scenario)包括成功场景和失败场景,场景主要是由基本流和备选流组合而成的。4.特殊需求 (Special Requirement)描述与该用例相关的非功能性需求(包括性能、可靠性、可用性和可扩展性等)和设计约束(所使用的操作系统、开发工具等)。5.前置条件 (Pre-Condition)执行用例之前系统必须所处的状态。6.后置条件 (Post-Condition)用例执行完毕后系统可能处于的一组状态。无需测试用例,所有的代码在一个```python```中请优化以下需求,使其更加明确和全面:{requirements}"""name: str = "RequirementsOpt"async def run(self, requirements: str):prompt = self.PROMPT_TEMPLATE.format(requirements=requirements)rsp = await self._aask(prompt)return rsp.strip()  # 返回优化后的需求# 代码运行Action
class CodeRun(Action):name: str = "CodeRun"async def run(self, code_text: str):try:result = subprocess.run(["python", "-c", code_text], text=True, capture_output=True, check=True)return result.stdoutexcept subprocess.CalledProcessError as e:return e.stderr# 设计Programmer Agent人设
class Programmer(Role):"""Programmer 角色类,继承自 Role 基类"""name: str = "cheems"profile: str = "Programmer"def __init__(self, **kwargs):"""初始化 Programmer 角色"""super().__init__(**kwargs)  # 调用基类构造函数self.set_actions([RequirementsOpt, CodeWrite, CodeRun])  # 为角色配备三个动作self._set_react_mode(react_mode="by_order")  # 顺序执行async def _act(self) -> Message:"""定义角色行动逻辑"""logger.info(f"{self._setting}: 准备 {self.rc.todo}")  # 记录日志todo = self.rc.todo  # 按照排列顺序获取待执行的动作msg = self.get_memories(k=1)[0]  # 获取最相似的一条记忆 (用户输入)# 优化需求》编写代码》运行代码result = await todo.run(msg.content)# 构造 Message 对象msg = Message(content=result, role=self.profile, cause_by=type(todo))self.rc.memory.add(msg)  # 将运行结果添加到记忆return msg  # 返回最终的 Message# 运行我们的Agent
async def main():msg = "如何用python设计一个ToDoList,使用Tkinter库,尽量不要安装额外包,安装包的代码要直接在python代码中运行,而非手动输入cmd;"role = Programmer()  # 实例化 Programmerlogger.info(msg)  # 记录日志信息result = await role.run(msg)  # 得到运行结果logger.info(result)  # 记录运行结果await main() # 异步运行 main 函数
2024-12-11 16:57:47.304 | INFO     | __main__:main:119 - 如何用python设计一个ToDoList,使用Tkinter库,尽量不要安装额外包,安装包的代码要直接在python代码中运行,而非手动输入cmd;
2024-12-11 16:57:47.305 | INFO     | __main__:_act:100 - cheems(Programmer): 准备 RequirementsOpt为了使ToDoList应用程序的需求更加明确和全面,我们可以按照您提供的模板来细化需求。以下是针对该应用程序的优化需求说明:### 简要说明
开发一个基于Python和Tkinter库的图形用户界面(GUI)待办事项列表(ToDoList)应用程序。该应用程序允许用户创建、查看、编辑和删除待办事项,无需安装任何额外的包。### 事件流
1. **基本流**- 启动应用程序时,显示一个窗口,其中包含添加新待办事项的输入框和按钮。- 用户输入待办事项并点击添加按钮,待办事项被添加到列表中。- 用户可以点击列表中的待办事项来编辑或删除它。- 用户可以清除所有待办事项。2. **备选流**- 如果用户尝试添加空白的待办事项,应用程序应阻止并提示用户输入内容。- 如果用户尝试编辑待办事项,但未做任何更改,应用程序应允许取消编辑。- 如果用户尝试删除待办事项,应用程序应请求确认。### 用例场景
1. **成功场景**- 用户成功添加一个待办事项。- 用户编辑并保存待办事项。- 用户删除一个待办事项。- 用户清除所有待办事项。2. **失败场景**- 用户尝试添加空白的待办事项,应用程序显示错误消息。- 用户尝试编辑待办事项但取消操作,待办事项保持不变。### 特殊需求
- 应用程序应具有直观的用户界面。
- 应用程序应在所有主流操作系统上运行。
- 应用程序应避免使用额外的包,所有必需的代码应在脚本内提供。### 前置条件
- Python环境已安装。
- Tkinter库随Python一同安装,无需额外步骤。### 后置条件
- 应用程序启动后,用户界面应正确显示。
- 待办事项列表中的数据应正确反映用户的添加、编辑和删除操作。以下是一个简化版的Python代码示例,它实现了上述需求,并直接在代码中包含了Tkinter库的使用:```python
import tkinter as tk
from tkinter import messageboxclass ToDoListApp:def __init__(self, root):self.root = rootself.root.title("To Do List")self.listbox = tk.Listbox(root)self.listbox.pack(fill="both", expand=True)self.entry = tk.Entry(root)self.entry.pack(side="bottom", fill="x")self.entry.bind('<Return>', self.add_item)tk.Button(root, text="Add", command=self.add_item).pack(side="bottom")def add_item(self, event=None):item = self.entry.get()if item:self.listbox.insert(tk.END, item)self.entry.delete(0, tk.END)else:messagebox.showwarning("Warning", "Please enter a to-do item.")def run(self):self.root.mainloop()if __name__ == "__main__":root = tk.Tk()app = ToDoListApp(root)app.run()
```请注意,上述代码仅提供了添加待办事项的基本功能,为了完整实现需求,还需要添加编辑、删除和清除所有待办事项的功能。由于代码较长,这里仅提供了核心框架。2024-12-11 16:58:16.614 | WARNING  | metagpt.utils.cost_manager:update_cost:49 - Model GLM-4 not found in TOKEN_COSTS.
2024-12-11 16:58:16.634 | INFO     | __main__:_act:100 - cheems(Programmer): 准备 CodeWriteCertainly! Below is an extended version of the Python code using Tkinter that includes the functionality to edit, delete, and clear all the to-do items in the list.```python
import tkinter as tk
from tkinter import messageboxclass ToDoListApp:def __init__(self, root):self.root = rootself.root.title("To Do List")self.listbox = tk.Listbox(root)self.listbox.pack(fill="both", expand=True)self.listbox.bind('<Double-Button-1>', self.edit_item)self.entry = tk.Entry(root)self.entry.pack(side="bottom", fill="x")self.entry.bind('<Return>', self.add_item)tk.Button(root, text="Add", command=self.add_item).pack(side="left", anchor="sw")tk.Button(root, text="Delete", command=self.delete_item).pack(side="left", anchor="sw")tk.Button(root, text="Clear All", command=self.clear_all).pack(side="left", anchor="sw")def add_item(self, event=None):item = self.entry.get()if item:self.listbox.insert(tk.END, item)self.entry.delete(0, tk.END)else:messagebox.showwarning("Warning", "Please enter a to-do item.")def edit_item(self, event=None):try:index = self.listbox.curselection()[0]item = self.listbox.get(index)self.listbox.delete(index)self.entry.delete(0, tk.END)self.entry.insert(tk.END, item)self.entry.select_range(0, tk.END)except IndexError:messagebox.showwarning("Warning", "No item selected for editing.")def delete_item(self):try:index = self.listbox.curselection()[0]confirm = messagebox.askokcancel("Confirm", "Are you sure you want to delete this item?")if confirm:self.listbox.delete(index)except IndexError:messagebox.showwarning("Warning", "No item selected for deletion.")def clear_all(self):confirm = messagebox.askokcancel("Confirm", "Are you sure you want to clear all items?")if confirm:self.listbox.delete(0, tk.END)def run(self):self.root.mainloop()if __name__ == "__main__":root = tk.Tk()app = ToDoListApp(root)app.run()
```This code provides the following functionalities:
- Double-clicking an item in the listbox will allow you to edit it.
- A "Delete" button to remove the currently selected item from the listbox.
- A "Clear All" button to remove all items from the listbox2024-12-11 16:58:39.547 | WARNING  | metagpt.utils.cost_manager:update_cost:49 - Model GLM-4 not found in TOKEN_COSTS.
2024-12-11 16:58:39.549 | INFO     | __main__:_act:100 - cheems(Programmer): 准备 CodeRun

在这里插入图片描述

参考链接

https://github.com/qianyouliang/MetaGPT-Learn

如果有任何问题,欢迎在评论区提问。


http://www.ppmy.cn/news/1555775.html

相关文章

uniapp video 安卓小程序seek第一次打开时视频能跳转到指定位置,第二次就没有跳转到指定位置

问题&#xff1a; 1.ios的小程序测试没问题&#xff0c;看完视频再次点击视频就在上一次看到的位置 2.但是安卓第一次进去会在上一次位置&#xff0c;返回上一页再点击视频进去就从头开始 原因&#xff1a; 找了好久是 videoId的问题 ,我写的videoId myVideo &#xff0c;因…

有根树【东北大学oj数据结构7-1】C语言

创建一个程序&#xff0c;为给定的有根树 T 的每个节点 u 输出以下信息。 u的节点号 u的父节点号 u的深度 u的节点类型&#xff08;根、内部节点或叶&#xff09; u的孩子名单 这里我们假设给定的树有n个节点&#xff0c;每个节点都分配了一个从0到n-1的数字。 输入 输入的第…

WPF+MVVM案例实战与特效(三十八)- 封装一个自定义的数字滚动显示控件

文章目录 1、运行效果2、案例实现1、功能设计2、页面布局3、控件使用4、运行效果3、拓展:多数字自定义控件1、控件应用4、总结1、运行效果 在Windows Presentation Foundation (WPF)应用程序中,自定义控件允许开发者创建具有特定功能和外观的独特UI元素。本博客将介绍一个名…

Python 命令搭建 Https的服务器

要使用Python命令行搭建HTTPS服务器&#xff0c;您可以使用http.server模块&#xff08;在Python 3.x中可用&#xff09;&#xff0c;并结合ssl模块来创建安全的HTTPS连接。以下是一个简单的步骤指南&#xff1a; 准备证书&#xff1a; 在搭建HTTPS服务器之前&#xff0c;您需要…

Android仿闲鱼发布弹簧动画

Android仿闲鱼发布弹簧动画 仿闲鱼发布的弹簧动画显示弹框&#xff0c;效果还不错 一、思路&#xff1a; 用SpringAnimation动画 二、效果图&#xff1a; 看视频更直观点&#xff1a; Android开发案例分享仿闲鱼发布弹簧动画 三、关键代码&#xff1a; public class MoodP…

OpenCV--图像查找

OpenCV--图像查找 代码和笔记 代码和笔记 import cv2 import numpy as np""" 图像查找--特征匹配的应用&#xff0c;通过特征匹配和单应性矩阵 单应性变换&#xff1a;描述物体在世界坐标系&#xff08;原图&#xff09;和像素坐标系&#xff08;对比图&#x…

手机膜介绍

因为自己开店的原因&#xff0c;现在每天都在对不同的货进行对比&#xff0c;一直在发库存&#xff0c;库存的文章基本也都发没了&#xff0c;所以开始分享开店过程中遇到的事&#xff0c;来给大家介绍一下手机膜。 手机钢化膜、水凝膜、软膜和UV膜是四种常见的手机屏幕保护膜…

Docker-Dockerfile、registry

Dockerfile 一、概述 1、commit的局限 很容易制作简单的镜像&#xff0c;但碰到复杂的情况就十分不方便&#xff0c;例如碰到下面的情况&#xff1a; 需要设置默认的启动命令需要设置环境变量需要指定镜像开放某些特定的端口 2、Dockerfile是什么 Dockerfile是一种更强大的镜…