Files
freedakgmail 93a469061d
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled
CI / security-scan (push) Has been cancelled
初始提交:边缘AI算力机统一AI通讯层
2026-08-03 07:44:05 +08:00

43 KiB
Raw Permalink Blame History

边缘 AI 算力机统一 AI 通讯层 — 产品需求文档(PRD)

文档定位:基于 0-req.md 需求规格,定义产品功能细节、用户交互流程、API 规格和交付标准,用于指导设计与研发。

版本:1.0 | 状态:初始草案 | 关联需求:0-req.md


1. 产品概述

1.1 产品定位

Edge AI Gateway 是部署在边缘 AI 算力机上的统一 AI 通讯层软件。它作为业务应用与底层推理服务之间的唯一入口,对每次 AI 调用进行准入、上下文编排、排队调度、模型路由、连接管理和资源治理。

1.2 核心价值主张

角色 痛点 价值
业务应用开发者 多种推理引擎协议不同,模型替换需改代码 一套 OpenAI 兼容 API,逻辑模型名解耦底层
系统管理员 并发请求导致 OOM,高优先级任务被阻塞 优先级队列 + 显存准入 + 公平调度
运维人员 无法统计 Token、延迟、排队和错误 统一指标、调用链和告警
安全合规 敏感数据可能泄露到云端 边缘优先 + 数据分级 + 出域审计

1.3 产品边界

┌─────────────────────────────────────────────────────┐
│                   业务应用 / Agent                    │
└──────────────────────┬──────────────────────────────┘
                       │ HTTP / SSE / WebSocket
┌──────────────────────▼──────────────────────────────┐
│              Edge AI Gateway(本产品)                │
│  ┌──────┬──────┬──────┬──────┬──────┬──────┬──────┐ │
│  │ 网关 │ 认证 │ 上下文│ 调度 │ 路由 │ 连接 │ 监控 │ │
│  └──────┴──────┴──────┴──────┴──────┴──────┴──────┘ │
└──────────────────────┬──────────────────────────────┘
                       │ 模型适配器
┌──────────────────────▼──────────────────────────────┐
│  Ollama  │  vLLM  │  llama.cpp  │  Triton  │  云端   │
└─────────────────────────────────────────────────────┘

本产品不包含: 模型训练/微调、数据标注、知识库构建、推理引擎本身的实现。


2. 目标用户与典型场景

2.1 用户画像

画像 A:业务应用开发者(主要用户)

  • 身份:在边缘算力机上部署 AI 应用的开发者。
  • 目标:快速接入 AI 能力,不关心底层是 Ollama 还是 vLLM。
  • 行为:通过 HTTP/SSE 调用 OpenAI 兼容 API,使用逻辑模型名,管理会话 ID。
  • 痛点:不同引擎协议不同;模型替换需改代码;历史消息过长导致报错。

画像 B:系统管理员

  • 身份:负责边缘算力机配置和运营的管理员。
  • 目标:合理分配算力,保证高优先级任务不被阻塞,敏感数据不出域。
  • 行为:配置模型映射、并发配额、优先级权限、安全策略和降级链。
  • 痛点:并发请求导致 OOM;无法控制哪个应用能用哪个模型;缺少降级机制。

画像 C:运维人员

  • 身份:负责系统监控和故障排查的运维工程师。
  • 目标:实时掌握系统健康状态,快速定位问题。
  • 行为:查看 Grafana 大盘,分析调用链日志,配置告警规则。
  • 痛点:无法统计首 Token 延迟、排队时长和 Token 消耗;故障时缺少链路追踪。

2.2 典型场景

场景 1:安防告警实时分析(P0 优先级)

触发:设备传感器检测到异常
应用:安防服务
流程:
  1. 安防应用提交 AI 请求,priority=P0local_only=true
  2. 网关鉴权通过,检查配额
  3. 上下文管理器组装设备日志 + 历史告警摘要
  4. 调度器将 P0 任务插入队首,资源管理器预留专用槽位
  5. 模型路由器选择本地 general-chat 模型
  6. 推理结果通过 SSE 流式返回
  7. 通讯层记录调用链和审计信息
预期:首 Token < 1s,不受后台批处理任务影响

场景 2:办公助手多轮对话(P2 优先级)

触发:用户在办公助手应用中提问
应用:办公助手
流程:
  1. 应用提交请求,session_id=session-001priority=P2
  2. 上下文管理器加载会话历史,计算 Token 预算
  3. 历史消息 + 知识检索 + 当前请求 = 18,000 Token,在预算内
  4. 调度器将任务放入 P2 队列
  5. 资源管理器检查显存,允许执行
  6. 推理结果流式返回,更新会话历史
预期:正常排队 < 5s,Token 自动管理不超限

场景 3:文档批量分析(P3 优先级,资源紧张时降级)

触发:用户上传文档请求分析
应用:文档分析
流程:
  1. 应用提交请求,priority=P3allow_smaller_model=true
  2. 调度器检查资源,发现显存不足
  3. 模型路由器按降级链切换到量化小模型
  4. 响应元数据中 degraded=trueactual_model 记录实际使用模型
  5. 审计日志记录降级原因
预期:功能完整但质量可能降低,降级过程对应用透明

场景 4:客户端断开后自动取消

触发:用户关闭浏览器,SSE 连接断开
流程:
  1. 连接管理器检测到 SSE 连接断开
  2. 触发取消信号,传播到调度器和模型适配器
  3. 模型适配器向推理引擎发送取消请求
  4. 执行槽位和 KV Cache 在 cancel_grace_period 内释放
  5. 任务状态变为 CANCELLED,记录取消原因
