334 lines
7.6 KiB
Markdown
334 lines
7.6 KiB
Markdown
# AI Provider 指南
|
||
|
||
## 概览
|
||
|
||
`aiprovider` 是 Planet 的模型适配服务。
|
||
|
||
它把模型厂商差异隔离在主后端之外,让系统其它部分可以调用稳定的业务 API:
|
||
|
||
- 调用方服务 -> `planet backend`
|
||
- `planet backend` -> `aiprovider`
|
||
- `aiprovider` -> 具体模型提供方
|
||
|
||
推荐默认方式:
|
||
|
||
- 外部调用方和跨服务调用方统一调用 `planet backend`
|
||
- 只有基础设施级内部任务才直接调用 `aiprovider`
|
||
|
||
## 职责边界
|
||
|
||
`backend` 负责:
|
||
|
||
- 身份认证和权限控制
|
||
- 业务层请求整理
|
||
- 稳定的 `/api/v1/ai/...` 接口
|
||
- 面向 `aiprovider` 的内部服务认证
|
||
|
||
`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`
|
||
- `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 <jwt>`
|
||
|
||
可选追踪头:
|
||
|
||
- `X-Request-ID: <caller-generated-id>`
|
||
|
||
后端会把 `X-Request-ID` 透传给 `aiprovider`,并在响应中返回同一个 header。
|
||
|
||
### AI Provider 内部 API
|
||
|
||
仅供内部调用的接口:
|
||
|
||
- `GET /v1/provider/status`
|
||
- `POST /v1/analyze`
|
||
|
||
认证方式:
|
||
|
||
- `X-Provider-Token: <shared-secret>`
|
||
|
||
可选追踪头:
|
||
|
||
- `X-Request-ID: <caller-generated-id>`
|
||
|
||
## 请求示例
|
||
|
||
### 通过后端调用
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8000/api/v1/ai/situational-awareness/analyze \
|
||
-H "Authorization: Bearer <access_token>" \
|
||
-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: <id>`
|
||
|
||
## 配置
|
||
|
||
### 后端
|
||
|
||
推荐的后端 `.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
|
||
AI_ANALYSIS_SYSTEM_PROMPT=你是态势感知分析助手。请基于输入的上下文、观测与约束,输出结构化、克制、可执行的分析。
|
||
```
|
||
|
||
### 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 切换,避免模型相关差异在系统里四处扩散。
|