1. 项目概览
https://github.com/bojieli/ai-agent-book
这是一个配套《深入理解 AI Agent》第 1 章"实验 1-1:上下文的关键作用"的 Python 示例项目。仓库实现了一个支持多模型供应商、多工具调用、会话历史、上下文消融实验与结果分析的 Context-Aware AI Agent。
项目核心目标不是只做一个"能聊天"的 Agent,而是通过可控地移除上下文中的不同组成部分,观察 Agent 在复杂财务、预算、PDF 解析、货币换算、代码计算等任务中的行为变化,从而理解:
- 历史消息为什么重要;
- 推理内容是否会影响后续决策;
- 工具调用定义缺失会造成什么后果;
- 工具执行结果不可见时 Agent 如何退化;
- 不同 LLM Provider 在工具调用和推理场景下的差异。
1.1 学习价值
- 理解 Agent 上下文工程:项目将上下文拆成历史、推理、工具调用、工具结果等组件,并提供 5 种上下文模式进行消融。
- 掌握 ReAct/Tool Calling 基本闭环:模型生成工具调用 → Agent 执行工具 → 工具结果回填 → 模型继续推理,直到给出最终答案。
- 学习多 Provider 适配方式:支持 Doubao、SiliconFlow、Kimi、DeepSeek,且均通过 OpenAI-compatible API 接入。
- 获得可运行的实验框架:不仅有交互式运行,还提供批量消融实验、结果 JSON、分析函数和报告生成入口。
- 建立工程化测试意识:包含单元测试、回归测试、Provider 手动检查脚本、异常工具 JSON 容错测试。
1.2 解决的行业痛点
| 行业/开发痛点 | 本项目对应解决方式 |
|---|---|
| Agent 效果不稳定,不知道是提示词、模型还是上下文导致 | 通过上下文消融实验隔离变量 |
| 多轮对话中 Agent 忘记之前工具调用或结果 | 保留完整历史模式,并对比 No History 模式 |
| 工具调用 JSON 异常导致循环中断 | tests/test_malformed_tool_json.py 覆盖异常参数容错 |
| 不同模型供应商工具调用能力不一致 | 提供多 Provider 配置与手动检查脚本 |
| 复杂财务任务需要 PDF、汇率、计算、代码执行组合完成 | 内置 parse_pdf、convert_currency、calculate、code_interpreter |
| 实验结果难以复现 | run_experiment_1_1.py 生成 JSON、证据文件、哈希与版本信息 |
1.3 前置知识要求
建议读者具备以下基础:
- Python 3.10+ 基础语法;
- 虚拟环境与
pip install -r requirements.txt的使用; .env环境变量配置;- LLM API Key 的基本申请与使用方式;
- 对 OpenAI Chat Completions、tool calling、messages 结构有初步了解;
- 知道 JSON、命令行参数、pytest 基本用法。
如果完全没有接触过 Agent,也可以先从"运行 quickstart → 阅读 agent.py → 执行单任务 → 再跑消融实验"的顺序学习。
2. 目录结构速览
主要目录与文件如下:
text
.
├── README.md
├── agent.py
├── config.py
├── create_sample_pdf.py
├── env.example
├── main.py
├── requirements.txt
├── run_experiment_1_1.py
├── task_result_full.json
├── test_experiment_1_1.py
├── fixtures/
│ └── pdfs/
│ ├── sample_financial_report_q1_2024.pdf
│ └── simple_expense_report.pdf
├── tests/
│ ├── conftest.py
│ ├── test_agent.py
│ ├── test_code_interpreter.py
│ ├── test_malformed_tool_json.py
│ └── manual/
│ ├── _bootstrap.py
│ ├── check_conversation_history.py
│ ├── check_deepseek.py
│ ├── check_deepseek_quick.py
│ ├── check_default_provider.py
│ ├── check_doubao.py
│ ├── check_doubao_quick.py
│ ├── check_kimi.py
│ ├── check_kimi_quick.py
│ ├── check_pdf_task.py
│ ├── check_provider_config.py
│ ├── check_provider_switching.py
│ ├── check_simple_task.py
│ ├── demo_conversation.py
│ ├── quickstart.py
│ └── show_sample_tasks.py
└── validation/
├── latest.json
└── real_20260729T153329Z/
├── evidence.json
└── evidence.sha256
目录职责清单:
| 路径 | 职责 |
|---|---|
agent.py |
Agent 核心实现,包括上下文模式、工具注册、工具执行、消息构造、API 调用日志 |
config.py |
Provider、模型、API Key、目录与模型配置管理 |
main.py |
主入口,支持单任务、交互模式、样例任务、消融实验与结果展示 |
run_experiment_1_1.py |
精确复现书中五组上下文消融实验的脚本 |
create_sample_pdf.py |
生成测试用 PDF 样例 |
tests/ |
pytest 自动化测试 |
tests/manual/ |
手动冒烟检查脚本,用于验证 Provider、会话历史、PDF 任务等 |
fixtures/pdfs/ |
预置 PDF 测试文件 |
validation/ |
验证数据与证据文件,包含 JSON 与 SHA256 |
requirements.txt |
Python 依赖清单 |
env.example |
环境变量示例文件 |
3. 核心模块与职责
3.1 agent.py:Agent 核心
agent.py 是整个项目最核心的文件,模块说明为"Context-Aware AI Agent with Tool Calls"。
它包含以下主要类:
| 类/函数 | 作用 |
|---|---|
ContextMode(Enum) |
定义上下文消融模式 |
ToolCall |
工具调用数据结构 |
AgentTrajectory |
记录 Agent 执行轨迹 |
ToolRegistry |
注册并执行工具 |
ContextAwareAgent |
上下文感知 Agent 主体 |
_reasoning_safe_temperature(model, requested) |
根据模型调整温度参数,避免某些推理模型参数不兼容 |
从 README 可知,项目包含 5 种上下文模式:
| 模式 | 含义 | 对 Agent 的影响 |
|---|---|---|
| Full Context | 完整上下文 | 同时保留历史、推理、工具调用、工具结果 |
| No History | 缺少历史工具调用跟踪 | 模型难以利用前序轮次信息 |
| No Reasoning | 不保留战略规划/推理内容 | 可能降低复杂任务规划能力 |
| No Tool Calls | 不能执行外部工具 | 无法读取 PDF、换算汇率、计算或执行代码 |
| No Tool Results | 看不到工具执行结果 | 模型可能继续猜测,而不是基于事实输出 |
ToolRegistry 中可用工具包括:
| 工具 | 方法 | 功能 |
|---|---|---|
| PDF 解析 | parse_pdf(url) |
下载并提取 PDF 文本 |
| 货币转换 | convert_currency(amount, from_currency, to_currency) |
实时汇率换算 |
| 计算器 | calculate(expression) |
计算数学表达式 |
| 代码解释器 | code_interpreter(code) |
执行 Python 代码,处理复杂计算 |
ContextAwareAgent 的关键方法职责如下:
| 方法 | 职责 |
|---|---|
__init__ |
初始化 API Key、上下文模式、Provider、模型、日志开关 |
_init_system_prompt |
构造系统提示词 |
_get_tools_description |
获取工具定义,供模型进行 tool calling |
_prepare_assistant_message |
准备 assistant 消息 |
_reasoning_content |
提取或处理模型推理内容 |
_json_snapshot |
生成可序列化 JSON 快照 |
_build_context |
根据上下文模式构造消息上下文 |
_log_request_response |
记录每次 API 请求与响应 |
_execute_tool |
根据工具名和参数执行本地工具 |
_prepare_messages_for_api |
整理发送给 API 的 messages |
3.2 config.py:配置管理
config.py 负责统一管理不同 Provider 的 API Key、默认模型、配置校验和目录创建。
Config 类主要方法:
| 方法 | 作用 |
|---|---|
get_api_key(cls, provider) |
获取指定 Provider 的 API Key |
get_default_model(cls, provider) |
获取指定 Provider 的默认模型 |
validate(cls, provider) |
校验 Provider 配置是否可用 |
create_directories(cls) |
创建运行所需目录 |
get_model_config(cls) |
获取模型配置 |
print_config(cls) |
打印当前配置 |
README 中列出的默认模型:
| Provider | 默认模型 | 特点 |
|---|---|---|
| Doubao | doubao-seed-1-6-thinking-250715 |
默认 Provider,适合中英文推理 |
| SiliconFlow | Qwen/Qwen3.5-397B-A17B |
适合复杂推理任务 |
| Kimi | kimi-k3 |
推理模型,温度被强制为 1,适合多轮和推理 |
| DeepSeek | deepseek-v4-flash |
高性价比工具调用模型,可切换 deepseek-v4-pro |
3.3 main.py:主程序与消融实验入口
main.py 是日常运行最常用的入口,支持:
- 单任务运行;
- 交互式对话;
- 样例 PDF 检查;
- 批量消融实验;
- 结果表格打印;
- 对比矩阵;
- 可视化;
- 报告生成。
关键函数和类:
| 名称 | 作用 |
|---|---|
run_single_task(...) |
运行单个任务 |
ensure_sample_pdfs() |
确保样例 PDF 存在 |
get_sample_tasks() |
获取样例任务 |
get_ablation_cases(num_cases) |
获取消融实验用例 |
run_ablation_study(...) |
运行批量消融实验 |
interactive_mode(...) |
交互式模式 |
main() |
命令行入口 |
AblationTestSuite |
消融实验套件 |
AblationTestSuite.run_single_test(...) |
单次测试 |
AblationTestSuite.run_ablation_study(...) |
执行多模式多用例实验 |
AblationTestSuite.analyze_results(...) |
分析结果 |
AblationTestSuite.print_results_table(...) |
打印结果表 |
AblationTestSuite.print_comparison_matrix(...) |
打印对比矩阵 |
AblationTestSuite.visualize_results(...) |
可视化结果 |
AblationTestSuite.generate_report(...) |
生成报告 |
3.4 run_experiment_1_1.py:书中实验复现脚本
该文件模块说明为"Run the exact five-arm context ablation from book/chapter1.md",即用于复现书中五组上下文消融实验。
它比 main.py 更强调实验可复现性,包含:
| 函数 | 作用 |
|---|---|
utc_now() |
获取 UTC 时间 |
git_value(*args) |
获取 Git 信息 |
package_version(distribution) |
获取依赖包版本 |
resolve_key(provider) |
解析 Provider API Key |
tool_call_dict(call) |
将工具调用转为字典 |
call_signatures(tool_calls) |
提取工具调用签名 |
response_message(turn) |
获取响应消息 |
request_roles(turn) |
获取请求中的角色序列 |
evaluate_context_contract(mode, turns) |
评估上下文契约是否符合模式要求 |
normalized_number_text(value) |
归一化数字文本 |
summarize_arm(mode, result, elapsed) |
汇总单组实验结果 |
token_usage(arms) |
汇总 Token 使用情况 |
analyze(arms) |
分析五组实验 |
write_json(path, payload) |
写入 JSON 结果 |
main() |
命令行入口 |
3.5 create_sample_pdf.py:样例 PDF 生成
该文件用于生成测试 PDF,包含两个函数:
| 函数 | 作用 |
|---|---|
create_financial_report() |
创建财务报告 PDF |
create_simple_expense_report() |
创建简单费用报告 PDF |
仓库中已经存在:
text
fixtures/pdfs/sample_financial_report_q1_2024.pdf
fixtures/pdfs/simple_expense_report.pdf
如果文件缺失,可以运行该脚本重新生成。具体命令参数未在解析摘要中发现,但文件包含 python_main_guard,通常可通过:
bash
python create_sample_pdf.py
尝试执行。
3.6 测试模块
自动化测试文件:
| 文件 | 作用 |
|---|---|
tests/test_agent.py |
测试工具注册、上下文模式、消融场景、轨迹重置 |
tests/test_code_interpreter.py |
测试代码解释器工具 |
tests/test_malformed_tool_json.py |
回归测试:工具参数 JSON 异常不能中断 ReAct 循环 |
test_experiment_1_1.py |
测试实验 1-1 的上下文契约 |
手动检查脚本:
| 脚本 | 用途 |
|---|---|
tests/manual/quickstart.py |
快速开始 |
tests/manual/check_simple_task.py |
简单任务冒烟 |
tests/manual/check_pdf_task.py |
PDF 解析与货币换算任务 |
tests/manual/check_conversation_history.py |
检查会话历史持久化 |
tests/manual/demo_conversation.py |
演示会话历史 |
tests/manual/check_provider_config.py |
检查 Provider 配置 |
tests/manual/check_provider_switching.py |
检查 Provider 切换 |
tests/manual/check_default_provider.py |
检查默认 Provider 是否为 Doubao |
tests/manual/check_doubao.py |
Doubao 完整检查 |
tests/manual/check_doubao_quick.py |
Doubao 快速检查 |
tests/manual/check_kimi.py |
Kimi 完整检查 |
tests/manual/check_kimi_quick.py |
Kimi 快速检查 |
tests/manual/check_deepseek.py |
DeepSeek 完整检查 |
tests/manual/check_deepseek_quick.py |
DeepSeek 快速检查 |
tests/manual/show_sample_tasks.py |
展示样例任务 |
3.7 核心原理通俗解读
可以把这个 Agent 理解成一个"会查资料、会用计算器、会写代码的实习生"。
它的工作流程类似下面的循环:
- 用户提出任务,例如"读取这份财务 PDF,把美元金额换算成人民币并汇总"。
- Agent 先看系统提示词、历史消息和工具列表。
- 如果需要 PDF,它调用
parse_pdf。 - 工具返回 PDF 文本后,Agent 再决定是否调用
convert_currency。 - 如果金额较多或逻辑复杂,它可能调用
code_interpreter写 Python 计算。 - 所有工具结果回到对话上下文后,Agent 生成最终答案。
上下文消融实验的本质就是:
- 不让它看历史,看它是否忘事;
- 不让它保留推理,看它是否缺少规划;
- 不给它工具定义,看它是否无法调用工具;
- 不给它工具结果,看它是否会"凭空回答"。
这也是项目最值得学习的地方:它把"上下文为什么重要"从抽象概念变成了可运行、可对比、可验证的实验。
4. 关键数据流与调用链
4.1 单任务执行主链路
以运行一个复杂财务任务为例,典型调用链如下:
text
命令行 / main.py
↓
main()
↓
run_single_task(api_key, task, context_mode, provider, model, output)
↓
ContextAwareAgent(...)
↓
agent._init_system_prompt()
↓
agent._get_tools_description()
↓
agent._prepare_messages_for_api()
↓
LLM Chat Completions API
↓
模型返回 assistant message / tool_calls
↓
agent._execute_tool(tool_name, arguments)
↓
ToolRegistry.parse_pdf / convert_currency / calculate / code_interpreter
↓
工具结果追加到上下文
↓
再次请求 LLM
↓
循环直到无工具调用,输出最终答案
↓
写入 output JSON / 控制台展示
4.2 工具调用数据流
工具调用过程中的数据结构大致如下:
text
用户任务
↓
messages: [system, user, ...history]
↓
模型返回 tool_calls
↓
ToolCall(tool_name, arguments)
↓
ToolRegistry 分发
↓
工具执行结果
↓
tool result message 回填 messages
↓
AgentTrajectory 记录轨迹
↓
下一轮模型推理
涉及的关键方法:
| 阶段 | 方法 |
|---|---|
| 准备工具描述 | _get_tools_description |
| 准备消息 | _prepare_messages_for_api |
| 构造上下文 | _build_context |
| 执行工具 | _execute_tool |
| 记录请求响应 | _log_request_response |
| 保存轨迹 | AgentTrajectory |
4.3 消融实验数据流
批量消融实验链路:
text
main.py / run_experiment_1_1.py
↓
读取任务或内置实验用例
↓
遍历 context_modes
↓
对每个模式创建 ContextAwareAgent
↓
执行同一任务
↓
收集结果、耗时、Token、工具调用、消息轨迹
↓
evaluate_context_contract / analyze_results
↓
输出表格、对比矩阵、JSON 报告
run_experiment_1_1.py 还会记录:
- UTC 时间;
- Git 信息;
- 包版本;
- 请求角色;
- 工具调用签名;
- Token 使用;
- 证据 JSON;
- SHA256 哈希。
这些信息有助于实验复现和结果校验。
4.4 五组上下文方案优劣对比
| 方案 | 优点 | 缺点 | 适合观察的问题 |
|---|---|---|---|
| Full Context | 信息最完整,Agent 能力最强 | Token 成本最高,可能引入冗余历史 | 作为基线组 |
| No History | 节省部分上下文,降低历史干扰 | 容易忘记前序工具调用和用户约束 | 历史消息对多轮任务的影响 |
| No Reasoning | 减少推理内容占用,输出可能更直接 | 复杂任务规划能力下降 | 推理内容对工具选择和任务分解的影响 |
| No Tool Calls | 可模拟纯文本模型或无工具场景 | 无法读取 PDF、计算、换算汇率 | 工具调用对任务完成的必要性 |
| No Tool Results | 可验证模型是否会盲目猜测 | Agent 缺少事实依据,答案容易错误 | 工具结果对最终答案可信度的影响 |
4.5 流程易错节点标注
| 节点 | 常见错误 | 影响 | 建议 |
|---|---|---|---|
| API Key 读取 | .env 未配置或 Provider 名错误 |
无法调用模型 | 使用 check_provider_config.py 检查 |
| 模型参数 | Kimi/DeepSeek 等推理模型对温度、max_tokens 有要求 | 请求报错或输出被截断 | 使用 _reasoning_safe_temperature,不要随意改参数 |
| 工具参数 JSON | 模型返回 malformed JSON | ReAct 循环中断 | 参考 test_malformed_tool_json.py 的容错逻辑 |
| PDF 解析 | URL 不可访问或 PDF 格式异常 | 工具返回错误 | 先用 fixtures/pdfs 中本地样例验证 |
| 货币转换 | 外部汇率服务不可用 | 金额换算失败 | 检查网络,必要时使用 code_interpreter 做固定汇率计算 |
| 代码解释器 | 执行了不安全代码或依赖缺失 | 本地运行失败或异常 | 只在沙箱/可信环境运行,避免执行未知代码 |
| 上下文模式 | 错误理解 No Tool Calls / No Tool Results | 实验结论偏差 | 结合 evaluate_context_contract 验证消息契约 |
| 结果保存 | 输出目录不存在 | JSON 写入失败 | 先运行配置中的目录创建逻辑 |
5. 关键类/函数速查表
5.1 agent.py
| 类/函数 | 类型 | 关键说明 |
|---|---|---|
ContextMode |
Enum | 定义 Full、No History、No Reasoning、No Tool Calls、No Tool Results 等模式 |
ToolCall |
dataclass | 表示一次工具调用 |
AgentTrajectory |
类 | 保存 Agent 执行轨迹 |
ToolRegistry.parse_pdf(url) |
方法 | 下载并解析 PDF |
ToolRegistry.convert_currency(amount, from_currency, to_currency) |
方法 | 货币换算 |
ToolRegistry.calculate(expression) |
方法 | 数学表达式计算 |
ToolRegistry.code_interpreter(code) |
方法 | 执行 Python 代码 |
ContextAwareAgent.__init__ |
方法 | 初始化 Agent |
ContextAwareAgent._init_system_prompt |
方法 | 构造系统提示词 |
ContextAwareAgent._get_tools_description |
方法 | 返回工具 schema/描述 |
ContextAwareAgent._build_context |
方法 | 根据模式裁剪上下文 |
ContextAwareAgent._execute_tool |
方法 | 分发并执行工具 |
ContextAwareAgent._prepare_messages_for_api |
方法 | 构造 API 请求消息 |
ContextAwareAgent._log_request_response |
方法 | 记录请求响应日志 |
_reasoning_safe_temperature |
函数 | 为推理模型调整温度 |
5.2 config.py
| 类/函数 | 类型 | 关键说明 |
|---|---|---|
Config.get_api_key |
class method | 获取 Provider API Key |
Config.get_default_model |
class method | 获取默认模型 |
Config.validate |
class method | 校验配置 |
Config.create_directories |
class method | 创建目录 |
Config.get_model_config |
class method | 获取模型配置 |
Config.print_config |
class method | 打印配置 |
5.3 main.py
| 类/函数 | 类型 | 关键说明 |
|---|---|---|
run_single_task |
函数 | 运行单个任务 |
ensure_sample_pdfs |
函数 | 确保样例 PDF 存在 |
get_sample_tasks |
函数 | 返回样例任务 |
get_ablation_cases |
函数 | 返回消融实验用例 |
run_ablation_study |
函数 | 运行消融实验 |
interactive_mode |
函数 | 交互式对话 |
main |
函数 | CLI 入口 |
AblationTestSuite.create_complex_financial_task |
方法 | 创建复杂财务任务 |
AblationTestSuite.create_multinational_budget_task |
方法 | 创建跨国预算任务 |
AblationTestSuite.run_single_test |
方法 | 执行单次测试 |
AblationTestSuite.run_ablation_study |
方法 | 执行消融套件 |
AblationTestSuite.analyze_results |
方法 | 分析结果 |
AblationTestSuite.print_results_table |
方法 | 打印结果表 |
AblationTestSuite.print_comparison_matrix |
方法 | 打印对比矩阵 |
AblationTestSuite.visualize_results |
方法 | 可视化结果 |
AblationTestSuite.generate_report |
方法 | 生成报告 |
5.4 run_experiment_1_1.py
| 函数 | 关键说明 |
|---|---|
utc_now |
生成 UTC 时间戳 |
git_value |
获取 Git 信息 |
package_version |
获取包版本 |
resolve_key |
解析 API Key |
tool_call_dict |
工具调用转字典 |
call_signatures |
提取工具调用签名 |
response_message |
获取响应消息 |
request_roles |
提取请求角色 |
evaluate_context_contract |
校验上下文模式契约 |
normalized_number_text |
归一化数字 |
summarize_arm |
汇总单组实验 |
token_usage |
汇总 Token |
analyze |
分析实验结果 |
write_json |
写入 JSON |
main |
CLI 入口 |
6. 如何运行与调试(基于摘要推断,无法确定则说明)
注意:以下命令基于 README 预览、文件入口线索和 Python 项目常规结构整理。未在解析摘要中明确出现的参数会标注"未在解析摘要中发现"。
6.1 环境准备
第 1 步:进入项目目录
目的:进入本章上下文实验项目。
bash
cd D:\组内产品\ai教育\ai-agent-book-main\ai-agent-book-main\chapter1\context
如果你使用 Windows PowerShell,路径也可以写成:
powershell
cd "D:\组内产品\ai教育\ai-agent-book-main\ai-agent-book-main\chapter1\context"
第 2 步:准备 Python 环境
README 中写明前置要求为:
text
Python 3.10+
建议创建虚拟环境:
bash
python -m venv .venv
Windows 激活:
bash
.venv\Scripts\activate
Linux/macOS 激活:
bash
source .venv/bin/activate
README 预览中还提到"Recommended from the repository root: use the shared Chapter 1 environment",说明书籍配套仓库可能推荐在章节目录上层使用共享环境。如果你的仓库根目录已有统一环境,应优先按书籍说明激活共享环境,再进入本目录。
第 3 步:安装依赖
目的:安装 Agent、PDF、OpenAI SDK、环境变量、表格输出等依赖。
bash
pip install -r requirements.txt
已知导入依赖包括:
PyPDF2openaipython-dotenvrequestsreportlabtabulate
其中 reportlab 用于 create_sample_pdf.py 生成 PDF,tabulate 在 main.py 中用于表格输出。
第 4 步:配置 .env
目的:配置至少一个 LLM Provider 的 API Key。
仓库提供了:
text
env.example
可复制为 .env:
Windows PowerShell:
powershell
Copy-Item env.example .env
或者CMD:
copy env.example .env
Linux/macOS:
bash
cp env.example .env
然后编辑 .env,填入对应 Provider 的 Key。支持的 Provider 包括:
| Provider | API Key 获取地址 |
|---|---|
| SiliconFlow | https://siliconflow.cn |
| Doubao | https://www.volcengine.com/ |
| Kimi | https://platform.moonshot.cn/ |
| DeepSeek | https://platform.deepseek.com/api_keys |
具体环境变量名称未在解析摘要中完整展示,请以 env.example 和 config.py 实际内容为准。
注意,默认使用API 为Doubao,需要根据实际修改。
bash
# LLM Provider Configuration (siliconflow, doubao, kimi, moonshot, deepseek, or zhipu)
LLM_PROVIDER=doubao
6.2 检查默认 Provider
目的:确认默认 Provider 是否为 上述 env 文件中设定的 模型。
运行:
bash
python tests/manual/check_default_provider.py
如果需要测试其他配置是否通过,如deepseek:
bash
python tests/manual/check_deepseek.py

