16 KiB
Arabica Sprint3 系统架构设计说明
1. Sprint3 设计概述
Sprint 2 完成了多维思维框架引擎的建设(基于 Prompt 原语),并实现了对本地知识库(Obsidian)的基本操作。
Sprint 3 的核心目标是在现有本地知识管理能力之上,增强外部学术检索、实现大模型意图路由,并彻底解决大模型在工具调用中的幻觉与崩溃问题。本次迭代将系统从“被动提供 Prompt 的工具箱”升级为“能够听懂自然语言意图并主动调度工具的高级智能体(Agent)”。
核心架构升级与关键功能:
- 意图驱动路由:删除了向客户端 UI 暴露的 Prompt 原语,将底层收口至
toolsController。通过系统提示词定义 4 大意图(文献检索、框架分析、保存内容、本地笔记分析),让大模型自主路由,实现全自然语言对话交互。 - 学术文献检索接入:集成 arXiv API,实现
search_arxiv工具,支持提取核心关键字进行检索,并自动格式化为大模型易读的 Markdown 文本。 - 高容错落盘机制:重构
save_note工具,通过将强类型校验放宽至z.any()结合底层JSON.stringify自动序列化,彻底解决了大模型生成长文本时的 JSON 转义崩溃问题。 - 抗死循环框架引擎:将静态框架 JSON 的读取封装为后台私有工具
fetch_framework_template。通过底层剥离 JSON 外壳并强行注入“🛑立即停止调用工具”的指令,解决大模型读取复杂 JSON 后的死循环调用幻觉。
2. 功能实现步骤说明
典型用户查询与文献检索流程(参见图 3-1):
sequenceDiagram
participant User as 用户
participant Client as Cherry Studio (MCP Client)
participant LLM as 大模型
participant Tools as Tools Controller (路由中心)
participant Arxiv as arXiv Service
participant Vault as Resource Service (本地知识库)
User->>Client: "用 SWOT 框架分析一下量子计算,并查查最新文献"
Client->>LLM: 传递自然语言意图
%% 意图 1:查询文献
LLM->>Client: 识别意图1,请求调用 search_arxiv
Client->>Tools: handleToolCall('search_arxiv', {query: 'quantum computing'})
Tools->>Arxiv: 发起 API 检索
Arxiv-->>Tools: 返回文献元数据
Tools-->>Client: 返回格式化文献列表
%% 意图 2:框架分析
LLM->>Client: 识别意图2,请求调用 fetch_framework_template
Client->>Tools: handleToolCall('fetch_framework_template', {framework_name: 'swot'})
Tools-->>Client: 返回纯文本 Prompt 并注入【强制刹车指令】
%% 大模型思考与输出
LLM->>Client: 停止调用工具,直接在聊天框输出分析报告
LLM->>Client: 报告末尾主动询问:"是否需要保存?"
%% 意图 3:保存落盘
User->>Client: "是的,保存下来"
Client->>LLM: 传递确认指令
LLM->>Client: 识别意图3,请求调用 save_note
Client->>Tools: handleToolCall('save_note', {filename: '...', content: <长文本或JSON对象>})
Tools->>Vault: 自动容错序列化并写入 Markdown
Vault-->>Tools: 写入成功
Tools-->>Client: 返回成功提示
LLM-->>User: 告知已保存至本地笔记
图 3-1:Sprint 3 核心工作流——文献检索与标准化落盘
上述时序图展示了系统在 Sprint 3 架构下,如何通过“意图识别 + 底层容错”处理一次包含多个动作的复杂用户指令。具体步骤解析如下:
- 多重意图触发:用户在客户端输入包含复合诉求的自然语言指令(例如:“用 SWOT 框架分析一下量子计算,并查查最新文献”)。
- 意图 1(学术检索)执行:大模型首先解析出“查找文献”的意图,自主生成检索词并调用
search_arxiv工具。toolsController充当路由网关,将请求分发给 arXiv 服务,拉取真实的学术数据,并将晦涩的 XML 格式化为清晰的 Markdown 列表返回给大模型。 - 意图 2(框架读取与防呆拦截)执行:大模型紧接着解析出“SWOT 分析”意图,调用后台私有工具
fetch_framework_template。此时,toolsController读取本地 JSON 配置,主动剥离 JSON 外壳,提取出纯文本 Prompt,并在头部强行拼接**“🛑立即停止调用任何工具”**的最高优先级刹车指令。 - 大模型思考与安全输出:大模型接收到“刹车指令”后,其工具调用的“冲动”被成功阻断(避免了因反复读取 JSON 导致的无限死循环幻觉)。大模型转为文本生成模式,直接在聊天框为用户输出详尽的分析报告。报告输出完毕后,大模型严格遵从系统纪律,主动向用户发起确认:“是否需要保存?”
- 意图 3(授权落盘与容错兜底)执行:用户回复确认(如:“是的,保存下来”)。大模型获取授权,识别出保存意图,调用
save_note工具并将上万字的分析报告作为参数传入。即使大模型在传参时发生了引号转义错误或误传了 JSON 对象,toolsController底层的 z.any() 容错与自动序列化机制 也会完美兜底,确保长文本安全无损地写入本地 Obsidian 知识库。 - 链路闭环:本地文件写入成功,系统通过大模型向用户反馈最终的成功状态,本次复杂交互圆满结束。
3. 系统组件架构设计
3.1 核心模块职责映射
| 模块 / 服务 | 职责说明 |
|---|---|
app.ts |
MCP Server 主入口。负责注册 search_arxiv、fetch_framework_template、save_note、list_local_notes、read_local_note 五大工具。**关键设计:**将 user_input 和 payload 参数类型设定为 z.any() 以规避底层 AI_JSONParseError。 |
toolsController.ts |
大脑与防火墙。接收工具请求。负责处理大模型的畸形传参(如对象序列化)、剥离 JSON 框架外壳、并在返回给大模型前拼接最高优先级的系统指令。 |
arxivService.ts |
学术检索服务。负责与外部数据库通信,提取标题、摘要、链接等核心信息。 |
resourceService.ts |
本地文件系统网关。负责安全的本地 Markdown 文件读写与列表扫描。 |
3.2 基于 Sprint 3 的项目目录结构
Sprint 3 移除了繁杂的独立 Controller,将逻辑高度内聚,形成了以 toolsController.ts 为核心的分发架构:
project-caffeine/
│
├── src/
│ ├── controllers/
│ │ ├── toolsController.ts # (修改)【核心路由】处理 5 大工具的分发、防呆与容错处理
│ │ └── resourcesController.ts # (修改)增加对 literature:// 资源的支持
│ ├── services/
│ │ ├── resourceService.ts # (修改)扩展支持 literature 协议的文件读写与扫描
│ │ └── arxivService.ts # (新增)【核心】封装 arXiv API 调用与 XML 解析
│ ├── models/
│ │ ├── schemas.ts # (修改)增加新工具的输入输出 Zod 校验
│ │ └── frameworks/ # (不变)思维框架定义 (静态 JSON 模板)
│ └── app.ts # (修改)MCP Server 主入口,注册新增的 Tools 和 Resources
│
├── tsconfig.json # (修改)TypeScript 编译与输出配置调整
└── package.json # (修改)新增第三方依赖(如 axios, zod, fast-xml-parser 等)
表 3-1:Sprint 3 新增/修改文件说明
| 文件/目录 | 状态 | 功能说明 |
|---|---|---|
src/controllers/toolsController.ts |
修改 | 【核心路由大脑】 统一接管 5 大工具的分发。负责拦截大模型的畸形传参并执行兜底序列化(JSON 容错);负责读取并剥离本地框架 JSON 外壳,注入“🛑立即停止调用工具”的强指令,防止大模型陷入死循环。 |
src/controllers/resourcesController.ts |
修改 | 【资源端点】 增加对 literature:// 协议的支持,使大模型可以通过统一接口读取已落盘的学术文献 Markdown 文件。 |
src/services/arxivService.ts |
新增 | 【学术网关】 负责与外部 arXiv 数据库通信。封装 HTTP 请求,解析复杂的 XML 响应格式,提取标题、摘要、链接等核心元数据,并返回大模型友好的 Markdown 纯文本列表。 |
src/services/resourceService.ts |
修改 | 【本地系统交互】 扩展现有的文件操作能力。负责安全的本地 Markdown 文件读取与写入,并在底层确保路径防穿越安全。 |
src/models/schemas.ts |
修改 | 【安全防线】 增加新工具的强类型参数校验。针对大模型易错的落盘操作,将 save_note 的入参校验适度放宽至 z.any() 以配合 Controller 层的容错。 |
src/models/frameworks/ |
不变 | 存放 SWOT、SCQA 等多维思维框架的静态 JSON 配置模板。 |
src/app.ts |
修改 | 【MCP 注册中心】 实例化 MCP Server,统一定义 server.tool 和 server.resource。显式声明 type: "text" as const 以解决 TypeScript 的强类型推断编译报错。 |
package.json |
修改 | 新增处理 HTTP 请求和数据解析的核心依赖,配置 npm run build 和 npm run test 等关键工程化脚本。 |
3.3 系统模块架构图
图 3-2:Sprint 3 组件架构与数据流
- 控制器层:
toolsController接收工具调用请求,分发给对应的服务;resourcesController处理资源读取请求(可复用原有逻辑,仅需扩展协议类型)。 - 服务层:
literatureService:调用apiClients并发请求 arXiv 和 Semantic Scholar,对返回结果进行字段映射、去重、排序,输出标准化的文献 JSON 数组。storageService:接收文献 JSON 和可选标签,调用yamlHelper生成 YAML Frontmatter,组合 Markdown 正文(默认为文献摘要),写入文件,返回文件绝对路径。resourceService:扩展现有功能,支持读取literature://协议下的 Markdown 文件(实际仍从同一知识库目录读取)。
- 工具层:
apiClients封装 HTTP 客户端,处理速率限制和错误重试;yamlHelper负责将 JSON 字段转换为符合 YAML 规范的字符串。 - 模型层:
literatureSchema.js定义文献的标准结构,schemas.js集成新工具的 Zod 校验。
4. MCP 标准通信接口设计 (Tools)
4.1 意图 1:学术文献查询 (search_arxiv)
- 描述:通过核心关键字检索 arXiv 学术库。
- 输入 Schema:
{ query: z.string() } - 容错与输出:在 Service 层自动过滤无效结果,将复杂的 XML 解析为带有 Markdown 排版的纯文本列表(标题、链接、摘要),防止大模型处理复杂结构时产生幻觉。
4.2 意图 2:框架模板获取 (fetch_framework_template)
- 描述:供大模型内部读取 SWOT、SCQA 等分析模板。不对外暴露 UI。
- 输入 Schema:
{ framework_name: z.string() } - 核心逻辑:
- 读取本地静态 JSON 配置。
- 剥离外壳:提取出纯文本的
system和userprompt,丢弃 JSON 结构。 - 强制刹车:在返回的开头拼接
【🛑立即停止调用任何工具,请直接在聊天框输出...】,阻断大模型的“工具调用死循环”。
4.3 意图 3:内容落盘保存 (save_note)
- 描述:将大模型生成的长文本或检索结果保存到本地 Obsidian 知识库。
- 输入 Schema:
{ filename: z.string(), content: z.any() } - 核心逻辑:大模型极易在长文本转义时出错。系统允许传入
z.any()(即接收 JSON Object),若发现传入的是对象而非字符串,toolsController会自动在底层执行JSON.stringify(content, null, 2)进行兜底序列化。
4.4 意图 4:本地笔记分析 (list_local_notes & read_local_note)
- 描述:继承 Sprint 2 的能力,大模型可主动列出本地笔记清单,并根据需要读取单篇或多篇笔记的内容以进行综合总结。
5. 安全、边界与质量保障
5.1 防越权落盘 (Authorization Boundary)
在系统级提示词(System Prompt)中设置了**“绝对红线”**:严禁大模型在没有主动询问并获得用户明确同意(如回复“保存”或“是”)的情况下,私自调用 save_note 工具。写盘动作必须由用户自然语言最终确认。
5.2 强类型收敛与 TS 错误阻断
针对 MCP SDK 要求 content 数组内的 type 必须为严格字面量 "text" 的限制,在 app.ts 中通过 type: "text" as const 进行显式断言,消除了编译期的类型推断模糊问题。
5.3 自动化测试覆盖
Sprint 3 引入了基于 Jest 的自动化测试套件:
arxivService.test.ts:通过 Mockglobal.fetch,测试 XML 解析的健壮性和网络异常处理。toolsController.test.ts:深度覆盖工具的路由分发、save_note的 JSON 畸形对象兜底序列化逻辑,以及fetch_framework_template是否成功注入了防死循环的“刹车指令”。
6. 总结
Sprint 3 在 Sprint 2 的本地知识管理基础上,通过新增文献检索与标准化存储模块,显著增强了系统的外部知识获取能力。我们通过将“决策权上交给大模型(意图识别)”与“容错权下放给底层代码(参数宽容与刹车指令)”相结合,解决了大语言模型在多工具、长文本复杂场景下的状态机崩溃难题,为后续更复杂的学术分析(Sprint 4 & 5)奠定了基础。
许可声明
本文档采用 知识共享署名--相同方式共享 4.0 国际许可协议 (CC BY--SA 4.0) 进行许可,© 2025-2026 Gitconomy Research.