预期:GPU 算力和显存不浪费,资源在 3s 内释放

场景 5:敏感数据强制本地处理

触发:处理包含个人隐私信息的请求
应用:医疗信息助手
流程:
  1. 应用提交请求,routing.local_only=true
  2. 网关识别数据策略级别为"敏感"
  3. 模型路由器强制选择本地模型,跳过所有云端降级选项
  4. 即使本地资源紧张,也排队等待而非路由到云端
  5. 审计日志记录"local_only enforced"
预期:敏感数据永不出域,合规可审计

3. 功能规格

3.1 API 网关

3.1.1 接口清单

接口 方法 阶段 说明
/v1/chat/completions POST P1 文本生成,支持流式(SSE)和非流式
/v1/embeddings POST P1 向量嵌入
/v1/models GET P1 可用模型列表
/v1/sessions POST P1 创建会话
/v1/sessions/{id} GET P1 查询会话
/v1/sessions/{id} DELETE P1 删除会话
/v1/tasks POST P2 提交异步任务
/v1/tasks/{id} GET P2 查询任务状态
/v1/tasks/{id} DELETE P2 取消任务
/v1/responses POST P2 响应式接口
/v1/audio/transcriptions POST P3 语音转文字
/v1/audio/speech POST P3 文字转语音
/v1/images/analyze POST P3 图像理解
/health GET P1 健康检查(进程存活)
/ready GET P1 就绪检查(依赖就绪)

3.1.2 请求格式

POST /v1/chat/completions 请求体:

{
  "model": "general-chat",
  "messages": [
    {
      "role": "system",
      "content": "你是一名设备维护专家"
    },
    {
      "role": "user",
      "content": "请分析设备异常日志并给出处理建议"
    }
  ],
  "stream": true,
  "session_id": "session-001",
  "idempotency_key": "app01-20260803-00001234",
  "priority": "P1",
  "max_output_tokens": 1200,
  "context_policy": "summary_and_recent",
  "timeouts": {
    "queue_ms": 5000,
    "first_token_ms": 10000,
    "inference_ms": 60000,
    "total_ms": 90000
  },
  "routing": {
    "local_only": true,
    "allow_smaller_model": true
  },
  "metadata": {
    "application": "device-maintenance",
    "user_id": "user-1001",
    "trace_id": "trace-abc123"
  }
}

字段说明:

字段 类型 必填 默认值 说明
model string 逻辑模型名
messages array OpenAI 格式消息数组
stream bool false 是否流式返回
session_id string 会话 ID,用于上下文关联
idempotency_key string 幂等键,防止重复推理
priority string P2 优先级 P0P4
max_output_tokens int 模型配置 最大输出 Token 数
context_policy string summary_and_recent 上下文组装策略
timeouts object 全局配置 分层超时覆盖
routing object 全局策略 路由控制
metadata object 应用元数据

3.1.3 响应格式

非流式响应:

{
  "request_id": "req-20260803-000001",
  "task_id": "task-20260803-000001",
  "session_id": "session-001",
  "status": "succeeded",
  "model": "general-chat",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "根据日志分析,建议..."
      },
      "finish_reason": "stop"
    }
  ],
  "logical_model": "general-chat",
  "actual_model": "qwen3-8b-int4",
  "node_id": "edge-node-01",
  "usage": {
    "input_tokens": 2380,
    "output_tokens": 615,
    "total_tokens": 2995
  },
  "timing": {
    "queue_ms": 86,
    "first_token_ms": 724,
    "inference_ms": 4380,
    "total_ms": 4588
  },
  "degraded": false
}

流式响应(SSE):

data: {"request_id":"req-20260803-000001","task_id":"task-20260803-000001","status":"streaming","logical_model":"general-chat","actual_model":"qwen3-8b-int4"}

data: {"choices":[{"index":0,"delta":{"role":"assistant","content":"根据"},"finish_reason":null}]}

data: {"choices":[{"index":0,"delta":{"content":"日志分析"},"finish_reason":null}]}

data: {"choices":[{"index":0,"delta":{"content":",建议..."},"finish_reason":"stop"}],"usage":{"input_tokens":2380,"output_tokens":615,"total_tokens":2995},"timing":{"queue_ms":86,"first_token_ms":724,"inference_ms":4380,"total_ms":4588},"finish_reason":"stop","degraded":false}

data: [DONE]

首帧 包含 request_idtask_idstatuslogical_modelactual_model,让客户端尽早知道任务已接受和实际使用的模型。

末帧 包含 usagetimingfinish_reasondegraded,让客户端获取完整统计。

[DONE] 标记流结束。

3.1.4 错误响应

{
  "error": {
    "code": "QUEUE_TIMEOUT",
    "message": "请求排队等待超时,当前队列长度: 47",
    "request_id": "req-20260803-000042",
    "retry_after_ms": 3000
  }
}
HTTP 状态码 错误码 说明
401 AUTH_FAILED 认证失败
403 PERMISSION_DENIED / POLICY_BLOCKED 权限不足或策略拦截
429 RATE_LIMITED / QUOTA_EXCEEDED / QUEUE_FULL 限流或配额不足
400 INVALID_REQUEST / CONTEXT_TOO_LARGE 参数错误或上下文超限
408 QUEUE_TIMEOUT / FIRST_TOKEN_TIMEOUT / INFERENCE_TIMEOUT 超时
409 REQUEST_CANCELLED 请求已取消
503 MODEL_UNAVAILABLE / RESOURCE_EXHAUSTED 模型不可用或资源不足
500 INTERNAL_ERROR 内部错误

