☰
Zotero AI管家源码揭秘:LLMService统一中间件与Provider自注册架构详解
2026/10/11 12:03:04 网站建设 项目流程
  • 人工智能
  • 大模型
  • AI 应用
  • 科研

【免费下载链接】zotero-AI-Butler

【Zotero AI 管家】调用大模型,自动精读论文库里的论文,总结为Zotero笔记。支持主流大模型平台!您只需像往常一样把文献丢进 Zotero, 管家会自动帮您精读论文,将文章揉碎了总结为笔记,让您“十分钟完全了解”这篇论文!

项目地址:https://gitcode.com/gh_mirrors/zo/zotero-AI-Butler
点击查看免费下载

Zotero AI 管家(zotero-AI-Butler)是一款调用大模型自动精读 Zotero 论文库的开源插件:把文献丢进 Zotero,它会自动将论文"揉碎"总结成笔记。而它之所以能同时支持 OpenAI、Google Gemini、Anthropic Claude、OpenRouter、火山方舟、Ollama 等主流大模型平台,核心秘密就在两层架构里:LLMService 统一中间件与Provider 自注册机制。本文带你完整读懂这套 LLM 调用架构的设计思路。

先看效果:一套插件,多家大模型

你在插件里看到的 AI 总结、思维导图、文献综述、侧边栏追问、一图总结等功能,背后走的都是同一条 LLM 调用链路。理解这条链路,是理解本项目源码的最佳入口。官方在 doc/LLMRefactorDesign.md 中给出的架构总览是这样的:

