配置说明
模型与服务商(openmaic.yml 和模型设置)、访问控制、功能开关及其他服务端选项。
OpenMAIC 有三个配置来源,各自只负责一件事:
| 来源 | 由谁编写 | 内容 | 何时生效 |
|---|---|---|---|
openmaic.yml | 运维人员 | 服务商、服务端默认分配、锁定的槽位,以及用户能否添加自己的 Key | 启动时(修改后需重启) |
| Web 端的模型设置 | 工作区的用户 | 用户自己的服务商,以及 openmaic.yml 未锁定槽位的分配,保存在数据库中 | 立即生效 |
环境变量(.env.local、容器 Secret) | 运维人员 | openmaic.yml 引用的密钥,以及其他所有服务端选项 | 启动时 |
DATABASE_URL is required; other environment variables are optional (see Deployment). Providers that use server credentials for model selection also need authorized model lists, as described below. See .env.example for environment variables, openmaic.example.yml for a sample model configuration, and Supported models for preset and model IDs.
早期版本只能通过服务商环境变量、server-providers.yml、DEFAULT_MODEL 和 MODEL_ROUTES 配置模型。除 MODEL_ROUTES 外,这些方式目前仍然可用,但已弃用,见从旧配置迁移。
模型与服务商
基本概念
- 服务商(provider):服务端可以调用的一个账号,例如一个 OpenAI key、一个 MiniMax Token Plan 或一个自托管的 OpenAI 兼容服务。每个服务商有一个你自己起的 ID,以及一个预设(preset),说明它是哪家厂商、覆盖哪些能力。
- 槽位(slot):产品里用到 AI 的一处地方,例如课程大纲、幻灯片内容、语音合成或联网搜索。每种能力的槽位构成一棵树;没有分配的槽位沿用父槽位。
- 分配(assignment):槽位使用哪个服务商的哪个模型(
provider:model),可以附带调用参数和回退模型;也可以写null关闭该槽位。
一项能力是否可用,只取决于它的槽位能否解析到一个分配,没有单独的开关。
openmaic.yml
服务端从启动目录(仓库根目录;Docker 镜像中为 /app)读取 openmaic.yml。设置 OPENMAIC_CONFIG 可以改用其他路径;相对路径同样相对于启动目录解析,且此时文件必须存在。没有该文件时,服务端使用 Web 端的设置,以及仍在设置中的旧版变量。
该文件只在启动时读取一次,修改后需要重启服务。服务启动前会完整校验文件:未设置的 ${VAR}、未知的预设或槽位、引用了未声明的服务商,或服务商不提供槽位所需的能力,都会让服务拒绝启动,并逐条列出问题所在的位置:
[boot] Invalid server configuration; the server will not start: Invalid model configuration in /app/openmaic.yml:
- providers.openai.apiKey: environment variable OPENAI_API_KEY is not set
- slots.course.outlines: unknown slot不要把密钥直接写进文件:用 ${VAR} 引用,并在环境变量中设置。来自环境变量的值不会出现在这些错误信息里。
完整示例
providers:
# <服务商 ID>:小写字母、数字和连字符
openai:
preset: openai
apiKey: ${OPENAI_API_KEY} # 启动时从环境变量读取
anthropic:
preset: anthropic
apiKey: ${ANTHROPIC_API_KEY}
openai-image: # 同一个 key,用于图像生成
preset: openai-image
apiKey: ${OPENAI_API_KEY}
minimax: # Token Plan:对话、图像、视频、TTS、搜索
preset: minimax
apiKey: ${MINIMAX_API_KEY}
tavily:
preset: tavily
apiKey: ${TAVILY_API_KEY}
local: # 任意 OpenAI 兼容服务
preset: openai-compatible
baseUrl: http://ollama:11434/v1
models: [qwen3:8b]
slots:
llm: openai:gpt-5.5 # 下面所有对话槽位的默认值
course.outline:
model: anthropic:claude-sonnet-4-6
fallback: openai:gpt-5.4-mini # 遇到可重试的失败时换用一次
course.content.slide:
model: minimax:MiniMax-M3
thinking: { enabled: false }
fallback: minimax:MiniMax-M2.7
classroom: local:qwen3:8b # 模型 ID 里可以有冒号
agent:
model: openai:gpt-5.5 # 需要支持工具调用
api: openai-completions
tts: minimax:speech-2.8-turbo
image: openai-image:gpt-image-2
webSearch: tavily # 只写服务商:使用它的默认模型
video: null # 默认关闭;用户可以自行开启
lock: [tts] # 对所有人固定,连同其子树
allowUserKeys: false # 用户只能在这些服务商中选择,不能自行添加使用这份文件时,slots 下写出的槽位是服务端默认值:用户可以在模型设置中逐一修改,只有被 lock 固定的 tts 对所有人不可更改。文件没写的对话槽位(例如 course.agents)沿用父槽位(llm);没写的能力根槽位(例如 asr 或 document)在用户分配之前保持未配置。设置 allowUserKeys: false 后,用户只能在这里声明的服务商中选择。
服务商
providers 下的每一项声明一个服务商。键名就是它的 ID,供槽位引用:1 到 63 个小写字母、数字和连字符,以字母或数字开头。
| 字段 | 是否必填 | 含义 |
|---|---|---|
preset | 是 | 使用哪个内置预设,见支持的模型 → 预设。 |
apiKey | 通常需要 | API key。不需要 key 的服务(本地服务、Brave、SearXNG、unpdf)可以省略。 |
baseUrl | 部分预设需要 | 替代预设自带端点的地址。openai-compatible、azure、searxng 和 mineru 必填。 |
models | For server-managed credentials | Authorized model ids. Deployment slot defaults/fallbacks for the capability are also authorized; catalogues and workspace assignments do not grant additional models. |
proxy | 否 | 该服务商请求使用的 HTTP 代理地址。 |
credentials | 部分预设需要 | 不使用单个 key 的服务所需的密钥对。AliDocMind 使用 accessKeyId 和 accessKeySecret。 |
options | 否 | 非机密的、服务商特有的设置,例如 voxcpm-tts 的 backend。名称由字母、数字、_ 和 - 组成;值为字符串、数字或布尔值(不能嵌套映射或列表),可以使用 ${VAR}。模型设置会显示 options,因此绝不要在其中放 key。仅限部署:模型设置无法设置它们。 |
voices | 否 | 仅用于 TTS 预设。用非空列表替换内置音色目录:每项必填 id、name,可选 language、gender(male、female、neutral);ID 不可重复,也不可包含保留的绑定分隔符 ::。用户音色仍会保留,Qwen 克隆音色继续使用克隆模型。不配置时保留内置目录。 |
options.defaultVoice | 否 | 当前服务商的默认音色 ID,必须是非空白字符串。配置此项时必须同时提供包含该 ID 的非空 voices 列表。仅配置 voices 时使用第一项;有效的显式选择优先。两个覆盖项均未配置时保持原默认逻辑。 |
大多数预设只覆盖一种能力,与内置 registry 一一对应:openai 预设只有对话,OpenAI 的图像、语音合成和语音识别分别是 openai-image、openai-tts 和 openai-whisper 预设。每种能力声明一个服务商;同一个 key 覆盖多种能力时,引用同一个 ${VAR} 即可。Token Plan 预设(minimax、tokendance、volcengine-ark、kimi-coding-plan)用一个 key 覆盖多种能力,每种能力使用该套餐自己的端点。服务商上的 baseUrl 会替换它覆盖的所有能力的端点,因此只有当 Token Plan 的全部能力都一起迁移时,才给它设置 baseUrl。
Amazon Bedrock(preset: bedrock)使用服务端的 AWS 凭证链(环境变量、profile 或 role)签名请求,区域取自 BEDROCK_REGION、AWS_REGION 或 AWS_DEFAULT_REGION;apiKey 是可选的 bearer token。
槽位
| 槽位 | 能力 | 父槽位 | 作用 |
|---|---|---|---|
llm | chat | — | 默认对话模型:下面任何槽位都不覆盖的对话调用 |
course.research | chat | llm | 课程调研时改写联网搜索查询 |
course.outline | chat | llm | 场景大纲 |
course.agents | chat | llm | 老师和同学智能体的人设 |
course.content | chat | llm | 场景内容(没有专属槽位的场景类型) |
course.content.slide | chat | course.content | 幻灯片场景 |
course.content.quiz | chat | course.content | 测验场景 |
course.content.interactive | chat | course.content | 互动场景 |
course.content.pbl | chat | course.content | 项目式学习(PBL)场景 |
course.actions | chat | llm | 场景动作(智能体在每个场景里说什么、做什么) |
classroom | chat | llm | 课堂对话、测验评分和 PBL 运行时 |
agent | chat | llm | 工作台智能体。需要工具调用能力。 还支持 api 和 contextWindow |
agent.title | chat | agent | 工作台会话标题。只能在 openmaic.yml 中配置,模型设置里不显示 |
tts | tts | — | 语音合成 |
asr | asr | — | 语音识别(语音输入、音视频转写) |
image | image | — | 图像生成 |
video | video | — | 视频生成 |
webFetch | webFetch | — | 网页内容提取(默认:builtin) |
webSearch | webSearch | — | 联网搜索 |
document | document | — | 文档解析服务(MinerU、MinerU Cloud、AliDocMind)。内置的 PDF 文本提取不需要服务 |
槽位的解析方式:
- 从调用所在的槽位开始,逐级向上直到能力根槽位,遇到的第一个分配生效。因此父槽位的分配就是整棵子树的默认值;修改父槽位,会同时改变所有没有自己分配的子槽位。
- 在锁定的子树内(该槽位或其祖先被
lock列出,或使用lock: all),只看openmaic.yml:向上查找到被锁定的槽位为止,文件中写出的第一个分配生效。其他位置以用户的选择为准:先从该槽位向上直到根槽位查找工作区自己的分配,只有完全没有时,才同样从该槽位向上查找openmaic.yml写的默认值。因此,工作区设置了父槽位时,没有被工作区改过的子槽位会跟随它,即使服务端在子槽位上写了默认值;服务端的值只是默认值。 null会停止向上查找:该槽位,以及它下面所有没有自己分配的槽位,都会被关闭。- 一直到根槽位都没有分配时,该能力处于未配置状态。调用会报错并指出槽位名,不会回退到任何厂商。
- 要求(requirement)属于声明它的槽位,按该槽位最终解析到的模型检查,无论是自己分配的还是继承的。
agent要求支持工具调用;如果内置模型目录表明它的模型不支持,智能体会拒绝运行,而不是勉强凑合。目录里没有的模型允许使用。agent.title没有要求,因此可以用更小的模型。
分配
分配有四种写法:
slots:
llm: openai:gpt-5.5 # 服务商:模型
webSearch: tavily # 只写服务商:使用它的默认模型
course.outline: # 带参数的对象
model: openai:gpt-5.5
fallback: anthropic:claude-sonnet-4-6
thinking: { effort: low }
video: null # 关闭对象写法支持以下字段:
| 字段 | 含义 |
|---|---|
model | 必填。服务商:模型;对话以外的槽位也可以只写 服务商。 |
fallback | 换用一次的回退模型,写法同上。仅适用于语言模型槽位,见回退模型。 |
thinking | 对话模型的推理参数:enabled(true/false)、mode(default、disabled、enabled、auto)、effort(none、minimal、low、medium、high、xhigh、max)、level(minimal、low、medium、high)、budgetTokens、excludeReasoningOutput。各服务商适配器只应用其 API 支持的部分。 |
api | 仅 agent:传输协议,openai-completions(默认)或 openai-responses。 |
contextWindow | 仅 agent:压缩上下文时假定的窗口大小,用于比模型目录中的值更小的情况。 |
agent 槽位不能设置 thinking.effort:它的工具调用传输无法同时使用推理强度和函数工具。
只写服务商 ID 的引用
不带 :model 的引用表示该服务商的默认模型:Token Plan 为该能力推荐的模型,否则是内置 registry 的默认模型。搜索和文档服务大多没有可选的模型,所以通常写成 webSearch: tavily 或 document: mineru-cloud。对话槽位必须写明模型,llm: openai 会在启动时被拒绝。
回退模型
回退模型只适用于语言模型槽位,即 llm 及其下的所有槽位。在 tts、asr、image、video、webSearch、webFetch 或 document 槽位上写 fallback 会被拒绝:openmaic.yml 在启动时拒绝,模型设置在保存时拒绝。
当主模型的调用在自身重试之后仍然以可重试的方式失败时,会换用槽位的 fallback 再试一次。可重试的失败包括:SDK 判定的临时错误、超时、网络错误、限流(429)、容量不足(503)或输出为空。服务商明确返回额度用尽时(OpenAI 兼容格式的额度错误码,例如 insufficient_quota,不论 HTTP 状态码),不会在主模型上重试,调用会直接换用回退模型。内容安全拒绝和其他 4xx 错误不会触发回退。回退对普通调用和流式调用都生效,并沿用槽位的 thinking 参数。
回退模型属于分配,随分配一起被继承:没有自己分配的 course.content.slide 会使用 course.content 的模型及其回退模型。有要求的槽位不会换用不满足要求的回退模型。
关闭某项能力
在它的槽位上写 null。video: null 默认关闭视频生成,用户仍可在模型设置中开启;再加上 lock: [video] 即对所有人保持关闭。course.content.pbl: null 只关闭 PBL 场景生成,course.content 的其余部分照常工作。对已关闭槽位的调用会立即失败,媒体相关接口返回 403,而不是换用其他厂商。
默认值、锁定与模型设置
openmaic.yml 在 slots 下写出的内容是服务端的默认值:用户可以在模型设置中修改,卡片上会标注服务端默认,恢复服务端默认会撤销用户的修改。在 lock 下列出的槽位由管理员固定,对所有人生效,并连同整棵子树一起固定:
lock: [llm, video] # 这些槽位及其下所有槽位
# lock: all # 所有槽位lock列出的每个槽位都必须在slots中写出(null也算:video: null加lock: [video]会对所有人关闭视频)。未知槽位,或slots中没有写出的锁定槽位,会让服务在启动时拒绝运行,并指出其位置(lock.1: ...)。- 锁定的槽位同时固定其子槽位:使用
lock: [llm]时,任何用户都不能设置course.outline或其他语言模型槽位,它们全部只按openmaic.yml解析。 lock: all固定所有槽位,无论是否写出;slots没写的能力根槽位因此对所有人都是未配置。但未指定的webFetch仍使用builtin;设置webFetch: null可将其关闭。null、服务端默认值与锁定可以组合:只写video: null时默认关闭,用户可以开启;加上lock: [video]后保持关闭。
设置界面会根据配置呈现三种形态之一:
| 形态 | 条件 | 显示内容 |
|---|---|---|
| 自己配置 | 开启 allowUserKeys(默认) | Token Plan、模型服务和课程模型配置 |
| 选择模型 | allowUserKeys: false | 只显示课程模型配置,在 openmaic.yml 声明的服务商中选择 |
| 由管理员配置 | 所有槽位都被锁定(lock: all) | 课程模型图,每张卡片均为只读(显示其模型,或已关闭、未设置) |
所有控件遵循同一条规则:只有使用它能改变什么时才显示。模型服务中某个能力的标签页及其添加服务入口,只在该能力还有用户可设置的槽位时出现;Token Plan 只在某个套餐还能填入未锁定的槽位时出现,接入套餐也绝不会改动锁定的槽位。课程模型配置中被锁定的卡片显示为一行只读内容,并标注由管理员固定。首页的模型选择器只在默认模型可以修改时出现(llm 未被锁定,且有服务商提供语言模型)。
Web 端的模型设置读写当前工作区的同一棵树:
- Token Plan:接入套餐会用该 key 添加套餐的服务商,并为套餐推荐、且仍未分配的槽位填入模型。解除接入会删除该服务商,原本使用它的槽位重新跟随父槽位。
- 模型服务:每种能力一个标签页(语言模型、图像、视频、语音合成、语音识别、文档解析、联网搜索),列出各自的服务。来自
openmaic.yml的服务商以只读方式显示,不显示任何关于 key 的信息。工作区配置的服务会成为工作区服务商:key 只能写入,只显示类似…abcd的掩码;自定义地址仅限语言模型(Azure 语音服务使用其官方区域地址,例如https://<region>.tts.speech.microsoft.com);自托管服务与密钥对需在openmaic.yml中配置。测试按钮在服务端检查已保存的服务商。 - 课程模型配置:主线模型就是
llm槽位,管线的每个环节对应自己的槽位(跟随主线即该环节没有自己的分配);图像、视频、语音、搜索和转写的开关会把对应槽位设为null。被锁定的槽位显示为一行只读内容;使用服务端默认值的槽位在用户修改后提供恢复服务端默认。
早期版本保存在浏览器中的服务商设置(服务商及其 key 和 Base URL、所选模型、Token Plan 接入状态,以及每种能力的选择)会一次性导入工作区。导入不会替换工作区已有的设置或 openmaic.yml 锁定子树中的槽位,并会跳过被 allowUserKeys: false 或校验拒绝的条目。收到 2xx 响应后,只有工作区已持有的内容会从浏览器中删除:服务端跳过的每个条目(媒体服务的自定义地址、工作区不可使用的预设、与部署声明重名的服务商 id 等)都会连同 key 保留在此浏览器中,不会再次发送,提示一次,并在「设置 → 模型服务」中连同原因列出,直到重新设置或被丢弃。带官方区域地址的 Azure 语音服务商会被导入。收到 400 时整份导入内容被拒绝:不会再次发送,其中各条目会连同 key 保留在此浏览器中,并与被跳过的条目一起列出;导入内容无法读取时会被丢弃。只有在 401、404、409、5xx 或网络错误时,导入内容才会保留在浏览器中,供之后重试。明确关闭过的语音输入会变为 asr: null;在已有可用服务商时关闭的语音讲解、图像或视频会变为 tts: null、image: null 或 video: null(openmaic.yml 锁定的槽位保持不变)。以下内容需要手动重新设置:按阶段设置的模型(在课程模型配置中,或在 openmaic.yml 的 slots 中)、推理设置(槽位上的 thinking)、自定义语音合成与语音识别服务商以及 AliDocMind 的密钥对(在 openmaic.yml 中;它们会保留在浏览器中,与被跳过的条目一起列出)、VoxCPM 后端(options.backend),以及百度搜索子来源(使用服务端默认值)。关闭的调研开关不会迁移(它只停止课程调研,对话和智能体仍会搜索),仅因默认值而处于关闭的开关也不会迁移:每项能力只要其槽位能解析就会运行。
工作区即持久化文档中所说的所有者(owner):默认的 Docker Compose 部署(单用户模式)只有一个工作区;多用户部署中,每个已登录账号各有一个工作区。
allowUserKeys
allowUserKeys: falseallowUserKeys(默认 true)决定用户能否添加自己的服务商、Key 和 Token Plan。设为 false 时,用户只能在 openmaic.yml 声明的服务商中,为未锁定的槽位选择模型:不显示 Token Plan 和添加服务入口,工作区之前添加的服务商也不再使用。请求自带的模型、密钥或端点(已弃用的 x-model、x-api-key、x-base-url 请求头以及媒体接口的服务商字段)也会被忽略,服务商测试按钮的请求头形式会被拒绝。由部署方承担全部费用的多用户部署通常会设置它,并锁定需要固定的槽位。
密钥与 OPENMAIC_SECRET_KEY
openmaic.yml中的 key 通过${VAR}来自环境变量,不会写入数据库,也不会发送到浏览器。- 工作区在模型设置中填写的 key 保存在数据库中,使用实例密钥
OPENMAIC_SECRET_KEY以 AES-256-GCM 加密。 - 未设置
OPENMAIC_SECRET_KEY时,服务端会在首次使用时于data/instance-secret.key(Docker Compose 中位于openmaic-data数据卷内)生成一个随机密钥,之后一直使用它。
请把该密钥和数据库备份放在一起:密钥丢失或更换后,之前保存的 key 无法读取,需要重新填写(模型设置会标出这些 key)。多个实例共用同一数据库时,或服务没有持久化数据目录时(例如未挂载数据卷的容器),请显式设置 OPENMAIC_SECRET_KEY;任意字符串都可以,例如 openssl rand -base64 32 的输出。
不设置它时,如果数据目录不能跨重启保留(没有挂载卷的容器、临时磁盘),每次启动都会生成新密钥;多个副本也会各自生成一个;工作目录只读时则无法创建密钥,在模型设置中保存 key 会失败。启动时,若 OPENMAIC_SECRET_KEY 未设置且数据目录不可写,或数据库中已有 key 是用与当前不同的密钥加密的(例如 data/instance-secret.key 丢失),服务端会记录警告,但仍会正常启动。
OPENMAIC_SECRET_KEY=... # 模型设置中保存的 key 所用的实例密钥
OPENMAIC_CONFIG=/etc/openmaic/openmaic.yml # 可选:openmaic.yml 的其他路径工作区可以添加什么
openmaic.yml 中的服务商可以是 schema 允许的任何内容。工作区在模型设置中添加的服务商限制更多,因为其端点和 key 由 Web 端的用户填写:
- 不提供 Amazon Bedrock:它会使用服务端自己的 AWS 凭证签名。
- 不能设置
proxy,也不能使用密钥对(credentials):AliDocMind 等使用密钥对认证的预设只能由部署配置。 - 只有提供对话能力的预设才能设置自定义
baseUrl,且带自定义端点的服务商只能用于对话槽位。URL 不能包含凭证、查询字符串或片段,并且必须解析到公网地址,除非服务端设置了ALLOW_LOCAL_NETWORKS=true。对它的请求不会跟随重定向。 - 本地模型服务(Ollama、Lemonade)必须填写自己的端点,不能使用预设默认的
localhost。 - 自托管的媒体、搜索和文档服务(VoxCPM2、FunASR、Lemonade 语音与图像、ComfyUI、SearXNG、自托管 MinerU)运行在服务端自己的网络中,只能由部署配置。
- 运维人员用旧版
<CAP>_<VENDOR>_ENABLED=false变量关闭的服务商不会提供。 - 工作区不能声明
openmaic.yml已经声明过的服务商 ID。
如果希望用户访问内网服务,请在 openmaic.yml 中声明这些服务商。
API 调用方与已弃用的请求字段
生成请求不再需要携带 key 或模型选择:/api/generate-classroom 等无浏览器 API 调用会按调用方所在的工作区,通过与 Web 端相同的槽位解析模型。
旧的请求头 x-model、x-api-key、x-base-url、x-provider-type、x-model-routes、x-image-provider、x-image-model、x-video-provider、x-video-model,以及语音、搜索和文档接口中对应的请求体字段,均已弃用。只有当它们会影响的槽位没有分配,或者在仍通过旧变量配置的服务端上只有由旧变量转换得到的默认值时(DEFAULT_MODEL 一直排在请求指定的模型之后),才会生效;openmaic.yml 中的默认值、工作区自己的选择和锁定的槽位优先,设为 null 的槽位无论请求写了什么都会拒绝。设置 allowUserKeys: false 时,它们一律被忽略。请求第一次使用这些字段时,服务端会记录一条警告。它们将在上述模型设置发布两个次版本后移除。
从旧配置迁移
没有 openmaic.yml 时,服务端会在启动时转换旧配置,记录一条弃用提示,并为每个无法转换的条目各记录一条提示:
| 旧配置 | 转换结果 |
|---|---|
服务商变量(OPENAI_API_KEY、TTS_MINIMAX_API_KEY 等)和 server-providers.yml | 部署服务商(在模型设置中只读)。服务商 ID 就是预设 ID,与旧的 provider ID 相同,只有联网搜索的 MiniMax(minimax-search)、联网搜索的豆包(doubao-search)和 Lemonade 图像(lemonade-image)例外 |
<PREFIX>_MODELS | 服务商的 models |
DEFAULT_MODEL | llm 的分配,作为工作区可以覆盖的默认值(不锁定)。agent 槽位和以前一样保持关闭 |
MODEL_FALLBACK | DEFAULT_MODEL 的回退模型。没有 DEFAULT_MODEL 时会被丢弃并给出提示 |
| 第一个配置的 TTS、ASR、图像、视频和文档服务商,以及按旧优先级选出的联网搜索服务商 | 该能力的默认分配(图像服务商由 DEFAULT_IMAGE_PROVIDER 指定) |
MODEL_ROUTES | 不转换。 服务拒绝启动(见下文) |
<CAP>_<VENDOR>_ENABLED=false | 仍然生效:无论谁分配,该服务商都保持关闭 |
存在 openmaic.yml 时,服务商变量、server-providers.yml、DEFAULT_MODEL、MODEL_FALLBACK 和 MODEL_ROUTES 都不再参与模型解析,并会给出提示。<CAP>_<VENDOR>_ENABLED=false 仍然生效;要关闭某项能力,请改为把它的槽位设为 null。
环境变量。 迁移前:
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
DEFAULT_MODEL=openai:gpt-5.5
MODEL_FALLBACK=anthropic:claude-sonnet-4-6
TTS_MINIMAX_API_KEY=...
TAVILY_API_KEY=tvly-...迁移后(key 仍留在环境变量中):
providers:
openai:
preset: openai
apiKey: ${OPENAI_API_KEY}
anthropic:
preset: anthropic
apiKey: ${ANTHROPIC_API_KEY}
minimax-tts:
preset: minimax-tts
apiKey: ${TTS_MINIMAX_API_KEY}
tavily:
preset: tavily
apiKey: ${TAVILY_API_KEY}
slots:
llm:
model: openai:gpt-5.5
fallback: anthropic:claude-sonnet-4-6
tts: minimax-tts
webSearch: tavily之后删除 DEFAULT_MODEL 和 MODEL_FALLBACK。服务商变量可以保留,作为 ${VAR} 引用的来源。<PREFIX>_BASE_URL 对应服务商的 baseUrl(OPENAI_BASE_URL → openai 下的 baseUrl;直接写 URL,或在变量仍然设置时写 ${OPENAI_BASE_URL}),<PREFIX>_MODELS 对应它的 models 列表。与转换得到的 DEFAULT_MODEL 一样,这里写出的 llm 是工作区可以修改的服务端默认值;如需对所有人固定,请加上 lock: [llm]。与转换结果不同,agent 现在会沿用 llm:如需保持工作台智能体关闭,请写 agent: null。
server-providers.yml。 迁移前:
providers:
azure:
apiKey: ...
baseUrl: https://YOUR-RESOURCE.openai.azure.com/openai
models: [my-deployment]
pdf:
alidocmind:
accessKeyId: ...
accessKeySecret: ...
web-search:
searxng:
baseUrl: http://searxng:8080迁移后:
providers:
azure:
preset: azure
apiKey: ${AZURE_OPENAI_API_KEY}
baseUrl: https://YOUR-RESOURCE.openai.azure.com/openai
models: [my-deployment]
alidocmind:
preset: alidocmind
credentials:
accessKeyId: ${ALIDOCMIND_ACCESS_KEY_ID}
accessKeySecret: ${ALIDOCMIND_ACCESS_KEY_SECRET}
searxng:
preset: searxng
baseUrl: http://searxng:8080
slots:
llm: azure:my-deployment
document: alidocmind
webSearch: searxngserver-providers.yml 的每个分组都对应使用相应预设的服务商(providers → 对话预设,tts、asr、pdf → 文档,image、video、web-search),accessKeyId/accessKeySecret 移到 credentials 下。
MODEL_ROUTES。 设置了 MODEL_ROUTES 但没有 openmaic.yml 的服务不会启动:
MODEL_ROUTES does not carry over to the model configuration: write the per-stage models as slots in openmaic.yml (or the file named by OPENMAIC_CONFIG) and remove MODEL_ROUTES按阶段的路由与槽位并非一一对应,因此不会自动转换。请把每条路由改写成该阶段所属的槽位:
MODEL_ROUTES 阶段 | 槽位 |
|---|---|
web-search-query-rewrite | course.research |
scene-outlines-stream | course.outline |
agent-profiles | course.agents |
scene-content | course.content |
scene-content:slide、:quiz、:interactive、:pbl | course.content.slide、.quiz、.interactive、.pbl |
scene-actions | course.actions |
chat-adapter、quiz-grade、pbl-v2-runtime 及其 :instructor、:open-task、:evaluate、:simulator 变体 | classroom |
generate-classroom | llm |
maic-agent-driver | agent |
conversation-title | agent.title |
pbl-chat、maic-agent | 无:这些阶段已移除,直接删掉 |
多个阶段共用一个槽位时,为该槽位指定它们应当共同使用的那个模型。路由里的 thinking 移到槽位的 thinking,maic-agent-driver 路由的 api 和 contextWindow 移到 agent 槽位。迁移前:
DEFAULT_MODEL=openai:gpt-5.5
MODEL_ROUTES='{"scene-outlines-stream":"anthropic:claude-sonnet-4-6","scene-content:slide":{"model":"openai:gpt-5.4","thinking":{"effort":"low"}},"maic-agent-driver":{"model":"openai:gpt-5.5","api":"openai-completions"}}'迁移后:
providers:
openai:
preset: openai
apiKey: ${OPENAI_API_KEY}
anthropic:
preset: anthropic
apiKey: ${ANTHROPIC_API_KEY}
slots:
llm: openai:gpt-5.5
course.outline: anthropic:claude-sonnet-4-6
course.content.slide:
model: openai:gpt-5.4
thinking: { effort: low }
agent:
model: openai:gpt-5.5
api: openai-completions一旦存在 openmaic.yml,服务商变量本身就不再配置任何东西:只靠变量配置的 TTS、图像、文档或网络搜索服务商(TTS_MINIMAX_API_KEY、IMAGE_SEEDREAM_API_KEY、PDF_MINERU_BASE_URL、TAVILY_API_KEY 等)不再被使用,除 webFetch 外,其他能力也不会得到默认服务商。请把用到的每个服务商写进 providers,并在 slots 中指定 tts、image、document、webSearch(以及 asr、video),做法同上面的环境变量示例;未指定的其他槽位保持未配置,除非某个工作区在模型设置中为它指定。
然后删除 MODEL_ROUTES、DEFAULT_MODEL 和 MODEL_FALLBACK。
Docker。 把文件挂载到应用旁边,key 仍放在 .env.local 中:
services:
openmaic:
volumes:
- ./openmaic.yml:/app/openmaic.yml:roACCESS_CODE —— 站点级访问密码
对共享部署(内部 demo、课堂),可以设置访问码,访客先输密码才能看到应用:
ACCESS_CODE=your-secret-code请使用足够长的随机值(至少 16 个字符),因为该密码是保护部署的唯一密钥。验证通过后会在 HTTP-only cookie 中保存一个签名令牌,有效期 7 天,由服务端强制校验,过期后需要重新验证。只有在受信任的反向代理之后设置 TRUST_PROXY_HEADERS=true(由代理覆盖 x-forwarded-for / x-real-ip)时才会限流:按客户端限流(每个客户端 60 秒内 10 次),验证成功会清空该客户端的计数;没有可信代理时应用无法把请求归因到具体客户端,因此完全不限流,保护依赖密码的长度和随机性。留空则关闭。
功能开关
功能开关的值为 true 或 1;除非另有说明,其他值视为关闭。NEXT_PUBLIC_* 开关会在构建时注入客户端,修改后需要重新构建:
# MAIC Editor(课堂编辑器)
NEXT_PUBLIC_MAIC_EDITOR_ENABLED=true
# Pi 播放态中的 PPT 与互动页课件引用(构建时开关;不影响编辑态引用)
NEXT_PUBLIC_COURSEWARE_REFERENCE_ENABLED=true
# 职业教育任务引擎(服务端开关)
OPENMAIC_ENABLE_VOCATIONAL=true
# 显示职业教育实验开关
NEXT_PUBLIC_SHOW_VOCATIONAL_TEST_UI=true
# 显示视频导出入口
NEXT_PUBLIC_ENABLE_VIDEO_EXPORT=true
# 显示实验性 PPTX 导入入口
NEXT_PUBLIC_ENABLE_PPTX_IMPORT=true
# 账户菜单「文档」打开的文档站地址(默认同源 /docs)
NEXT_PUBLIC_DOCS_URL=https://docs.example.com课堂对话固定由 Pi 运行,需要支持工具/函数调用的模型:在课程模型配置中为课堂互动选择这样的模型,或在 openmaic.yml 中设置 classroom 槽位(或它继承的 llm 槽位)。Gemini 请使用原生 google 预设,不要使用 Google 的 OpenAI 兼容端点。 内置模型目录标明不支持工具调用的模型会在推理前被拒绝,返回 400 MODEL_CONFIG_INVALID(reason: tool_calling_required),课程模型配置也会在课堂互动槽位上注明这一要求。
旧版 director-graph 课堂对话已移除,NEXT_PUBLIC_PI_CHAT_ENABLED 不再选择对话链路。请从配置中删除该变量:production 构建只接受未设置、空字符串、true 或 1(精确匹配),其他任何值都会构建失败并给出迁移提示。使用 Docker Compose 时,服务的 env_file(.env.local)提供的是运行时值,不进入构建参数。
PPTX 导入目前仍是实验性入口,解析结果尚未完整接入课堂数据流。以上 NEXT_PUBLIC_* 变量都是构建时开关;Docker 部署还需要通过 build args 传入,不能只写在容器运行时环境变量中。
其他服务端选项
以下服务端选项也可以通过环境变量配置:
# 场景内容并行生成;0 或未设置表示串行
PARALLEL_SCENE_CONCURRENCY=3
# 允许访问 localhost、内网等本地网络地址;仅用于自托管/内网部署
ALLOW_LOCAL_NETWORKS=true
# 可选的 MP4 渲染服务
RENDER_SERVICE_URL=http://render-service:9000
# 日志和推理
LOG_LEVEL=info
LOG_FORMAT=pretty
LLM_THINKING_DISABLED=false旧版服务商环境变量
这些变量和 server-providers.yml 是早期版本的配置方式。在没有 openmaic.yml 时它们仍然有效(见从旧配置迁移),但已弃用,将在模型设置发布两个次版本后移除。使用 openmaic.yml 时,它们只作为 ${VAR} 引用的来源。DEFAULT_MODEL 和 MODEL_FALLBACK 见迁移一节;MODEL_ROUTES 已不再读取。
LLM 提供方
云端提供方通常使用以下三个环境变量:API key、base URL 和 model 列表。其中 API key 通常是必填的,base URL 和 model 列表可选;Azure OpenAI 需要配置资源 endpoint,Ollama 和 Lemonade 不需要 API key。
OPENAI_API_KEY=sk-...
OPENAI_BASE_URL= # 可选的 base URL 覆盖
OPENAI_MODELS= # 可选的模型白名单(逗号分隔)支持的 provider 前缀:
| 前缀 | 提供方 |
|---|---|
OPENAI_ | OpenAI |
AZURE_OPENAI_ | Azure OpenAI |
ANTHROPIC_ | Anthropic |
GOOGLE_ | Google Gemini |
DEEPSEEK_ | DeepSeek |
QWEN_ | 阿里 Qwen |
KIMI_ | Moonshot Kimi |
MINIMAX_ | MiniMax(默认用 Anthropic 兼容端点) |
GLM_ | 智谱 GLM |
SILICONFLOW_ | SiliconFlow |
DOUBAO_ | 豆包(字节跳动) |
OPENROUTER_ | OpenRouter |
GROK_ | xAI Grok |
TENCENT_ | 腾讯混元 |
TENCENT_HUNYUAN_ | 腾讯混元(别名) |
XIAOMI_ | 小米 MiMo |
MIMO_ | 小米 MiMo(别名) |
OLLAMA_ | Ollama(本地) |
LEMONADE_ | Lemonade(本地) |
Azure OpenAI 使用 deployment name 作为模型 ID:
AZURE_OPENAI_API_KEY=...
AZURE_OPENAI_BASE_URL=https://YOUR-RESOURCE.openai.azure.com/openai
AZURE_OPENAI_MODELS=your-deployment-name如需连接其他 OpenAI 兼容的 LLM 服务,请在 openmaic.yml 中声明一个带 baseUrl 和 models 的 openai-compatible 服务商,或在 设置 → 模型服务 → 语言模型 中用 添加服务商 添加。
Gemini 课堂互动请使用原生 google 预设:在设置 → 模型服务中添加 Google,并在课程模型配置中为课堂互动选择该模型。Pi 会提前拒绝 Google 官方 OpenAI 兼容端点(https://generativelanguage.googleapis.com/v1beta/openai)并提示迁移;兼容路线的工具调用支持由 #1556 跟踪。此检查仅识别该官方端点,无法识别任意第三方网关背后的上游。
本地模型(Ollama 和 Lemonade)
Ollama 和 Lemonade 不需要 API key;本地服务的 base URL 应写在服务端配置中,以通过 SSRF 校验:
OLLAMA_BASE_URL=http://localhost:11434/v1
# LEMONADE_BASE_URL=http://localhost:13305/v1如需限制可用模型,可使用 OLLAMA_MODELS 或 LEMONADE_MODELS 指定模型白名单。
TTS 提供方
服务端 TTS 提供方使用 TTS_<PROVIDER>_API_KEY,可选 TTS_<PROVIDER>_BASE_URL。
# 豆包 TTS(火山引擎 Seed-TTS,原生 MP3)
TTS_DOUBAO_API_KEY=appId:accessKey
TTS_DOUBAO_BASE_URL= # 可选覆盖
# Qwen TTS
TTS_QWEN_API_KEY=
TTS_QWEN_BASE_URL= # 可选覆盖
# 小米 MiMo TTS
TTS_XIAOMI_API_KEY=
TTS_XIAOMI_BASE_URL=https://api.xiaomimimo.com/v1
# 任何 OpenAI 兼容的 TTS 端点
TTS_OPENAI_API_KEY=
TTS_OPENAI_BASE_URL=
# VoxCPM2(自托管 TTS,支持声音克隆,详见 VoxCPM2 单独页)
TTS_VOXCPM_BASE_URL=http://localhost:8000支持的 TTS 前缀包括 TTS_OPENAI_、TTS_AZURE_、TTS_GLM_、TTS_QWEN_、TTS_MINIMAX_、TTS_DOUBAO_、TTS_ELEVENLABS_、TTS_GOOGLE_、TTS_VOXCPM_、TTS_XIAOMI_ 和 TTS_LEMONADE_。本地 Lemonade TTS 和 VoxCPM2 不需要 API key。浏览器原生 TTS 不需要服务端配置。
管理员可以使用 TTS_<PROVIDER>_ENABLED=false 在服务端强制关闭某个 TTS 提供方。VoxCPM2(自托管 TTS + 声音克隆)请见单独的 VoxCPM2 章节。
对于自托管或纯 CPU 运行的较慢 TTS 服务(例如 Kokoro 或 VoxCPM),较长旁白单段合成可能超出默认的 30 秒(30000 ms)单请求超时。运维人员可在 .env.local 中配置 TTS_REQUEST_TIMEOUT_MS(例如 TTS_REQUEST_TIMEOUT_MS=120000 或 300000),为合成预留充足时间以避免超时报错。
如需使用其他 OpenAI 兼容的 TTS 端点,请在 openmaic.yml 中声明一个带该 baseUrl 的 openai-tts 服务商,并把 tts 槽位分配给它。工作区不能在模型设置中添加自定义 TTS 端点。
ASR(语音转文字)
# OpenAI Whisper
ASR_OPENAI_API_KEY=
ASR_OPENAI_BASE_URL= # 可选覆盖
# Qwen ASR
ASR_QWEN_API_KEY=
ASR_QWEN_BASE_URL= # 可选覆盖
# 小米 MiMo ASR
ASR_XIAOMI_API_KEY=
ASR_XIAOMI_BASE_URL=https://api.xiaomimimo.com/v1
# Azure ASR
ASR_AZURE_API_KEY=
ASR_AZURE_BASE_URL=https://{region}.api.cognitive.microsoft.com
# FunASR(本地,不需要 key)
ASR_FUNASR_BASE_URL=http://localhost:8000/v1
# Lemonade ASR(本地,不需要 key)
ASR_LEMONADE_BASE_URL=http://localhost:13305/v1使用 funasr-server --device cuda 启动 OpenAI 兼容服务。它在 /v1/audio/transcriptions 接收 WAV,并可在模型选择器中使用 SenseVoiceSmall、Paraformer 和 Fun-ASR-Nano。
浏览器原生 ASR 不需要服务端配置。
如需使用其他 OpenAI 兼容的 ASR 端点,请在 openmaic.yml 中以 openai-whisper 预设和它的 baseUrl 声明该服务,并把 asr 槽位分配给它。工作区不能在模型设置中添加自定义 ASR 端点:
providers:
my-asr:
preset: openai-whisper
apiKey: ${MY_ASR_API_KEY}
baseUrl: https://asr.example.com/v1
slots:
asr: my-asr:whisper-1图像生成提供方
图像生成提供方使用 IMAGE_<PROVIDER>_API_KEY,可选 IMAGE_<PROVIDER>_BASE_URL。支持的前缀包括:
IMAGE_OPENAI_、IMAGE_SEEDREAM_、IMAGE_QWEN_IMAGE_、IMAGE_NANO_BANANA_、IMAGE_MINIMAX_、IMAGE_GROK_、IMAGE_GLM_ 和 IMAGE_LEMONADE_。
GLM 图像(智谱 CogView)使用 CogView 模型(cogview-3-flash、cogview-4)生成图片:
providers:
glm-image-service:
preset: glm-image
apiKey: ${IMAGE_GLM_API_KEY}
# 可选:
baseUrl: https://open.bigmodel.cn/api/paas/v4
slots:
image: glm-image-service:cogview-3-flash也可以通过环境变量配置:
IMAGE_GLM_API_KEY=
# 可选:
IMAGE_GLM_BASE_URL=https://open.bigmodel.cn/api/paas/v4Lemonade 是本地服务,不需要 key:
IMAGE_LEMONADE_BASE_URL=http://localhost:13305/v1ComfyUI Image 不需要 API key。它运行在你自己的网络中,因此由部署配置:在 openmaic.yml 中用 ComfyUI 服务的地址声明它,并把 image 槽位分配给它。
providers:
comfyui:
preset: comfyui-image
baseUrl: http://host.docker.internal:8188
slots:
image: comfyui把以 API 格式导出的工作流 JSON 放到 OpenMAIC 的 public/ 目录中,文件名需匹配 comfyui-*.json 或包含 workflow;OpenMAIC 会自动发现这些文件并作为工作流提供。使用 Docker 时,请在构建镜像前加入工作流,或把单个工作流文件挂载到容器内的 /app/public/。由于该服务商由部署声明,运行在宿主机或内网中的 ComfyUI 不需要 ALLOW_LOCAL_NETWORKS。
视频生成提供方
视频生成提供方使用 VIDEO_<PROVIDER>_API_KEY,可选 VIDEO_<PROVIDER>_BASE_URL。支持的前缀包括:
VIDEO_SEEDANCE_、VIDEO_KLING_、VIDEO_SORA_、VIDEO_MINIMAX_、VIDEO_GROK_ 和 VIDEO_HAPPYHORSE_。
文档和媒体解析
课程材料的具体格式取决于所选解析器。当前支持文本、PDF、Office 文档、图片以及部分音视频格式;不同 provider 支持的格式和能力不同。
# MinerU 自托管
PDF_MINERU_BASE_URL=http://localhost:8888
# MinerU 自托管的可选后端
PDF_MINERU_BACKEND=pipeline
# MinerU Cloud
PDF_MINERU_CLOUD_API_KEY=
PDF_MINERU_CLOUD_BASE_URL=https://mineru.net/api/v4
# AliDocMind(使用阿里云 AccessKey,而不是单独的 API key)
ALIDOCMIND_ACCESS_KEY_ID=
ALIDOCMIND_ACCESS_KEY_SECRET=
ALIDOCMIND_BASE_URL= # 可选覆盖unpdf 内置于 OpenMAIC,可用于基础 PDF 解析。Office 文档、图片和需要 OCR、表格、公式或版面分析的材料,应选择兼容的 MinerU 或 AliDocMind provider。
AliDocMind 的文档解析支持 PDF、DOCX、PPTX、XLSX,以及 PNG、JPG/JPEG、BMP、GIF。当前音视频材料仅支持通过 AliDocMind 解析:视频格式为 MP4、MOV、AVI、MKV、WMV,音频格式为 MP3、WAV、AAC;不支持 M4A。
联网搜索
配置 Tavily、Exa、Firecrawl、Bocha、Brave、Baidu、SearXNG 或 MiniMax:
TAVILY_API_KEY=
TAVILY_BASE_URL= # 可选覆盖
EXA_API_KEY=
EXA_BASE_URL=https://api.exa.ai # 可选覆盖
FIRECRAWL_API_KEY=
FIRECRAWL_BASE_URL=https://api.firecrawl.dev # 可选覆盖
BOCHA_API_KEY=
BOCHA_BASE_URL= # 可选覆盖
BAIDU_API_KEY=
BAIDU_BASE_URL=https://qianfan.baidubce.com # 可选覆盖
# 自托管 SearXNG,不需要 API key
SEARXNG_BASE_URL=
WEB_SEARCH_MINIMAX_API_KEY=
WEB_SEARCH_MINIMAX_BASE_URL=https://api.minimaxi.com # 可选覆盖Brave 和 SearXNG 不需要 API key。联网搜索没有逐次生成的开关:只要工作区的 webSearch 槽位能解析就会运行;关闭它(在 openmaic.yml 中写 webSearch: null,或在 设置 → 课程模型配置 中关闭搜索开关)会影响该工作区之后的生成。Grok 的联网搜索通过 Grok LLM 的搜索工具提供,不是独立的联网搜索 provider。
server-providers.yml
已被 openmaic.yml 取代。两者同时存在时,只有 openmaic.yml 用于配置模型。
除了环境变量,你也可以把代码中已注册 provider 的配置放在项目根目录下的 server-providers.yml 文件里。服务端启动时加载,结构与环境变量分类对应:
providers:
openai:
apiKey: sk-...
baseUrl: https://api.openai.com/v1
models:
- gpt-5.5
anthropic:
apiKey: sk-ant-...
tts:
doubao-tts:
apiKey: appId:accessKey
asr:
openai-whisper:
apiKey: sk-...
pdf:
mineru:
baseUrl: http://localhost:8888
alidocmind:
accessKeyId: your-access-key-id
accessKeySecret: your-access-key-secret
image:
seedream:
apiKey: ...
video:
seedance:
apiKey: ...
web-search:
tavily:
apiKey: tvly-...
exa:
apiKey: ...
firecrawl:
apiKey: fc-...
searxng:
baseUrl: http://localhost:8080环境变量会逐字段覆盖 YAML 中的同名 provider 配置。键名必须使用代码中已注册的 provider ID,例如 openai、doubao-tts、openai-whisper、mineru、alidocmind、seedream、seedance、exa、tavily 或 searxng;未知 ID 不能在这里注册为自定义 LLM provider。
服务端托管服务商的模型授权
对于使用部署凭据把所选模型发往上游的服务商,请在 openmaic.yml 中设置显式的 models 列表(providers.<id>.models),或设置对应的 *_MODELS 环境变量 / server-providers.yml 中该部分的 models 列表。这适用于对话、图像、视频、语音合成、语音识别和基于模型的联网搜索。模型 ID 在加载配置时去掉首尾空白后精确匹配,区分大小写。确定性的适配器别名按声明的模型 ID 授权。请求未列出的模型会返回 HTTP 403,错误码 PROVIDER_DISABLED,消息为“This model is not authorized for server-managed credentials”。
破坏性变更: 没有显式列表时,只能使用部署的默认/回退模型,以及该能力的槽位所引用的主模型/回退模型。在旧版配置下,DEFAULT_MODEL 和 MODEL_FALLBACK 授权对话模型。只写服务商的媒体槽位只授权该适配器的默认模型,不授权该预设的整个模型目录。工作区的分配无法扩大部署的授权范围。音色注册和合成也必须授权为音色兼容性而选择的模型。
迁移时,列出用户应能选择的每个模型,重启服务,并更新不再获授权的工作区选择。对于有凭据但没有列表的服务商,启动日志会指出需要添加的设置。用户自己的服务商凭据,以及 Ollama、Lemonade 这类无需 key 的本地服务商不受影响。未配置凭据的服务商不受限制,因此不要把它指向会自行添加上游凭据的网关(例如内部的 OpenAI 兼容代理):请给该网关一个 key,把它配置为带 models 列表的有凭据服务商,或在网关本身限制模型。没有模型选择的文档解析器和搜索服务(如 Tavily)不需要模型列表。
providers:
openai:
preset: openai
apiKey: ${OPENAI_API_KEY}
models: [gpt-5.4-mini]
slots:
llm: openai:gpt-5.4-mini旧版等价写法:OPENAI_API_KEY=... 和 OPENAI_MODELS=gpt-5.4-mini。媒体能力使用能力前缀,例如 IMAGE_SEEDREAM_MODELS、VIDEO_SEEDANCE_MODELS、TTS_OPENAI_MODELS、ASR_OPENAI_MODELS 和 WEB_SEARCH_CLAUDE_MODELS。
DeepSeek 联网搜索与网页抓取
deepseek 预设在对话、联网搜索和托管 Markdown 提取之间共享 DEEPSEEK_API_KEY 和 API 基础地址。搜索使用 POST /v1/tools/search,最多返回 50 条结果,查询按 Unicode code point 截断到 128 个字符,优先使用 summary,为空时回退到 snippet。抓取使用 POST /v1/tools/fetch,读取 content 和非空的可选 title。
旧版配置需要设置 WEB_SEARCH_DEEPSEEK_ENABLED=true,或在 server-providers.yml 中显式添加 web-search.deepseek。仅配置对话凭据不会启用搜索或替换已有搜索默认项。WEB_SEARCH_DEEPSEEK_ENABLED=false 会强制禁用搜索。存在 openmaic.yml 时,旧版变量不能指定槽位,必须显式声明服务商并指定 webSearch 和/或 webFetch。
The default API base is https://api.deepseek.com/v1. On api.deepseek.com, every base path (including /beta) is normalized to /v1 before appending /tools/search or /tools/fetch. Custom gateway bases preserve their configured path prefix; a bare root gets /v1 first. Custom endpoints belong in deployment configuration, while client and workspace overrides remain restricted to official endpoints. The default fetch reader remains builtin. See DeepSeek official pricing for current request charges. Failed requests and searches with no results are not billed.
providers:
deepseek:
preset: deepseek
apiKey: ${DEEPSEEK_API_KEY}
baseUrl: https://api.deepseek.com/v1
slots:
webSearch: deepseek
webFetch: deepseekKimi 对话与联网搜索
声明一个 Kimi 账号,并将两个槽位都分配给它:
providers:
kimi:
preset: kimi
apiKey: ${KIMI_API_KEY}
# 可选:国际版开放平台使用 https://api.moonshot.ai/v1。
# baseUrl: https://api.moonshot.ai/v1
slots:
llm: kimi:kimi-k3
webSearch: kimi使用 Coding Plan 密钥时,请设置 preset: kimi-coding-plan 和 llm: kimi:kimi-for-coding;其默认地址为 https://api.kimi.com/coding/v1。开放平台和 Coding Plan 密钥必须使用各自对应的基础 URL。 在旧版配置中,只有显式启用后,KIMI_API_KEY 和可选的 KIMI_BASE_URL 才会为搜索提供凭据:设置 WEB_SEARCH_KIMI_ENABLED=true,或在 server-providers.yml 中添加 web-search.kimi(例如设置 enabled: true)。仅有对话凭据不会启用搜索,也不会改变默认搜索服务商。即使槽位已分配给 Kimi,WEB_SEARCH_KIMI_ENABLED=false 仍会禁用 Kimi 搜索。WEB_SEARCH_KIMI_ENABLED 是 Kimi 搜索的唯一开关。 KIMI_MODELS 仅适用于对话。旧版对话和搜索账号冲突时会产生警告,并跳过搜索条目;如需使用不同账号,请在 openmaic.yml 中声明不同的服务商 ID。 存在 openmaic.yml 时,请显式声明服务商并分配槽位。设置和首次使用向导允许通过同一账号使用两项能力。
端点选择取决于基础路径:去掉末尾斜杠后,以 /coding/v1 结尾的路径使用 /search,其他路径使用 /tools/search_pro。部署配置的自定义代理必须保留这一布局。向导只为官方账号地址推荐搜索,因此工作区自定义对话代理不会自动获得搜索分配。
存在 openmaic.yml 时,请声明 providers.<id>: { preset: kimi } 并分配 slots.webSearch: <id>;旧版变量 WEB_SEARCH_KIMI_ENABLED 无法分配该槽位。
网页抓取服务槽位
webFetch 决定智能体的 fetch_url 工具使用哪个读取服务。在旧版配置、空配置和 YAML 配置中,默认使用 builtin;即使 lock: all 下没有指定该根槽位也是如此。显式设置 webFetch: null 会关闭抓取,并从后续运行中移除该工具及其提示。每次请求只使用一个服务商,不会回退或升级到其他服务。无效的服务商引用或被策略拒绝的工作区端点会在智能体启动前的能力解析阶段导致整个智能体运行失败,与 webSearch 一致。这属于配置错误,并非 fetch_url 返回的失败结果,也不会自动改用内置读取服务。
| 服务商 | 凭据 | 内容提取 |
|---|---|---|
builtin | 无需凭据 | 本地 Readability/Turndown 读取服务;PDF 使用 document 槽位 |
kimi | 已有 Kimi 服务商的密钥和基础地址 | 托管 Markdown 提取服务,也接收 PDF 网址 |
deepseek | 现有 DeepSeek 对话密钥和 API 基础地址 | 托管 Markdown 提取 |
firecrawl | Firecrawl API 密钥(preset: firecrawl) | 托管 Markdown 提取服务,返回页面主体内容,也接收 PDF 网址 |
providers:
reader:
preset: kimi
apiKey: ${KIMI_API_KEY}
baseUrl: https://api.moonshot.cn/v1
slots:
webFetch: readerkimi 和 kimi-coding-plan 预设都提供 webFetch。使用 Coding Plan 凭据时,请指定 preset: kimi-coding-plan,其默认基础地址为 https://api.kimi.com/coding/v1;显式配置的基础地址会保留。Moonshot 开放平台地址(https://api.moonshot.cn/v1 和 https://api.moonshot.ai/v1)使用 /tools/fetch,Coding Plan 使用 /fetch。两者都发送带有 { "url": ... } 的 POST 请求,并使用 Bearer 身份验证。适配器接受 markdown 或 content。维护者使用真实密钥测试了 POST https://api.kimi.com/coding/v1/fetch,确认响应包含 { markdown, title, url };国际端点的可用性仍未验证。请求遵循服务商的 proxy 设置和标准代理环境变量。
DeepSeek 也通过 deepseek 预设提供托管 Markdown 提取,复用对话密钥和 API 基础地址。按上面的示例显式指定 webFetch,调用 /v1/tools/fetch,并保留部署配置中的网关地址。超时和仅对传输错误重试一次的行为与 Kimi 相同,不重试 HTTP 错误或无效响应。
在 设置 → 模型服务 → 网页抓取 中使用已有服务商凭据。该密钥与同一服务商的对话服务共享,修改或移除密钥也会影响对话。在 课程模型配置 → 网页抓取 中选择读取服务。管理员锁定后,卡片为只读。首次设置会保留内置默认值,直到明确选择其他读取服务。工作区凭据可使用官方 API 基础地址;自定义抓取地址和代理必须由管理员在 openmaic.yml 中声明。
与 kimi 不同,firecrawl 使用单独的密钥:在 openmaic.yml 中声明 preset: firecrawl 的服务商并设置 apiKey(例如 ${FIRECRAWL_API_KEY}),或在 设置 → 模型服务 → 网页抓取 中填写密钥。它以 Bearer 认证发送 POST /v2/scrape,以 Markdown 返回页面主体内容。默认基础地址为 https://api.firecrawl.dev;自托管 Firecrawl 的基础地址须由管理员在 openmaic.yml 中声明。
同一个 firecrawl 服务商也提供联网搜索(POST /v2/search):一把密钥和一个基础地址同时用于两者,因此可以把同一个服务商同时指定给 slots.webSearch 和 slots.webFetch。旧版的 FIRECRAWL_API_KEY 和 FIRECRAWL_BASE_URL 变量配置的就是这个服务商;在把 webFetch 指定给它之前,网页抓取仍使用 builtin。
网址转发给托管服务之前,必须通过会话网址授权、严格网址规范化和全部本地 DNS 地址检查。接收内容前,也会对服务返回的最终网址执行相同检查。托管服务控制其自身的 DNS 和中间重定向,本地检查无法固定其网络连接。返回的文本仍是不可信数据,经过验证页面检测、字节限制和截断标记处理,并沿用网页素材持久化及 {trusted, untrusted} 结果结构。
交互场景依赖库
交互场景从部署自身加载 KaTeX、Three.js(含 addons)、Chart.js 和 Tailwind v4 浏览器运行时,而不是从公共 CDN 加载。pnpm install、pnpm dev 和 pnpm build 会把已安装包中的固定版本复制到 public/vendor/interactive,并通过 /vendor/interactive 提供。只有包含数学公式的页面才会加载 KaTeX。
INTERACTIVE_ASSET_BASE_URL 是公开的构建时配置。如需从自己的 CDN 或对象存储提供这些文件,请复制 public/vendor/interactive 并保留其中的包名/版本路径,把该变量设为新的基础地址(例如 https://assets.example.com/interactive)后重新构建;Docker 构建通过 --build-arg 传入。交互场景运行在沙箱 iframe 中,因此该主机必须以正确的 MIME 类型提供 JavaScript、CSS 和字体文件,并返回 Access-Control-Allow-Origin: *。
已保存的交互 HTML 会在课堂中打开时,以及导出独立 HTML 或视频之前重新处理,因此指向这些库的兼容公共 CDN 引用会被改写,无需重新生成课程。指向其他库、不兼容版本、旧版 Tailwind v3 Play CDN(cdn.tailwindcss.com)和 Google Fonts 的引用保持不变,仍需要能访问对应主机。