RATE_LIMITEDQUEUE_FULL 响应应附带 Retry-After 头。


3.2 认证与权限

3.2.1 认证流程

客户端请求
  │
  ├─ Authorization: Bearer <api_key>  ──→ API Key 校验
  ├─ Authorization: Bearer <jwt>     ──→ JWT 校验
  ├─ mTLS 证书                        ──→ 证书校验
  │
  ▼
  认证通过 → 提取 application_id, tenant_id, user_id
  认证失败 → 返回 401 AUTH_FAILED

3.2.2 权限模型

Application
  ├── allowed_models: [general-chat, fast-chat]
  ├── allowed_priorities: [P1, P2, P3]
  ├── max_running_tasks: 4
  ├── max_queued_tasks: 100
  └── data_policy:
        ├── allow_cloud: false
        └── sensitive_level: standard

User (within Application)
  ├── max_running_tasks: 1
  └── requests_per_minute: 20

3.2.3 管理接口

管理接口与业务接口分离,使用独立端口和独立认证:

接口 方法 说明
/admin/applications GET/POST/PUT/DELETE 应用管理
/admin/models GET/POST/PUT/DELETE 模型配置
/admin/policies GET/PUT 安全策略配置
/admin/quotas GET/PUT 配额配置
/admin/tasks GET 任务监控
/admin/metrics GET 内部指标

3.3 会话与上下文

3.3.1 会话生命周期

创建会话 (POST /v1/sessions)
  │
  ├── 配置: max_messages, max_tokens, ttl, idle_timeout
  │
  ▼
活跃 ──── 新消息写入 ──→ 更新 last_active
  │
  ├── idle_timeout 到期 ──→ 过期清理
  ├── max_messages 达到 ──→ 触发摘要压缩
  ├── 用户删除 ──→ 立即清除
  └── ttl 到期 ──→ 过期清理

3.3.2 上下文组装流程

输入: session_id + 当前请求 + context_policy
  │
  ├─ 1. 加载平台安全规则 (最高优先级)
  ├─ 2. 加载应用系统提示词
  ├─ 3. 注入用户身份与权限信息
  ├─ 4. 加载会话长期摘要
  ├─ 5. 加载最近 N 轮原始对话
  ├─ 6. [可选] 加载知识库检索结果
  ├─ 7. [可选] 加载工具调用结果
  ├─ 8. 追加当前用户请求
  ├─ 9. 追加输出格式与长度约束
  │
  ├─ 计算 Token 总量
  │   ├─ ≤ 预算 → 直接使用
  │   └─ > 预算 → 执行裁剪流程
  │
  └─ 输出: 组装后的 messages + token_count + budget_report

3.3.3 Token 预算分配示例

模型窗口 32,768 Token,安全系数 0.9,可用预算 29,491 Token

上下文部分 分配比例 Token 数
平台与应用系统指令 7% 2,000
会话摘要 14% 4,000
最近对话 31% 9,000
知识检索结果 27% 8,000
当前请求与工具结果 10% 3,000
模型输出预留 21% 6,000
合计 100% ~29,000

3.3.4 上下文裁剪策略

超限?
  │
  ├─ Step 1: 删除重复/低相关度知识片段 → 重新计算
  ├─ Step 2: 压缩工具返回结果 → 重新计算
  ├─ Step 3: 删除最早无关键状态对话 → 重新计算
  ├─ Step 4: 早期对话转为摘要 → 重新计算
  ├─ Step 5: 减少检索结果数量/长度 → 重新计算
  ├─ Step 6: [策略允许] 切换更大上下文模型 → 重新计算
  └─ Step 7: 仍超限 → 返回 CONTEXT_TOO_LARGE

保护项(不可裁剪): 系统指令、权限信息、当前用户请求、输出约束。


3.4 队列与调度

3.4.1 调度流程

请求准入
  │
  ├─ 鉴权 → 配额检查 → 限流检查 → 参数校验 → 幂等检查
  │
  ▼
创建任务 (状态: QUEUED)
  │
  ├─ 按优先级放入对应队列
  │   ├── P0 队列 (reserved_realtime_slots)
  │   ├── P1 队列
  │   ├── P2 队列 (默认)
  │   ├── P3 队列
  │   └─ P4 队列 (仅空闲时)
  │
  ▼
调度循环 (每个 tick)
  │
  ├─ 1. 检查资源管理器: 显存、执行槽位、模型状态
  ├─ 2. 按加权公平队列选择下一个任务
  │     weight = base_priority_weight + aging_bonus(wait_time)
  ├─ 3. 检查任务是否超时 (queue_timeout)
  │     ├─ 超时 → 状态变为 TIMED_OUT
  │     └─ 未超时 → 分派执行
  └─ 4. 提交到模型适配器 (状态: DISPATCHING → RUNNING)

3.4.2 优先级与公平性配置

scheduler:
  max_running_tasks: 8
  max_queued_tasks: 500
  fairness: weighted_fair_queue
  priority_aging_seconds: 30
  reserved_realtime_slots: 2

  priorities:
    P0:
      weight: 100
      reserved_slots: 2
    P1:
      weight: 50
    P2:
      weight: 25
    P3:
      weight: 10
    P4:
      weight: 1
      run_only_when_idle: true

