- 新增 providers/models 数据库表、迁移和数据访问层 - 新增 15 个后端 API 路由(供应商/模型 CRUD + 连通性测试) - 新增 AI 服务层(registry.ts: buildProviderRegistry + testProviderConnection) - 新增前端模型管理页面(Tabs: 供应商/模型,含表格、表单、工具栏) - 新增前端 hooks(use-providers, use-models) - 新增共享类型和 MODEL_CAPABILITIES 常量 - 新增 10 个测试文件(66 个测试用例,4 个因 bun test ESM 兼容问题待修复) - 更新开发文档(architecture, backend, frontend) - 附带 apply-review 修复:统一错误响应、提取共享常量、清理重复测试 注意:registry.test.ts 中 4 个测试因 bun test 无法解析 createProviderRegistry ESM 导出而失败,详情见 context.md
14 KiB
背景
Alfred·阿福定位为"基于 AI 的信息综合处理平台",但当前项目(v0.1.0)没有任何 AI/LLM 集成。项目已完成基础架构(Bun 全栈、SQLite + Drizzle ORM、React 19 + Ant Design 6 + React Router 7、TanStack React Query),并拥有管理控制台(Dashboard + 项目管理)和工作台控制台。
本次变更在管理控制台中新增"模型管理"功能,让用户能够配置 AI 供应商和模型,为后续所有 AI 功能提供基础设施。这是项目 AI 能力的第一个里程碑。
当前状态:
- 后端:
src/server/使用 Bun.serve(),路由在routes/目录按功能拆分,DB schema 在src/server/db/schema.ts,数据访问层在src/server/db/projects.ts - 前端:
src/web/使用 console 模式,admin 菜单在consoles/admin/menu.tsx,页面在pages/目录 - 零 AI/LLM 相关代码
讨论记录
- 已确认结论:
- 使用 Vercel AI SDK(
ai+@ai-sdk/openai+@ai-sdk/anthropic+@ai-sdk/openai-compatible)作为统一 AI 调用层 - 三种供应商类型:
openai、anthropic、openai-compatible(覆盖 DeepSeek、Qwen、Ollama 等) - API Key 明文存储于 SQLite,可接受(本地/自部署单用户工具)
- AI 注册表不使用缓存层:每次 AI 调用时从 DB 查询供应商+模型 → 构建
createProviderRegistry→ 调用 AI SDK(开销 ~1ms,远小于网络 I/O) - 功能调用(function calling)视为基础能力,不列入 capability 标签
- 使用 Vercel AI SDK(
- 用户偏好:
- 前端使用 antd
Tabs组件在同一页面内展示供应商和模型两个标签页 - 供应商表单中 type 默认值为
openai-compatible,baseURL 不设默认值 - 连通性测试为可选功能,不阻塞模型创建
- 前端使用 antd
- 约束:
- 严格遵循现有代码模式(路由拆分、数据访问函数、hooks、页面组件结构)
- 不引入新的样式系统
- 被否决方案:
- API Key 加密存储:对本地/自部署单用户场景过度设计
- AI 注册表缓存:增加复杂度但收益极小(~1ms vs 数百毫秒网络 I/O)
- LangChain 等重量级框架:Vercel AI SDK 更轻量且 API 更统一
需求
| 需求 | 验收标准 |
|---|---|
| 供应商 CRUD | 管理员可新增、查看、编辑、删除供应商(名称、类型、baseURL、apiKey) |
| 供应商类型支持 | 支持 openai、anthropic、openai-compatible 三种类型,各自对应 AI SDK 不同 provider 工厂 |
| 模型 CRUD | 管理员可新增、查看、编辑、删除模型(名称、所属供应商、modelId、能力标签、可选参数) |
| 能力标签多选 | 模型表单中可多选能力标签(text / reasoning / image-generation / video-generation / audio-generation / image-recognition / video-recognition / audio-recognition) |
| 连通性测试 | 供应商编辑/创建时可测试 API 连通性,返回成功/失败提示 |
| 模型启用/禁用 | 供应商和模型均可启用/禁用,不影响数据 |
| 管理控制台菜单 | Admin 控制台侧栏新增"模型管理"菜单项 |
| AI 注册表服务 | 后端提供 AI 注册表构建服务,按需从 DB 查询构建,供后续 AI 功能调用 |
| 级联约束 | 删除供应商时,若存在关联模型则阻止删除,用户需先处理关联模型 |
数据模型规格
providers 表
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | TEXT | PK, UUID | 自动生成 |
| name | TEXT | NOT NULL, UNIQUE | 供应商显示名称 |
| type | TEXT | NOT NULL | 枚举:openai | anthropic | openai-compatible,默认 openai-compatible |
| baseUrl | TEXT | NOT NULL | API 基础 URL,不设默认值,由用户填写 |
| apiKey | TEXT | NOT NULL | API 密钥,明文存储,GET 接口完整返回 |
| enabled | INTEGER | NOT NULL, DEFAULT 1 | 1=启用, 0=禁用 |
| createdAt | TEXT | NOT NULL | ISO 8601 时间戳 |
| updatedAt | TEXT | NOT NULL | ISO 8601 时间戳 |
models 表
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | TEXT | PK, UUID | 自动生成 |
| name | TEXT | NOT NULL | 模型显示名称 |
| providerId | TEXT | NOT NULL, FK → providers.id | 所属供应商 |
| modelId | TEXT | NOT NULL | API 调用用的模型标识(如 gpt-4o) |
| capabilities | TEXT | NOT NULL | JSON 数组,能力标签(见下方定义) |
| contextLength | INTEGER | 可选 | 上下文窗口长度 |
| maxOutputTokens | INTEGER | 可选 | 最大输出 token 数 |
| enabled | INTEGER | NOT NULL, DEFAULT 1 | 1=启用, 0=禁用 |
| createdAt | TEXT | NOT NULL | ISO 8601 时间戳 |
| updatedAt | TEXT | NOT NULL | ISO 8601 时间戳 |
唯一约束: (providerId, modelId) 联合唯一——同一供应商下 modelId 不可重复,不同供应商可以有相同 modelId。
能力标签定义(ModelCapability):
"text" | "reasoning" | "image-generation" | "video-generation" | "audio-generation" | "image-recognition" | "video-recognition" | "audio-recognition"
存储为 JSON 数组字符串,如 ["text","reasoning","image-recognition"]。
目标 / 非目标
目标:
- 在管理控制台提供完整的供应商和模型管理界面
- 建立后端 AI 服务层(注册表 + 类型定义),为后续 AI 功能提供可复用基础
- 完成 Vercel AI SDK 集成的依赖安装和基础配置
- 新增 DB migration 支持 providers 和 models 表
非目标:
- 不实现实际的 AI 调用功能(文本生成、图片生成等)——这是后续变更的内容
- 不实现 API Key 加密存储
- 不实现供应商/模型的导入导出功能
- 不实现多用户权限控制
执行约束
- 依赖限制:
- 新增 npm 依赖仅限
ai、@ai-sdk/openai、@ai-sdk/anthropic、@ai-sdk/openai-compatible - 使用
bun add安装,严禁 npm/pnpm - 优先使用项目已有依赖(Drizzle ORM、antd、TanStack React Query 等)
- 新增 npm 依赖仅限
- 约束:
- 后端遵循 Bun 内置 API > es-toolkit > 三方库优先级
- 前端遵循 antd 组件默认能力优先,禁止内联 style、覆盖 antd 内部类名
- Git 提交格式:中文,"类型: 简短描述"
- 质量门禁:
- 新增代码必须编写完善的测试
- 不允许跳过任何测试
- 代码变更需执行文档影响分析
- 相关方:
- 本变更为基础设施层,所有后续 AI 功能变更将依赖本变更的 AI 注册表服务
- 文档 / 沟通:
- 每次代码变更执行文档影响分析:用户可见行为变更 →
docs/user/,开发流程/架构变更 →docs/development/
- 每次代码变更执行文档影响分析:用户可见行为变更 →
- 兼容性 / 连续性:
- 无需考虑向前兼容性
影响范围
| 范围 | Artifacts / 参考资料 | 预期变更 | 备注 |
|---|---|---|---|
| DB Schema | src/server/db/schema.ts |
新增 providers 和 models 表定义 | 遵循现有 projects 表模式 |
| DB Migration | drizzle/ |
新增 migration SQL 文件 | 自动生成 |
| 数据访问层 | src/server/db/projects.ts(参考模式) |
新增 providers.ts 和 models.ts |
CRUD + 启用/禁用 |
| DB 导出 | src/server/db/index.ts |
新增 providers 和 models schema 导出 | 遵循现有导出模式 |
| 共享类型 | src/shared/api.ts |
新增供应商和模型相关类型定义 | 前后端共用 |
| 后端路由 | src/server/routes/ |
新增 providers/ 和 models/ 目录 |
CRUD + 连通性测试 |
| 服务器入口 | src/server/server.ts |
注册新路由 | 懒加载导入 |
| AI 服务层 | src/server/ai/(新建) |
新增 registry.ts 和 types.ts |
AI 注册表构建服务 |
| 前端菜单 | src/web/consoles/admin/menu.tsx |
新增"模型管理"菜单项 | |
| 前端页面 | src/web/pages/models/(新建) |
新增模型管理页面(Tabs + 表格 + 表单) | 遵循 projects 页面模式 |
| 前端组件 | src/web/pages/models/components/(新建) |
ProviderTable、ProviderFormModal、ModelTable、ModelFormModal | |
| 前端路由 | src/web/routes.tsx |
新增 /models 路由 |
|
| 前端 Hooks | src/web/hooks/ |
新增 use-providers.ts、use-models.ts |
TanStack React Query |
| 依赖 | package.json |
新增 ai、@ai-sdk/openai、@ai-sdk/anthropic、@ai-sdk/openai-compatible |
|
| 测试 | tests/ |
新增后端路由、数据访问、前端 hooks 和组件测试 | |
| 文档 | docs/development/backend.md |
更新后端架构说明,补充 AI 服务层 | 开发文档 |
| 文档 | docs/development/frontend.md |
补充模型管理页面组件说明 | 开发文档 |
决策
| 决策 | 理由 | 已否决替代方案 |
|---|---|---|
| 使用 Vercel AI SDK | 轻量、统一 API、支持多供应商、TypeScript 优先、与 Bun 兼容 | LangChain(过重,API 复杂)、自行封装 fetch(维护成本高,无法统一接口) |
| 三种供应商类型 | 覆盖主流场景:OpenAI(Responses API + Chat Completions API)、Anthropic、OpenAI 兼容协议(DeepSeek/Qwen/Ollama 等) | 仅区分"OpenAI 协议"和"其他"(丢失 Anthropic 特有能力) |
| API Key 明文存储 | 本地/自部署单用户场景,加密增加复杂度但安全性提升有限 | 加密存储(过度设计) |
| AI 注册表不缓存 | DB 查询 + 注册表构建开销 ~1ms,远小于网络 I/O;无缓存则无需处理失效/一致性问题 | 内存缓存(增加复杂度,收益极小) |
| capability 标签用 JSON 数组 | 灵活可扩展,SQLite 中 TEXT 字段存储 JSON 数组 | 关联表(过度设计,标签数量有限且固定) |
| 连通性测试不阻塞操作 | 测试是辅助功能,网络波动不应阻止用户保存配置 | 强制测试通过才能保存(用户体验差) |
| 删除供应商时阻止而非级联删除 | 防止误删导致模型数据丢失,用户需先处理关联模型 | CASCADE 删除(数据安全风险) |
| GET 接口完整返回 apiKey | 本地/自部署单用户场景,前端使用 antd Password 组件隐藏显示,无需脱敏 | apiKey 脱敏返回(增加复杂度,编辑时需额外处理) |
| providerId + modelId 联合唯一 | 同一供应商下 modelId 不可重复,不同供应商可有相同 modelId;符合 AI SDK 注册表 key 格式 providerId:modelId |
modelId 全局唯一(限制过严)、无约束(可能导致注册表冲突) |
| 连通性测试使用 generateText 最小请求 | 调用 generateText({ model, prompt: 'hi' }) 验证连通性和 apiKey 有效性,简单直接 |
仅验证 HTTP 连接(不验证 apiKey)、listModels(并非所有供应商支持) |
| 启用/禁用使用 enable/disable 双端点 | 语义明确,与 archive/restore 模式一致;供应商/模型的启用禁用是布尔切换,双端点更清晰 | toggle 单端点(语义含糊,前端需知道当前状态才能确定操作) |
| 供应商 type 默认 openai-compatible | 覆盖最广(DeepSeek/Qwen/Ollama 等),用户只需填写 baseURL 和 apiKey 即可使用 | 默认 openai(限制性强,不适合自部署场景) |
| baseURL 不设默认值 | 不同部署环境的 baseURL 差异大,自动填充可能误导用户填错地址 | 设默认值(看似方便,但可能掩盖配置错误) |
执行计划
阶段 1:基础层(DB + 类型 + 依赖)
- 安装 Vercel AI SDK 相关依赖
- 在
src/server/db/schema.ts新增 providers 和 models 表定义 - 生成 DB migration
- 在
src/shared/api.ts新增供应商和模型相关类型定义 - 在
src/server/ai/types.ts新增 AI 相关类型定义(ModelCapability 等)
阶段 2:后端(数据访问 + 路由 + AI 服务)
6. 新增 src/server/db/providers.ts 数据访问函数
7. 新增 src/server/db/models.ts 数据访问函数
8. 新增 src/server/routes/providers/ 目录下的 CRUD 路由处理器(含 enable/disable 双端点)
9. 新增 src/server/routes/models/ 目录下的 CRUD 路由处理器(含 enable/disable 双端点)
10. 新增 src/server/routes/providers/test.ts 连通性测试路由
11. 在 src/server/server.ts 注册所有新路由
12. 新增 src/server/ai/registry.ts,包含 buildProviderRegistry(db)(从 DB 查询启用的供应商构建 AI SDK Provider Registry)和 testProviderConnection(config)(使用 generateText 测试连通性)
阶段 3:前端(页面 + 组件 + Hooks)
13. 新增 src/web/hooks/use-providers.ts 和 src/web/hooks/use-models.ts
14. 在 src/web/consoles/admin/menu.tsx 新增"模型管理"菜单项
15. 在 src/web/routes.tsx 新增 /models 路由
16. 新增 src/web/pages/models/index.tsx 页面(Tabs 布局)
17. 新增 src/web/pages/models/components/ProviderTable.tsx
18. 新增 src/web/pages/models/components/ProviderFormModal.tsx
19. 新增 src/web/pages/models/components/ModelTable.tsx
20. 新增 src/web/pages/models/components/ModelFormModal.tsx
阶段 4:测试 21. 后端数据访问层测试(providers.ts、models.ts) 22. 后端路由测试(providers/、models/) 23. AI 注册表测试 24. 前端 hooks 测试 25. 前端组件测试
阶段 5:文档
26. 执行文档影响分析,更新 docs/development/ 相关文档
验证计划
| 需求 / 风险 | 验证方式 |
|---|---|
| 供应商 CRUD API | 后端路由测试覆盖创建、查询、更新、删除、启用/禁用 |
| 模型 CRUD API | 后端路由测试覆盖创建、查询、更新、删除、启用/禁用 |
| 供应商删除约束 | 测试删除有关联模型的供应商时返回错误 |
| 连通性测试 API | 测试 mock 场景下的成功/失败响应 |
| AI 注册表构建 | 测试从 DB 数据正确构建 AI SDK provider 实例 |
| DB Migration | 测试 migration 正确创建表和索引 |
| 前端供应商管理 | 组件测试覆盖表格渲染、表单提交、启用/禁用操作 |
| 前端模型管理 | 组件测试覆盖表格渲染、表单提交、能力标签多选 |
| 前端菜单和路由 | 测试菜单项显示和路由跳转 |
| 文档完整性 | 检查 docs/development/ 和 docs/user/ 是否已更新 |
风险 / 权衡
- [Vercel AI SDK 与 Bun 的兼容性] -> AI SDK 基于 Web 标准 API,Bun 对 Web API 支持良好;安装后需验证 import 正常
- [OpenAI-compatible 供应商行为不一致] -> 注册表构建时使用
createOpenAICompatible标准接口;连通性测试帮助用户提前发现问题 - [API Key 明文存储安全风险] -> 文档中说明安全模型(单用户本地部署);未来可按需增加加密
- [migration 与现有数据兼容性] -> 新增表不影响现有 projects 表;migration 为增量操作
待解决问题
| 状态 | 问题 | 所需决策 |
|---|---|---|
| 无 | 无待解决问题。 | 无需决策 |