【AgentScope Java新手村系列】(19)多模态-图像音频视频

简介: 多模态 — 废弃 ImageBlock/AudioBlock/VideoBlock,统一用 DataBlock + Base64Source 内联或 URLSource 远程引用图片。一条消息可拼多个 Block,REST 端点仅稳定支持图片。

第十九章 多模态:图像、音频、视频——ImageBlock 统一替换为 DataBlock

1.x 的 ImageBlock / AudioBlock / VideoBlock 在 2.0.0中被统一替换为 DataBlock,通过 mediaType 字段区分类型。

旧代码里 new ImageBlock(...) / new AudioBlock(...) 在 2.0 中仍然兼容(标 @Deprecated),但新代码请统一用 DataBlock

本章先给旧 API 对照,再讲 DataBlock 的统一用法。

依赖:多模态模型需通过 OpenAI 兼容端点调用,依赖 agentscope-extensions-model-openai
DashScope 专有协议暂不支持多模态——示例使用 OpenAIChatModel + DashScope 兼容地址
https://dashscope.aliyuncs.com/compatible-mode/v1

19.1 1.x 与 2.0 对照

1.x 2.0
ImageBlock DataBlock.builder().mediaType("image/png")
AudioBlock DataBlock.builder().mediaType("audio/mp3")
VideoBlock DataBlock.builder().mediaType("video/mp4")
Base64Source Base64Source(保留,但走 DataBlock.source(...)
URLSource URLSource(保留,走 DataBlock.source(...)

19.2 第一个多模态消息

这个例子在演示什么?

DataBlock 把一张本地图片(PNG 文件)编码为 Base64,和文本拼成一条多模态消息发给 Agent。Agent 收到的不再是纯文本,而是"文字 + 图片"——它能看到图片内容并给出描述。

import io.agentscope.core.agent.RuntimeContext;
import io.agentscope.core.message.Base64Source;
import io.agentscope.core.message.DataBlock;
import io.agentscope.core.message.TextBlock;
import io.agentscope.core.message.UserMessage;
import io.agentscope.extensions.model.openai.OpenAIChatModel;
import io.agentscope.harness.HarnessAgent;

import java.nio.file.Files;
import java.util.Base64;
import java.util.List;

public class Chapter19_Multimodal {
   

    public static void main(String[] args) throws Exception {
   
        // 1. 读图片并编码 base64
        byte[] bytes = Files.readAllBytes(Path.of("./cat.png"));
        String b64 = Base64.getEncoder().encodeToString(bytes);

        // 2. 构造 DataBlock
        DataBlock imageBlock = DataBlock.builder()
                .source(Base64Source.builder()
                        .data(b64)
                        .mediaType("image/png")
                        .build())
                .build();

        // 3. 多模态 user 消息
        UserMessage msg = new UserMessage(
                "user",
                TextBlock.builder().text("这张图片里有什么?").build(),
                imageBlock);

        // 4. agent 调用
        HarnessAgent agent = HarnessAgent.builder()
                .name("vision_bot")
                .sysPrompt("你是一个视觉助理,详细描述图片。")
                .model(OpenAIChatModel.builder()
                        .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                        .modelName("qwen3-omni-flash")
                        .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                        .stream(true)
                        .formatter(new OpenAIChatFormatter())
                        .build())
                .workspace(Path.of("./workspace"))
                .build();

        System.out.println(agent.call(List.of(msg), RuntimeContext.empty()).block().getTextContent());
    }
}

19.3 DataBlock 字段

DataBlockio.agentscope.core.message)核心字段:

字段 类型 说明
source Source 数据来源,必填
mediaType String MIME 类型(image/png / audio/mp3 / video/mp4 / application/pdf
name String 可选文件名
metadata Map 业务方附加元信息

Source 有两种:

  • Base64Source —— 内联 base64 编码数据
  • URLSource —— 远程 URL,agent 自动下载

19.4 音频 / 视频

视频和音频的 DataBlock 构造和图片一模一样,换个 mediaType 就行。但同样的代码,图片能跑、音频和视频跑不了。

限制不在 DashScope 本身,在 AgentScope 的内置 ChatModel。OpenAIChatModel 也好、DashScopeChatModel 也好,底层全部走 REST HTTP 协议。HTTP 请求体的多模态字段只支持 image_url 这一种格式,input_audio 和视频帧都塞不进去。

DashScope 自己是能处理音频的,只是需要走不同的协议通道:

  • WebSocket 实时流。Qwen-Omni 实时对话、语音识别都是 WebSocket 长连接,双向推流。AgentScope 没有内置 WebSocket 客户端。
  • DashScope 原生 HTTP 多模态格式。ONE-PEACE、Qwen-VL 这些模型支持 HTTP 传入音频 URL,但走的是 DashScope 自有协议,不是 OpenAI 兼容格式。

两条路都能通,但都不在 AgentScope 的 ChatModel 覆盖范围内。想用的话,学第 20 章 TTS 的做法:自己用 @Tool 包装 DashScope SDK,AgentScope 只负责调工具、不在框架层处理音频字节。

本章示例聚焦图片。图片是 REST 端点唯一稳定支持的多模态输入,也是绝大多数业务最常用的多模态场景。

19.5 与 Tool 的协作

业务方工具可以返回 DataBlock —— 适合 OCR / 截图 / 渲染结果:

@Tool(name = "screenshot_page", description = "截图某个 URL")
public DataBlock screenshot(
        @ToolParam(name = "url") String url) throws Exception {
   

    // 调 puppeteer / playwright 拿 png
    byte[] png = playwright.screenshot(url);
    String b64 = Base64.getEncoder().encodeToString(png);

    return DataBlock.builder()
            .source(Base64Source.builder()
                    .data(b64)
                    .mediaType("image/png")
                    .build())
            .name("screenshot.png")    // name 挂在 DataBlock 上,不是 Base64Source
            .build();
}

LLM 看到工具返回 DataBlock 会自动把它纳入上下文——框架内部会把 DataBlock 包装成 ToolResultBlock 再发给 LLM,无需手动构造。

19.6 1.x 旧代码的兼容路径

ImageBlock / AudioBlock / VideoBlock 在 2.0 仍存在(标 @Deprecated):

// 1.x 老代码仍能跑
import io.agentscope.core.message.ImageBlock;

ImageBlock oldStyle = new ImageBlock(b64, "image/png");   // 2.0 编译会出 warning

ImageBlock 内部就是 DataBlock.builder().mediaType("image/...")。建议新代码统一用 DataBlock;老代码改起来很便宜(1 行换 1 行)。

19.7 完整可运行示例

这个例子在演示什么?

一条消息里同时拼了两种来源的图片:本地文件走 Base64Source(内联编码)、远程 URL 走 URLSource(引用地址)。Agent 一次性拿到两张图,可以对比分析。这就是多模态的本质——不限制 Block 数量,需要几个拼几个。

public class Chapter19_FullMultimodal {
   

    public static void main(String[] args) throws Exception {
   
        // 方式一:本地文件 Base64 内联
        DataBlock fromFile = DataBlock.builder()
                .source(Base64Source.builder()
                        .data(Base64.getEncoder().encodeToString(
                                Files.readAllBytes(Path.of("./cat.png"))))
                        .mediaType("image/png")
                        .build())
                .build();

        // 方式二:远程 URL 引用
        DataBlock fromUrl = DataBlock.builder()
                .source(URLSource.builder()
                        .url("https://example.com/dog.jpg")
                        .mimeType("image/jpeg")
                        .build())
                .build();

        UserMessage msg = new UserMessage(
                "user",
                TextBlock.builder().text("对比这两张图片有什么不同。").build(),
                fromFile,
                fromUrl);

        HarnessAgent agent = HarnessAgent.builder()
                .name("multimodal_bot")
                .sysPrompt("你是多模态助理,可以理解图片内容。")
                .model(OpenAIChatModel.builder()
                        .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                        .modelName("qwen3-omni-flash")
                        .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                        .stream(true)
                        .formatter(new OpenAIChatFormatter())
                        .build())
                .workspace(Path.of("./workspace"))
                .build();

        System.out.println(agent.call(List.of(msg), RuntimeContext.empty()).block().getTextContent());
    }
}

音频/视频的 DataBlock 构造方式和图片完全一样,只需改 mediaType。是否能被模型理解取决于模型端点的协议支持——大部分 REST HTTP 端点仅支持图片多模态,音频/视频输入需要 WebSocket 实时协议。

19.8 最小迁移清单(1.x ImageBlock → 2.0 DataBlock)

1.x 用法 2.0 等价
new ImageBlock(b64, "image/png") DataBlock.builder().source(Base64Source.builder().data(b64).mediaType("image/png").build()).build()
new AudioBlock(b64, "audio/mp3") DataBlock.builder().mediaType("audio/mp3")
new VideoBlock(url, "video/mp4") DataBlock.builder().source(URLSource.builder().url(url).mimeType("video/mp4").build())
msg.getContentBlocks(ImageBlock.class) msg.getContentBlocks(DataBlock.class) 后按 mediaType 区分

19.9 本章小结

  • 2.0 用 DataBlock 统一图片 / 音频 / 视频 / 文件。
  • ImageBlock / AudioBlock / VideoBlock 仍兼容但被弃用。
  • 工具可返回 DataBlock —— LLM 自动纳入上下文。
  • mediaType 字段决定 LLM 端路由(视觉 / 音频 / 视频模型)。
目录
相关文章
|
前端开发 NoSQL Java
【AgentScope Java新手村系列】(2)第一个Agent-基础对话
第一个Agent-基础对话 — 演示 HarnessAgent 的 Builder 模式创建、ReAct 推理循环、流式事件与思考模式三个核心能力。
865 2
|
3月前
|
前端开发 安全 中间件
【AgentScope Java新手村系列】(14)人机交互
人机交互 — Permission 系统五种模式配合 ALLOW/DENY/ASK 规则,运行时 HITL 自动拦截与决策收集。
482 6
【AgentScope Java新手村系列】(14)人机交互
|
2月前
|
Java 关系型数据库 MySQL
【AgentScope Java新手村系列】(18)Skills技能系统
用 SKILL.md 文件定义可复用技能,HarnessAgent 自动扫描匹配,智能体按需调用。
419 0
|
6月前
|
人工智能 前端开发 Java
【SpringAIAlibaba新手村系列】(4)流式输出与响应式编程
本文围绕 Spring AI 中的流式输出与响应式编程展开,重点解释了传统一次性响应与流式返回的差异,以及 Flux 在异步数据流中的核心作用。文章结合 ChatModel.stream() 与 ChatClient 的多种代码示例,说明如何实现 AI 内容的边生成边返回,并帮助读者理解流式调用在用户体验、性能和长文本场景中的实际价值。
1746 4
【SpringAIAlibaba新手村系列】(4)流式输出与响应式编程
|
NoSQL Java 关系型数据库
【AgentScope Java新手村系列】(5)记忆与会话管理
记忆与会话管理 — AgentState 管理上下文窗口,AgentStateStore 持久化,RuntimeContext.sessionId 隔离多用户会话。
639 0
|
3月前
|
自然语言处理 Java API
【AgentScope Java新手村系列】(7)子Agent编排
子Agent编排 — SubagentDeclaration 描述子 agent,主 agent 通过 agent_spawn 工具同步/异步委派子任务。
709 0
|
前端开发 Java 中间件
【AgentScope Java新手村系列】(1)框架简介与环境搭建
本章带你快速入门AgentScope Java 2.0:从GitHub拉取v2.0.0-RC2源码、Maven编译安装,到纯Java构建HarnessAgent,接入DeepSeek等主流LLM,跑通首个可对话智能体——完成学习之旅的“第0步”。
292 0
【AgentScope Java新手村系列】(1)框架简介与环境搭建
|
2月前
|
中间件 Java API
【AgentScope Java新手村系列】(17)长期记忆系统
长期记忆 — 废弃 LongTermMemory,改用 MEMORY.md + Compaction 压缩 + MemoryFlush 冲刷 + @Tool 主动写。三层机制互补,框架自动维护,业务方按需定制。
455 0
|
前端开发 Java 中间件
【AgentScope Java新手村系列】(3)工具系统
工具系统 — @Tool/@ToolParam 注解将 Java 方法注册为 Agent 能力,自主决定调用时机,支持同步/异步返回。
526 0
|
3月前
|
SQL JSON Java
【AgentScope Java新手村系列】(15)MCP协议工具
MCP协议工具 — tools.json 一行声明一个 MCP server,支持 stdio/sse/ws 协议,McpMeta 传递调用元数据。
491 1

热门文章

最新文章