# AI Provider Guide ## Overview `aiprovider` is the model-adapter service for Planet. It isolates model-vendor details from the main backend so the rest of the system can call a stable business API: - Caller service -> `planet backend` - `planet backend` -> `aiprovider` - `aiprovider` -> concrete model provider The recommended default is: - External and cross-service callers use `planet backend` - Only infrastructure-grade internal jobs call `aiprovider` directly ## Responsibilities `backend` is responsible for: - authentication and authorization - business-level request shaping - stable `/api/v1/ai/...` endpoints - internal service-to-service authentication toward `aiprovider` `aiprovider` is responsible for: - model protocol adaptation - provider selection by `.env` - timeout and lightweight retry - request tracing via `X-Request-ID` This now follows an OpenClaw-like seam: - `AI_PROVIDER` identifies the vendor or logical provider - `AI_PROVIDER_API` identifies the wire adapter That split makes MiniMax, Claude-compatible gateways, and self-hosted OpenAI-compatible services easier to model without overloading one config field. ## Supported Providers `aiprovider` currently supports these provider identities: - `openai` - `anthropic` - `minimax` - `ollama` Supported request adapters: - `openai-completions` - `anthropic-messages` - `ollama-generate` Backward-compatible aliases still accepted: - `openai_compatible` - `anthropic_compatible` - `claude_compatible` Provider mapping: - `vLLM`, `LM Studio`, `One API`: `AI_PROVIDER=openai`, `AI_PROVIDER_API=openai-completions` - `MiniMax`: `AI_PROVIDER=minimax`, `AI_PROVIDER_API=anthropic-messages` - Claude-compatible gateways: `AI_PROVIDER=anthropic`, `AI_PROVIDER_API=anthropic-messages` - `Ollama`: `AI_PROVIDER=ollama`, `AI_PROVIDER_API=ollama-generate` ## API Surfaces ### Main backend API Preferred stable entrypoints: - `GET /api/v1/ai/provider/status` - `POST /api/v1/ai/situational-awareness/analyze` Authentication: - `Authorization: Bearer ` Optional tracing header: - `X-Request-ID: ` The backend will propagate `X-Request-ID` to `aiprovider` and return the same header in the response. ### AI provider internal API Internal-only endpoints: - `GET /v1/provider/status` - `POST /v1/analyze` Authentication: - `X-Provider-Token: ` Optional tracing header: - `X-Request-ID: ` ## Request Example ### Call through backend ```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" } }' ``` ### Call `aiprovider` directly ```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" } }' ``` ## Response Shape Both backend and `aiprovider` return the same payload shape: ```json { "provider": "minimax", "api": "anthropic-messages", "model": "MiniMax-M2.7", "content": "1) 态势摘要 ...", "content_blocks": [], "text_blocks": [], "thinking_blocks": [], "raw_response": {} } ``` Both services also return: - `X-Request-ID: ` ## Configuration ### Backend Recommended backend `.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 ``` Reference file: - [backend/.env.example](/home/ray/dev/linkong/planet/backend/.env.example) ### AI Provider Reference file: - [aiprovider/.env.example](/home/ray/dev/linkong/planet/aiprovider/.env.example) Frontend local reference: - [frontend/.env.example](/home/ray/dev/linkong/planet/frontend/.env.example) Common settings: ```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-compatible example ```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 CN example ```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 note: - This follows the same Anthropic Messages request shape as the official MiniMax examples. - For MiniMax, `aiprovider` now disables `thinking` by default unless the caller explicitly passes a `thinking` object. - This mirrors OpenClaw's caution around MiniMax Anthropic-compatible behavior. ### Anthropic-compatible example ```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 example ```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 ``` ## Deployment Modes ### Single machine Recommended local flow: - `backend` on `localhost:8000` - `aiprovider` on `localhost:8010` - local model gateway on `localhost:11434` or another local port Helpers already included: - [planet.sh](/home/ray/dev/linkong/planet/planet.sh) - [docker-compose.local-model.yml](/home/ray/dev/linkong/planet/docker-compose.local-model.yml) ### Multi-machine Example topology: - app machine: `backend` - AI gateway machine: `aiprovider` - model machine: local model service or cloud proxy In that case, this becomes service-to-service HTTP RPC: - caller -> backend - backend -> `http://10.0.0.12:8010` - `aiprovider` -> model endpoint Recommended cross-machine backend config: ```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 ``` Recommended operating rules: - keep `aiprovider` on a private network - protect it with `X-Provider-Token` at minimum - always send `X-Request-ID` - keep callers on the backend API unless they are infrastructure jobs ## Retry And Failure Behavior `backend -> aiprovider`: - retries lightweight network / 5xx failures - returns `502` when the provider service is unavailable `aiprovider -> model provider`: - retries lightweight network / 5xx failures - returns `502` when the model provider is unavailable This is intentionally conservative. It avoids masking persistent errors while still absorbing short hiccups. ## Operational Notes - `./planet.sh start` now starts `aiprovider` automatically - `./planet.sh restart -a` restarts only `aiprovider` - `./planet.sh log -a` tails `aiprovider` logs - `./planet.sh health` reports `aiprovider` health ## Recommended Calling Policy - Frontend and application services: call `backend` - Scheduled infra jobs and diagnostics: optionally call `aiprovider` - Do not let multiple business services integrate model vendors independently That keeps provider switching centralized and avoids model-specific drift across the system.