feat: 打通智能体图片媒体运行链路
- 增加稳定媒体引用解析与模型图片能力校验 - 修复图片 Data URI 与模型完整文本读取 - 补充媒体解析和消息兼容测试
This commit is contained in:
@@ -5,7 +5,9 @@ import io.agentscope.core.message.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -15,6 +17,9 @@ import java.util.Map;
|
||||
*/
|
||||
public class AgentScopeMessageAdapter {
|
||||
|
||||
/** AgentScope URLSource 中用于持久化业务媒体引用的私有协议。 */
|
||||
public static final String MEDIA_REFERENCE_SCHEME = "easyagents-media://";
|
||||
|
||||
/**
|
||||
* 将运行时消息转换为 AgentScope 消息。
|
||||
*
|
||||
@@ -276,6 +281,11 @@ public class AgentScopeMessageAdapter {
|
||||
.data(block.getData())
|
||||
.build();
|
||||
}
|
||||
if (block.getReference() != null && !block.getReference().isBlank()) {
|
||||
String encodedReference = Base64.getUrlEncoder().withoutPadding()
|
||||
.encodeToString(block.getReference().getBytes(StandardCharsets.UTF_8));
|
||||
return URLSource.builder().url(MEDIA_REFERENCE_SCHEME + encodedReference).build();
|
||||
}
|
||||
return URLSource.builder().url(block.getUrl()).build();
|
||||
}
|
||||
|
||||
@@ -286,7 +296,30 @@ public class AgentScopeMessageAdapter {
|
||||
return;
|
||||
}
|
||||
if (source instanceof URLSource urlSource) {
|
||||
block.setUrl(urlSource.getUrl());
|
||||
String url = urlSource.getUrl();
|
||||
if (url != null && url.startsWith(MEDIA_REFERENCE_SCHEME)) {
|
||||
block.setReference(decodeReference(url));
|
||||
} else {
|
||||
block.setUrl(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 AgentScope 私有 URLSource 解码业务媒体引用。
|
||||
*
|
||||
* @param url 私有协议 URL
|
||||
* @return 原始业务媒体引用
|
||||
*/
|
||||
public static String decodeReference(String url) {
|
||||
if (url == null || !url.startsWith(MEDIA_REFERENCE_SCHEME)) {
|
||||
return null;
|
||||
}
|
||||
String encoded = url.substring(MEDIA_REFERENCE_SCHEME.length());
|
||||
try {
|
||||
return new String(Base64.getUrlDecoder().decode(encoded), StandardCharsets.UTF_8);
|
||||
} catch (IllegalArgumentException error) {
|
||||
throw new IllegalArgumentException("Invalid agent media reference.", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.easyagents.agent.runtime.agentscope;
|
||||
import com.easyagents.agent.runtime.*;
|
||||
import com.easyagents.agent.runtime.event.*;
|
||||
import com.easyagents.agent.runtime.event.interceptor.AutoContextInterceptor;
|
||||
import com.easyagents.agent.runtime.event.interceptor.MediaReferenceInterceptor;
|
||||
import com.easyagents.agent.runtime.event.interceptor.ToolHitlInterceptor;
|
||||
import com.easyagents.agent.runtime.event.observer.AgentRuntimeErrorObserver;
|
||||
import com.easyagents.agent.runtime.event.observer.ReasoningLifecycleObserver;
|
||||
@@ -303,6 +304,12 @@ public class AgentScopeReActRuntime implements AgentRuntime {
|
||||
if (userMessage.getContentBlocks() == null || userMessage.getContentBlocks().isEmpty()) {
|
||||
throw new AgentRuntimeException("Agent user message content is required.");
|
||||
}
|
||||
boolean containsImage = userMessage.getContentBlocks().stream()
|
||||
.anyMatch(block -> block instanceof AgentMediaBlock mediaBlock
|
||||
&& "image".equalsIgnoreCase(mediaBlock.getMediaKind()));
|
||||
if (containsImage && !initRequest.getAgentDefinition().getModelSpec().isSupportImage()) {
|
||||
throw new AgentRuntimeException("The configured model does not support image input.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1087,6 +1094,7 @@ public class AgentScopeReActRuntime implements AgentRuntime {
|
||||
if (memory instanceof AutoContextMemory) {
|
||||
interceptors.add(new AutoContextInterceptor(eventBridge, memoryResult.getAutoContextConfig()));
|
||||
}
|
||||
interceptors.add(new MediaReferenceInterceptor(initRequest.getMediaResolver()));
|
||||
List<AgentToolSpec> runtimeToolSpecs = mergeToolSpecs(definition.getToolSpecs(), toolkitBuildResult.mcpToolSpecs(),
|
||||
toolkitBuildResult.operateToolSpecs());
|
||||
interceptors.add(new ToolHitlInterceptor(eventBridge, approvalCoordinator,
|
||||
|
||||
Reference in New Issue
Block a user