applications:
  security_service:
    max_running_tasks: 4
    max_queued_tasks: 100
    allowed_priorities: [P0, P1]
  office_assistant:
    max_running_tasks: 2
    max_queued_tasks: 50
    allowed_priorities: [P2, P3]
  doc_analyzer:
    max_running_tasks: 1
    max_queued_tasks: 30
    allowed_priorities: [P3, P4]

users:
  default_max_running_tasks: 1
  default_requests_per_minute: 20

3.4.3 显存准入估算

输入: model, input_tokens, max_output_tokens, concurrency
  │
  ├─ model_weight_mem = 模型权重大小 (查表)
  ├─ kv_cache_input = input_tokens × per_token_kv_size
  ├─ kv_cache_output = max_output_tokens × per_token_kv_size
  ├─ batch_temp = 估算并发批次临时显存
  ├─ multimodal_mem = 图像/音频编码占用 (如适用)
  ├─ safety_margin = total × safety_margin_ratio (默认 0.08)
  │
  ├─ estimated_total = model_weight + kv_cache_input + kv_cache_output
  │                   + batch_temp + multimodal_mem + safety_margin
  │
  ├─ estimated_total ≤ available_vram?
  │   ├─ 是 → 准入,状态变为 DISPATCHING
  │   └─ 否 → 按降级链处理
  │       ├─ 减少输出长度 → 重新估算
  │       ├─ 切换量化模型 → 重新估算
  │       ├─ 切换小模型 → 重新估算
  │       ├─ 排队等待 → 状态保持 QUEUED
  │       └─ 拒绝 → 返回 RESOURCE_EXHAUSTED
  └─

3.5 连接与超时管理

3.5.1 分层超时时间线

请求到达
│
├── connect_timeout (建立连接)
│   └── 超时 → 连接失败,不创建任务
│
├── queue_timeout (排队等待)
│   └── 超时 → 返回 QUEUE_TIMEOUT
│
├── first_token_timeout (首 Token 等待)
│   └── 超时 → 取消任务或切换模型
│
├── inference_timeout (推理执行)
│   └── 超时 → 向推理引擎发送取消信号
│
├── idle_timeout (流式空闲)
│   └── 超时 → 检查模型状态,终止异常连接
│
├── total_timeout (总时间)
│   └── 超时 → 强制结束整个生命周期
│
└── cancel_grace_period (取消后等待)
    └── 超时 → 隔离或重启异常实例

3.5.2 默认超时配置

timeouts:
  default_connect_ms: 5000
  default_queue_ms: 5000
  default_first_token_ms: 10000
  default_inference_ms: 60000
  default_idle_ms: 15000
  default_total_ms: 90000
  cancel_grace_period_ms: 3000

3.5.3 取消传播链路

触发源:
  ├─ 客户端主动取消 (DELETE /v1/tasks/{id})
  ├─ SSE/WebSocket 连接断开 (TCP FIN/RST)
  ├─ 队列超时
  ├─ 首 Token 超时
  ├─ 推理超时
  ├─ 总超时
  ├─ 管理员终止
  ├─ 权限撤销
  └─ 设备危险状态 (温度/显存/负载)
      │
      ▼
  网关标记任务为 CANCELLED
      │
      ▼
  调度器从队列移除 (如仍在排队)
      │
      ▼
  连接管理器向模型适配器发送取消信号
      │
      ▼
  模型适配器调用推理引擎取消 API
      │
      ├─ 取消成功 → 释放执行槽位 + KV Cache
      └─ cancel_grace_period 内未响应 → 隔离实例
      │
      ▼
  记录取消原因和资源释放时间

3.6 任务状态机

                    ┌──────────┐
                    │ RECEIVED │
                    └────┬─────┘
                         ▼
                   ┌───────────┐
                   │ VALIDATING│
                   └──┬────┬──┘
             ┌────────┘    └────────┐
             ▼                       ▼
      ┌──────────┐            ┌───────────┐
      │ REJECTED │            │  QUEUED    │
      └────┬─────┘            └─┬──┬──┬───┘
           │             ┌─────┘  │  └──────┐
           │             ▼        ▼         ▼
           │     ┌──────────┐ ┌────────┐ ┌───────────┐
           │     │TIMED_OUT │ │CANCELLED│ │DISPATCHING│
           │     └────┬─────┘ └───┬────┘ └──┬───┬───┘
           │          │           │          │   │
           │          │           │          ▼   ▼
           │          │           │    ┌──────┐ ┌──────┐
           │          │           │    │RUNNING│ │FAILED│
           │          │           │    └─┬──┬─┘ └──┬───┘
           │          │           │      │  │      │
           │          │           │      ▼  ▼      │
           │          │           │   ┌─────────┐  │
           │          │           │   │STREAMING│  │
           │          │           │   └─┬─┬─┬─┬─┘  │
           │          │           │     │ │ │ │    │
           │          │           │     ▼ ▼ ▼ ▼    │
           │          │           │  ┌────┐┌────┐  │
           │          │           │  │SUCC││TIME│  │
           │          │           │  │EED ││OUT │  │
           │          │           │  └─┬──┘└─┬──┘  │
           │          │           │    │      │     │
           ▼          ▼           ▼    ▼      ▼     ▼
      ┌────────┐ ┌────────┐ ┌────────┐ ┌──────┐ ┌──────┐
      │REJECTED│ │TIMED_  │ │CANCEL  │ │SUCCE │ │FAILED│
      │ (终态) │ │OUT(终态)│ │LED(终态)│ │ED(终态)│ │(终态)│
      └────────┘ └────────┘ └────────┘ └──────┘ └──────┘

