MetaGPT第三章学习

文章探讨了大语言模型(LLM)在智能体中的应用,涉及感知(观察)、决策(思考)和执行行动(包括编写代码和使用工具),以及如何通过PromptTemplate引导模型生成高质量代码。实例展示了如何使用MetaGPT创建一个可执行代码的智能体,如RunnableCoder,能完成任务并返回运行结果。
摘要由CSDN通过智能技术生成

知识背景:

Agent = 大语言模型(LLM) + 观察 + 思考 + 行动 + 记忆

  1. 大语言模型(LLM):LLM作为智能体的“大脑”部分,使其能够处理信息,从交互中学习,做出决策并执行行动。

  2. 观察:这是智能体的感知机制,使其能够感知其环境。智能体可能会接收来自另一个智能体的文本消息、来自监视摄像头的视觉数据或来自客户服务录音的音频等一系列信号。这些观察构成了所有后续行动的基础。

  3. 思考:思考过程涉及分析观察结果和记忆内容并考虑可能的行动。这是智能体内部的决策过程,其可能由LLM进行驱动。

  4. 行动:这些是智能体对其思考和观察的显式响应。行动可以是利用 LLM 生成代码,或是手动预定义的操作,如阅读本地文件。此外,智能体还可以执行使用工具的操作,包括在互联网上搜索天气,使用计算器进行数学计算等。

  5. 记忆:智能体的记忆存储过去的经验。这对学习至关重要,因为它允许智能体参考先前的结果并据此调整未来的行动。

在MetaGPT中定义的一个agent运行示例如下:

单动作Agent

 PROMPT_TEMPLATE = """
    Write a python function that can {instruction} and provide two runnable test cases.
    Return ```python your_code_here ``` with NO other texts,
    your code:
    """

看不懂PROMPT_TEMPLATE, 去看了一下

LangChain:Prompt Templates介绍及应用_prompttemplate-CSDN博客

发现

“Prompt Templates可以帮助我们指导语言模型生成更高质量的文本,从而更好地完成我们的任务。

Prompt Templates可能包含:

  • 对语言模型的指令
  • 一组few-shot examples,以帮助语言模型生成更好的响应
  • 对语言模型的问题”。

为了透彻理解这段代码,我询问了小布,使用安第斯GPT对每一行代码进行注释

import re#导入正则表达式库
import asyncio#导入异步I/O库
from metagpt.actions import Action#导入'Actions'类
from metagpt.roles import Role#导入'Role'类
from metagpt.schema import Message#导入'Message'类
from metagpt.logs import logger#导入'logger'

class SimpleWriteCode(Action):#定义一个SimpleWriteCode类,继承自'action'类

    PROMPT_TEMPLATE = """
    Write a python function that can {instruction} and provide two runnable test cases.
    Return ```python your_code_here ``` with NO other texts,
    your code:
    """#定义一个名为`PROMPT_TEMPLATE`的类变量,它是一个字符串,描述了如何生成一个提示,让用户编写一个Python函数。

    def __init__(self, name="SimpleWriteCode", context=None, llm=None):#初始化,name的值默认为SimpleWriteCode。
        super().__init__(name, context, llm)#context 前置知识

    async def run(self, instruction: str):#定义一个名为'run'的异步方法,该方法接受一个参数`instruction`,表示需要执行的操作。

        prompt = self.PROMPT_TEMPLATE.format(instruction=instruction)#使用模板字符串`PROMPT_TEMPLATE`生成一个新的提示,并将操作`instruction`替换到模板中的相应变量。

        rsp = await self._aask(prompt)#使用`_aask`方法向用户发送生成的提示,并等待用户的响应。响应存储在`rsp`变量中。

        code_text = SimpleWriteCode.parse_code(rsp)#调用`parse_code`静态方法来解析用户提供的代码。

        return code_text

    @staticmethod#定义一个静态方法。
    def parse_code(rsp):
        pattern = r'```python(.*)```'#定义一个正则表达式模式,用于匹配Python代码块。
        match = re.search(pattern, rsp, re.DOTALL)#使用正则表达式匹配用户提供的响应,查找Python代码块。
        code_text = match.group(1) if match else rsp #如果找到匹配的代码块,则将匹配的代码块存储在`code_text`中。如果没有找到匹配的代码块,则使用整个响应作为`code_text`。
        return code_text#在`run`方法的最后,返回解析后的代码文本。