6.3 快速开始
目的:用最小任务验证 Agent 是否能正常调用模型。
运行:
bash
python tests/manual/quickstart.py
该脚本导入了:
_bootstrapagentconfigossys
预期效果:
- 脚本会把项目根目录加入 Python 路径;
- 读取配置;
- 初始化 Agent;
- 发起一次简单模型调用。
正常控制台输出特征未在解析摘要中发现。如果出现 API Key 缺失、模型不存在或网络错误,请参考第 8 节排查。目前,测试脚本内部硬编码参数被写死,仅能使用豆包。
6.4 检查简单任务
目的:排除复杂 PDF、多工具链路的影响,先验证基础对话和 Agent 循环。
运行:
bash
python tests/manual/check_simple_task.py
该脚本包含 test_simple_task(),并导入了 time,可能用于简单计时或等待。
预期效果:
- Agent 能完成一个简单任务;
- 控制台应展示任务执行过程或最终结果;
- 不应出现工具参数解析异常。
具体输出内容未在解析摘要中发现。
6.5 检查 PDF 与货币换算任务
目的:验证 parse_pdf 和 convert_currency 工具链路。
运行:
bash
python tests/manual/check_pdf_task.py
该脚本包含:
text
test_pdf_with_currencies()
预期效果:
- Agent 读取 PDF;
- 提取财务文本;
- 根据任务需要调用货币转换;
- 输出汇总或换算结果。
仓库中已有 PDF:
text
fixtures/pdfs/sample_financial_report_q1_2024.pdf
fixtures/pdfs/simple_expense_report.pdf
如果 PDF 文件缺失,可运行:
bash
python create_sample_pdf.py
运行后预期会重新生成样例 PDF。生成路径和控制台提示未在解析摘要中发现,需以脚本实际输出为准。
6.6 检查会话历史
目的:验证多轮对话中历史消息是否被保留。
运行:
bash
python tests/manual/check_conversation_history.py
或运行演示脚本:
bash
python tests/manual/demo_conversation.py
预期效果:
- Agent 在第二轮对话中能够引用第一轮上下文;
- 可用于对比 Full Context 与 No History 模式的差异。
6.7 检查不同 Provider
Doubao
bash
python tests/manual/check_doubao.py
快速检查:
bash
python tests/manual/check_doubao_quick.py
Kimi
bash
python tests/manual/check_kimi.py
快速检查:
bash
python tests/manual/check_kimi_quick.py
DeepSeek
bash
python tests/manual/check_deepseek.py
快速检查:
bash
python tests/manual/check_deepseek_quick.py
这些脚本通常覆盖:
- 基础对话;
- 工具调用;
- 货币转换;
- 模型信息。
具体测试项以 check_deepseek.py、check_kimi.py 中的函数为准。
6.8 运行主程序
main.py 提供 argparse 入口。可先查看帮助:
bash
python main.py --help
解析摘要中未列出完整 CLI 参数,因此以下运行方式需以 --help 实际输出为准。
常见能力包括:
- 单任务;
- 交互模式;
- 批量消融;
- 指定 Provider;
- 指定模型;
- 指定输出文件。
先执行 python main.py --help,支持示例:

