215 lines
16 KiB
Markdown
215 lines
16 KiB
Markdown
<!--
|
||
---
|
||
title: Arabica Sprint3 系统架构设计说明
|
||
description: Project Caffeine 文献查询功能系统架构设设计,聚焦外围学术检索与双轨制数据落盘模块的实现。
|
||
type: Architecture Design
|
||
version: v1.0.0 (Arabica) - Sprint 3
|
||
file: arabica-sprint3-architecture-specification.md
|
||
author: Gitconomy Research-郭晧
|
||
date: 2026-03-11
|
||
tags:
|
||
- Project Caffeine
|
||
- MCP Server
|
||
- Sprint 3
|
||
- Literature Search
|
||
- PKM
|
||
- Node.js
|
||
license: CC BY-SA 4.0
|
||
status: Active
|
||
---
|
||
-->
|
||
# 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):
|
||
|
||
```mermaid
|
||
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 架构下,如何通过“意图识别 + 底层容错”处理一次包含多个动作的复杂用户指令。具体步骤解析如下:
|
||
|
||
1. **多重意图触发**:用户在客户端输入包含复合诉求的自然语言指令(例如:“*用 SWOT 框架分析一下量子计算,并查查最新文献*”)。
|
||
2. **意图 1(学术检索)执行**:大模型首先解析出“查找文献”的意图,自主生成检索词并调用 `search_arxiv` 工具。`toolsController` 充当路由网关,将请求分发给 arXiv 服务,拉取真实的学术数据,并将晦涩的 XML 格式化为清晰的 Markdown 列表返回给大模型。
|
||
3. **意图 2(框架读取与防呆拦截)执行**:大模型紧接着解析出“SWOT 分析”意图,调用后台私有工具 `fetch_framework_template`。此时,`toolsController` 读取本地 JSON 配置,**主动剥离 JSON 外壳**,提取出纯文本 Prompt,并在头部强行拼接**“🛑立即停止调用任何工具”**的最高优先级刹车指令。
|
||
4. **大模型思考与安全输出**:大模型接收到“刹车指令”后,其工具调用的“冲动”被成功阻断(避免了因反复读取 JSON 导致的无限死循环幻觉)。大模型转为文本生成模式,直接在聊天框为用户输出详尽的分析报告。报告输出完毕后,大模型严格遵从系统纪律,主动向用户发起确认:“*是否需要保存?*”
|
||
5. **意图 3(授权落盘与容错兜底)执行**:用户回复确认(如:“*是的,保存下来*”)。大模型获取授权,识别出保存意图,调用 `save_note` 工具并将上万字的分析报告作为参数传入。即使大模型在传参时发生了引号转义错误或误传了 JSON 对象,`toolsController` 底层的 **z.any() 容错与自动序列化机制** 也会完美兜底,确保长文本安全无损地写入本地 Obsidian 知识库。
|
||
6. **链路闭环**:本地文件写入成功,系统通过大模型向用户反馈最终的成功状态,本次复杂交互圆满结束。
|
||
|
||
---
|
||
|
||
## 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() }`
|
||
* **核心逻辑**:
|
||
1. 读取本地静态 JSON 配置。
|
||
2. **剥离外壳**:提取出纯文本的 `system` 和 `user` prompt,丢弃 JSON 结构。
|
||
3. **强制刹车**:在返回的开头拼接 `【🛑立即停止调用任何工具,请直接在聊天框输出...】`,阻断大模型的“工具调用死循环”。
|
||
|
||
### 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`:通过 Mock `global.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.
|