每次状态变化记录:

{
  "task_id": "task-20260803-000001",
  "from_state": "QUEUED",
  "to_state": "DISPATCHING",
  "timestamp": "2026-08-03T06:56:00.123Z",
  "reason": "resource_available",
  "node_id": "edge-node-01",
  "model_instance": "qwen3-8b-int4#0",
  "operator": "scheduler"
}

3.7 模型路由

3.7.1 逻辑模型映射

models:
  general-chat:
    provider: vllm
    actual_model: qwen3-8b-int4
    endpoint: http://127.0.0.1:8001
    context_window: 32768
    max_output_tokens: 4096
    max_concurrency: 4
    residency: always
    cancel_supported: true

  fast-chat:
    provider: ollama
    actual_model: qwen3:4b
    endpoint: http://127.0.0.1:11434
    context_window: 16384
    max_output_tokens: 2048
    max_concurrency: 2
    residency: on_demand
    idle_unload_seconds: 600

  vision-analysis:
    provider: ollama
    actual_model: llama3.2-vision:11b
    endpoint: http://127.0.0.1:11434
    context_window: 8192
    max_output_tokens: 2048
    max_concurrency: 1
    residency: on_demand
    idle_unload_seconds: 300

3.7.2 路由决策矩阵

决策因素 数据来源 权重
任务类型/模态 请求参数 必须 match
数据隐私级别 应用策略 + 请求 routing 硬约束
模型已加载 资源管理器
队列长度 调度器
显存余量 资源管理器
模型错误率 可观测模块
设备温度/功耗 系统监控
延迟要求 请求 priority
成本 配置

3.7.3 降级链执行

请求需要 general-chat 模型
  │
  ├─ 1. 检查 general-chat 本地实例是否可用
  │     ├─ 可用 → 使用
  │     └─ 不可用 ↓
  │
  ├─ 2. 检查同设备上的小模型 (fast-chat)
  │     ├─ 可用且 allow_smaller_model=true → 使用,degraded=true
  │     └─ 不可用 ↓
  │
  ├─ 3. 检查其他边缘节点 (第三阶段)
  │     ├─ 可用 → 转发,degraded=true
  │     └─ 不可用 ↓
  │
  ├─ 4. 返回缓存/规则化结果 (如适用)
  │     ├─ 命中 → 返回,degraded=true
  │     └─ 未命中 ↓
  │
  ├─ 5. 检查云端模型 (如 allow_cloud=true 且数据策略允许)
  │     ├─ 可用 → 路由云端,degraded=true,审计记录
  │     └─ 不可用 ↓
  │
  └─ 6. 返回 MODEL_UNAVAILABLE 或系统繁忙

3.8 可靠性机制

3.8.1 幂等控制

请求到达,携带 idempotency_key
  │
  ├─ 查询幂等存储 (Redis / SQLite)
  │   ├─ 存在且未过期 → 返回原任务状态/结果
  │   ├─ 存在且已过期 → 创建新任务,更新幂等记录
  │   └─ 不存在 → 创建新任务,写入幂等记录
  │
  └─ 幂等记录结构:
      {
        "idempotency_key": "app01-20260803-00001234",
        "tenant_id": "tenant-01",
        "application_id": "app-01",
        "task_id": "task-20260803-000001",
        "created_at": "2026-08-03T06:56:00Z",
        "expires_at": "2026-08-03T07:06:00Z",
        "status": "succeeded"
      }

3.8.2 熔断器状态机

                  错误率 < 阈值
            ┌──────────────────────┐
            │                      │
            ▼                      │
      ┌──────────┐          ┌──────────┐
      │  CLOSED  │◄────────│  HALF    │
      │ (正常路由) │          │  OPEN    │
      └────┬─────┘          └────┬─────┘
           │                     │
           │ 错误率 ≥ 阈值         │ 探测请求成功
           │ 或连续错误            │
           ▼                     │
      ┌──────────┐               │
      │   OPEN   │───────────────┘
      │ (熔断中)  │ 探测间隔后
      └──────────┘ 放行单个请求

熔断范围:模型实例、设备节点、云端供应商、具体 API。

3.8.3 背压执行

系统负载评估 (每个 tick)
  │
  ├─ 负载 < 70% → 正常运行
  │
  ├─ 负载 70%-85% → Level 1 背压
  │   ├─ 限制 P4 新请求
  │   └─ 缩短 P3/P4 队列等待时间
  │
  ├─ 负载 85%-95% → Level 2 背压
  │   ├─ 限制 P3/P4 新请求
  │   ├─ 降低单请求 max_output_tokens 上限
  │   └─ 将批处理任务延后
  │
  └─ 负载 > 95% → Level 3 背压
      ├─ 限制 P2 及以下新请求
      ├─ 路由至备用节点/小模型
      └─ 返回 503 + Retry-After

3.9 可观测性

3.9.1 指标暴露

通过 Prometheus /metrics 端点暴露指标:

# 请求指标
edgeai_requests_total{application,model,priority,status}  # Counter
edgeai_request_duration_seconds{application,model}         # Histogram
edgeai_queue_time_seconds{application,model}               # Histogram
edgeai_first_token_latency_seconds{application,model}      # Histogram
edgeai_tokens_total{application,model,direction}           # Counter (input/output)
edgeai_tokens_per_second{model}                            # Gauge
edgeai_active_tasks{application,model}                     # Gauge
edgeai_queue_length{priority}                              # Gauge

