自托管 AFFiNE 配 AI:三个坑和一份能用的配置

我把 AFFiNE 的 AI 功能搞通了。搞通之前走了不少弯路,记录一下,下次遇到类似问题可以直接照做。

背景

AFFiNE 自托管之后,AI 功能默认是关闭的 —— 不是「功能没开发完」,而是它需要你自己配 API key。官方的文档有写,但有些细节文档没说清楚,或者说清楚了但藏在 GitHub issue 里。

我的 AFFiNE 部署在飞牛 NAS 上,Docker Compose 管理,版本 v0.26.7。AI 那栏一直灰着,报错变了好几次。

完整配置步骤

第一步:环境变量

Docker Compose 里加一行:

environment:
- selfhosted=true

这一行决定了 AFFiNE 用自托管模式的 AI 逻辑。不加的话就算你配了 key 也报 NO_COPILOT_PROVIDER_AVAILABLE

我的 .env 里已经有了,这个不用动。

第二步:Admin 面板配 Provider

访问 https://你的域名/admin,用管理员账号登录(Admin 账号跟普通 AFFiNE 账号是分开的,Docker 部署时第一个注册的就是 Admin)。

Settings → AI → 展开。

OpenAI Provider

如果你用的是 OpenAI 官方 API:

{"apiKey": "sk-xxx"}

如果你用的是中转站(比如我用的 xuedingmao):

{"apiKey": "sk-xxx", "baseURL": "https://你的中转站/v1", "oldApiStyle": true}

oldApiStyle: true,别忘了加。AFFiNE v0.25+ 默认走 OpenAI 的 Responses API,中转站只认 /v1/chat/completions。不加就报 Not Found

Gemini Provider

同样要配。AFFiNE 有些功能硬编码绑定了 Gemini—— 即使你在 scenarios 里把所有模型都指向 OpenAI,它还是会去调 Gemini。

如果只用官方 Gemini API:

{"apiKey": "你的Gemini key"}

如果走中转站(中转站支持 Gemini 模型的话):

{"apiKey": "你的中转站key", "baseURL": "https://你的中转站/v1", "oldApiStyle": true}

Scenarios(模型映射)

打开 “Use custom models” 开关,配好每个场景用的模型。我的配置:

{
"chat": "gpt-5.3-chat-latest",
"image": "gpt-image-2",
"coding": "gpt-5.3-codex",
"rerank": "gpt-4.1",
"embedding": "text-embedding-3-small",
"audio_transcribing": "whisper-1",
"polish_and_summarize": "gpt-5.5",
"quick_decision_making": "gpt-5.4-mini",
"quick_text_generation": "gpt-5.4-mini",
"complex_text_generation": "gpt-5.5"
}

你的模型名取决于你的中转站 / 官方 API 支持哪些。建议先去中转站的 /v1/models 接口确认。

第三步:用户授权

Accounts → 找到你的用户 → Open menu → Edit → 打开两个开关:

  • UnlimitedCopilot:解除 10 次试用限制
  • AIEarlyAccess:开启 AI 功能入口

不打开的话,你会发现 AI 能用但用几次就弹「已到达使用上限」。

第四步:重启

改完 Admin 面板的配置后,必须重启 AFFiNE 容器。在 Docker 里 restart 一下 affine 服务就行。

不重启的话 —— 我试过 —— 配置保存了但 AI 还是报错。

踩过的坑

坑 1:NO_COPILOT_PROVIDER_AVAILABLE

报错信息:

Internal Server Error: No copilot provider available: gemini-2.5-flash
Identify: NO_COPILOT_PROVIDER_AVAILABLE

根因:只配了 OpenAI provider,没配 Gemini provider。AFFiNE 某些 AI 功能(比如 AI 菜单里的特定操作)是硬编码绑 Gemini 的,scenarios 覆盖不了。

修法:把 Gemini provider 也配上。

在 GitHub issue #14295 #13775 里都有类似的报告。

坑 2:COPILOT_PROVIDER_SIDE_ERROR / Too Many Requests

报错信息:

Internal Server Error: Provider gemini failed with AI_RetryError error:
Failed after 3 attempts. Last error: Too Many Requests
Identify: COPILOT_PROVIDER_SIDE_ERROR

根因:其实能报这个错,已经是好消息了 —— 说明 Gemini provider 配对了、key 也验过了。只是 API 返回了限流。

如果你走的是中转站,可能是因为短期大量测试触发了限流。等几分钟就好。

GitHub issue #13775 里也记录了这个错误模式,不过那个 issue 的根因是 AFFiNE 服务端 bug(v0.25.0 的 transcription 问题),v0.25.4 已修。

坑 3:中转站配 Gemini 不加 baseURL

Admin 面板里 Gemini provider 的默认占位符只有 {"apiKey":""},没有 baseURL 字段。如果你用的是中转站,光填 key 不够 ——AFFiNE 会去调 Google 的 API,而不是你的中转站。

修法:手动加上 baseURLoldApiStyle,格式跟 OpenAI provider 一样。

这个在 GitHub issue #13600 里有类似的讨论(OpenAI 中转站 + baseURL 的问题)。

坑 4:改了配置没重启

Admin 面板里 Save 成功了,回到 AFFiNE 主界面 ——AI 还是报旧错误。

根因:AFFiNE 的 AI 配置在服务端是热加载的,但不是所有模块都热加载。有些配置需要容器重启才生效。

修法:改完配置就 restart 容器。一步到位,省得怀疑自己配错了。

验证清单

配置完成后,逐项确认:

  • Docker Compose 里有 selfhosted=true
  • Admin 面板 → AI → “Use custom models” 开关已打开
  • OpenAI provider:apiKey + baseURL + oldApiStyle
  • Gemini provider:apiKey + baseURL + oldApiStyle
  • Scenarios 模型映射已填,模型名在中转站 / 官方 API 真实存在
  • Accounts → 自己的用户 → UnlimitedCopilot + AIEarlyAccess 已开
  • AFFiNE 容器已重启
  • 打开一个文档,AI 助手能正常对话

如果还报 NO_COPILOT_PROVIDER_AVAILABLE,检查哪个 provider 没配。如果报 COPILOT_PROVIDER_SIDE_ERROR,检查中转站限流和 oldApiStyle

后记

自托管 AFFiNE 的 AI 配置,本质是把云服务的 AI 逻辑「嫁接」到自己的 API key 上。官方在逐步解耦 ——v0.25 加了 oldApiStyle、v0.26 完善了 Admin 面板 —— 但还没做到「开箱即用」。

一句话:provider 全配上,中转站别忘了 oldApiStyle,改完重启。