AI-Inference-Managed-by-AI 有限硬件资源上的 AI 推理优化与调度系统
Go 二进制是薄基础设施层——硬件检测、知识解析、Pod 生成、请求代理。 简单一次性查询可使用内置 Go Agent (L3a) 以最小延迟响应。 复杂智能逻辑由外部 AI Agent 通过 MCP 工具实现。
策略 = Agent 的事。基础设施 = Go 的事。 Go 代码不包含 if-else 决策树、规则引擎、或任何 "策略" 代码。
能力扩展的主要方式是写 YAML 知识文件,而不是写新代码。
- 支持新引擎 → 写 Engine Asset YAML
- 支持新模型 → 写 Model Asset YAML
- 支持新硬件 → 写 Hardware Profile YAML(可能加少量检测代码)
- 沉淀调优经验 → Knowledge Note (YAML / SQLite)
80% 的能力扩展不需要重新编译。
用 K3S Pod YAML 描述期望状态,系统自动收敛。
- 容器的启动、重试、健康检查、生命周期 —— K3S 管
- GPU 显存和算力的切分与隔离 —— HAMi 管
- AIMA 只做:(1) 从知识生成 Pod YAML, (2) kubectl apply, (3) 查询状态
| 职责 | 选型 | 替代方案 |
|---|---|---|
| 容器编排 | K3S | 标准 K8s, MicroK8s |
| GPU 虚拟化 | HAMi | MIG, MPS, Flex:ai |
| 状态存储 | SQLite | PostgreSQL, etcd |
| Agent 接口 | MCP (JSON-RPC) | gRPC, REST |
| 服务发现 | mDNS | Consul, etcd |
| Agent 接入 | 任何 MCP Client | Claude Code, GPT 等 |
每个工具可独立替换,彼此解耦。
L3a: Go Agent ── 工具调用循环 + 会话级记忆 ──────────── 良好解 (动态+进程内)
^ override
L2: 知识库 ──── 确定性匹配 ────────────────────────── 已知好解 (静态)
^ override
L1: 人类 CLI ── 手动指定参数 ──────────────────────── 指定解
^ override
L0: 默认值 ──── YAML 知识 (go:embed + ~/.aima/catalog/ overlay 合并) ── 可用解 (always)
每层独立可用。无 Agent、无网络、无知识库 → L0 仍能启动推理服务。
Agent 每次探索(调优、排障、部署尝试)产出结构化的 Knowledge Note。 其他设备的 Agent 复用这些知识,跳过已知失败、从最优起点开始。
AIMA 的所有核心功能必须在完全离线下可用。网络连接是"锦上添花"。
AIMA 管理的"设备"不限于本机——架构预留远程设备扩展点。
远程设备(如手机、IoT 节点)通过 device.register 注册能力向量和网络地址,
AIMA 通过 Remote Runtime 将推理请求代理到远程设备。
当前版本仅支持本机设备;远程设备支持计划在 v3.0 实现。
┌─────────────────────────────────────────────────────────────┐
│ External Agent (远程/强力) — 可选 │
│ Claude Code / GPT / 自定义 MCP Client │
├───────────────────────────────────────────────────────────────┤
│ Agent Layer │
│ L3a: Go Agent (内置轻量) │ External Agent (MCP Client) │
├───────────────────────────────────────────────────────────────┤
│ Knowledge Layer (知识层) │
│ 6 种知识资产 (go:embed YAML + 磁盘 overlay) + SQLite 查询 │
├───────────────────────────────────────────────────────────────┤
│ Orchestration Layer (编排层) — 按需分层 │
│ Tier 1: Docker + CDI │ Tier 2: + K3S + HAMi (GPU 分区) │
├───────────────────────────────────────────────────────────────┤
│ Infrastructure Layer (基础设施层) — AIMA Go 二进制 │
│ 56 MCP 工具 · LAN 推理代理 (:6188) · Fleet REST API │
│ Web UI (嵌入式 SPA) · TUI 终端仪表盘 · mDNS 多网卡发现 · 审计+回滚 │
└─────────────────────────────────────────────────────────────┘
| 领域 | 文档 | 主要内容 |
|---|---|---|
| 核心原则 | 本文档 | 设计原则、架构全景 |
| Model | docs/model.md | 模型扫描、导入、删除、元数据 |
| Engine | docs/engine.md | 引擎镜像、拉取、导入、Native 二进制 |
| Runtime | docs/runtime.md | K3S Runtime、Docker Runtime、Native Runtime、Multi-Runtime 抽象 |
| Knowledge | docs/knowledge.md | 知识库、配置解析、Pod 生成 |
| HAL | docs/hal.md | 硬件检测、能力向量 |
| K3S | docs/k3s.md | K8s 集成、Pod 管理、HAMi |
| Stack | docs/stack.md | 分层基础设施(Docker/CTK/K3S/HAMi/aima-serve) |
| MCP | docs/mcp.md | MCP 服务器、工具定义 |
| CLI | docs/cli.md | 命令行接口 |
| Agent | docs/agent.md | Go Agent |
| Web UI | — | 嵌入式 SPA 仪表盘 (Alpine.js, 同端口 :6188) |
ConfigResolver 不仅用 gpu_arch 匹配 variant,还根据硬件规格和运行时状态做两层过滤:
静态层(部署前校验)
在 findModelVariant() 和 InferEngineType() 中,利用 YAML 中定义的 vram_min_mib 和 unified_memory
字段,跳过当前硬件无法承载的 variant。例如 RTX 4060 (8GB, Ada) 部署 qwen3-8b 时,
跳过要求 16384 MiB 的 vllm-Ada variant,自动落到 llamacpp wildcard variant。
过滤阈值全部在 YAML 中定义(Model Asset 的 variant.hardware 字段),Go 代码仅做数值比较。
当 HardwareInfo 的显存/统一显存字段为零值时,跳过所有检查(graceful degradation,兼容旧调用方)。
动态层(部署前适配)
CheckFit() 在 resolve 之后、部署之前运行,根据 hal.CollectMetrics() 采集的实时 GPU 显存占用,
自动调低 gpu_memory_utilization 以避免 OOM。512 MiB 安全余量,最低阈值 0.1。
采集失败时不阻止部署(graceful degradation)。
HAL Detect (静态规格) ──→ HardwareInfo ──→ findModelVariant (VRAM/统一显存过滤)
HAL Metrics (动态状态) ──→ HardwareInfo ──→ CheckFit (gpu_memory_utilization 自动调整)
Hardware Profile YAML ──→ ContainerAccess ──→ GeneratePod (厂商无关容器配置)
容器访问配置
Hardware Profile YAML 的 container 字段描述该硬件在 K3S 容器中运行推理时需要的厂商特定配置:
devices: 需挂载的宿主机设备(如 AMD ROCm 的/dev/kfd,/dev/dri; Ascend 的/dev/davinci*)env: 注入到容器的环境变量(如 NVIDIA 的LD_LIBRARY_PATH, AMD 的LD_PRELOAD)volumes: 额外的 hostPath 挂载(如 Ascend 的 driver/firmware 只读挂载)security: securityContext 配置(如supplemental_groups用于 video/render 组权限)docker_runtime: Docker 自定义 Runtime(如 Ascend 的--runtime ascend)network_mode: 网络模式(如"host"→--network host,跳过端口映射)shm_size: 共享内存大小(如"500g")init: 是否使用--init进程管理
ConfigResolver 在 Resolve() 中通过 findContainerAccess() 匹配当前硬件的 container 配置,
传入 ResolvedConfig.Container,最终由 GeneratePod() 通用渲染。
Env 合并规则:hardware container env(基础层)+ engine env(覆盖层),引擎 env 在冲突时优先。
不可违反的架构约束:
INV-1: 不为引擎类型写代码。 引擎行为定义在 YAML。添加新引擎 = 写 YAML。
引擎支持的模型格式通过 metadata.supported_formats 声明,运行时 Catalog.FormatToEngine() 动态映射。
默认引擎通过 metadata.default: true 标记,运行时 Catalog.DefaultEngine() 动态读取。
INV-2: 不为模型/硬件类型写代码。 模型元数据在 YAML。模型类型是知识,不是代码分支。
硬件约束(vram_min_mib、unified_memory)同样在 YAML 中定义,Go 代码仅做数值比较。
厂商特定的容器访问配置(设备挂载、环境变量、安全上下文)定义在 Hardware Profile YAML 的 container 字段中,
Pod 生成器通用渲染,不含 NVIDIA/AMD/Intel 等厂商分支。
HAL 层的 GPU enrichment 使用表驱动 map(gpuEnrichers),新增厂商 = 添加 map 条目。
INV-3: 最小化运行时管理。 K3S 管 Pod 的创建、监控、重启、销毁。 Native runtime 只做极简进程管理(start/stop/logs)。
INV-4: 职责分离的状态存储。 AIMA 系统状态在 aima.db。
INV-5: MCP 工具即真相。 CLI 是 MCP 工具的包装。CLI 永不实现 MCP 工具之外的逻辑。
所有 CLI 命令(含 ask, agent install/status, status, knowledge list, config, fleet)均通过 ToolDeps 调用 MCP 工具。
Fleet CLI 的 mDNS 发现逻辑也在 ToolDeps 层实现(fleet.info 每次自动扫描,其余 fleet 工具懒发现),CLI 和 MCP Agent 走完全相同的代码路径。
当前共 56 个 MCP 工具覆盖所有功能领域 (Hardware 2 + Model 6 + Engine 6 + Deploy 8 + Knowledge 6 + Benchmark 4 + Catalog 3 + Central 3 + Data 2 + System 2 + Agent 3 + Automation 4 + Fleet 2 + Scenario 2 + OpenClaw 1 + Stack 1 + Support 1)。
工具通过 4 个 Profile 按场景过滤可见性:Full(56), Operator(39), Patrol(10), Explorer(20)。
当前 agent.ask 通过 ListToolsForProfile() 消费 profile。Explorer 使用独立的 ExplorerAgentPlanner(文档驱动 PDCA agent loop),通过 ExplorerToolExecutor 提供 7 个 bash 风格工具(cat/ls/write/append/grep/query/done)操作工作区文档,不依赖 MCP profile 工具列表。
INV-6: 探索即知识。 Agent 每次探索必须产出 Knowledge Note。
INV-7: 知识对齐优化链路。 知识资产严格对齐 PRD 优化链路。
INV-8: 离线可用。 所有核心功能必须在完全离线下可用。
aima serve 启动 OpenAI 兼容的 HTTP 推理代理(默认端口 6188,定义在 proxy.DefaultPort),
同时提供本地部署路由和远程服务自动发现:
开发者机器 (无 GPU): GPU 服务器:
┌──────────────────────┐ ┌─────────────────────┐
│ aima serve │ │ aima serve (systemd) │
│ :6188 │ │ :6188 │
│ │ mDNS │ │
│ ┌──────────────────┐ │ _llm._tcp │ ┌──────────────────┐ │
│ │ Remote Discovery │←├──────────────────┤→│ mDNS Advertiser │ │
│ │ (10s interval) │ │ │ │ (lanIPs filter) │ │
│ └────────┬─────────┘ │ │ └──────────────────┘ │
│ │ │ │ │
│ ┌────────▼─────────┐ │ HTTP proxy │ ┌──────────────────┐ │
│ │ Route Table │─├──────────────────┤→│ vLLM / llamacpp │ │
│ │ model → backend │ │ │ │ pod / process │ │
│ └──────────────────┘ │ │ └──────────────────┘ │
└──────────────────────┘ └─────────────────────┘
- 本地优先:本地部署的 backend(
Remote=false)始终优先于远程同名模型 - 自动发现:
--discover开启 mDNS 扫描,每 10s 查询远程/v1/models并注册 - 防自发现:
isLocalIP()+ 端口匹配过滤自身 mDNS 广播,避免路由回环 - Stale 清理:每轮发现后,移除不再存活的远程 backend
- Agent LLM 端点降级:Go Agent (L3a) 的 LLM 后端在本地无模型时,自动通过 mDNS 发现 Fleet 中的远程 LLM 端点并 hot-swap(
DiscoverFunc注入,懒触发,不持久化)
- 服务类型:
_llm._tcp - 默认开启:
aima serve默认启用 mDNS 广播(--mdns=true),可用--mdns=false关闭 - IP 筛选:
lanIPs()排除 loopback、Docker bridge (172.16-31.x)、K3S overlay (10.x) - TXT 记录:
aima=1,models=a,b,c
aima init 采用分层初始化,按需安装基础设施:
- Tier 1 (
aima init): Docker (containerd + dockerd) + nvidia-ctk (CDI) + aima-serve - Tier 2 (
aima init --k3s): Tier 1 + K3S + HAMi(GPU 分区、多模型调度)
每个 Stack Component YAML 声明 install.tier,FilterByTier() 根据请求层级过滤。
Archive 方法支持多 systemd unit 依赖链(如 Docker: containerd.service → docker.service)。
systemd 单元配置:
Type=simple(非 sd_notify)Environment=HOME=/root(systemd 不设 HOME)- env 文件:
/etc/aima/aima-serve.env(非 K3S 组件使用独立目录) - 子命令/服务类型可配置(
StackInstall.Subcommand/ServiceType),向后兼容 K3S
Pod 生成支持 {{.ModelName}} 和 {{.ModelPath}} 模板变量用于 string 类型的 config 值。
vLLM engine YAML 通过 served_model_name: "{{.ModelName}}" 确保 vLLM 的对外模型名与 AIMA 一致。
Fleet 子系统让局域网内多台 AIMA 设备协同工作——自动发现、状态汇聚、远程工具执行。
设备 A (aima serve) 设备 B (aima serve)
┌──────────────────────┐ ┌──────────────────────┐
│ Fleet Registry │ mDNS │ Fleet Registry │
│ ├─ local device │←─────────→│ ├─ local device │
│ └─ discovered peers │ _llm._tcp│ └─ discovered peers │
│ │ │ │
│ REST API (:6188) │ HTTP │ REST API (:6188) │
│ /api/v1/devices/* │←─────────→│ /api/v1/devices/* │
└──────────────────────┘ └──────────────────────┘
| 端点 | 方法 | 用途 |
|---|---|---|
/api/v1/device |
GET | 本设备状态 |
/api/v1/tools |
GET | 本设备 MCP 工具列表 |
/api/v1/tools/{name} |
POST | 在本设备执行 MCP 工具 |
/api/v1/devices |
GET | 所有发现的设备列表 |
/api/v1/devices/{id} |
GET | 远程设备详情 |
/api/v1/devices/{id}/tools |
GET | 远程设备工具列表 |
/api/v1/devices/{id}/tools/{name} |
POST | 在远程设备执行 MCP 工具 |
fleet.info, fleet.exec
Server 端为每个 LAN 接口创建独立的 mdns.Server 实例,Client 端并行查询所有接口并按 Name 去重。 解决 WiFi↔有线切换后 mDNS 单接口绑定断连的问题。
- Fleet 权限分层:
fleet.exec作为 transport 保持高权限,CLI 远程执行默认等同于远端本地 MCP 调用;仅屏蔽链式fleet.exec递归。Agent 通过fleet.exec调用时,adapter 会对内层tool_name施加与本地 Agent 相同的 blocked/confirmable 护栏,防止借远程路径绕过审批与高风险限制。 - API Key 热更新:
system.config set api_key <KEY>立即传播到 Proxy、MCP Server、Fleet Client 三条认证路径,无需重启。 - LLM Config 热更新:
system.config set llm.endpoint/llm.model/llm.api_key立即热替换 OpenAIClient,无需重启。LLM 配置持久化在 SQLite,优先级: env var > SQLite > default。 - Timing-safe 比较: 所有 Bearer token 校验使用
crypto/subtle.ConstantTimeCompare,防止侧信道攻击。Scheme 大小写不敏感(RFC 7235)。 - CORS 限制: 推理代理 CORS 仅允许 loopback Origin(localhost/127.0.0.1/[::1]),防止外部网页 CSRF 调用本地 API。
- MCP Slowloris 防护: MCP HTTP 服务器设置
ReadHeaderTimeout: 10s,防止慢速连接耗尽资源。 - 统一 JSON 错误格式: Proxy 所有错误响应使用 OpenAI 兼容 JSON 格式(
WriteJSONError),含 502 反向代理错误。 - Native PID 安全: Delete 操作通过
/proc/PID/cmdline验证进程身份,防止 OS PID 复用导致误杀。 - Fleet Client 并发安全:
fleet.Client.SetAPIKey()使用sync.RWMutex保护,支持运行时热更新。 - 敏感值脱敏:
system.config读写api_key和llm.api_key时响应中显示***,不回显明文。CLIaima config get/set同样脱敏。 - Fleet 自动发现: Fleet MCP 工具自带 mDNS 发现能力,
fleet.info每次调用都执行扫描,其余 fleet 工具在 registry 为空时自动触发发现。云端 Agent 通过 MCP 即可直接管理 LAN 设备,无需 CLI 或serve --discover。 - Central Server 安全: 中央知识服务器同样使用
crypto/subtle.ConstantTimeCompare进行 Bearer token 校验,Scheme 大小写不敏感(RFC 7235)。ReadHeaderTimeout: 10s防 Slowloris,MaxBytesReader(10 MiB)限制 ingest body 大小防 OOM。Sync 客户端使用http.Client{Timeout: 30s}防止因中央服务器无响应导致 CLI 挂起。
所有 MCP 工具调用记录到 SQLite audit_log 表,包含时间戳、工具名、参数、结果、调用来源。
破坏性操作 (model.remove, engine.remove, deploy.delete) 执行前自动保存快照到 rollback_snapshots 表。
agent.rollback_list 查看可回滚操作,agent.rollback 一键恢复。
Agent (L3a) 调用以下工具时被完全拦截,返回错误:
model.remove— 删除模型记录engine.remove— 删除引擎镜像deploy.delete— 停止部署
Agent 调用以下工具时需要用户批准才能执行:
deploy.apply— 创建或替换推理部署
流程: Agent 调用 deploy.apply → adapter 拦截 → 内部调 deploy.dry_run 获取部署计划 → 返回 NEEDS_APPROVAL + plan + approval_id → Agent 展示计划给用户 → 用户在同一会话中回复 "approved" → Agent 调用 deploy.approve(id) → 执行部署。
--dangerously-skip-permissions (CLI) 或 dangerously_skip_permissions (MCP agent.ask 参数) 可跳过审批门控。
Agent 单次决策循环限制 ≤ 30 轮工具调用 (可配置),防止无限循环。
独立 Go 二进制 (cmd/central/main.go),聚合多设备的知识数据。
Edge Device A ──push──→ ┌──────────────────────┐ ←──pull── Edge Device B
│ Central Server │
│ SQLite + REST API │
│ :8080 │
│ POST /api/v1/ingest │
│ GET /api/v1/query │
│ GET /api/v1/sync │
│ GET /api/v1/stats │
└──────────────────────┘
- 数据库: SQLite (与边端一致,零 CGO)。未来可升级 PostgreSQL。
- 认证: Bearer token (API Key) +
crypto/subtle.ConstantTimeCompare - 去重:
config_hash索引,相同配置不重复入库 - Edge 端通过
central.sync(action=push|pull|status)MCP 工具交互 - 配置:
system.config set central.endpoint <url>+central.api_key
internal/tui/tui.go — Bubble Tea (charmbracelet/bubbletea) 实现的终端仪表盘。
- 3 个 Tab: Dashboard (设备+GPU)、Deployments (部署列表)、Metrics (GPU 详细指标)
- 每 2 秒轮询 AIMA REST API (
/api/v1/status,/api/v1/deployments,/api/v1/power) - 键盘导航: Tab/←→ 切换、1-3 直跳、q 退出
- 只读视图,不执行任何修改操作
最后更新:2026-04-09 (Explorer Agent Planner: 文档驱动 PDCA 工作流替代单次 JSON prompt, ExplorerWorkspace + 7 工具 + 知识库查询; engine discovery 解耦; 56 MCP tools)