- 人工智能
- 大模型
- AI 应用
- 科研
【免费下载链接】zotero-AI-Butler
【Zotero AI 管家】调用大模型,自动精读论文库里的论文,总结为Zotero笔记。支持主流大模型平台!您只需像往常一样把文献丢进 Zotero, 管家会自动帮您精读论文,将文章揉碎了总结为笔记,让您“十分钟完全了解”这篇论文!
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"一行,整个注册表就自动就位。
这种"注册逻辑写在模块自身"的插件式架构,好处一目了然:
- 开闭原则:新增供应商时,中间件和注册表零改动;
- 解耦:
ProviderRegistry不反向依赖任何具体 Provider,避免循环引用; - 可发现:
ProviderRegistry.list()可直接用于报错提示与设置页。
如果要新增一个大模型平台
doc/LLMRefactorDesign.md#L152-L161 给出了清晰的 8 步清单,其中前 4 步就是自注册架构的完整体现:
- 新建
src/modules/llmproviders/{Vendor}Provider.ts; - 实现
ILlmProvider并声明capabilities; - 文件底部调用
ProviderRegistry.register(new VendorProvider())自注册; - 在
llmproviders/index.ts中导出该 Provider; - 之后才是密钥映射(
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, 管家会自动帮您精读论文,将文章揉碎了总结为笔记,让您“十分钟完全了解”这篇论文!
相关推荐
LPE Workshop工具集解析:Windows权限提升必备工具
LPE Workshop工具集解析:Windows权限提升必备工具 LPE Workshop(Local Privilege Escalation Worksh
NocoBase DataSourceManager 数据源管理器 API 详解:多数据源架构、中间件与类型注册
NocoBase DataSourceManager 数据源管理器 API 详解:多数据源架构、中间件与类型注册 DataSourceManager 是 Noc
低代码后端前端人工智能AI 应用工作流自动化MindIE/FramePack社区贡献指南:如何参与项目开发与优化
MindIE/FramePack社区贡献指南:如何参与项目开发与优化 欢迎来到FramePack开源社区!🎉 作为一款基于昇腾NPU的高性能AI视频生成工具,
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考