# AI Provider 指南 ## 概览 `aiprovider` 是 Planet 的模型适配服务。 它把模型厂商差异隔离在主后端之外,让系统其它部分可以调用稳定的业务 API: - 调用方服务 -> `planet backend` - `planet backend` -> `aiprovider` - `aiprovider` -> 具体模型提供方 推荐默认方式: - 外部调用方和跨服务调用方统一调用 `planet backend` - 只有基础设施级内部任务才直接调用 `aiprovider` ## 职责边界 `backend` 负责: - 身份认证和权限控制 - 业务层请求整理 - 稳定的 `/api/v1/ai/...` 接口 - 面向 `aiprovider` 的内部服务认证 - 读取配置中心保存的默认 provider、模型和每个 provider 的 key,并通过内部请求头覆盖 `aiprovider` 的 `.env` 默认值 `aiprovider` 负责: - 模型协议适配 - 在没有后端覆盖头时基于 `.env` 选择 provider - 超时和轻量重试 - 通过 `X-Request-ID` 串联请求追踪 当前配置采用类似 OpenClaw 的拆分方式: - `AI_PROVIDER` 标识厂商或逻辑 provider - `AI_PROVIDER_API` 标识实际请求协议适配器 这个拆分能更清楚地表达 MiniMax、Claude 兼容网关、自托管 OpenAI 兼容服务等情况,避免把所有含义塞进一个配置项。 ## 支持的 Provider `aiprovider` 当前支持以下 provider 标识: - `openai` - `anthropic` - `minimax` - `ollama` 支持的请求适配器: - `openai-completions` - `openai-responses` - `anthropic-messages` - `ollama-generate` 仍然兼容的历史别名: - `openai_compatible` - `anthropic_compatible` - `claude_compatible` 推荐映射关系: - `vLLM`、`LM Studio`、`One API`:`AI_PROVIDER=openai`,`AI_PROVIDER_API=openai-completions` - `MiniMax`:`AI_PROVIDER=minimax`,`AI_PROVIDER_API=anthropic-messages` - Claude 兼容网关:`AI_PROVIDER=anthropic`,`AI_PROVIDER_API=anthropic-messages` - `Ollama`:`AI_PROVIDER=ollama`,`AI_PROVIDER_API=ollama-generate` ## API 面 ### 主后端 API 推荐使用的稳定入口: - `GET /api/v1/ai/provider/status` - `POST /api/v1/ai/situational-awareness/analyze` 认证方式: - `Authorization: Bearer ` 可选追踪头: - `X-Request-ID: ` 后端会把 `X-Request-ID` 透传给 `aiprovider`,并在响应中返回同一个 header。 ### 设置中心 API AI 配置页使用的接口: - `GET /api/v1/settings/integrations` - `PUT /api/v1/settings/integrations` - `POST /api/v1/settings/integrations/ai-provider/connect` - `GET /api/v1/settings/integrations/ai-provider/secrets` - `GET /api/v1/settings/integrations/ai-provider/presets` - `POST /api/v1/settings/integrations/ai-provider/presets/{provider}/refresh` - `GET /api/v1/settings/ai-prompts` - `PUT /api/v1/settings/ai-prompts/{task_key}` - `POST /api/v1/settings/ai-prompts/{task_key}/reset` 这些接口都需要用户登录。`secrets` 接口只用于配置页点击显示 key/token 时取回明文,隐藏时前端恢复为脱敏预览。 模型目录刷新和轻量连通性测试共用 `backend/app/services/llm_model_catalog.py`,直接请求当前供应商的模型接口,不再依赖 models.dev。使用当前表单草稿中的基础地址、协议和凭证;不传草稿时读取已保存配置。国内、国际和自定义网关地址保持各自的地域与路径。缺少必需凭证时返回 400 并提示配置 API Key;上游超时、鉴权或响应错误返回安全提示,并保留上次目录。 成功目录和 `refreshed_at` 按供应商保存到 `system_settings` 的 `llm_provider_preset:` 分类。该动态分类使用对应供应商预设作为默认值,提交前校验分类,避免已提交却返回失败。列表优先返回已保存目录,未刷新过的供应商显示内置建议。刷新不修改 `external_integrations` 的当前模型、协议、地址或凭证;页面保留草稿,目录加载失败时保留已显示模型并明确提示失败。 ### 模型目录接口 以下接口于 2026-09-13 对照官方文档核对。表中的 URL 是模型列表地址,配置表单仍填写生成接口的基础地址。需要凭证的目录必须使用对应服务地域的 API Key。 | 供应商 | 模型列表 GET 接口 | 鉴权与解析 | | --- | --- | --- | | [MiniMax](https://platform.minimax.io/docs/api-reference/models/anthropic/list-models) | `https://api.minimaxi.com/anthropic/v1/models`;国际站使用 `api.minimax.io` | `x-api-key`;`data[].id`;处理 `has_more/last_id` | | [OpenAI](https://developers.openai.com/api/reference/resources/models/methods/list) | `https://api.openai.com/v1/models` | Bearer;`data[].id` | | [Anthropic](https://platform.claude.com/docs/en/api/models/list) | `https://api.anthropic.com/v1/models` | `x-api-key`、`anthropic-version`;按 `after_id` 翻页 | | [DeepSeek](https://api-docs.deepseek.com/api/list-models) | `https://api.deepseek.com/v1/models` | Bearer;`data[].id` | | [阿里百炼](https://help.aliyun.com/zh/model-studio/list-models) | 同地域主机的 `/api/v1/models` | Bearer;`output.models[].model`;按 `page_no/page_size/output.total` 翻页,筛选 `capabilities=TG` | | [Moonshot / Kimi](https://platform.kimi.ai/docs/api/list-models) | `https://api.moonshot.ai/v1/models`;国内站使用 `api.moonshot.cn` | Bearer;`data[].id` | | [OpenRouter](https://openrouter.ai/docs/api/api-reference/models/list-all-models-and-their-properties) | `https://openrouter.ai/api/v1/models` | 支持公共目录;有凭证时附带 Bearer;`data[].id` | | [OpenCode Go](https://opencode.ai/docs/go/#models) | `https://opencode.ai/zen/go/v1/models` | 支持公共目录;有凭证时附带 Bearer;`data[].id` | | [Ollama](https://docs.ollama.com/api/tags) | 本机或配置服务器的 `/api/tags` | 本地无需 Key;`models[].model/name`;空目录表示尚未安装模型 | 百炼的北京、东京、法兰克福、弗吉尼亚新接口要求实际业务空间主机,例如 `.cn-beijing.maas.aliyuncs.com`;新加坡使用 `dashscope-intl.aliyuncs.com`,香港使用 `cn-hongkong.dashscope.aliyuncs.com`。系统只替换目录路径,不猜测业务空间或跨地域切换凭证。旧北京域名若不再接受账号凭证,应按控制台给出的业务空间地址更新基础地址。 完整分页和重试受 30 秒总超时保护;网络故障及 502/503/504 最多尝试两次,鉴权失败不重试。按接口提供的创建/发布日期倒序排列;日期相同时保留上游顺序,不截断为固定数量。公共目录只表示供应商公开的模型集合,不代表账号已获得每个模型的生成权限。 Admin 的 AI 页面按业务信息架构组织为: - `模型供应商` - 管理 provider、协议适配、默认模型、LLM API Key、代理地址、代理 token、模型列表刷新、设为默认和轻量连通性测试。 - `工具调用` - 管理 WebSearch、OCR 等工具。工具内部先选 provider,再编辑该 provider 的 API、key 和高级参数。 - `提示词` - 按 prompt 分组和 task key 编辑系统提示词 / 用户提示词;保存和重置只作用于当前 task。 - `Playground` - 使用当前默认 provider 和 prompt 配置发起真实会话;AI 回复使用 Markdown 渲染。 保存、设为默认和连通性测试是三个独立职责:保存只持久化表单,设为默认只切换默认 provider/tool,连通性测试只验证当前草稿是否可用,不应隐式保存或切换默认项。 `ai-prompts` 接口用于运维配置页的“提示词”Tab。默认提示词来自后端随发布包携带的版本化资源,业务代码只引用稳定 task key;接口只保存运维覆盖值。重置时删除覆盖值并恢复当前发布包中的缺省提示词。 ### 提示词边界 `aiprovider` 是纯模型适配器,不注入通用业务 system prompt。新闻汉化、告警研判、BGP 简报、位置 factcheck、数据源映射和凭据教程等入口各自通过 task key 解析有效提示词。告警研判 prompt 只会在告警相关 task 中作为 system prompt 传入,不会污染其它 LLM 调用。 ### Agent 与工具边界 Agent 工作流属于 `backend`,不属于 `aiprovider`。后续 Earth LLM 指令、态势感知、多角色模拟、WebSearch、数据库查询、证据存储和配置提案应用都应由后端 Agent Runtime 编排;`aiprovider` 只接收后端整理好的模型请求并返回规范化响应。 如果某个 provider 支持原生 tool calling,`aiprovider` 可以透传协议字段并规范化响应块,但工具白名单、参数校验、权限策略、运行记录和写入审批仍必须留在后端。provider 不支持原生 tools 时,后端使用 JSON tool-call fallback,不应为了某个模型厂商把业务工具下沉到 `aiprovider`。 ### AI Provider 内部 API 仅供内部调用的接口: - `GET /v1/provider/status` - `POST /v1/analyze` 认证方式: - `X-Provider-Token: ` 可选追踪头: - `X-Request-ID: ` ## 请求示例 ### 通过后端调用 ```bash curl -X POST http://localhost:8000/api/v1/ai/situational-awareness/analyze \ -H "Authorization: Bearer " \ -H "X-Request-ID: bgp-incident-20260407-001" \ -H "Content-Type: application/json" \ -d '{ "title": "BGP异常研判", "objective": "总结当前风险并给出处置建议", "observations": [ "collector A 在 5 分钟内出现多次 origin 变更", "异常集中在同一地区前缀" ], "constraints": [ "不要编造不存在的数据", "区分事实和推断" ], "context": { "source": "bgp-monitor", "severity": "high" } }' ``` ### 直接调用 `aiprovider` ```bash curl -X POST http://localhost:8010/v1/analyze \ -H "X-Provider-Token: change_me" \ -H "X-Request-ID: ai-batch-job-001" \ -H "Content-Type: application/json" \ -d '{ "title": "链路波动分析", "objective": "给出简要态势摘要和下一步建议", "observations": [ "多个节点出现延迟上升" ], "constraints": [ "不要假设根因已经确认" ], "context": { "region": "APAC" } }' ``` ## 响应结构 后端和 `aiprovider` 返回相同的 payload 结构: ```json { "provider": "minimax", "api": "anthropic-messages", "model": "MiniMax-M2.7", "content": "1) 态势摘要 ...", "content_blocks": [], "text_blocks": [], "thinking_blocks": [], "raw_response": {} } ``` 两个服务都会返回: - `X-Request-ID: ` ## 配置 ### 运行时配置链路 LLM 的全局默认配置由后端配置中心统一决定。实际调用顺序是: 1. 前端或业务代码调用 `backend` 的 `/api/v1/ai/...`。 2. `backend` 从 PostgreSQL 的 `system_settings` 表读取 `category = external_integrations`。 3. `payload.ai_provider.default_provider` 决定当前默认 provider。 4. `payload.ai_provider.providers[provider]` 提供该 provider 的 `api_key`、`provider_api`、`base_url`、`model`、`max_tokens`、`anthropic_version`。 5. `backend` 把这些值转换成 `X-AI-Provider`、`X-AI-Provider-API`、`X-AI-Base-URL`、`X-AI-API-Key`、`X-AI-Model` 等内部请求头。 6. `aiprovider` 收到头后用这些值覆盖自己的 `.env`,再调用真实模型厂商。 因此,只要 AI 设置页保存了新的默认 provider/model/key,Playground、告警摘要、数据源映射生成等所有后端 AI 调用都会使用同一个新默认配置。 #### 持久化结构 AI 配置仍保存在 PostgreSQL,不写入 JSON 文件。核心结构如下: ```json { "ai_provider": { "service_url": "http://localhost:8010", "service_token": "", "default_provider": "openai", "providers": { "openai": { "provider_api": "openai-completions", "base_url": "https://api.openai.com/v1", "model": "gpt-5.1", "api_key": "", "max_tokens": 4096, "anthropic_version": "2023-06-01" }, "minimax": { "provider_api": "anthropic-messages", "base_url": "https://api.minimaxi.com/anthropic", "model": "MiniMax-M2.7", "api_key": "", "max_tokens": 1200, "anthropic_version": "2023-06-01" } }, "timeout_seconds": 60, "retry_attempts": 2 } } ``` 历史单槽配置会在读取时兼容映射到当前 provider 的 `providers[provider]`,保存后写回新结构。 #### Key fallback 每个 provider 都有自己的 key 槽。解析顺序是: 1. PostgreSQL 中 `providers[provider].api_key` 2. `aiprovider/.env` 中 preset 对应的专属变量,例如 `OPENAI_API_KEY`、`MINIMAX_API_KEY`、`ANTHROPIC_API_KEY` 3. `aiprovider/.env` 中的通用 `AI_API_KEY` `.env` 只是兜底。配置页保存或测试连接成功后,PostgreSQL 中的配置会成为全局默认。 Admin 的密钥状态必须按 provider / tool 精确判断: - 数据库中当前 provider/tool 有密钥时,显示为“已配置”。 - 数据库没有密钥,但 fallback provider、model 或 tool 与当前项匹配时,可以显示 fallback 的脱敏预览。 - 数据库没有密钥且 fallback 不匹配当前项时,显示为“未配置”,不能把其它 provider 的 `.env` 通用 key 当成当前项已配置。 - 脱敏规则保留 key 第一个 `-` 之前的前缀,例如 `sk-********`;明文显示只在有权限的配置页面内按需触发。 工具 key 使用同样规则。WebSearch、OCR 这类工具必须先匹配当前工具和 provider,再决定能否使用 fallback。 ### 轻量连通性测试 Admin 插头按钮检查代理服务配置,再查询当前供应商目录;只有目录请求成功且包含所选模型时才返回 `success=true`。404、鉴权失败、无效响应和缺失模型都不会因命中内置建议而被改判成功。提示明确区分“找到模型”和“实际生成成功”;完整调用由 Playground 或业务任务验证。测试不保存表单或切换默认供应商。 ### OpenCode Go 路由模型 OpenCode Go 的模型协议映射由后端目录集中维护:MiniMax M3/M2.7/M2.5 和已核对的 Qwen3.6/3.7/3.8 模型使用 Anthropic Messages;GPT-5.6 Luna、Grok 4.6 和 Muse Spark Contributor 使用 Responses;其余已支持模型使用 Chat Completions。官方 `/models` 当前只提供模型 ID,新增模型的协议仍需对照官方端点表核对。前端选择模型时同步对应协议,后端覆盖旧的已知错误映射。Responses 请求使用 `input`、`max_output_tokens` 和 `store=false`;回复解析文本及推理摘要。OpenCode 请求携带应用 User-Agent 和会话标识;Playground 同一会话保持标识稳定。MiniMax M3 的通用 `thinking=enabled` 转为官方 `adaptive` 格式。 #### 配置页行为 - Provider 下拉框决定当前默认 provider。 - 模型下拉框保存当前 provider 的默认模型。 - LLM API Key 输入框隐藏时显示脱敏预览;有 `-` 前缀的 key 会保留前缀,例如 `sk-********`,没有前缀的 key 全量脱敏。 - 点击眼睛会从后端取回完整明文;再次隐藏会恢复脱敏预览。 - “保存 AI 配置”直接保存当前表单为全局默认配置。 - “测试连接”先用当前表单发起真实模型链路测试,成功后也会保存为全局默认配置;失败不会覆盖旧配置。 - 清空输入框并保存表示保留旧 key,不表示删除 key。 ### 后端 推荐的后端 `.env`: ```env AI_PROVIDER_SERVICE_URL=http://localhost:8010 AI_PROVIDER_SERVICE_TOKEN=change_me AI_PROVIDER_TIMEOUT_SECONDS=60 AI_PROVIDER_RETRY_ATTEMPTS=2 ``` 参考文件: - [backend/.env.example](/home/ray/dev/linkong/planet/backend/.env.example) ### AI Provider 参考文件: - [aiprovider/.env.example](/home/ray/dev/linkong/planet/aiprovider/.env.example) 前端本地参考: - [frontend/.env.example](/home/ray/dev/linkong/planet/frontend/.env.example) 通用配置: ```env SERVICE_NAME=planet-ai-provider SERVICE_VERSION=0.1.0 AI_PROVIDER_SERVICE_TOKEN=change_me AI_TIMEOUT_SECONDS=60 AI_HTTP_RETRY_ATTEMPTS=2 ``` 可选 provider 专属 key: ```env MINIMAX_API_KEY=sk-cp-xxxxx OPENAI_API_KEY=sk-xxxxx ANTHROPIC_API_KEY=sk-ant-xxxxx DEEPSEEK_API_KEY=sk-xxxxx DASHSCOPE_API_KEY=sk-xxxxx MOONSHOT_API_KEY=sk-xxxxx OPENROUTER_API_KEY=sk-or-xxxxx ``` ### OpenAI 兼容示例 ```env AI_PROVIDER=openai AI_PROVIDER_API=openai-completions AI_BASE_URL=http://127.0.0.1:8001/v1 AI_API_KEY=local-key AI_MODEL=your-local-model ``` ### MiniMax 中国区示例 ```env AI_PROVIDER=minimax AI_PROVIDER_API=anthropic-messages AI_BASE_URL=https://api.minimaxi.com/anthropic AI_API_KEY=sk-cp-xxxxx AI_MODEL=MiniMax-M2.7 AI_MAX_TOKENS=1200 AI_ANTHROPIC_VERSION=2023-06-01 ``` MiniMax 说明: - 这里使用官方 MiniMax 示例中的 Anthropic Messages 请求结构。 - 对 MiniMax,`aiprovider` 默认不会开启 `thinking`,除非调用方显式传入 `thinking` 对象。 - 这个行为和 OpenClaw 对 MiniMax Anthropic 兼容接口的谨慎处理保持一致。 ### Anthropic 兼容示例 ```env AI_PROVIDER=anthropic AI_PROVIDER_API=anthropic-messages AI_BASE_URL=https://your-claude-compatible-endpoint.example.com/anthropic AI_API_KEY=your_api_key AI_MODEL=your-model AI_MAX_TOKENS=1200 AI_ANTHROPIC_VERSION=2023-06-01 ``` ### Ollama 示例 ```env AI_PROVIDER=ollama AI_PROVIDER_API=ollama-generate AI_BASE_URL=http://127.0.0.1:11434 AI_API_KEY= AI_MODEL=qwen2.5:7b ``` ## 部署模式 ### 单机部署 推荐的本地流程: - `backend` 运行在 `localhost:8000` - `aiprovider` 运行在 `localhost:8010` - 本地模型网关运行在 `localhost:11434` 或其它本地端口 仓库内已包含辅助入口: - [planet.sh](/home/ray/dev/linkong/planet/planet.sh) - [docker-compose.local-model.yml](/home/ray/dev/linkong/planet/docker-compose.local-model.yml) ### 多机部署 示例拓扑: - 应用机器:`backend` - AI 网关机器:`aiprovider` - 模型机器:本地模型服务或云代理 此时链路变成服务间 HTTP RPC: - caller -> backend - backend -> `http://10.0.0.12:8010` - `aiprovider` -> 模型端点 推荐的跨机器后端配置: ```env AI_PROVIDER_SERVICE_URL=http://10.0.0.12:8010 AI_PROVIDER_SERVICE_TOKEN=change_me AI_PROVIDER_TIMEOUT_SECONDS=60 AI_PROVIDER_RETRY_ATTEMPTS=2 ``` 推荐运行规则: - 将 `aiprovider` 放在私有网络内 - 至少用 `X-Provider-Token` 保护它 - 始终发送 `X-Request-ID` - 除基础设施任务外,调用方优先走后端 API ## 重试和失败行为 `backend -> aiprovider`: - 对轻量网络错误和 5xx 失败进行重试 - provider 服务不可用时返回 `502` `aiprovider -> model provider`: - 对轻量网络错误和 5xx 失败进行重试 - 模型提供方不可用时返回 `502` 这个策略故意保持保守:它能吸收短暂抖动,但不会掩盖持续性错误。 ## 运维说明 - `./planet.sh start` 会自动启动 `aiprovider` - `./planet.sh restart -a` 只重启 `aiprovider` - `./planet.sh log -a` 跟随查看 `aiprovider` 日志 - `./planet.sh health` 会报告 `aiprovider` 健康状态 ## 推荐调用策略 - 前端和应用服务:调用 `backend` - 定时基础设施任务和诊断任务:可选直接调用 `aiprovider` - 不要让多个业务服务分别接入模型厂商 这样可以集中管理 provider 切换,避免模型相关差异在系统里四处扩散。