被动交互示例

被动交互示例

源码位置:agentsdk_for_java/example/src/main/java/com/agibot/aiem/

8 个被动交互示例按输入输出复杂度分为三类。每个 *Example.java 都是可独立运行的 main, 仅在 register* 注册的回调类型与 onRequest 签名上有差异,其余流程(创建实例、注册鉴权、基类共享回调、初始化)完全一致。

通用骨架(所有示例共享)

java
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,可选重载以下方法(不重载则使用默认日志实现):

java
@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)。

java
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 形参。

java
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 处理。

java
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,下游需要语音回复。

java
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

适用场景:看图理解、视觉问答。

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

适用场景:看图说话、视觉问答+语音回复。

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

适用场景:边听边看,全模态理解,文本回复。

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

适用场景:全模态端到端,最贴近真实机器人对话。

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 内调用:

java
AgentParam skillParam = AgentParam.create()
    .setInteger("step", 3)
    .setDouble("speed", 0.5)
    .setString("target", "kitchen");

response.onSkill(eventId, itemId, "movement", "walk_forward", skillParam);

错误处理

业务处理失败时通过 response.onError(...) 通知机器人端:

java
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