B2 Skill 工具模块 README
本仓库是从团队总体
agent代码仓库中提取出的个人 B2 方向模块。README 重点说明本模块完成的基础功能、进阶功能、独立运行方式,以及它在团队 Agent 系统中的接口边界。
1. 模块概述
1.1 模块名称
B2 Skill 工具模块
1.2 模块说明
B2 负责为本地 Agent 系统提供可独立调用的 Skill 工具函数。模块接收 JSON 对象作为输入,执行计算、文件读取、本地检索、表格分析、格式转换、文档读取、代码沙箱、单元测试沙箱和 Web 搜索等操作,并统一返回 SkillResult JSON 对象。
该模块在完整系统中的作用是把“模型想调用工具”转化为真实可执行的本地能力。B3 工具层会把模型生成的 tool call 参数传给 B2 Skill,B2 执行后返回结构化结果,再由 B3 封装成 ToolMessage 交回 Agent 主循环。
1.3 完成情况概览
| 类型 | 完成情况 |
|---|---|
| 基础要求 | 已完成 calculator、file_reader、local_file_search、table_analyzer、format_converter 五个基础 Skill,并提供正常/异常输入样例。 |
| 进阶要求 | 已完成 document_reader、read_then_convert、python_sandbox、python_unit_test_sandbox、web_search 五个扩展 Skill。 |
| 可独立运行的演示 | code/b2_run_skill.py 命令行入口;code/b2_webui_server.py WebUI 入口。 |
| 与团队系统集成情况 | 团队总体项目中 B3 通过 skills.<skill_name> 调用 B2 Skill,并将结果封装为 ToolMessage。 |
2. 环境、模型与数据依赖
2.1 运行环境
| 项目 | 要求 |
|---|---|
| Python 版本 | Python 3.10+ |
| 必要依赖 | Python 标准库 + PyMuPDF(用于 PDF 解析) |
| 是否需要模型 | 不需要 |
| 是否需要 GPU | 不需要 |
| 是否需要外部数据集 | 不需要,仓库内已包含演示样例数据 |
2.2 模型依赖
B2 Skill 模块不直接调用大模型,不需要下载模型文件。
| 模型 | 来源 | 项目内相对路径 | 用途 |
|---|---|---|---|
| 无 | 无 | 无 | B2 只负责工具执行,不负责模型推理。 |
2.3 数据集或样例数据依赖
| 数据或文件 | 来源 | 项目内相对路径 | 用途 |
|---|---|---|---|
| Skill 正常/异常输入样例 | 从团队总体仓库提取 | data/tool_inputs/ |
验证每个 Skill 的成功路径和错误处理路径。 |
| 本地文本样例 | 项目自带 | data/docs/、data/b4_file/agent_intro.txt |
file_reader、local_file_search、read_then_convert 演示;data/docs/ 中包含多份 Agent 工具调用 假数据,用于展示检索 score 排序。 |
| PDF, DOCX, PPTX 文档样例 | 项目自带 | data/documents/ |
document_reader_demo.pdf, docx_sample.docx, ppt_sample.pptx 演示;documents/8-王稳淞.pdf 用于复杂 PDF 验证。 |
| CSV 表格样例 | 项目自带 | data/tables/results.csv |
table_analyzer 演示。 |
| B2 端到端任务样例 | 从团队总体仓库提取 | data/runtime_input_b2_*.json |
团队完整 Agent 流程中调用 B2 的任务输入样例。 |
2.4 安装步骤
cd B2_repo
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
requirements.txt 记录了最小运行依赖,目前主要是 PyMuPDF,用于 PDF 文档解析。
3. 文件结构与接口边界
3.1 文件结构
B2_repo/
├── code/
│ ├── b2_run_skill.py # B2 命令行入口,读取 JSON 输入并保存 SkillResult
│ ├── b2_webui_server.py # B2 WebUI 服务入口
│ └── common/ # JSON、路径、日志和结果结构工具
├── skills/ # B2 的 10 个 Skill 实现
├── data/
│ ├── tool_inputs/ # 每个 Skill 的正常/异常输入样例
│ ├── docs/ # 本地文本检索和读取样例
│ ├── documents/ # PDF 文档读取样例
│ ├── tables/ # 表格分析样例
│ └── runtime_input_b2_*.json
├── webui/ # B2 Skill Console 静态页面
├── prompts/ # 团队端到端演示用 system prompt
├── outputs/ # 运行后生成结果
├── requirements.txt # B2 最小依赖说明
└── README.md # 个人模块说明文档
3.2 接口边界
| 类型 | 来源 / 去向 | 数据格式 | 说明 |
|---|---|---|---|
| 输入 | 命令行用户、WebUI、团队 B3 工具层 | JSON 对象 | 每个 Skill 接收一个顶层 JSON object,字段由具体工具定义。 |
| 输出 | outputs/B2_skills/ 或 outputs/B2_webui/ |
JSON 对象 | 输出统一为 SkillResult,包含 skill_name、status、input、output、error、latency_ms。 |
| 文件读取边界 | data/ 目录 |
相对路径 | 文件类 Skill 只允许读取 data/ 内部文件,防止路径越界。 |
| 团队集成接口 | B3 tool layer | Python 函数调用 + JSON 结果 | B3 根据工具名调用 skills/<name>.py 中的同名函数。 |
4. 基础要求实现与演示
4.1 基础功能说明
B2 基础版本实现五个通用 Skill:
calculator:安全计算算术表达式。file_reader:读取data/下的.txt、.md文件。local_file_search:在本地文本文件中按关键词检索并返回排序结果。table_analyzer:分析 CSV/TSV 表格的行列、预览和数值列统计。format_converter:将文本转换为 Markdown 或 JSON,并写入输出文件。
这些基础 Skill 覆盖了 Agent 常见的计算、读取、检索、表格分析和格式转换能力。
4.2 基础功能实现路径
| 文件 / 函数 / 脚本 | 作用 |
|---|---|
code/b2_run_skill.py |
命令行统一入口,负责读取输入 JSON、动态加载 Skill、写出结果和运行日志。 |
skills/calculator.py |
使用 AST 白名单实现安全算术表达式计算。 |
skills/file_reader.py |
读取本地文本文件,并限制路径只能位于 data/ 下。 |
skills/local_file_search.py |
对本地文本做关键词抽取、词频统计、排序和片段返回。 |
skills/table_analyzer.py |
使用 csv.DictReader 读取表格并统计数值列。 |
skills/format_converter.py |
将文本转 Markdown/JSON,并安全写入输出目录。 |
code/common/schemas.py |
定义 SkillResult 和统一错误结构。 |
基础流程:
JSON 输入文件 -> b2_run_skill.py -> 目标 Skill 函数 -> SkillResult JSON -> outputs/B2_skills/
4.3 基础功能输入格式与样例
| 字段 / 输入文件 | 类型 / 格式 | 是否必需 | 说明 |
|---|---|---|---|
--skill |
字符串 | 是 | Skill 名称,例如 calculator。 |
--input |
JSON 文件路径 | 是 | 顶层必须是 JSON object。 |
--outdir |
目录路径 | 是 | 保存结果 JSON 和运行日志。 |
--data_root |
目录路径 | 否 | 文件类 Skill 的数据根目录,默认是 data/。 |
样例输入:
| 样例文件 | 用途 |
|---|---|
data/tool_inputs/tool_input_calculator.json |
验证表达式计算成功路径。 |
data/tool_inputs/tool_input_file_reader.json |
验证本地文本读取成功路径。 |
data/tool_inputs/tool_input_file_search.json |
验证本地关键词检索和排序。 |
data/tool_inputs/tool_input_table_analyzer.json |
验证 CSV 表格统计。 |
data/tool_inputs/tool_input_format_converter.json |
验证 Markdown/JSON 转换和文件写出。 |
data/tool_inputs/tool_input_*_error.json |
验证错误输入会被封装进 SkillResult.error,CLI 不崩溃。 |
4.4 基础功能演示命令
cd B2_repo/code
python b2_run_skill.py --skill calculator --input ../data/tool_inputs/tool_input_calculator.json --outdir ../outputs/B2_skills
python b2_run_skill.py --skill file_reader --input ../data/tool_inputs/tool_input_file_reader.json --outdir ../outputs/B2_skills
python b2_run_skill.py --skill local_file_search --input ../data/tool_inputs/tool_input_file_search.json --outdir ../outputs/B2_skills
python b2_run_skill.py --skill table_analyzer --input ../data/tool_inputs/tool_input_table_analyzer.json --outdir ../outputs/B2_skills
python b2_run_skill.py --skill format_converter --input ../data/tool_inputs/tool_input_format_converter.json --outdir ../outputs/B2_skills
运行后应观察:
- 终端打印对应的
<skill>_result.json路径。 outputs/B2_skills/下生成每个 Skill 的结果文件。outputs/B2_skills/skill_run_log.jsonl追加记录运行时间、状态和耗时。
4.5 基础功能输出格式
| 输出文件 / 返回字段 | 格式 | 说明 |
|---|---|---|
outputs/B2_skills/<skill>_result.json |
JSON 对象 | 单次 Skill 执行结果。 |
outputs/B2_skills/skill_run_log.jsonl |
JSONL | 多次 Skill 执行历史日志。 |
status |
字符串 | success 或 error。 |
output |
JSON 对象或 null |
成功时保存业务输出。 |
error |
JSON 对象或 null |
失败时保存异常类型、错误码和错误信息。 |
latency_ms |
数字 | Skill 执行耗时。 |
4.6 基础功能结果截图
calculator 基础功能运行截图如下
calculator 关键输出文件截图如下
file_reader 基础功能运行截图如下
file_reader 关键输出文件截图如下
local_file_search 基础功能运行截图如下
local_file_search 关键输出文件截图如下
table_analyzer 基础功能运行截图如下
table_analyzer 关键输出文件截图如下
format_converter 基础功能运行截图如下
format_converter 关键输出文件截图如下
5. 进阶要求实现与演示
5.1 选择的进阶要求
| 进阶要求 | 是否完成 | 对应文件 / 函数 | 简要说明 |
|---|---|---|---|
| 文档读取 Skill | 是 | skills/document_reader.py |
支持 PDF/DOCX/PPTX 文本提取,并返回元数据和告警。 |
| 组合型 Skill | 是 | skills/read_then_convert.py |
复用 file_reader 和 format_converter,实现读取后转换。 |
| Python 代码沙箱 | 是 | skills/python_sandbox.py |
通过 AST 检查、子进程和超时限制运行短 Python 代码。 |
| Python 单元测试沙箱 | 是 | skills/python_unit_test_sandbox.py |
执行用户代码并逐条验证表达式测试用例。 |
| Web 搜索 Skill | 是 | skills/web_search.py |
支持 mock 搜索结果和真实 DuckDuckGo HTML 搜索。 |
| WebUI 演示界面 | 是 | code/b2_webui_server.py、webui/ |
提供浏览器页面选择 Skill、加载样例、执行并查看结果。 |
5.2 进阶功能总体设计
功能说明
基础 Skill 主要解决“读本地文本、算表达式、查表格、做简单转换”的问题。进阶部分在同一套 SkillResult 接口上继续扩展了五类能力:复杂文档读取、组合式工具编排、受限代码执行、单元测试验证和 Web 搜索。这样团队 Agent 不需要改 B1/B3 的调用链,只要增加一个已注册的 Skill 名称,就能获得新的外部能力。
扩展部分的设计重点有三个:
- 保持调用方式一致:所有扩展 Skill 仍然通过
b2_run_skill.py --skill <name> --input <json>独立运行,也能被 B3 作为普通 Python 函数调用。 - 保持结果结构一致:成功时返回 JSON object,失败时把异常封装进
SkillResult.error,避免一个工具失败拖垮 Agent 主循环。 - 保持边界清晰:本地文件读取都限制在
data/下;写文件只写到传入的output_dir;代码执行和联网搜索都放到独立子进程中,并设置长度、超时和输出上限。
进阶 Skill 总流程:
扩展 JSON 输入 -> b2_run_skill.py/run_skill -> 目标 Skill -> 业务 output 或 error -> SkillResult -> CLI/WebUI/B3
扩展 Skill 注册路径
| 文件 / 函数 / 脚本 | 作用 |
|---|---|
code/b2_run_skill.py |
SKILL_MODULES 注册 10 个 Skill,并通过 inspect.signature 自动注入 data_root、output_dir。 |
skills/document_reader.py |
扩展文档读取,支持 .pdf、.docx、.pptx。 |
skills/read_then_convert.py |
复用两个基础 Skill,展示工具之间的组合调用。 |
skills/python_sandbox.py |
扩展代码运行能力,带 AST 检查、子进程隔离、超时和输出截断。 |
skills/python_unit_test_sandbox.py |
扩展代码评测能力,逐条运行表达式测试用例并返回测试报告。 |
skills/web_search.py |
扩展外部信息获取能力,支持 mock 离线结果和 DuckDuckGo HTML live 搜索。 |
5.3 进阶功能 1:document_reader 多格式文档读取
功能说明
document_reader 用来弥补基础 file_reader 只能读取 .txt、.md 的不足。团队 Agent 在处理课程报告、PDF 论文、Office 文档或幻灯片时,可以通过这个 Skill 把文件正文抽取成普通文本,再交给后续问答、摘要或格式转换流程使用。
实现时没有把三类文档混在一起处理,而是按后缀选择不同解析策略:
- PDF:使用 PyMuPDF 打开文档,逐页抽取 text,若页面没有文本再尝试 blocks 抽取。
- DOCX:把
.docx当作 zip 容器读取word/document.xml,按段落抽取w:t文本。 - PPTX:读取
ppt/slides/slide*.xml,按幻灯片顺序拼接Slide 1、Slide 2等定位信息。
输入格式与样例
| 字段 / 输入文件 / 配置项 | 类型 / 格式 | 是否必需 | 说明 |
|---|---|---|---|
path |
字符串 | 是 | data/ 下的相对路径,例如 documents/8-王稳淞.pdf。 |
max_chars |
正整数 | 否 | 最多返回字符数,默认 4000,上限 50000。 |
data/tool_inputs/tool_input_document_reader.json |
JSON 文件 | 可选 | PDF 样例,验证复杂 PDF 文本抽取。 |
data/tool_inputs/tool_input_document_reader_docx.json |
JSON 文件 | 可选 | DOCX 样例,验证 Office XML 段落抽取。 |
data/tool_inputs/tool_input_document_reader_ppt.json |
JSON 文件 | 可选 | PPTX 样例,验证幻灯片文本抽取。 |
演示命令
cd B2_repo/code
python b2_run_skill.py --skill document_reader --input ../data/tool_inputs/tool_input_document_reader.json --outdir ../outputs/B2_skills
python b2_run_skill.py --skill document_reader --input ../data/tool_inputs/tool_input_document_reader_docx.json --outdir ../outputs/B2_skills
python b2_run_skill.py --skill document_reader --input ../data/tool_inputs/tool_input_document_reader_ppt.json --outdir ../outputs/B2_skills
输出格式
| 返回字段 | 格式 | 说明 |
|---|---|---|
content |
字符串 | 抽取并清洗后的正文。 |
num_chars |
数字 | 实际返回字符数。 |
source |
字符串 | 相对 data/ 的来源路径。 |
file_type |
字符串 | pdf、docx 或 pptx。 |
truncated |
布尔值 | 是否因为 max_chars 被截断。 |
metadata |
JSON 对象 | 文件大小、PDF 页数、DOCX 段落数或 PPTX 页数。 |
warnings |
数组 | 解析失败页、扫描版 PDF 无文本等非致命告警。 |
示例图片
5.4 进阶功能 2:read_then_convert 组合型 Skill
功能说明
read_then_convert 不是重新写一套读取和转换逻辑,而是组合已有的 file_reader 和 format_converter。这个扩展的重点是验证 B2 Skill 之间可以互相复用:上层只发起一次 tool call,B2 内部完成“读文件 -> 截断控制 -> 格式转换 -> 写文件”的连续流程。
这个设计对团队系统有实际价值。B3/B1 不需要知道中间有两个工具,也不需要保存临时文本;它只拿到最终结构化结果和生成文件路径,适合处理“读取一份资料并整理成 Markdown/JSON”这类复合任务。
输入格式与样例
| 字段 / 输入文件 / 配置项 | 类型 / 格式 | 是否必需 | 说明 |
|---|---|---|---|
path |
字符串 | 是 | data/ 下的 .txt 或 .md 文件路径。 |
target_format |
字符串 | 是 | 目前支持 markdown 或 json。 |
max_chars |
正整数 | 否 | 读取阶段最多保留的字符数,默认 2000。 |
output_filename |
字符串 | 否 | 生成文件名,代码会取 basename 防止路径穿越。 |
data/tool_inputs/tool_input_read_then_convert.json |
JSON 文件 | 是 | 读取 docs/agent_intro.txt 并生成 agent_intro_converted.md。 |
演示命令
cd B2_repo/code
python b2_run_skill.py --skill read_then_convert --input ../data/tool_inputs/tool_input_read_then_convert.json --outdir ../outputs/B2_skills
输出格式
| 返回字段 | 格式 | 说明 |
|---|---|---|
source |
字符串 | 读取的源文件相对路径。 |
num_chars |
数字 | 读取阶段返回的字符数。 |
truncated |
布尔值 | 源文件是否被截断。 |
target_format |
字符串 | 目标格式。 |
formatted_text |
字符串 | 转换后的文本,可直接给 Agent 继续使用。 |
generated_file_path |
字符串 | 转换结果落盘路径。 |
示例图片
5.5 进阶功能 3:python_sandbox 受限 Python 代码执行
功能说明
python_sandbox 用来让 Agent 执行短小、可控的 Python 片段,例如临时计算、简单数据处理或验证一段逻辑。它不是生产级安全沙箱,但比直接 exec 用户代码更适合课程演示和团队联调。
实现中做了多层限制:
- 静态检查:用 AST 拦截
import、global、nonlocal、open、eval、exec、__import__、dunder 属性等高风险能力。 - 子进程隔离:用
subprocess.run([sys.executable, "-I", "-c", RUNNER])在独立解释器中执行代码。 - 最小内建:只暴露
abs、sum、range、len、print、math、statistics等基础能力。 - 资源限制:代码长度上限 4000 字符,超时上限 5 秒,输出上限 8000 字符。
- 结果封装:子进程把 stdout/stderr/status 打包成 JSON,父进程再返回到
SkillResult.output。
输入格式与样例
| 字段 / 输入文件 / 配置项 | 类型 / 格式 | 是否必需 | 说明 |
|---|---|---|---|
code |
字符串 | 是 | 待执行 Python 代码。 |
timeout_seconds |
数字 | 否 | 执行超时时间,默认 2 秒,上限 5 秒。 |
max_output_chars |
正整数 | 否 | stdout/stderr 最大返回长度,默认 2000。 |
data/tool_inputs/tool_input_python_sandbox.json |
JSON 文件 | 是 | 运行列表求和和 math.sqrt 示例。 |
data/tool_inputs/tool_input_python_sandbox_error.json |
JSON 文件 | 否 | 使用 import os,验证危险语法会被拒绝。 |
演示命令
cd B2_repo/code
python b2_run_skill.py --skill python_sandbox --input ../data/tool_inputs/tool_input_python_sandbox.json --outdir ../outputs/B2_skills
python b2_run_skill.py --skill python_sandbox --input ../data/tool_inputs/tool_input_python_sandbox_error.json --outdir ../outputs/B2_skills
输出格式
| 返回字段 | 格式 | 说明 |
|---|---|---|
status |
字符串 | 子进程内用户代码状态,通常为 success 或 error。 |
stdout |
字符串 | 用户代码 print 输出。 |
stderr |
字符串 | 用户代码异常或子进程错误信息。 |
returncode |
数字 | 子进程退出码。 |
timed_out |
布尔值 | 是否超时。 |
truncated |
布尔值 | 输出是否被截断。 |
workdir |
字符串 | 本次沙箱运行目录。 |
示例图片
5.6 进阶功能 4:python_unit_test_sandbox 单元测试沙箱
功能说明
python_unit_test_sandbox 是在代码沙箱基础上的进一步扩展,用于“执行一段函数代码,并用表达式测试用例验证结果”。它适合团队 Agent 回答编程题、生成函数后自检,或在演示中展示工具能返回结构化测试报告。
和 python_sandbox 相比,它多了测试用例校验流程:先执行用户代码,再在同一命名空间里逐条 eval 测试表达式。单条测试失败不会中断整批测试,而是记录 actual、expected、passed 和 error,最后汇总 passed_count、failed_count、all_passed。
样例里第三条 is_even(7) 的期望值故意写成 true,实际返回 false,因此输出中会出现 2 条通过、1 条失败。这个样例能证明该 Skill 不只是展示成功路径,也能准确呈现失败 case。
输入格式与样例
| 字段 / 输入文件 / 配置项 | 类型 / 格式 | 是否必需 | 说明 |
|---|---|---|---|
code |
字符串 | 是 | 待测 Python 代码,限制和 python_sandbox 一致。 |
tests |
JSON 数组 | 是 | 每项包含 expression 和 expected。最多 20 条。 |
expression |
字符串 | 是 | 测试表达式,例如 add(1, 2),单条上限 500 字符。 |
expected |
任意 JSON 值 | 是 | 期望结果,会和表达式实际值做相等比较。 |
timeout_seconds |
数字 | 否 | 整批执行超时,默认 2 秒,上限 5 秒。 |
max_output_chars |
正整数 | 否 | stdout/stderr 最大返回长度。 |
data/tool_inputs/tool_input_python_unit_test_sandbox.json |
JSON 文件 | 是 | add 与 is_even 函数测试样例。 |
演示命令
cd B2_repo/code
python b2_run_skill.py --skill python_unit_test_sandbox --input ../data/tool_inputs/tool_input_python_unit_test_sandbox.json --outdir ../outputs/B2_skills
输出格式
| 返回字段 | 格式 | 说明 |
|---|---|---|
status |
字符串 | 测试执行状态,正常跑完为 completed。 |
passed_count |
数字 | 通过测试数量。 |
failed_count |
数字 | 失败测试数量。 |
all_passed |
布尔值 | 是否所有测试都通过。 |
cases |
JSON 数组 | 每条测试的 expression、expected、actual、passed、error。 |
stdout / stderr |
字符串 | 待测代码或测试阶段输出。 |
returncode / workdir |
数字 / 字符串 | 子进程退出码和运行目录。 |
示例图片
5.7 进阶功能 5:web_search Web 搜索
功能说明
web_search 给 B2 增加外部信息获取能力,适合 Agent 需要查询公开网页标题、链接和摘要的场景。为了兼顾验收稳定性和真实联网能力,它实现了两种模式:
- mock 模式:输入里传
mock_results,Skill 只做字段校验和排序返回,不依赖网络,适合课堂验收和离线演示。 - live 模式:不传
mock_results时,子进程请求 DuckDuckGo HTML 页面,主进程用轻量正则提取标题、链接和摘要。
真实联网请求放在子进程里执行,并设置查询长度、top_k、超时和 HTML 大小上限,避免网络异常影响主流程。DuckDuckGo 结果链接如果包含 uddg 参数,会被还原成真实目标 URL。
输入格式与样例
| 字段 / 输入文件 / 配置项 | 类型 / 格式 | 是否必需 | 说明 |
|---|---|---|---|
query |
字符串 | 是 | 搜索关键词,最多 200 字符。 |
top_k |
正整数 | 否 | 返回结果数量,默认 5,上限 10。 |
timeout_seconds |
数字 | 否 | live 模式请求超时,默认 5 秒,上限 10 秒。 |
mock_results |
JSON 数组 | 否 | 传入后启用 mock 模式,每项包含 title、url、snippet。 |
data/tool_inputs/tool_input_web_search.json |
JSON 文件 | 是 | mock 搜索样例,稳定可复现。 |
data/tool_inputs/tool_input_web_search_live.json |
JSON 文件 | 否 | live 搜索样例,需要当前网络可访问 DuckDuckGo。 |
演示命令
cd B2_repo/code
python b2_run_skill.py --skill web_search --input ../data/tool_inputs/tool_input_web_search.json --outdir ../outputs/B2_skills
python b2_run_skill.py --skill web_search --input ../data/tool_inputs/tool_input_web_search_live.json --outdir ../outputs/B2_skills
输出格式
| 返回字段 | 格式 | 说明 |
|---|---|---|
query |
字符串 | 实际搜索词。 |
source |
字符串 | mock 或 duckduckgo_html。 |
request_mode |
字符串 | mock 或 subprocess。 |
results |
JSON 数组 | 搜索结果列表。 |
results[].rank |
数字 | 排名。 |
results[].title |
字符串 | 标题。 |
results[].url |
字符串 | 结果链接。 |
results[].snippet |
字符串 | 摘要。 |
示例图片
5.8 进阶功能 6:B2 WebUI 演示界面
功能说明
WebUI 提供浏览器界面,用于选择 Skill、加载正常/异常样例、编辑 JSON 输入、执行工具并查看结果和运行日志。它方便课堂展示,也方便非命令行用户验证 B2 的所有 Skill。
实现路径
| 文件 / 函数 / 脚本 | 作用 |
|---|---|
code/b2_webui_server.py |
提供 HTTP API:/api/skills、/api/sample、/api/run、/api/history、/api/clear_history。 |
webui/index.html |
WebUI 页面结构。 |
webui/app.js |
前端状态管理、样例加载、执行请求和结果渲染。 |
webui/styles.css |
页面样式。 |
输入格式与样例
| 字段 / 输入文件 / 配置项 | 类型 / 格式 | 是否必需 | 说明 |
|---|---|---|---|
skill |
字符串 | 是 | 通过页面选择 Skill 后自动传入。 |
input |
JSON 对象 | 是 | WebUI 文本框中的 JSON 输入。 |
data/tool_inputs/*.json |
JSON 文件 | 否 | 页面可自动加载的正常、异常和 live 样例。 |
演示命令
cd B2_repo/code
python b2_webui_server.py --host 127.0.0.1 --port 18087
浏览器访问:
http://127.0.0.1:18087/
输出格式
| 输出文件 / 返回字段 | 格式 | 说明 |
|---|---|---|
outputs/B2_webui/<skill>_result.json |
JSON 对象 | WebUI 最近一次执行的 SkillResult。 |
outputs/B2_webui/skill_run_log.jsonl |
JSONL | WebUI 运行日志。 |
API 响应 result |
JSON 对象 | 当前执行的 SkillResult。 |
API 响应 history |
JSON 数组 | 最近运行记录。 |
运行结果
5.9 扩展功能开发与联调经历
扩展部分的开发不是一次性堆功能,而是按“先稳定接口,再增加能力,再处理边界”的顺序推进。
第一步先把所有 Skill 都统一成普通 Python 函数,并让 b2_run_skill.py 只负责通用工作:读取 JSON、动态导入模块、注入共享路径、捕获异常、写结果文件和记录 JSONL 日志。这样后面新增 document_reader、python_sandbox、web_search 时,不需要重复写入口代码,也方便 B3 直接复用同一批函数。
第二步扩展本地资料处理能力。最初的 file_reader 只能读纯文本,不能覆盖报告 PDF、Office 文档和课件,所以增加了 document_reader。实现中遇到的主要问题是三类文件的内部结构完全不同:PDF 需要逐页抽取,DOCX/PPTX 本质上是 zip + XML。最后采用“按后缀分发解析器”的方式,保留 metadata 和 warnings,让调用方能判断文档是否被截断、是否可能是扫描版 PDF。
第三步验证 Skill 的可组合性。read_then_convert 只写了很少的新逻辑,但它证明了基础 Skill 可以在 B2 内部被编排。这里特别处理了两个边界:读取阶段继续沿用 data_root 沙箱,写文件阶段沿用 output_dir,因此组合后仍然不会逃出团队约定的输入和输出目录。
第四步实现代码执行类扩展。直接运行模型生成的 Python 代码风险很高,所以先加 AST 检查,再放到隔离子进程中执行,并只暴露少量安全内建函数。python_unit_test_sandbox 继续复用这套限制,但把输出从单纯 stdout 升级成测试报告,让 Agent 能知道每条 case 的实际值和期望值,而不是只能看到一段控制台文本。
第五步处理 Web 搜索的不稳定性。真实搜索依赖网络和搜索页面结构,验收时不一定稳定,所以 web_search 设计成 mock 优先、live 可选。mock 样例保证离线也能演示完整接口;live 样例则展示该 Skill 具备真实联网搜索能力。两种模式返回同一套 query/source/request_mode/results 字段,B3 和前端不需要区分内部实现。
第六步补 WebUI。CLI 适合开发验证,但课堂展示时频繁复制命令不方便,所以增加 b2_webui_server.py 和静态页面。WebUI 会从后端读取 Skill 列表、加载正常/异常样例、提交 /api/run,并把结果和历史记录展示出来。它本质上仍然调用 run_skill,因此不会形成另一套逻辑,展示结果和 CLI 结果保持一致。
6. 与团队系统的集成说明
团队系统中的调用链路如下:
B1 Agent 主循环 -> B4 生成 AIMessage/tool_calls -> B3 校验并执行 tool call -> B2 Skill 函数 -> B3 ToolMessage -> B1 汇总最终回答
集成方式:
- 团队总体仓库通过
skillsPython 包导入 B2 的具体 Skill 文件。 - B3 根据工具配置和 tool call 名称找到对应 Skill。
- B3 将 tool call 的
args作为关键字参数传入 Skill。 - 文件类 Skill 通过
data_root参数限定读取范围。 - 写文件类 Skill 通过
output_dir参数保存生成文件。 - B2 返回的普通业务结果会被包成统一
SkillResult,再由 B3 写入 ToolMessage。
联调中需要注意的接口一致性:
- 输入顶层必须是 JSON object,不能是数组或纯字符串。
- Skill 成功输出也必须是 JSON object,便于 B3 序列化。
- 异常不应导致 Agent 主流程崩溃,而是写入
SkillResult.error。 - 文件路径统一按
data/相对路径解释,避免不同运行目录导致路径不一致。
7. 已知问题与后续改进
| 优先级 | 已知问题 | 当前影响 | 当前原因 | 后续改进 |
|---|---|---|---|---|
| 高 | python_sandbox 只适合课程演示级代码执行 |
可以运行短代码,但不能承诺生产级安全隔离 | 当前主要依赖 AST 白名单、最小内建函数、独立子进程和超时控制,没有做容器隔离、内存限制和系统调用限制 | 后续可把执行环境迁移到 Docker/Firejail 等隔离环境中,增加 CPU、内存、文件系统、网络访问和进程数量限制。 |
| 高 | web_search live 模式受网络和页面结构影响 |
真实搜索在弱网、无网或 DuckDuckGo HTML 结构变化时可能失败 | 当前实现直接解析 DuckDuckGo HTML 页面,虽然有 mock 模式兜底,但 live 模式仍依赖外部网页稳定性 | 验收和离线演示优先使用 mock_results;后续可接入 SerpAPI、Bing Web Search 等稳定搜索 API,并保留 mock 作为测试夹具。 |
| 中 | document_reader 对扫描版 PDF 只能返回告警 |
普通文字型 PDF 可以解析,扫描件或图片型 PDF 无法提取正文 | 当前使用 PyMuPDF 读取文本流,没有 OCR 能力 | 后续可接入 OCR 流程,例如 PaddleOCR、Tesseract 或云 OCR,并在 warnings 中标记 OCR 置信度和页码。 |
| 中 | document_reader 对 DOCX/PPTX 只提取纯文本 |
能读取段落和幻灯片文字,但不能保留表格结构、图片、备注、样式和版式 | 当前直接解析 Office XML 中的文本节点,目标是轻量、少依赖、可演示 | 后续可增加表格提取、幻灯片备注提取和图片 OCR;输出中补充 sections 数组,保留页码、段落、表格等结构化信息。 |
| 中 | python_unit_test_sandbox 只支持表达式级测试 |
适合验证函数返回值,但不适合复杂项目、文件输入、pytest 风格测试或依赖安装 | 当前测试用例格式是 expression + expected,并在同一受限命名空间中逐条 eval |
后续可增加 pytest 子模式,支持多文件代码包、测试超时统计、失败 traceback 摘要和更细的测试分类。 |
| 低 | local_file_search 仍是轻量关键词检索 |
可以完成本地 demo 检索,但语义相近、同义词和长文档召回效果有限 | 当前主要基于关键词匹配、词频和片段排序,没有向量索引或中文分词优化 | 后续可加入中文分词、BM25 或向量检索,并把返回字段扩展为 score_breakdown,方便解释排序依据。 |
| 低 | WebUI 主要用于演示,不是完整管理后台 | 可以加载样例、运行 Skill、查看历史,但不支持多用户、鉴权和长期任务管理 | 当前使用 Python 标准库 HTTP server 和静态页面,重点是低依赖、易启动 | 后续可增加结果文件下载、历史记录筛选、长任务取消、执行中日志流式展示,并在需要多人使用时补充鉴权。 |
8. 许可证信息
本项目采用 MIT License,详见 LICENSE。




















