架构概述
架构概述
Python SDK 与 Java SDK 架构 一致,本页着重描述 Python 端的差异点。
系统架构
text
┌─────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 灵心平台 (LinkSoul Platform) │
│ │
│ ┌─────────────────────┐ Bridge (桥接器) ┌─────────────────────┐ │
│ │ LinkskyGateway │ ◄──────────────────────────────► │ 交互网关 (Gateway) │ │
│ │ (二开网关) │ Boss Channel (控制面) │ │ │
│ │ 接收二开SDK连接 │ Worker Channel (数据面) │ 连接机器人终端 │ │
│ │ 认证 & 消息路由 │ 双向信令握手 │ 音频/视频/指令转发 │ │
│ └──────────┬──────────┘ └──────────┬──────────┘ │
│ │ │ │
└─────────────│────────────────────────────────────────────────────────│─────────────────────────┘
│ │
│ WebSocket (wss) │ WebSocket / TCP
│ wss://open.agibot.com/api/V1/open-portal/app/wss/agent-sdk │
│ │
┌─────────────▼──────────────┐ ┌────────────▼─────────────┐
│ 您的二开应用 (AgentSdk) │ │ 机器人终端 / 智能体 │
│ │ │ │
│ ┌──────────────────────┐ │ │ ┌────────────────────┐ │
│ │ LinkskyClient │ │ │ │ 音频采集 (MIC) │ │
│ │ (websocket-client) │ │ │ │ 视频采集 (Camera) │ │
│ └──────────┬───────────┘ │ │ │ TTS 播放 (Speaker) │ │
│ │ │ │ │ 动作执行 (Motor) │ │
│ ┌──────────▼───────────┐ │ │ └────────────────────┘ │
│ │ MessageRouter │ │ └──────────────────────────┘
│ │ (handlers.py 分发) │ │
│ └──────────┬───────────┘ │
│ │ │
│ ┌──────────▼───────────┐ │
│ │ PassiveCallback │ │ 被动交互:机器人发起 → 二开处理 → 返回结果
│ │ (8 种业务子类) │ │ Audio → ASR → LLM → TTS
│ ├──────────────────────┤ │
│ │ TaskFlowRequest │ │ 主动交互:二开发起 → 网关转发 → 机器人响应
│ │ (主动交互任务流) │ │ register_task_flow / start_request / task_request / end_request
│ └──────────────────────┘ │
└────────────────────────────┘
数据流向
被动交互(机器人 → 二开 SDK)
text
机器人麦克风 → 交互网关 → Bridge Worker → LinkskyGateway(二开网关) → AgentSdk → callback.on_request()
│
callback 返回 → AgentSdk → LinkskyGateway(二开网关) → Bridge Worker → 交互网关 → 机器人扬声器
主动交互(二开 SDK → 机器人)
text
agent_sdk.register_task_flow() → LinkskyGateway(二开网关) → Bridge Boss → 交互网关 → 机器人
│
机器人响应 → 交互网关 → Bridge Boss → LinkskyGateway(二开网关) → AgentSdk → callback.on_*_ack()
模块结构
text
linksoul_agentsdk/
├── __init__.py # 公开 AgentSdk, AgentParam, AgentMeta, ... 11 个顶层符号
├── agent_sdk.py # 主入口(单例工厂、回调注册、生命周期)
├── agent_param.py # 扩展参数(链式 set_string/set_integer/...)
├── agent_meta.py # 智能体元数据
├── agent_auth_callback.py # 鉴权回调抽象基类
├── id_generator.py # 唯一 ID 生成(基于 secrets)
├── client/linksky_client.py # HMAC-SHA256 网关签名
├── enums.py # 5 个枚举:AgentCallbackType / AgentEventType / FlowMode / ...
├── client/ # WebSocket 通信层
│ ├── linksky_client.py # 同步阻塞 WebSocket 客户端 + 重连 + 心跳
│ ├── message_router.py # 收到 JSON → 按 event_type 分发到 handler
│ └── handlers.py # 各事件具体处理函数(被动 + 主动 ack)
├── passive/ # 被动交互
│ ├── base.py # PassiveCallback / AgentSdkResponse / GreetResponse
│ ├── audio2_llm.py # Audio2LlmCallback + Audio2LlmResponse
│ ├── audio2_tts.py / asr2_llm.py / asr2_tts.py
│ ├── asr_video2_vlm.py / asr_video2_tts.py
│ └── audio_video2_vlm.py / audio_video2_tts.py
├── active/ # 主动交互
│ └── task_flow.py # TaskFlowRequest + 4 个 Flow*Callback
└── mgr/ # 全局管理器
├── callback_type_mgr.py # app_id → 已注册 callback type 集合
├── response_mgr.py # event_id → Response 缓存 + TTL 清理
├── task_flow_mgr.py # flow_id → TaskFlowRequest 映射
└── agent_thread_mgr.py # agent_id → 单线程 worker 绑定
通信协议
连接认证
WebSocket HTTP Header:
AGIBOT_APP_ID: 应用 IDAGIBOT_AUTHORIZATION:Bearer <JWT Token>
JWT Payload:{"appId": "xxx", "callbackTypes": "[\"asr2llm\"]", "exp": <epoch+3600>}
消息格式 (JSON)
json
{
"type": "agentsdk.audio_request.start",
"agentId": "AGENT_0000001",
"eventId": "event_xxxxx",
"robotCid": "cid_xxx",
"cid": "cid_xxx"
}
线程模型
| 线程 | 数量 | 职责 |
|---|---|---|
linksky-recv-<app_id> | 1 | WebSocket 接收线程,跑 ws.run_forever |
agent-worker-N | 1..50 | 每个 agent_id(灵心平台配置的智能体 ID)绑定一个串行 worker,保证同一智能体消息顺序处理 |
threading.Timer daemon | 0..1 | 重连定时器 |
关键约定:用户在
on_request内的所有response.on_*调用都跑在 worker 线程。LinkskyClient.send_text内部用threading.Lock序列化,可在任意线程安全调用。
重连机制
- 连接失败/断开后自动重连
- 重连延迟:3 秒(
reconnect_delay,可在构造时覆盖) - 默认无限重连(
max_reconnect_attempts=-1),直到调用agent_sdk.release() - 心跳:每 10 秒发送 Ping(websocket-client 内置)
典型时序
下面以 Audio2Tts(音频输入 → ASR + LLM + TTS 全管道)为例展示一次完整对话的时序。
其他被动回调只是 on_request 收到的数据形态不同,整体节奏一致。
mermaid
sequenceDiagram
participant Robot as 机器人
participant IGW as 交互网关
participant Bridge as Bridge 桥接器
participant Linksky as LinkskyGateway<br/>(二开网关)
participant SDK as AgentSdk<br/>(二开应用)
Note over SDK,Linksky: 启动阶段
SDK->>Linksky: WebSocket 连接 + JWT 鉴权
Linksky-->>SDK: on_auth_state(code=0)
Robot->>IGW: 机器人上线
IGW->>Bridge: 上线事件
Bridge->>Linksky: 上线事件
Linksky-->>SDK: on_robot_online(agent_id, agent_meta)
Note over Robot,SDK: 一次对话
Robot->>IGW: 用户开始说话 (VAD start)
IGW->>Linksky: audio_request.start
Linksky-->>SDK: on_request(flag=0)
loop 音频帧
Robot->>IGW: PCM 音频帧
IGW->>Linksky: audio_request.append
Linksky-->>SDK: on_request(flag=1, buf=audio)
end
Robot->>IGW: VAD end
IGW->>Linksky: audio_request.commit
Linksky-->>SDK: on_request(flag=2)
Note over SDK: 业务侧 ASR → LLM → TTS
SDK->>Linksky: response.on_asr_middle / on_asr_final
SDK->>Linksky: response.on_interrupt(event_id, "chat", None)
SDK->>Linksky: response.on_llm_item_delta × N
SDK->>Linksky: response.on_llm_item_done / on_llm_done
SDK->>Linksky: response.on_tts_item_delta × N
SDK->>Linksky: response.on_tts_item_done / on_tts_done
Linksky->>IGW: 转发响应帧
IGW->>Robot: 屏幕显示 + 扬声器播放
关键点:
- 一次对话的整个生命周期通过
event_id关联,跨多次on_request/response.on_*调用都共用同一个event_id。 - ASR/LLM/VLM/TTS 都是流式输出,可以多次
*_delta,最后用*_done收尾。 - 命中有效指令时必须先
on_interrupt,再on_skill/on_llm_*/on_vlm_*/on_tts_*。 - 技能下发
response.on_skill(...)与文本/音频输出可以并行,互不阻塞;具体可下发的技能见 语义技能参考。 - 业务侧异常时调用
response.on_error(event_id, code, msg)通知机器人端。