feat: add aiprovider service foundation
This commit is contained in:
290
docs/aiprovider.md
Normal file
290
docs/aiprovider.md
Normal file
@@ -0,0 +1,290 @@
|
||||
# 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`
|
||||
|
||||
## Supported Providers
|
||||
|
||||
`aiprovider` currently supports:
|
||||
|
||||
- `openai`
|
||||
- `openai_compatible`
|
||||
- `anthropic`
|
||||
- `anthropic_compatible`
|
||||
- `claude_compatible`
|
||||
- `ollama`
|
||||
|
||||
Provider mapping:
|
||||
|
||||
- `vLLM`, `LM Studio`, `One API`: `openai_compatible`
|
||||
- `MiniMax`, Claude-compatible gateways: `claude_compatible`
|
||||
- `Ollama`: `ollama`
|
||||
|
||||
## API Surfaces
|
||||
|
||||
### Main backend API
|
||||
|
||||
Preferred stable entrypoints:
|
||||
|
||||
- `GET /api/v1/ai/provider/status`
|
||||
- `POST /api/v1/ai/situational-awareness/analyze`
|
||||
|
||||
Authentication:
|
||||
|
||||
- `Authorization: Bearer <jwt>`
|
||||
|
||||
Optional tracing header:
|
||||
|
||||
- `X-Request-ID: <caller-generated-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: <shared-secret>`
|
||||
|
||||
Optional tracing header:
|
||||
|
||||
- `X-Request-ID: <caller-generated-id>`
|
||||
|
||||
## Request Example
|
||||
|
||||
### Call through backend
|
||||
|
||||
```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"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### 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": "openai_compatible",
|
||||
"model": "gpt-4o-mini",
|
||||
"content": "1) 态势摘要 ...",
|
||||
"raw_response": {}
|
||||
}
|
||||
```
|
||||
|
||||
Both services also return:
|
||||
|
||||
- `X-Request-ID: <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_compatible
|
||||
AI_BASE_URL=http://127.0.0.1:8001/v1
|
||||
AI_API_KEY=local-key
|
||||
AI_MODEL=your-local-model
|
||||
```
|
||||
|
||||
### Claude-compatible example
|
||||
|
||||
```env
|
||||
AI_PROVIDER=claude_compatible
|
||||
AI_BASE_URL=https://your-claude-compatible-endpoint.example.com
|
||||
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_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.
|
||||
Reference in New Issue
Block a user