# 资源指标
edgeai_gpu_utilization{device}                             # Gauge
edgeai_gpu_memory_used_bytes{device}                       # Gauge
edgeai_gpu_memory_total_bytes{device}                      # Gauge
edgeai_kv_cache_usage_ratio{model}                         # Gauge
edgeai_model_loaded{model}                                 # Gauge (0/1)
edgeai_model_load_time_seconds{model}                     # Histogram
edgeai_device_temperature_celsius{device}                 # Gauge
edgeai_device_power_watts{device}                          # Gauge

# 质量指标
edgeai_degradation_total{application,from_model,to_model} # Counter
edgeai_context_trimming_total{application}                # Counter
edgeai_policy_blocked_total{application,reason}           # Counter
edgeai_cancellation_total{application,reason}             # Counter

3.9.2 调用链日志结构

每次调用生成一条结构化 JSON 日志,通过 request_idtask_idsession_idtrace_id 串联:

{
  "timestamp": "2026-08-03T06:56:00.123Z",
  "level": "INFO",
  "event": "task_state_change",
  "request_id": "req-20260803-000001",
  "task_id": "task-20260803-000001",
  "session_id": "session-001",
  "trace_id": "trace-abc123",
  "application": "device-maintenance",
  "tenant_id": "tenant-01",
  "user_id": "user-1001",
  "from_state": "QUEUED",
  "to_state": "DISPATCHING",
  "logical_model": "general-chat",
  "actual_model": "qwen3-8b-int4",
  "node_id": "edge-node-01",
  "reason": "resource_available",
  "queue_time_ms": 86,
  "input_tokens": 2380,
  "output_tokens": 0,
  "prompt_hash": "sha256:abc123...",
  "context_version": "v3",
  "degraded": false
}

日志策略:

  • 默认 metadata_only:不记录完整 Prompt 内容,只记录哈希。
  • 排障模式 full:通过管理接口临时开启,记录完整内容,自动过期关闭。
  • 敏感字段自动脱敏(API Key、密钥、个人信息)。

3.9.3 告警规则

告警名称 条件 严重级别
HighFirstTokenLatency P95 首 Token 延迟 > 阈值持续 5min Warning
QueueNearFull 队列使用率 > 80% 持续 2min Warning
ModelOOM 检测到 OOM 或模型进程重启 Critical
ModelErrorRateHigh 某模型错误率 > 10% 持续 5min Warning
GpuTemperatureDanger GPU 温度 > 阈值 Critical
ResourceLeakDetected 任务取消后资源未释放 Critical
CloudFallbackSpike 云端降级比例异常增加 Warning
AuthFailureSpike 认证失败或策略拦截异常增加 Warning

4. 配置规格

4.1 全局配置文件

server:
  host: 0.0.0.0
  port: 8080
  admin_port: 8081
  max_request_body_mb: 20

auth:
  enabled: true
  methods: [api_key, jwt]
  jwt_issuer: edge-ai-gateway
  jwt_secret_env: EDGEAI_JWT_SECRET

scheduler:
  max_running_tasks: 8
  max_queued_tasks: 500
  fairness: weighted_fair_queue
  priority_aging_seconds: 30
  reserved_realtime_slots: 2

timeouts:
  default_connect_ms: 5000
  default_queue_ms: 5000
  default_first_token_ms: 10000
  default_inference_ms: 60000
  default_idle_ms: 15000
  default_total_ms: 90000
  cancel_grace_period_ms: 3000

context:
  safety_margin_ratio: 0.08
  default_policy: summary_and_recent
  max_session_messages: 200
  session_idle_ttl_minutes: 60
  enable_prompt_persistence: false

models:
  general-chat:
    provider: vllm
    actual_model: qwen3-8b-int4
    endpoint: http://127.0.0.1:8001
    context_window: 32768
    max_output_tokens: 4096
    max_concurrency: 4
    residency: always
    cancel_supported: true

  fast-chat:
    provider: ollama
    actual_model: qwen3:4b
    endpoint: http://127.0.0.1:11434
    context_window: 16384
    max_output_tokens: 2048
    max_concurrency: 2
    residency: on_demand
    idle_unload_seconds: 600

routing:
  sensitive_data_local_only: true
  allow_cloud_fallback_by_default: false
  overload_strategy:
    - same_model_other_instance
    - smaller_local_model
    - backup_edge_node
    - reject

circuit_breaker:
  error_rate_threshold: 0.1
  min_requests: 10
  window_seconds: 60
  open_duration_seconds: 30
  half_open_max_requests: 1

backpressure:
  level1_threshold: 0.70
  level2_threshold: 0.85
  level3_threshold: 0.95

observability:
  metrics_enabled: true
  metrics_path: /metrics
  tracing_enabled: true
  prompt_logging: metadata_only
  audit_retention_days: 180
  log_level: info

storage:
  session_db: sqlite:///var/lib/edgeai/sessions.db
  task_state: sqlite:///var/lib/edgeai/tasks.db
  redis:
    enabled: false
    endpoint: redis://127.0.0.1:6379

4.2 环境变量