业务功能层 noteGenerator / mindmapService / literatureReviewService / SummaryView ▼ LLMService(统一中间件) 读取偏好与 API Key → 准备 text / pdf-base64 / multi-pdf 组装 LLMOptions → 重试与密钥轮换 → 返回统一 LLMResponse ▼ ProviderRegistry(自注册注册表) ▼ llmproviders/* 各供应商 Provider

分层的关键收益:业务功能只描述"任务 + 提示词 + 内容来源",不再关心 PDF 怎么送、SSE 怎么解析、哪个平台用什么参数——这些差异全部被中间件和 Provider 各自消化。

第一层:LLMService 统一中间件

核心实现位于 src/modules/llmService.ts,它对外只暴露一组静态方法(generate、chat、chatWithEndpoint、testConnection、listModels等),是新业务代码的标准入口。

1. 统一请求:LLMGenerateRequest

一次调用被抽象为"任务 + 内容 + 选项"三要素,典型用法见 doc/LLMRefactorDesign.md:

await LLMService.generate({ task: "table", prompt, content: { kind: "pdf-attachment", item, attachment }, });

其中content支持多种"内容来源",这是中间件最能体现价值的设计:

kind含义
text调用方已准备好的文本
zotero-item由中间件从 Zotero 条目自动读取 PDF 或附件
pdf-attachment只分析指定的 PDF 附件
pdf-files多 PDF 输入,支持多文件上传或降级为文本
legacy兼容旧LLMClient的桥接层

2. 输入策略:按能力选择 PDF / Base64 / 文本

不同平台对 PDF 的支持差异很大(有的原生吃 PDF Base64,有的只能传纯文本)。中间件通过LLMContentPolicy(auto/text/pdf-base64/mineru)统一决策,见 src/modules/llmService.ts#L1131-L1150:它综合全局偏好、端点级覆盖(LLMEndpoint.pdfProcessMode)和 Provider 声明的capabilities来决定最终输入形态,而不是让业务代码去判断"这是 Gemini 还是 OpenAI"。多 PDF 场景也在这里兜底:只有当maxPdfFiles > 1且 Provider 实现了generateMultiFileSummary时才真正上传多文件,否则自动降级。

3. 端点路由、重试与密钥轮换

多端点管理由 src/modules/llmEndpointManager.ts 负责,它维护每个端点的providerType / apiUrl / apiKey / model,并支持两种路由策略(见 doc/LLMRefactorDesign.md#L198-L202):

  • 优先级(priority):按设置页排序依次尝试,失败切下一个,到尾后回绕;
  • 轮询(roundRobin):游标llmRoundRobinCursor每完成一次真实请求就推进到下一个端点。

LLMService.runGenerateWithEndpointRouting()(src/modules/llmService.ts#L576-L609)实现了核心重试循环:在maxApiSwitchCount(默认 3)次尝试内按路由顺序逐端点调用,全部失败才抛出LLMApiExhaustedError;同时支持旧版多 API Key 轮换。所有阶段进度(准备 → 上传 → 等待 → 流式输出)都通过onStatus回调透出,驱动你在 Zotero 里看到的任务进度条。

4. 兼容壳:旧 LLMClient 平滑过渡

src/modules/llmClient.ts 保留了旧方法签名,但内部已全部委托给 LLMService——这是一个教科书式的"门面兼容层"做法,让上层模块可以渐进迁移,而不会绕过中间件。

第二层:Provider 自注册架构

如果说 LLMService 是"总管",那么 Provider 就是各家大模型的"专业代理"。这一层的设计非常克制、干净。

1. 一个极小的注册表

src/modules/llmproviders/ProviderRegistry.ts 全部实现只有十几行:一个静态Map,加上register/get/list三个方法。它不 import 任何具体 Provider,完全不感知有哪些供应商存在。

2. 统一契约:ILlmProvider

所有 Provider 必须实现 src/modules/llmproviders/ILlmProvider.ts 接口:

  • 必选:generateSummary(生成总结)、chat(多轮对话)、testConnection(连接测试);
  • 可选:listModels(拉取模型列表)、generateMultiFileSummary(多 PDF 处理);
  • 必声明:capabilities能力描述,如 GeminiProvider.ts#L40-L49 中声明supportsPdfBase64: true, maxPdfFiles: 20。

Provider 内部只处理供应商协议差异:HTTP payload 结构、SSE 流式事件解析、非流式响应结构、错误响应格式。中间件根据capabilities决定是否启用多文件上传等功能,实现了"能力驱动"而非"名称驱动"。

3. 自注册:文件末尾一行代码

每个 Provider 文件末尾都有一行自注册代码,例如 OpenAIProvider.ts#L1439:

ProviderRegistry.register(new OpenAIProvider());

而 src/modules/llmproviders/index.ts 只做了两件事:导出类型和接口,以及导入所有 Provider 模块触发副作用注册(注释里写得很直白:"Ensure providers are loaded and self-registered")。llmService.ts只需import "./llmproviders"一行,整个注册表就自动就位。

这种"注册逻辑写在模块自身"的插件式架构,好处一目了然:

  1. 开闭原则:新增供应商时,中间件和注册表零改动;
  2. 解耦:ProviderRegistry不反向依赖任何具体 Provider,避免循环引用;
  3. 可发现:ProviderRegistry.list()可直接用于报错提示与设置页。

如果要新增一个大模型平台

doc/LLMRefactorDesign.md#L152-L161 给出了清晰的 8 步清单,其中前 4 步就是自注册架构的完整体现:

  1. 新建src/modules/llmproviders/{Vendor}Provider.ts;
  2. 实现ILlmProvider并声明capabilities;
  3. 文件底部调用ProviderRegistry.register(new VendorProvider())自注册;
  4. 在llmproviders/index.ts中导出该 Provider;
  5. 之后才是密钥映射(ApiKeyManager)、prefs.js默认值、设置页 UI 和LLMService.buildOptions()中的端点映射。

可以看到,架构层面(注册、调度、重试、内容策略)完全不需要动,改动被严格限制在"供应商协议适配 + 配置项"范围内——这正是中间件 + 自注册架构想达到的效果。

小结

Zotero AI 管家的 LLM 调用架构可以归纳为一句话:

业务层只描述任务,LLMService 统一处理路由/重试/输入形态,Provider 通过自注册声明能力并适配各自协议。

  • 中间件收敛了 PDF Base64 / 文本提取 / 多文件上传、多端点优先级与轮询、API Key 轮换等所有横切关注点(src/modules/llmService.ts);
  • ILlmProvider+capabilities让能力协商代替了脆弱的平台名称判断(src/modules/llmproviders/ILlmProvider.ts);
  • ProviderRegistry用十几行代码实现了可扩展的插件注册表(src/modules/llmproviders/ProviderRegistry.ts)。

这套"统一中间件 + Provider 自注册"的模式,对任何需要对接多家 AI 平台的插件、小程序或后端服务,都非常值得借鉴。如果你想亲手上手,可以 clone 仓库git clone https://gitcode.com/gh_mirrors/zo/zotero-AI-Butler,从llmproviders/index.ts读起,一路追到各 Provider 的实现,半小时即可摸清全貌。

  • 人工智能
  • 大模型
  • AI 应用
  • 科研

【免费下载链接】zotero-AI-Butler

【Zotero AI 管家】调用大模型,自动精读论文库里的论文,总结为Zotero笔记。支持主流大模型平台!您只需像往常一样把文献丢进 Zotero, 管家会自动帮您精读论文,将文章揉碎了总结为笔记,让您“十分钟完全了解”这篇论文!

项目地址:https://gitcode.com/gh_mirrors/zo/zotero-AI-Butler
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询