6.9 运行消融实验
书中实验复现脚本:
bash
python run_experiment_1_1.py --help
该脚本支持 argparse,建议先查看帮助再运行。
笔者使用的是Deepseek的API,修改参数:
text
parser.add_argument("--provider", default="deepseek", choices=sorted(KEY_ENV))
parser.add_argument("--model", default="deepseek-v4-flash")
增加环境配置导入:
text
from dotenv import load_dotenv
import os
# 加载当前目录下的.env文件
load_dotenv()
运行python run_experiment_1_1.py后结果如:

运行后生成:
- JSON 结果文件;
- 实验证据文件;
- SHA256 校验文件;
- 控制台分析结果。
项目设计了实验证据留存机制,仓库中目录:
text
validation/
├── latest.json
└── real_20260729T153329Z/
├── evidence.json
└── evidence.sha256
6.10 运行自动化测试
目的:验证核心工具、上下文模式、异常 JSON 容错和实验契约。
运行全部测试:
bash
pytest
也可运行指定文件:
bash
pytest tests/test_agent.py
pytest tests/test_code_interpreter.py
pytest tests/test_malformed_tool_json.py
pytest test_experiment_1_1.py
预期效果:
test_agent.py验证计算器、货币转换、PDF 解析结构、上下文构建、工具执行、轨迹重置;test_code_interpreter.py验证代码解释器;test_malformed_tool_json.py验证异常工具参数 JSON 不会中断 Agent;test_experiment_1_1.py验证五组上下文模式的消息契约。
6.11 调试建议
| 调试目标 | 建议方式 |
|---|---|
| 确认配置是否读取 | 运行 check_provider_config.py |
| 确认默认 Provider | 运行 check_default_provider.py |
| 确认模型是否可用 | 运行对应 Provider 的 quick 脚本 |
| 确认工具是否正常 | 运行 check_pdf_task.py 或 pytest tests/test_agent.py |
| 确认上下文是否符合模式 | 运行 pytest test_experiment_1_1.py |
| 查看请求响应 | 使用 ContextAwareAgent(..., verbose=True),具体参数名以代码为准 |
| 定位工具 JSON 异常 | 参考 tests/test_malformed_tool_json.py |
| 复现实验 | 使用 run_experiment_1_1.py 并保存 JSON 输出 |
7. 可扩展点与二次开发建议
7.1 新增工具
项目的工具集中在 ToolRegistry 中。新增工具的一般步骤:
- 在
ToolRegistry中新增方法,例如search_web(query)。 - 在
_get_tools_description中补充工具 schema。 - 在
_execute_tool中增加工具名到方法的分发。 - 在
tests/test_agent.py中添加单元测试。 - 如果工具依赖外部服务,增加手动检查脚本。
- 更新 README 或实验文档。
建议工具示例:
- 网页搜索;
- 数据库查询;
- Excel/CSV 解析;
- 邮件发送;
- 内部知识库检索;
- 汇率缓存;
- 单位换算。
7.2 新增 Provider
项目已支持 OpenAI-compatible API,多 Provider 接入成本较低。扩展步骤:
- 在
config.py中增加 Provider 名称、base URL、默认模型; - 在
.env.example中增加对应 API Key 示例; - 增加
tests/manual/check_xxx.py和check_xxx_quick.py; - 验证工具调用格式是否与 OpenAI SDK 兼容;
- 检查推理模型是否需要特殊 temperature、max_tokens;
- 运行
check_provider_switching.py验证切换能力。
7.3 新增上下文模式
当前 5 种模式围绕历史、推理、工具调用、工具结果展开。可以继续扩展:
| 新模式 | 说明 |
|---|---|
| System Prompt Only | 只保留系统提示词和当前用户问题 |
| Recent K Turns | 只保留最近 K 轮对话 |
| Tool Result Summary | 工具结果压缩为摘要 |
| Retrieved Context Only | 只保留检索结果,不保留完整历史 |
| No System Prompt | 移除系统提示词 |
| Structured Memory | 将历史转为结构化记忆 |
扩展时需要同步修改:
ContextMode;_build_context;_prepare_messages_for_api;evaluate_context_contract;test_experiment_1_1.py或新增测试。
7.4 增强实验评估
当前项目已有结果分析、Token 统计、上下文契约校验。可进一步增加:
- 最终答案正确性自动评分;
- 工具调用准确率;
- 冗余工具调用次数;
- 平均轮次;
- 失败类型分类;
- 多次运行取平均值;
- 不同模型横向对比;
- Markdown/HTML 报告导出;
- 成本估算。
7.5 提升安全性
code_interpreter 可执行 Python 代码,二次开发时应特别注意:
- 不要直接暴露到公网;
- 使用容器或沙箱隔离;
- 限制文件系统访问;
- 限制网络访问;
- 设置超时时间;
- 禁止危险模块,如
os.system、subprocess、socket等; - 对用户输入和模型生成代码做安全审计。
7.6 改进可观测性
建议增加:
- 结构化日志;
- 每轮 tool call 耗时;
- API 重试次数;
- 工具异常分类;
- Prompt/Response 落盘;
- Trace ID;
- OpenTelemetry 或 Langfuse 等追踪系统集成。
7.7 落地场景
| 场景 | 落地方式 |
|---|---|
| 财务报表分析 | 使用 PDF 解析 + 货币转换 + 代码解释器汇总 |
| 跨国预算编制 | 多币种预算统一换算并生成表格 |
| 费用报销审核 | 解析费用 PDF/票据,计算合计并校验规则 |
| 教学实验 | 演示上下文各组成部分对 Agent 表现的影响 |
| 模型选型 | 同一任务横向比较 Doubao、Kimi、DeepSeek、SiliconFlow |
| Agent 评测平台 | 将本项目改造成最小化 Agent eval harness |
| 企业内部知识库助手 | 新增检索工具,对比不同上下文策略 |
7.8 面试考点提炼
| 考点 | 可结合项目回答的要点 |
|---|---|
| Agent 的基本循环 | 用户输入 → 模型推理 → tool call → 工具执行 → 结果回填 → 最终答案 |
| 上下文工程 | 历史、推理、工具定义、工具结果分别影响什么 |
| 消融实验 | 控制变量,比较 Full Context 与缺失组件模式 |
| Tool Calling | 工具 schema、参数解析、异常 JSON 容错 |
| 多模型适配 | OpenAI-compatible API、Provider 配置、模型默认值 |
| ReAct 退化分析 | 无工具结果时模型可能幻觉,无历史时容易遗忘 |
| Token 成本 | 完整上下文效果好但成本高,摘要/滑动窗口可降本 |
| 可复现实验 | 保存 JSON、Git 信息、依赖版本、证据哈希 |
| 安全问题 | 代码解释器必须沙箱化 |
| 评测指标 | 正确率、工具调用次数、轮次、耗时、Token、失败率 |
8. 常见问题与排查清单
8.1 API Key 未配置或读取失败
【故障现象】运行 quickstart.py、main.py 或 Provider 检查脚本时提示 API Key 缺失、认证失败或无法初始化 Agent。
【根因】.env 文件不存在、Key 未填写、Provider 名称与配置不匹配,或环境变量未被 python-dotenv 加载。
【修复方案】
-
确认项目根目录存在
.env; -
从
env.example复制生成.env; -
按
config.py中要求填写对应 Provider 的 Key; -
运行:
bashpython tests/manual/check_provider_config.py -
再运行对应 Provider 的 quick 脚本验证。
8.2 默认 Provider 不符合预期
【故障现象】未指定 Provider 时,程序没有使用 Doubao,或提示某个 Provider 配置缺失。
【根因】本地配置覆盖了默认值,或 config.py 中默认 Provider 逻辑与预期不一致。
【修复方案】
-
运行:
bashpython tests/manual/check_default_provider.py -
检查
.env中是否设置了默认 Provider; -
如需显式指定,运行命令时传入 Provider 参数,具体参数名以
python main.py --help为准。
8.3 模型名称不可用或已废弃
【故障现象】API 返回 model not found、invalid model 或类似错误。
【根因】使用了错误模型 ID、旧别名,或当前账号没有该模型权限。README 中提到 DeepSeek 旧别名 deepseek-chat / deepseek-reasoner 已废弃,建议使用 V4 ID。
【修复方案】
- 优先使用 README 中列出的默认模型;
- DeepSeek 使用
deepseek-v4-flash或deepseek-v4-pro; - Kimi 使用
kimi-k3; - Doubao 使用
doubao-seed-1-6-thinking-250715; - SiliconFlow 使用
Qwen/Qwen3.5-397B-A17B; - 通过
--model参数指定模型,实际参数名以--help为准。
8.4 温度或 max_tokens 参数报错
【故障现象】调用 Kimi、DeepSeek 等推理模型时提示 temperature、max_tokens 或 thinking 输出相关参数错误。
【根因】不同推理模型对采样参数和输出长度有特殊要求。README 中提到 Kimi K3 会强制 temperature 为 1,并设置足够大的 max_tokens。
【修复方案】
- 不要随意绕过
_reasoning_safe_temperature; - 使用项目默认模型配置;
- 如自定义模型,在
config.py中补充该模型的参数规则; - 运行对应 Provider 的检查脚本确认参数兼容性。
8.5 工具调用 JSON 解析失败导致循环中断
【故障现象】模型返回工具调用后,程序因参数 JSON 格式错误而异常退出。
【根因】模型可能输出 malformed JSON,而 Agent 没有对异常参数做容错。
【修复方案】
-
先运行回归测试:
bashpytest tests/test_malformed_tool_json.py -
确认
_execute_tool或 Agent 主循环中对 JSON 解析异常进行捕获; -
将错误信息作为工具结果或 assistant 可观察信息返回,让模型自我修正;
-
不要因为单次工具参数错误直接终止整个 ReAct 循环。
8.6 PDF 解析失败
【故障现象】Agent 调用 parse_pdf 后无法提取文本,或提示 PDF 下载/读取失败。
【根因】URL 不可访问、网络受限、PDF 文件损坏、PDF 是扫描件图片、本地样例文件缺失。
【修复方案】
-
先使用仓库自带 PDF:
textfixtures/pdfs/sample_financial_report_q1_2024.pdf fixtures/pdfs/simple_expense_report.pdf -
运行:
bashpython tests/manual/check_pdf_task.py -
如果样例 PDF 缺失,运行:
bashpython create_sample_pdf.py -
对扫描件 PDF,需要额外 OCR 能力,当前摘要中未发现内置 OCR 模块。
8.7 货币转换工具失败
【故障现象】convert_currency 报错、返回空值或结果不符合预期。
【根因】外部汇率服务不可用、网络受限、货币代码错误、金额格式不正确。
【修复方案】
- 检查网络连接;
- 确认货币代码如
USD、CNY等是否正确; - 使用
pytest tests/test_agent.py验证货币转换基础逻辑; - 如果外部服务不稳定,可扩展本地缓存或固定汇率 fallback;
- 复杂汇总可让 Agent 改用
code_interpreter计算。
8.8 代码解释器执行失败
【故障现象】code_interpreter 工具执行 Python 代码时报错,或结果与预期不一致。
【根因】生成代码引用了未安装依赖、运行目录不对、代码本身有 bug,或被安全策略限制。
【修复方案】
-
运行:
bashpytest tests/test_code_interpreter.py -
检查
requirements.txt是否已安装; -
在可信环境中单独执行模型生成的代码片段;
-
为代码解释器增加超时、异常捕获和依赖白名单;
-
不要在生产环境直接执行不可信代码。
8.9 No History 模式表现异常
【故障现象】Agent 在 No History 模式下仍似乎能看到历史,或者 Full Context 模式下反而忘记历史。
【根因】上下文构建逻辑不符合模式契约,或消息裁剪位置不正确。
【修复方案】
-
运行:
bashpytest test_experiment_1_1.py -
重点检查
_build_context和_prepare_messages_for_api; -
使用
evaluate_context_contract验证每轮请求中的角色和消息; -
打开 verbose 日志查看实际发送给 API 的 messages。
8.10 No Tool Calls / No Tool Results 模式不符合预期
【故障现象】No Tool Calls 模式下模型仍调用工具,或 No Tool Results 模式下模型仍看到工具结果。
【根因】工具描述未被移除,或工具结果消息仍被加入 API 请求。
【修复方案】
- 检查
_get_tools_description是否根据ContextMode控制工具字段; - 检查
_build_context是否过滤 tool result; - 使用
test_full_contract_uses_raw_followup_context、test_no_tool_results_requires_literal_hidden_observations等测试验证; - 保存请求 JSON,确认发送给模型的 tools 字段和 messages 内容。
8.11 Provider 切换失败
【故障现象】从 Doubao 切换到 Kimi/DeepSeek/SiliconFlow 后请求失败。
【根因】不同 Provider 的 base URL、模型名、API Key、温度参数或工具调用格式存在差异。
【修复方案】
-
运行:
bashpython tests/manual/check_provider_switching.py -
分别运行目标 Provider 的完整检查脚本;
-
检查
config.py中 Provider 配置; -
确认对应
.env中 Key 已填写; -
先用 quick 脚本验证,再跑复杂任务。
8.12 手动脚本无法导入 agent 或 config
【故障现象】运行 tests/manual/*.py 时出现 ModuleNotFoundError: No module named 'agent'。
【根因】手动脚本位于子目录中,直接运行时 Python 路径可能不包含项目根目录。
【修复方案】
-
确认脚本导入了
_bootstrap; -
_bootstrap.py中提供了add_project_root(),应确保它被调用; -
从项目根目录运行脚本,例如:
bashpython tests/manual/quickstart.py -
不要只在
tests/manual目录中直接运行而绕过路径初始化。
8.13 测试依赖真实 API 导致失败
【故障现象】运行 pytest 时某些测试因网络、API Key 或模型调用失败。
【根因】部分测试可能是集成测试或手动测试,需要真实 Provider 环境。摘要中未明确所有测试是否已 mock。
【修复方案】
- 先运行不依赖外部服务的单元测试;
- 配置好 API Key 后再运行集成测试;
- 对需要联网的测试使用标记或单独运行;
- 参考
unittest.mock在tests/test_agent.py、tests/test_malformed_tool_json.py中的用法扩展 mock 测试。
8.14 输出文件或报告未生成
【故障现象】运行消融实验后没有找到 JSON、报告或可视化结果。
【根因】未指定输出路径、目录不存在、命令参数不完整,或运行过程中提前失败。
【修复方案】
-
运行:
bashpython main.py --help python run_experiment_1_1.py --help -
查看输出参数说明;
-
先调用
Config.create_directories()或确保程序自动创建目录; -
检查控制台是否有异常堆栈;
-
确认当前用户对项目目录有写入权限。
8.15 实验结果不可复现
【故障现象】两次运行结果差异很大,或无法与 validation/ 中证据对齐。
【根因】LLM 输出具有随机性、外部汇率变化、PDF/网络内容变化、模型版本更新、依赖版本不同。
【修复方案】
- 使用
run_experiment_1_1.py记录完整实验信息; - 保存 Git 信息、依赖版本、时间戳和结果 JSON;
- 对外部工具结果做缓存或 mock;
- 多次运行取平均值;
- 使用
evidence.sha256校验证据文件是否被修改; - 记录模型 ID、Provider、temperature、max_tokens 等参数。