变量名 说明 示例
EDGEAI_JWT_SECRET JWT 签名密钥
EDGEAI_ADMIN_KEY 管理接口认证密钥
EDGEAI_CLOUD_API_KEY 云端模型 API 密钥
EDGEAI_DB_PATH 数据库文件路径 /var/lib/edgeai
EDGEAI_LOG_LEVEL 日志级别 info
EDGEAI_CONFIG_PATH 配置文件路径 /etc/edgeai/config.yaml

5. 产品指标与成功标准

5.1 北极星指标

单台边缘算力机同时服务的应用数 × 平均每应用日调用成功率

5.2 核心产品指标

指标 MVP 目标 生产目标
通讯层附加延迟 ≤ 50ms ≤ 20ms
首 Token P95 延迟 ≤ 3s ≤ 1s
请求成功率 ≥ 95% ≥ 99%
客户端断开后资源释放时间 ≤ 5s ≤ 3s
模型替换后 API 兼容性 100% 100%
并发上限下 OOM 次数 0 0
跨租户数据泄露事件 0 0

5.3 用户满意度指标

指标 目标
应用接入耗时(从零到首次成功调用) ≤ 30 分钟
模型替换对应用的影响 零代码修改
运维故障定位时间 ≤ 10 分钟(通过调用链)

6. 交付计划

6.1 里程碑

里程碑 内容 交付物
M1: MVP 统一 API + 鉴权 + 队列 + 超时 + 取消 + Ollama 适配 + 基础指标 可部署的二进制 + 配置文件 + API 文档
M2: 治理增强 会话持久化 + 幂等 + 模型路由 + 降级 + 熔断 + 背压 + vLLM 适配 + 监控大盘 增量功能 + Grafana 面板
M3: 多节点多模态 多节点调度 + 视觉/语音接口 + WebSocket + 云端路由 + 多租户计量 集群部署方案 + 多模态适配器

6.2 MVP 交付清单