class SimpleCoder(Role):#定义一个名为`SimpleCoder`的类,该类继承自`Role`类。
    def __init__(
        self,
        name: str = "Alice",
        profile: str = "SimpleCoder",
        **kwargs,
    ):#初始化
        super().__init__(name, profile, **kwargs)#调用父类(即`Role`类)的初始化方法,并传递相应的参数。
        self._init_actions([SimpleWriteCode])#初始化一个动作列表,其中包含一个`SimpleWriteCode`对象。

    async def _act(self) -> Message:#定义一个异步方法`_act`,该方法返回一个`Message`对象。
        logger.info(f"{self._setting}: ready to {self._rc.todo}")#使用日志记录器记录一条信息,表示准备执行某个任务。
        todo = self._rc.todo  #从上下文中获取待执行的任务,并将其存储在变量`todo`中。

        msg = self.get_memories(k=1)[0]  # 从记忆中获取最近的一条消息,并将其存储在变量`msg`中。

        code_text = await todo.run(msg.content)#调用`todo`对象的`run`方法,将`msg.content`作为参数。这个方法应该会生成一段Python代码。将生成的代码存储在`code_text`变量中。
        msg = Message(content=code_text, role=self.profile,
                      cause_by=type(todo))#创建一个`Message`对象,其中包含生成的代码、角色上下文和任务类型。

        return msg#在`_act`方法的末尾,返回生成的消息对象。

async def main():#定义一个异步函数`main`。
    msg = "判断一个数是不是素数"#定义一个字符串`msg`,表示要执行的任务。
    role = SimpleCoder()#创建一个`SimpleCoder`对象。
    logger.info(msg)#使用日志记录器记录一条信息,表示任务开始。
    result = await role.run(msg)#调用`SimpleCoder`对象的`run`方法,将任务传递给对象。这个方法将生成一个`Message`对象,包含执行结果。
    logger.info(result)#使用日志记录器记录一条信息,表示任务执行结果。

asyncio.run(main())#运行`main`函数,启动整个程序。

基于 判断一个数是不是素数,该程序运行结果如下:

但是运行结果有问题 不清楚是什么导致的

再次运行 正确

多动作Agent

现在需要智能体不仅可以写出代码,还需要返回运行结果。

import os
import re
import subprocess
import asyncio

import fire
import sys
from metagpt.llm import LLM
from metagpt.actions import Action
from metagpt.roles import Role
from metagpt.schema import Message
from metagpt.logs import logger

class SimpleWriteCode(Action):

    PROMPT_TEMPLATE = """
    Write a python function that can {instruction} and provide two runnnable test cases.
    Return ```python your_code_here ``` with NO other texts,
    your code:
    """

    def __init__(self, name: str = "SimpleWriteCode", context=None, llm: LLM = None):
        super().__init__(name, context, llm)

    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

    @staticmethod
    def parse_code(rsp):
        pattern = r'```python(.*)```'
        match = re.search(pattern, rsp, re.DOTALL)
        code_text = match.group(1) if match else rsp
        return code_text

class SimpleRunCode(Action):
    def __init__(self, name: str = "SimpleRunCode", context=None, llm: LLM = None):
        super().__init__(name, context, llm)

    async def run(self, code_text: str):
        result = subprocess.run([sys.executable, "-c", code_text], capture_output=True, text=True)
        code_result = result.stdout
        logger.info(f"{code_result=}")
        return code_result

class RunnableCoder(Role):
    def __init__(
        self,
        name: str = "Alice",
        profile: str = "RunnableCoder",
        **kwargs,
    ):
        super().__init__(name, profile, **kwargs)
        self._init_actions([SimpleWriteCode, SimpleRunCode])
        self._set_react_mode(react_mode="by_order")

    async def _act(self) -> Message:
        logger.info(f"{self._setting}: ready to {self._rc.todo}")
        # By choosing the Action by order under the hood
        # todo will be first SimpleWriteCode() then SimpleRunCode()
        todo = self._rc.todo

        msg = self.get_memories(k=1)[0] # find the most k recent messagesA
        result = await todo.run(msg.content)

        msg = Message(content=result, role=self.profile, cause_by=type(todo))
        self._rc.memory.add(msg)
        return msg

async def main():
    msg = "帮我写一个输出小于等于随机数的质数并求和的代码"
    role = RunnableCoder()
    logger.info(msg)
    result = await role.run(msg)
    logger.info(result)

asyncio.run(main())

运行结果如下:


第三章任务:

还在想......

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值