被动交互示例
被动交互示例
源码位置:
agentsdk_for_java/example/src/main/java/com/agibot/aiem/
8 个被动交互示例按输入输出复杂度分为三类。每个 *Example.java 都是可独立运行的 main,
仅在 register* 注册的回调类型与 onRequest 签名上有差异,其余流程(创建实例、注册鉴权、基类共享回调、初始化)完全一致。
通用骨架(所有示例共享)
String url = "wss://open.agibot.com/api/V1/open-portal/app/wss/agent-sdk";
String appId = "您通过灵心开放平台创建的应用获取的appId";
String appKey = "您通过灵心开放平台创建的应用获取的appKey";
String appSecret = "您通过灵心开放平台创建的应用获取的appSecret";
// 第一步:创建 SDK 实例(单例,同一 appId 多次调用返回同一实例)
AgentSdk agentSdk = AgentSdk.create(url, appId, appKey, appSecret);
// 第二步:注册验签回调
agentSdk.registerAuth(new AgentAuthCallback() {
@Override
public void onAuthState(String appId, int code, String msg) {
log.info("onAuthState => appId: {}, code: {}, msg: {}", appId, code, msg);
}
});
// 第三步:注册业务回调(按场景选择 register* 方法,见下文各示例)
agentSdk.registerXxx(new XxxCallback(agentSdk) { /* ... */ });
// 第四步:初始化(建立 WebSocket,自动重连)
agentSdk.initialize();
基类共享回调(v1.4.0+)
所有 *Callback 都继承自 PassiveCallback,可选重载以下方法(不重载则使用默认日志实现):
@Override
public void onRobotOnline(String agentId, AgentMeta agentMeta) {
// 机器人上线,初始化该机器人的资源
log.info("onRobotOnline => agentId: {}, agentMeta: {}", agentId, agentMeta);
}
@Override
public void onRobotOffline(String agentId) {
// 机器人下线,清理该机器人相关的资源
log.info("onRobotOffline => agentId: {}", agentId);
}
@Override
public void onFaceInfo(String agentId, String eventId, AgentParam param) {
// 识别到人脸 / 声纹 UID(v1.4.0 开放)
log.info("onFaceInfo => agentId {}, eventId {}, param {}", agentId, eventId, param);
}
@Override
public void onVideoFrame(String agentId, String eventId, int flag, byte[] buf,
boolean isKeyFrame, long localTs, AgentParam param) {
// 视频帧透传:flag=2 H264,flag=3 图片
log.info("onVideoFrame => agentId {}, eventId {}, flag {}, isKeyFrame {}, localTs {}, param {}",
agentId, eventId, flag, isKeyFrame, localTs, param);
}
@Override
public void onGreetSignal(String agentId, String eventId, AgentParam param, GreetResponse response) {
// 主动打招呼信令,可通过 response.onGreetVlm*/onGreetTts* 应答
log.info("onGreetSignal => agentId {}, eventId {}, param {}", agentId, eventId, param);
}
@Override
public void onState(String agentId, String eventId, String stateName, String stateValue) {
// 机器人状态推送(v1.4.0 起合并到此处,不再单独注册 StateListenCallback)
log.info("onState => agentId {}, eventId {}, stateName {}, stateValue {}",
agentId, eventId, stateName, stateValue);
}
后续每个示例只展示
register*调用 +onRequest主体,其余按"通用骨架"组装即可。
一、纯音频类
Audio2LlmExample — 音频输入 → ASR + LLM 文本输出
源码:
Audio2LlmExample.java适用场景:语音对话,纯文本回复(不合成 TTS)。
agentSdk.registerAudio2Llm(new Audio2LlmCallback(agentSdk) {
/**
* @param flag 0 VAD开始,1 中间音频,2 VAD结束
* @param buf 音频字节数组(当 flag 为 1 时有效)
*/
@Override
public void onRequest(String agentId, String eventId, int flag,
byte[] buf, AgentParam param, Audio2LlmResponse response) {
// 可选获取智能体默认及自定义元数据
AgentMeta agentMeta = agentSdk.getAgentMeta(agentId);
String defWakeupWord = agentMeta.getWakeupWord();
String yourParamKey = agentMeta.getString("您的自定义参数key");
// 1) ASR:根据 flag 分阶段送 ASR
if (flag == 0) {
// 初始化 ASR 客户端
} else if (flag == 1) {
// 给 ASR 传音频
} else if (flag == 2) {
// VAD 结束
}
String asrMiddle = "今天";
String asrFinal = "今天天气咋样";
response.onAsrMiddle(eventId, asrMiddle);
response.onAsrFinal(eventId, asrFinal);
// 2) 语义理解 / LLM 流式输出
String itemId = "itemId_000001";
// 如语义理解为有效指令需返回打断,拒识则无需返回
response.onInterrupt(eventId, "chat", null);
// 如分类为技能则返回技能(可选)
AgentParam skillParam = AgentParam.create().setInteger("step", 3);
response.onSkill(eventId, itemId, "movement", "move_forward", skillParam);
String textDelta = "假设这就是LLM流式生成的结果";
response.onLlmItemDelta(eventId, itemId, textDelta);
response.onLlmItemDone(eventId, itemId);
response.onLlmDone(eventId);
// 异常处理
// response.onError(eventId, 1010, "假设调用asr出错了");
}
// ... 基类共享回调,见上文 ...
});
Audio2TtsExample — 音频输入 → ASR + LLM + TTS 完整管道
源码:
Audio2TtsExample.java适用场景:最常见的语音对话→语音回复闭环。
onRequest签名比Audio2Llm多一个itemId形参。
agentSdk.registerAudio2Tts(new Audio2TtsCallback(agentSdk) {
/**
* @param itemId 本轮回复的 itemId(多意图时按意图区分)
* @param flag 0 VAD开始,1 中间音频,2 VAD结束
* @param buf 音频字节数组(当 flag 为 1 时有效)
*/
@Override
public void onRequest(String agentId, String eventId, String itemId, int flag,
byte[] buf, AgentParam param, Audio2TtsResponse response) {
// 1) ASR
if (flag == 0) {
// 初始化 ASR
} else if (flag == 1) {
// 给 ASR 传音频
} else if (flag == 2) {
// VAD 结束
}
response.onAsrMiddle(eventId, "今天");
response.onAsrFinal(eventId, "今天天气咋样");
// 2) LLM 流式输出
String textDelta = "假设这就是LLM流式生成的结果";
response.onLlmItemDelta(eventId, itemId, textDelta);
response.onLlmItemDone(eventId, itemId);
response.onLlmDone(eventId);
// 3) 打断 + 技能(可选)
response.onInterrupt(eventId, "chat", null);
AgentParam skillParam = AgentParam.create().setInteger("step", 3);
response.onSkill(eventId, itemId, "movement", "move_forward", skillParam);
// 4) TTS 流式输出
byte[] audio = new byte[1024];
response.onTtsItemDelta(eventId, itemId, audio);
response.onTtsItemDone(eventId, itemId);
response.onTtsDone(eventId);
// 异常处理
// response.onError(eventId, 1010, "假设调用asr出错了");
}
// ... 基类共享回调 ...
});
二、纯文本类
Asr2LlmExample — ASR 文本输入 → LLM 输出
源码:
Asr2LlmExample.java适用场景:上游已完成 ASR 识别,只做语义理解/LLM 处理。
agentSdk.registerAsr2Llm(new Asr2LlmCallback(agentSdk) {
/**
* @param text 查询文本,一般为 final asr
*/
@Override
public void onRequest(String agentId, String eventId, String text,
AgentParam param, Asr2LlmResponse response) {
// 拿 text 做语义理解 + LLM
response.onInterrupt(eventId, "chat", null);
String itemId = "itemId_000001";
AgentParam skillParam = AgentParam.create().setInteger("step", 3);
response.onSkill(eventId, itemId, "movement", "move_forward", skillParam);
String textDelta = "假设这就是LLM流式生成的结果";
response.onLlmItemDelta(eventId, itemId, textDelta);
response.onLlmItemDone(eventId, itemId);
response.onLlmDone(eventId);
// response.onError(eventId, 1010, "...");
}
// ... 基类共享回调 ...
});
Asr2TtsExample — ASR 文本输入 → LLM + TTS 输出
源码:
Asr2TtsExample.java适用场景:上游已 ASR,下游需要语音回复。
agentSdk.registerAsr2Tts(new Asr2TtsCallback(agentSdk) {
@Override
public void onRequest(String agentId, String eventId, String text,
AgentParam param, Asr2TtsResponse response) {
String itemId = "itemId_000001";
// LLM
String textDelta = "假设这就是LLM流式生成的结果";
response.onLlmItemDelta(eventId, itemId, textDelta);
response.onLlmItemDone(eventId, itemId);
response.onLlmDone(eventId);
// 打断 + 技能
response.onInterrupt(eventId, "chat", null);
AgentParam skillParam = AgentParam.create().setInteger("step", 3);
response.onSkill(eventId, itemId, "movement", "move_forward", skillParam);
// TTS
byte[] audio = new byte[1024];
response.onTtsItemDelta(eventId, itemId, audio);
response.onTtsItemDone(eventId, itemId);
response.onTtsDone(eventId);
}
// ... 基类共享回调 ...
});
三、多模态类(文本/音频 + 视频)
AsrVideo2VlmExample — ASR 文本 + 视频 → VLM 输出
源码:
AsrVideo2VlmExample.java适用场景:看图理解、视觉问答。
agentSdk.registerAsrVideo2Vlm(new AsrVideo2VlmCallback(agentSdk) {
/**
* @param flag 3 ASR 文本,4 H264 视频,5 图片
* @param text flag=3 时有效
* @param buf flag=4/5 时有效
*/
@Override
public void onRequest(String agentId, String eventId, int flag, String text,
byte[] buf, AgentParam param, AsrVideo2VlmResponse response) {
// text + 视频(buf)联合做 VLM 推理
String itemId = "itemId_000001";
response.onInterrupt(eventId, "chat", null);
AgentParam skillParam = AgentParam.create().setInteger("step", 3);
response.onSkill(eventId, itemId, "movement", "move_forward", skillParam);
String textDelta = "假设这就是LLM流式生成的结果";
response.onVlmItemDelta(eventId, itemId, textDelta);
response.onVlmItemDone(eventId, itemId);
response.onVlmDone(eventId);
}
// ... 基类共享回调 ...
});
AsrVideo2TtsExample — ASR 文本 + 视频 → VLM + TTS 输出
源码:
AsrVideo2TtsExample.java适用场景:看图说话、视觉问答+语音回复。
agentSdk.registerAsrVideo2Tts(new AsrVideo2TtsCallback(agentSdk) {
@Override
public void onRequest(String agentId, String eventId, int flag, String text,
byte[] buf, AgentParam param, AsrVideo2TtsResponse response) {
String itemId = "itemId_000001";
String textDelta = "假设这就是LLM流式生成的结果";
// 1) VLM
response.onVlmItemDelta(eventId, itemId, textDelta);
response.onVlmItemDone(eventId, itemId);
response.onVlmDone(eventId);
// 2) 打断 + 技能
response.onInterrupt(eventId, "chat", null);
AgentParam skillParam = AgentParam.create().setInteger("step", 3);
response.onSkill(eventId, itemId, "movement", "move_forward", skillParam);
// 3) TTS
byte[] audio = new byte[1024];
response.onTtsItemDelta(eventId, itemId, audio);
response.onTtsItemDone(eventId, itemId);
response.onTtsDone(eventId);
}
// ... 基类共享回调 ...
});
AudioVideo2VlmExample — 音频 + 视频 → ASR + VLM 输出
源码:
AudioVideo2VlmExample.java适用场景:边听边看,全模态理解,文本回复。
agentSdk.registerAudioVideo2Vlm(new AudioVideo2VlmCallback(agentSdk) {
/**
* @param flag 0 VAD开始,1 中间音频,2 VAD结束,3 H264 视频流
* @param buf flag=1 音频;flag=3 H264
*/
@Override
public void onRequest(String agentId, String eventId, int flag, byte[] buf,
AgentParam param, AudioVideo2VlmResponse response) {
// 1) ASR:根据 flag 分阶段送 ASR
if (flag == 0) {
// 初始化 ASR
} else if (flag == 1) {
// 给 ASR 传音频
} else if (flag == 2) {
// VAD 结束
}
response.onAsrMiddle(eventId, "今天");
response.onAsrFinal(eventId, "今天天气咋样");
// 2) 打断 + 技能
String itemId = "itemId_000001";
response.onInterrupt(eventId, "chat", null);
AgentParam skillParam = AgentParam.create().setInteger("step", 3);
response.onSkill(eventId, itemId, "movement", "move_forward", skillParam);
// 3) VLM 流式输出(结合视频帧)
String textDelta = "假设这就是LLM流式生成的结果";
response.onVlmItemDelta(eventId, itemId, textDelta);
response.onVlmItemDone(eventId, itemId);
response.onVlmDone(eventId);
}
// ... 基类共享回调 ...
});
AudioVideo2TtsExample — 音频 + 视频 → ASR + VLM + TTS 输出
源码:
AudioVideo2TtsExample.java适用场景:全模态端到端,最贴近真实机器人对话。
agentSdk.registerAudioVideo2Tts(new AudioVideo2TtsCallback(agentSdk) {
/**
* @param flag 0 VAD开始,1 中间音频,2 VAD结束,3 H264 视频流
* @param buf flag=1 音频;flag=3 H264
*/
@Override
public void onRequest(String agentId, String eventId, int flag, byte[] buf,
AgentParam param, AudioVideo2TtsResponse response) {
// 1) ASR
if (flag == 0) {
// 初始化 ASR
} else if (flag == 1) {
// 给 ASR 传音频
} else if (flag == 2) {
// VAD 结束
}
response.onAsrMiddle(eventId, "今天");
response.onAsrFinal(eventId, "今天天气咋样");
String itemId = "itemId_000001";
// 2) 打断 + 技能
response.onInterrupt(eventId, "chat", null);
AgentParam skillParam = AgentParam.create().setInteger("step", 3);
response.onSkill(eventId, itemId, "movement", "move_forward", skillParam);
// 3) VLM 流式输出
String textDelta = "假设这就是LLM流式生成的结果";
response.onVlmItemDelta(eventId, itemId, textDelta);
response.onVlmItemDone(eventId, itemId);
response.onVlmDone(eventId);
// 4) TTS 流式输出
byte[] audio = new byte[1024];
response.onTtsItemDelta(eventId, itemId, audio);
response.onTtsItemDone(eventId, itemId);
response.onTtsDone(eventId);
}
// ... 基类共享回调 ...
});
横切关注点
技能指令返回
当 LLM/VLM 判断需要执行某项技能(如导航、抓取),在 onRequest 内调用:
AgentParam skillParam = AgentParam.create()
.setInteger("step", 3)
.setDouble("speed", 0.5)
.setString("target", "kitchen");
response.onSkill(eventId, itemId, "movement", "walk_forward", skillParam);
错误处理
业务处理失败时通过 response.onError(...) 通知机器人端:
try {
// 业务处理...
} catch (AsrServiceException e) {
response.onError(eventId, 5001, "ASR服务不可用: " + e.getMessage());
} catch (LlmServiceException e) {
response.onError(eventId, 5002, "LLM服务超时");
} catch (Exception e) {
response.onError(eventId, 5999, "未知错误");
}
选择哪个示例?
| 你的输入 → 输出 | 推荐示例 |
|---|---|
| 音频 → 文本 | Audio2LlmExample |
| 音频 → 语音 | Audio2TtsExample |
| 文本 → 文本 | Asr2LlmExample |
| 文本 → 语音 | Asr2TtsExample |
| 文本+视频 → 文本 | AsrVideo2VlmExample |
| 文本+视频 → 语音 | AsrVideo2TtsExample |
| 音频+视频 → 文本 | AudioVideo2VlmExample |
| 音频+视频 → 语音 | AudioVideo2TtsExample |