序号 功能项 优先级 对应需求
1 POST /v1/chat/completions(流式 + 非流式) P0 FR-1.1
2 GET /v1/models P0 FR-1.1
3 GET /health + GET /ready P0 FR-1.1
4 API Key 鉴权 P0 FR-2.1
5 应用级 + 模型级并发限制 P0 FR-2.3
6 五级优先级队列 P0 FR-4.2
7 加权公平调度 + 优先级老化 P1 FR-4.3
8 Token 预算计算 + 基础裁剪 P0 FR-3.2, FR-3.3
9 分层超时(queue + first_token + inference + total P0 FR-5.1
10 SSE 流式输出 P0 FR-1.2
11 客户端断开 → 推理取消 P0 FR-5.2
12 任务状态机 P0 FR-6
13 Ollama 模型适配器 P0 FR-11.1
14 请求/Token/延迟/错误指标 P0 FR-10.1
15 统一错误码 P0 FR-1.6
16 会话创建/查询/删除 P1 FR-3.4
17 逻辑模型映射 P0 FR-7.1
18 GPU 使用率/显存指标 P1 FR-10.1

6.3 第二阶段交付清单

序号 功能项 对应需求
1 会话持久化与历史摘要 FR-3.4, FR-3.5
2 Redis 任务状态 + 幂等控制 FR-8.1
3 动态模型路由 + 小模型降级 FR-7.2, FR-7.3
4 显存准入估算 FR-4.5
5 连续批处理控制 FR-4.6
6 模型驻留 + 自动卸载 FR-4.7
7 熔断 + 有限重试 + 背压 FR-8.2, FR-8.3, FR-8.4
8 vLLM 模型适配器 FR-11.1
9 管理后台 API 3.2.3
10 Grafana 监控大盘 FR-10.1
11 调用链日志 + 告警规则 FR-10.2, FR-10.3
12 异步任务接口 (/v1/tasks) FR-1.1
13 Prompt 注入防护 FR-3.7

7. 依赖与约束

7.1 外部依赖

依赖 用途 MVP 必需
Ollama 推理引擎
vLLM 推理引擎 否(第二阶段)
SQLite 会话/配置/任务状态存储
Redis 幂等/共享状态(可选)
Prometheus 指标采集
Grafana 指标展示 否(第二阶段)

7.2 技术约束

  • 通讯层与推理服务必须独立进程部署。
  • 通讯层必须能检测推理实例崩溃并重新接入。
  • 第一阶段不引入分布式组件(除可选 Redis)。
  • 配置文件为 YAML 格式,支持热重载。
  • 日志为结构化 JSON,输出到 stdout 和/或文件。

7.3 安全约束

  • 密钥不写入代码、日志或普通配置文件。
  • 云端降级默认禁止。
  • 敏感数据强制本地处理。
  • 日志默认不记录完整 Prompt。

8. 开放问题与决策

8.1 决策汇总

编号 问题 决策 阶段
Q1 通讯层实现语言选择 Go M1
Q2 MVP 认证方式 API Key 优先,JWT 预留接口 M1 仅 API Key
Q3 管理后台形式 仅管理 API,无 UI M1-M2
Q4 Token 计数策略 引擎返回优先,估算兜底 M1 实现
Q5 KV Cache 估算方式 配置静态值 → 引擎查询 → 历史回归 M2 实现
Q6 多 GPU/NPU 混合调度 不实现,预留接口 M3

8.2 Q1:通讯层实现语言 — Go

维度 Go Rust Python(FastAPI)
并发模型 goroutine 天然适合高并发流式 async/tokio 性能最优但学习曲线陡 asyncio 可用但 GCL 限制 CPU 密集
SSE/流式 标准库 net/http 原生支持 hyper/tokio 性能更好但复杂 FastAPI StreamingResponse 够用
部署体积 单二进制,无运行时依赖 单二进制,无运行时依赖 需要 Python 运行时 + 依赖包
边缘适配 交叉编译简单,内存占用低 最优但开发慢 内存占用最高
团队上手 中等,语法简单 高,学习曲线陡 最低,但维护性差
生态 HTTP/JSON/gRPC 一等公民 生态在完善中 最丰富但类型安全弱

决策理由:

  • 边缘设备要求单二进制部署、低内存占用、无运行时依赖。
  • goroutine 天然适配大量 SSE 流式连接和取消信号传播。
  • HTTP/JSON/gRPC 生态成熟,开发效率高于 Rust。
  • 配置热重载、结构化日志、Prometheus 客户端都有成熟库。

如果团队有 Rust 经验且对延迟有极致要求,Rust 是更优选择,但 MVP 阶段 Go 的开发效率优势更大。

8.3 Q2MVP 认证方式 — API Key 优先,JWT 预留接口

决策: MVP 仅实现 API Key,认证模块设计为策略模式,预留 JWT 扩展点。

理由:

  • API Key 实现简单(Header 校验 + 存储查表),MVP 阶段应用数量少,足够使用。
  • JWT 需要签发、刷新、吊销机制,工作量大且 MVP 阶段无明确需求。
  • 认证接口设计为可插拔策略,第二阶段加 JWT 不影响上层逻辑。
// 预留接口
type Authenticator interface {
    Authenticate(r *http.Request) (*Identity, error)
}

type APIKeyAuthenticator struct { ... }  // MVP 实现
type JWTAuthenticator struct { ... }      // 第二阶段实现

8.4 Q3:管理后台 — 仅管理 API,无 UI

决策: MVP 仅提供管理 API,第三阶段再考虑 UI。

理由:

  • 管理后台 UI 开发量大(前端框架 + 组件 + 交互),对 MVP 核心价值无贡献。
  • 边缘算力机的管理员通常是技术人员,API + YAML 配置 + curl 足够。
  • 第二阶段可通过 Grafana 覆盖大部分监控需求。
  • 如果后续需要 UI,可用轻量方案(如 Go 模板 + HTMX,不引入 React)。

MVP 管理接口清单:

接口 用途
GET/POST/PUT/DELETE /admin/applications 应用管理
GET/POST/PUT/DELETE /admin/models 模型配置
GET/PUT /admin/policies 安全策略
GET/PUT /admin/quotas 配额配置
GET /admin/tasks 任务监控

8.5 Q4:Token 计数 — 引擎返回优先,估算兜底

决策: 优先使用推理引擎返回的 Token 数,未返回时通讯层自行估算。

推理完成
  │
  ├─ 引擎返回 usage?
  │   ├─ 是 → 直接使用(最准确)
  │   └─ 否 → 通讯层估算
  │       ├─ input_tokens = tokenizer.encode(messages).count
  │       └─ output_tokens = tokenizer.encode(response).count
  │
  └─ 估算场景:
      ├─ 排队阶段需要预估 input_tokens(必须估算)
      └─ 流式输出中途需要实时 output_tokens(按 chunk 估算)

实现建议:

  • 集成 tiktoken 或模型对应的 tokenizer,按模型配置选择。
  • 排队准入阶段必须估算 input_tokens(引擎尚未执行)。
  • 推理完成后优先用引擎返回值覆盖估算值。
  • 流式输出中按 chunk 粗估 output_tokens,完成后用引擎值修正。
  • 估算误差记录到指标,用于后续校准。

8.6 Q5KV Cache 估算 — 配置静态值 → 引擎查询 → 历史回归

决策: 三步走策略。

第一步(M2 初始):按模型配置静态值

models:
  general-chat:
    kv_cache_per_token_bytes: 131072  # 128KB/token (示例)
    # 按架构推算公式:
    # per_token_kv = 2 × num_layers × num_kv_heads × head_dim × bytes_per_element

例如 Qwen3-8B32 层,8 KV heads128 head dimFP16):

2 × 32 × 8 × 128 × 2 = 131,072 bytes ≈ 128KB/token

第二步(M2 运行中):从推理引擎查询实际值

vLLM 等引擎可暴露 KV Cache 使用量,通讯层记录实际值与估算值的偏差,动态修正系数。

第三步(M2 稳定后):历史数据回归

收集 (input_tokens, actual_kv_cache_used) 样本,按模型回归修正系数,写入配置。

8.7 Q6:多 GPU/NPU 混合调度 — 不实现,预留接口

决策: MVP 不实现混合调度,但资源管理器接口设计为多设备感知。

理由:

  • 边缘算力机大多数场景为单 GPU 或单 NPU,MVP 不需要混合调度。
  • 混合调度涉及异构设备能力描述、跨设备显存管理、任务亲和性匹配,复杂度高。
  • 接口设计应预留,第三阶段扩展为多设备调度器。
type Device struct {
    ID       string
    Type     DeviceType  // GPU / NPU / CPU
    VRAM     uint64
    Compute  uint64
    Models   []string    // 已加载模型
}

type ResourceManager interface {
    Estimate(task *Task, device *Device) (bool, error)  // 预留多设备
    Acquire(task *Task, device *Device) (*Slot, error)
    Release(slot *Slot) error
    ListDevices() []*Device
}

MVP 实现单设备版本,ListDevices() 返回单个设备,第三阶段扩展为多设备调度器。