Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mini Agent

一个完全用于学习的最小 Python Agent

Python 3.10+ OpenAI Chat Completions Agent Tool Calling DDGS Web Search MIT License

项目不使用 LangChain、AutoGen 等 Agent 框架,只使用 OpenAI Python SDK 展示 Agent 最核心的工作方式:

用户问题
  -> 调用 OpenAI
  -> 模型决定是否调用工具
  -> Python 执行工具
  -> 将工具结果回填给模型
  -> 再次调用 OpenAI
  -> 模型返回最终答案

设计目标

  • 只支持 OpenAI Chat Completions 风格接口。
  • 一次运行只回答一个问题,不提供 REPL 交互模式。
  • 核心代码集中在 agent.py,便于从上到下完整阅读。
  • 记录每一步请求、OpenAI 原始响应、工具调用和工具结果。
  • 保留最大执行步数,防止模型无限调用工具。
  • 工具实现刻意保持简单,让注意力集中在 Agent 主循环。

项目结构

mini-agent/
├── agent.py          # Agent 循环、OpenAI 调用和工具实现
├── requirements.txt # Python 依赖
├── .env.example     # 环境变量示例,仅作参考
├── .gitignore       # 排除本地缓存和密钥文件

└── README.md

环境要求

  • Python 3.10 或更高版本
  • OpenAI API Key

安装

python -m pip install -r requirements.txt

配置

运行前需要通过当前操作系统或 Shell 的环境变量设置方式配置:

环境变量 必填 默认值 说明
OPENAI_API_KEY OpenAI API Key
OPENAI_MODEL gpt-4o-mini 默认模型
OPENAI_BASE_URL OpenAI 官方地址 OpenAI 兼容接口地址

运行

每次命令只执行一个问题:

python agent.py "现在几点?"
python agent.py "请计算 (123 + 456) * 2"
python agent.py "搜索 Python 3.14 的主要变化"

指定模型:

python agent.py --model gpt-4o-mini "计算 2 ** 10"

限制最大 Agent 步数:

python agent.py --max-steps 4 "现在几点,再计算 25 * 16"

关闭过程日志,只显示最终答案:

python agent.py --quiet "计算 100 / 4"

日志说明

默认情况下,每条日志都会带上源码文件名、行号和函数名,例如:

2026-07-27 15:00:00,000 | INFO | agent.py:164 | run_agent() | OpenAI raw response:

程序会输出以下可观测信息:

  1. 当前 Agent 步数。

  2. 本次发送给 OpenAI 的完整 messages

  3. OpenAI SDK 返回的原始响应。

  4. 模型要求调用的工具名和参数。

  5. Python 工具的执行结果。

  6. Agent 是否已经生成最终答案。

示意流程:

Agent step 1
OpenAI request messages: user question
OpenAI raw response: assistant requests calculate(...)
Tool call: calculate
Tool result: 1694

Agent step 2
OpenAI request messages: question + tool call + tool result
OpenAI raw response: assistant final answer
Answer: 结果是 1694

日志不会输出 OPENAI_API_KEY,但会包含用户问题、模型回答和工具结果。处理敏感数据时应使用 --quiet,或者进一步调整日志策略。

核心实现解析

1. 工具 Schema

TOOL_SCHEMAS 使用 OpenAI function calling 格式向模型描述工具。模型只能看到工具名称、说明和参数结构,看不到 Python 函数源码。

本项目提供三个工具:

  • get_current_time():返回当前本地时间。
  • calculate(expression):使用简洁的 eval() 计算表达式,仅供教学。
  • web_search(query):通过 ddgs 执行真实网页搜索,返回最多 5 条结果。

2. 工具注册表

TOOL_FUNCTIONS 建立工具名到 Python 函数的映射:

TOOL_FUNCTIONS = {
    "get_current_time": get_current_time,
    "calculate": calculate,
}

模型返回 calculate 时,程序通过这个字典找到并执行真正的 Python 函数。

3. Agent Loop

run_agent() 是项目核心。它维护一个 messages 列表,并在每一步调用:

client.chat.completions.create(
    model=model,
    messages=messages,
    tools=TOOL_SCHEMAS,
    tool_choice="auto",
)

如果响应中没有 tool_calls,模型的文本就是最终答案。如果存在 tool_calls,程序执行工具,并追加一条 role="tool" 的消息:

{
    "role": "tool",
    "tool_call_id": tool_call.id,
    "content": result,
}

下一次请求会携带完整历史,因此模型能看到工具执行结果并继续回答。

4. 为什么需要 tool_call_id

一次响应可能包含多个工具调用。tool_call_id 用于准确关联模型发出的工具请求和 Python 返回的工具结果。

5. 为什么需要 max_steps

模型可能持续或重复调用工具。max_steps 给循环设置明确上限,避免程序无限运行。默认最多执行 8 轮。

如何添加新工具

以新增天气工具为例:

  1. agent.py 中实现 Python 函数:
def get_weather(city: str) -> str:
    return "这里调用真实天气 API"
  1. 注册函数:
TOOL_FUNCTIONS["get_weather"] = get_weather
  1. TOOL_SCHEMAS 中增加对应 JSON Schema。

Schema 名称、注册表名称和函数参数必须保持一致。

与生产级 Agent 的差距

本项目刻意保持教学性质,没有实现:

  1. 流式输出
  2. 多轮对话历史
  3. 上下文压缩
  4. 并行工具调用

这些能力很重要,但不属于理解 Agent 最小循环所必需的部分。

安全说明

  • 不要将 API Key 写入 agent.py 或提交到 Git。

  • calculate() 为了教学简洁性使用了受限命名空间的 eval(),仍不应处理不可信输入或用于生产环境。

  • 接入文件、Shell、数据库或网络工具时,需要额外增加权限控制、参数验证、超时和隔离机制。

  • OpenAI API 调用可能产生费用,请关注所选模型和账户用量。

开源协议

本项目基于 MIT License 开源。你可以自由使用、复制、修改、合并、发布和分发本项目,但需要保留原始版权声明和许可证文本。

About

一个完全用于学习的最小 Python Agent

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages