mini-swe-agent源码解读(进行中)
https://github.com/SWE-agent/mini-swe-agent
虽然声称100行代码的Agent(The 100 line AI agent),但实际上这个仓库几万行代码
说实在的,我读的速度都没有他写的速度快。
前置准备:
1、知道使用litellm调用大模型
2、prompt_toolkit来获取用户的终端输入
3、使用from rich.console import Console进行终端的输出
4、使用platformdirs获取用户目录,finding the right location to store user data and configuration varies per platform
5、typer: typer命令行工具开发库,说起typer你可能不知道,但是fastapi可能听过,typer和fastapi的主要开发者都是tiangolo。
6、变成系统命令
[project.scripts]
mini = “minisweagent.run.mini:app”
mini-swe-agent = “minisweagent.run.mini:app”
mini-extra = “minisweagent.run.mini_extra:main”
mini-e= “minisweagent.run.mini_extra:main”
7、使用dotenv从.env加载环境变量
dotenv.load_dotenv(dotenv_path=global_config_file)
8、使用subprocess.run来执行命令,这个是此agent能起作用的核心
(我们好奇cursor生成文件和修改文件用的是什么?)
9、from jinja2 import Template模版的渲染
入口
python run/mini.py -t “say hello world”
代码中抽象出了几个概念
model
agent:代理中有执行环境和model
Environments: 这个不是环境变量,这个分为本地环境和docker环境,环境可以执行命令
先从最令人激动的点模型调用说起
LitellmModel
model.query封装了litellm,这块可以理解
role有: system user assistant
当通过api来调用大模型的时候,就这三个
剩下的就是你怎么利用大模型的返回值了
然后看看对话是怎么处理的?
初始 self.messages: list[dict] = []是空的
system_template: str = "You are a helpful assistant that can do anything."
instance_template: str = ("Your task: {{task}}. Please reply with a single shell command in triple backticks. ""To finish, the first line of the output of the shell command must be 'MINI_SWE_AGENT_FINAL_OUTPUT'."
)self.messages = []self.add_message("system", self.config.system_template)self.add_message("user", self.render_template(self.config.instance_template, task=task))
第一次增加系统提示词和用户提示词
对话完成后,会把大模型的返回值,存储到self.messages里面,这样下次继续带着对话。
agent.run
def run(self, task: str) -> tuple[str, str]:"""Run step() until agent is finished. Return exit status & message"""self.messages = []self.add_message("system", self.config.system_template)self.add_message("user", self.render_template(self.config.instance_template, task=task))while True:try:self.step()except NonTerminatingException as e:self.add_message("user", str(e))except TerminatingException as e:self.add_message("user", str(e))return type(e).__name__, str(e)
这是随便找的一个,你看在同一个对话下的数据实际上都携带着呢
查看流程图
execute前进行确认
# 这段代码学到了match user_input := self._prompt_and_handle_special(prompt).strip():case "" | "/y":pass # confirmed, do nothingcase "/u": # Skip execution action and get back to queryraise NonTerminatingException("Command not executed. Switching to human mode")case _:raise NonTerminatingException(f"Command not executed. The user rejected your command with the following message: {user_input}")
mode有三种
_MODE_COMMANDS_MAPPING = {“/u”: “human”, “/c”: “confirm”, “/y”: “yolo”}
命令的解析和执行
output = self.execute_action(self.parse_action(response))
好多人
思考:
意图识别、对话压缩
可以增加意图识别,因为用户的输入不一定就是任务,可以在任务前增加一个意图识别的过程。
如果即将超出上下文的显示可以对对话进行压缩