StudyMate Agent 是一个课程资料助手,用 FastAPI 提供 JSON 接口。
项目使用 MCP(Model Context Protocol,模型上下文协议)风格工具调用,包含一个 Agent 展示入口和两个功能测试接口:
- Agent 展示入口:用户用自然语言描述需求,Agent 根据上下文生成标准化
tool_call,再由 MCP Server 执行。 - 功能测试接口:便于 Apifox 分别验证工具能力,实际执行也统一经过 MCP Server。
支持的两个工具能力:
pdf_summary:上传 PDF 后提取文本,并返回前 800 字摘要。web_info:抓取网页标题和 description 信息。
用户自然语言请求
-> Agent 分析意图和上下文
-> Agent 生成 tool_call / tool_calls JSON
-> MCP Server 校验并执行已注册工具
-> FastAPI 返回 decision、tool_call 和 result
职责边界:
agent/agent_core.py:只生成工具调用计划,不直接导入或调用 PDF、网页工具。mcp_server.py:维护可扩展工具注册表,接收标准化tool_call并执行工具。main.py:协调文件上传、Agent 规划、MCP 执行和 HTTP JSON 返回。agent/tools/:保留具体工具实现。
本项目实验操作统一在 VS Code 内完成。不要单独打开 Windows Terminal、CMD、PowerShell 或 Anaconda Prompt。
需要执行命令时,使用 VS Code 顶部菜单:
Terminal -> New Terminal
也可以使用快捷键:
Ctrl + `
后续所有 Conda 环境创建、环境激活、依赖安装、服务启动和本地验证命令,都在 VS Code 的集成终端中执行。
- 打开 VS Code。
- 点击
File -> Open Folder...。 - 选择或新建用于实验的父目录。
- 在 VS Code 中打开集成终端。
- 在集成终端中执行:
mkdir studymate-agent
cd studymate-agent如果你已经拿到本项目文件,直接在 VS Code 中通过 File -> Open Folder... 打开 studymate-agent 文件夹即可。
studymate-agent/
├── main.py
├── mcp_server.py
├── requirements.txt
├── README.md
├── CLAUDE.md
├── uploads/
├── agent/
│ ├── __init__.py
│ ├── agent_core.py
│ ├── schemas.py
│ ├── prompts/
│ │ └── system_prompt.txt
│ └── tools/
│ ├── __init__.py
│ ├── pdf_tool.py
│ └── web_tool.py
└── tests/
├── test_agent_core.py
├── test_api.py
├── test_mcp_server.py
└── test_tools.py
uploads/ 用于保存上传的 PDF 文件,服务启动或上传时会自动创建。
在 VS Code 集成终端中执行:
conda create -n studymate_env python=3.9 -y
conda activate studymate_env确认终端提示符前面出现:
(studymate_env)
这表示当前 VS Code 集成终端已经进入 studymate_env 虚拟环境。
确认当前路径位于 studymate-agent 项目根目录,并且已经激活 studymate_env,然后在 VS Code 集成终端中执行:
pip install -r requirements.txt所有依赖都会安装到 Conda 虚拟环境中,不会污染全局 Python 环境。
在 VS Code 中打开命令面板:
Ctrl + Shift + P
输入并选择:
Python: Select Interpreter
然后选择 studymate_env 对应的 Python 解释器。
在 VS Code 集成终端中执行:
python main.py服务默认运行在:
http://127.0.0.1:8101
看到类似 Uvicorn running on http://127.0.0.1:8101 的输出后,再打开 Apifox 测试接口。
服务启动动作仍然在 VS Code 集成终端中完成。Apifox 只用于发送 HTTP 请求和保存实验截图。
- Method:
GET - URL:
http://127.0.0.1:8101/health - 预期返回:
{
"code": 200,
"message": "ok",
"agent_name": "StudyMate Agent"
}这是实验展示的重点接口,用于体现 Agent 和普通后端工具接口的区别。
- Method:
POST - URL:
http://127.0.0.1:8101/api/agent/ask - Body:
multipart/form-data - 参数:
user_request:用户自然语言需求,例如帮我总结这份课程资料或帮我获取这个网页信息question:可替代user_request的自然语言需求字段file:可选,上传 PDF 文件url:可选,输入example.com或https://example.com
测试 PDF 场景:
user_request = 帮我总结这份课程 PDF
file = 选择一个 PDF 文件
测试网页场景:
user_request = 帮我获取这个网页的标题和描述
url = example.com
成功返回示例:
{
"code": 200,
"data": {
"agent_name": "StudyMate Agent",
"mode": "agentic_request",
"user_request": "帮我获取这个网页的标题和描述",
"decision": {
"status": "ready",
"selected_tool": "web_info",
"reason": "用户需求和可用上下文指向网页标题与描述抓取,已选择网页信息工具。",
"confidence": "high",
"available_context": {
"pdf_file": false,
"url": true
},
"required_context": null
},
"tool_call": {
"tool": "web_info",
"arguments": {
"url": "example.com"
}
},
"result": {
"url": "https://example.com",
"title": "Example Domain",
"description": "..."
}
}
}多工具调用时,Agent 会生成两个 MCP tool_call,并返回对应结果:
{
"code": 200,
"data": {
"agent_name": "StudyMate Agent",
"user_request": "请分别总结这个 PDF,并抓取这个网页标题",
"decision": {
"status": "ready",
"selected_tool": "multiple_tools",
"available_context": {
"pdf_file": true,
"url": true
}
},
"tool_calls": [
{
"tool": "pdf_summary",
"arguments": {
"file_path": "..."
}
},
{
"tool": "web_info",
"arguments": {
"url": "example.com"
}
}
],
"results": [
{
"tool": "pdf_summary",
"result": {
"summary": "..."
}
},
{
"tool": "web_info",
"result": {
"title": "Example Domain"
}
}
]
}
}如果需求不明确,Agent 不会盲目调用工具,而是返回需要补充的上下文:
{
"code": 200,
"data": {
"agent_name": "StudyMate Agent",
"mode": "agentic_request",
"user_request": "帮我处理一下",
"decision": {
"status": "need_more_context",
"selected_tool": null,
"reason": "用户需求中没有明确指向 PDF 摘要或网页信息抓取,也没有提供可用上下文。",
"confidence": "low",
"available_context": {
"pdf_file": false,
"url": false
},
"required_context": "请上传 PDF,或提供 URL,并说明需要摘要还是抓取网页信息。"
},
"tool_call": null,
"result": {
"message": "请上传 PDF,或提供 URL,并说明需要摘要还是抓取网页信息。"
}
}
}- Method:
POST - URL:
http://127.0.0.1:8101/api/agent/pdf-summary - Body:
multipart/form-data - 参数:
file:选择一个 PDF 文件
成功返回示例:
{
"code": 200,
"data": {
"agent_name": "StudyMate Agent",
"action": "pdf_summary",
"result": {
"file_path": "...",
"text_length": 1234,
"summary": "..."
}
}
}- Method:
POST - URL:
http://127.0.0.1:8101/api/agent/web-info - Body:
multipart/form-data - 参数:
url:example.com或https://example.com
成功返回示例:
{
"code": 200,
"data": {
"agent_name": "StudyMate Agent",
"action": "web_info",
"result": {
"url": "https://example.com",
"title": "Example Domain",
"description": "..."
}
}
}异常时返回 HTTP 500,并包含:
{
"code": 500,
"error": "错误信息"
}本地验证也在 VS Code 集成终端中执行:
python -m compileall .
python -m unittest discover -s tests实验报告建议保存以下截图:
- VS Code 项目结构截图:证明文件完整。
- VS Code 中的
agent/prompts/system_prompt.txt截图:证明 Agent 系统提示明确。 - VS Code 集成终端中的 FastAPI 启动截图:证明服务正常运行。
- Apifox 的
/health接口调用截图。 - Apifox 的
/api/agent/ask自然语言 Agent 入口截图:证明 Agent 会根据需求和上下文选择工具。 - Apifox 的 PDF 摘要接口调用截图。
- Apifox 的网页信息接口调用截图。
- Codex 生成代码过程截图:可作为 Reflection 证据。
- 说明本实验如何体现 Tool Use:
pdf_summary和web_info分别调用 PDF 解析与网页抓取工具。 - 说明本实验如何体现 Context Integration:Agent 将上传 PDF 或外部网页内容作为外部上下文处理。
- 说明本实验如何体现 Agent 行为:用户先用自然语言提出需求,Agent 读取上下文后选择工具并生成标准化
tool_call。 - 说明 MCP 职责分离:Agent 不直接调用工具,MCP Server 接收
tool_call后统一完成参数校验、工具路由和执行。 - 说明 Vibe Coding 过程:通过自然语言描述需求,由 Codex 生成项目结构、接口、工具函数、测试和文档。
- 说明环境操作方式:项目创建、Conda 环境、依赖安装和服务启动都在 VS Code 集成终端中完成,没有单独打开系统终端。
- 说明局限性:PDF 摘要当前是截取式摘要,不包含真实大模型改写;网页抓取依赖目标网站可访问性和页面 metadata 完整度。