Agent Scope Java 2.x 系列【4】模型层

文章目录

  • [1. 概述](#1. 概述)
  • [2. 模型认证层](#2. 模型认证层)
    • [2.1 CredentialBase](#2.1 CredentialBase)
    • [2.2 ModelCard](#2.2 ModelCard)
    • [2.3 八种实现](#2.3 八种实现)
    • [2.4 Builder 示例](#2.4 Builder 示例)
    • [2.5 fromJson() :从配置反序列化](#2.5 fromJson() :从配置反序列化)
    • [2.6 与 Model 包的关系](#2.6 与 Model 包的关系)
    • [2.7 使用示例](#2.7 使用示例)
  • [3. 模型接入层](#3. 模型接入层)
    • [3.1 Model 接口](#3.1 Model 接口)
    • [3.2 ChatModelBase 抽象基类](#3.2 ChatModelBase 抽象基类)
    • [3.3 模型实现类](#3.3 模型实现类)
    • [3.4 GenerateOptions 生成参数](#3.4 GenerateOptions 生成参数)
    • [3.5 ExecutionConfig 执行策略](#3.5 ExecutionConfig 执行策略)
    • [3.6 ChatResponse 模型响应](#3.6 ChatResponse 模型响应)
    • [3.7 ChatUsage Token 用量](#3.7 ChatUsage Token 用量)
    • [3.8 ModelRegistry 模型注册中心](#3.8 ModelRegistry 模型注册中心)
    • [3.9 ToolSchema 工具 Schema](#3.9 ToolSchema 工具 Schema)
    • [3.10 EndpointType 端点类型](#3.10 EndpointType 端点类型)
    • [3.11 使用示例](#3.11 使用示例)

1. 概述

模型层采用两层结构:

  • 上层是 Credentialio.agentscope.core.credential),承载某个提供商的 API 鉴权字段
  • 下层是 Chat Modelio.agentscope.core.model),即在该凭证基础上对接的具体推理模型实现

2. 模型认证层

io.agentscope.core.credential 是模型层的上半部分 ------认证层。它与 model 包(推理层)共同构成 AgentScope 的两层模型架构:

text 复制代码
Credential(本包)              Model(model 包)
═══════════════════            ═══════════════════
"以什么身份调用"                "调用哪个模型做什么"

DashScopeCredential  ──关联──→ DashScopeChatModel
OpenAICredential     ──关联──→ OpenAIChatModel
AnthropicCredential  ──关联──→ AnthropicChatModel
...

核心设计 :先注册凭证 → 从凭证获取模型列表 → 选择模型创建 ChatModel。这样前端只需鉴权一次,就能展示该提供商支持的所有模型。

类图:

text 复制代码
CredentialBase (abstract)
    │  id: String
    │  listModels() → Mono<List<ModelCard>>
    │  getChatModelClass() → Class<? extends ChatModelBase>
    │
    ├── DashScopeCredential    ← 通义千问        apiKey + baseUrl
    ├── OpenAICredential       ← OpenAI 兼容      apiKey + baseUrl + organization
    ├── AnthropicCredential    ← Claude          apiKey + baseUrl
    ├── GeminiCredential       ← Google Gemini   apiKey
    ├── DeepSeekCredential     ← DeepSeek        apiKey + baseUrl
    ├── KimiCredential         ← Moonshot Kimi   apiKey + baseUrl
    ├── XAICredential          ← xAI Grok        apiKey
    └── OllamaCredential       ← 本地 Ollama      host

ModelCard (Record)
    modelName: String
    displayName: String
    contextSize: Integer

2.1 CredentialBase

抽象基类:

java 复制代码
public abstract class CredentialBase {
    private final String id;

    // 唯一标识
    public final String getId();

    // 关联的 ChatModel 类型
    public abstract Class<? extends ChatModelBase> getChatModelClass();

    // 列出此凭证下可用的模型(异步,部分提供商需 API 调用)
    public Mono<List<ModelCard>> listModels();
}

2.2 ModelCard

模型卡片:

java 复制代码
public record ModelCard(
    String modelName,       // API 名称,如 "qwen-max"
    String displayName,     // 展示名称,如 "Qwen Max"
    Integer contextSize     // 上下文窗口大小(token)
) {}

通过 credential.listModels() 获取,供前端渲染模型选择器。

2.3 八种实现

凭证 TYPE 常量 字段 关联 ChatModel
DashScopeCredential "dashscope" apiKey, baseUrl DashScopeChatModel
OpenAICredential "openai" apiKey, baseUrl, organization OpenAIChatModel
AnthropicCredential "anthropic" apiKey, baseUrl AnthropicChatModel
GeminiCredential "gemini" apiKey GeminiChatModel
DeepSeekCredential "deepseek" apiKey, baseUrl OpenAIChatModel
KimiCredential "kimi" apiKey, baseUrl OpenAIChatModel
XAICredential "xai" apiKey OpenAIChatModel
OllamaCredential "ollama" host OllamaChatModel

DeepSeek / Kimi / XAI 都是 OpenAI 兼容 API,因此复用 OpenAIChatModel,只凭证字段和默认地址不同。

2.4 Builder 示例

java 复制代码
// DashScope
DashScopeCredential dashscope = DashScopeCredential.builder()
    .id("my-dashscope")
    .apiKey(System.getenv("DASHSCOPE_API_KEY"))
    .build();

// OpenAI
OpenAICredential openai = OpenAICredential.builder()
    .id("my-openai")
    .apiKey("sk-xxx")
    .baseUrl("https://api.openai.com/v1")
    .organization("org-xxx")
    .build();

// DeepSeek
DeepSeekCredential deepseek = DeepSeekCredential.builder()
    .id("my-deepseek")
    .apiKey("sk-xxx")       // 默认 baseUrl: https://api.deepseek.com
    .build();

// Ollama(本地,无需 apiKey)
OllamaCredential ollama = OllamaCredential.builder()
    .id("local-ollama")
    .host("http://localhost:11434")
    .build();

2.5 fromJson() :从配置反序列化

每个凭证都有静态 fromJson() 方法,支持从 JSON 配置文件或数据库反序列化:

java 复制代码
// 通用格式:{ "type": "dashscope", "apiKey": "sk-xxx", ... }
DashScopeCredential cred = DashScopeCredential.fromJson(
    "my-dashscope",           // id
    "dashscope",              // type
    "{\"apiKey\":\"sk-xxx\"}" // config JSON
);

2.6 与 Model 包的关系

复制代码
┌─────────────────────────────────────────────────────────┐
│                    ModelRegistry                         │
│  resolve("dashscope:qwen-max")                          │
│      │                                                   │
│      ├── 1. 查找 ProviderEntry "dashscope:"              │
│      ├── 2. 调用 ModelFactory(modelName)                 │
│      │       ├── 读取环境变量 DASHSCOPE_API_KEY          │
│      │       └── 创建 DashScopeChatModel(apiKey, name)  │
│      └── 3. 返回 Model 实例                              │
└─────────────────────────────────────────────────────────┘

Credential 的职责:

  1. 存储认证信息(apiKey / baseUrl / host
  2. 通过 listModels() 获取可用模型列表
  3. 通过 getChatModelClass() 告知应创建哪种 ChatModel

Model 的职责:

  1. 接收 Messages + ToolSchema → 返回 ChatResponse
  2. 处理 HTTP/gRPC 通信
  3. 管理 GenerateOptionstemperature / maxTokens 等)

2.7 使用示例

创建凭证并获取模型列表:

java 复制代码
DashScopeCredential credential = DashScopeCredential.builder()
    .id("prod-dashscope")
    .apiKey("sk-xxx")
    .build();

// 异步获取可用模型列表
credential.listModels().subscribe(models -> {
    for (ModelCard card : models) {
        System.out.printf("%s | %s | %d tokens%n",
            card.modelName(), card.displayName(), card.contextSize());
    }
});

从凭证创建 ChatModel

java 复制代码
DashScopeCredential credential = DashScopeCredential.builder()
    .id("my-ds").apiKey("sk-xxx").build();

// 获取凭证的模型列表 → 选择第一个 → 创建 ChatModel
credential.listModels()
    .map(models -> models.get(0).modelName())
    .map(modelName -> DashScopeChatModel.builder()
        .apiKey(credential.getApiKey())
        .modelName(modelName)
        .build())
    .subscribe(model -> {
        // 用 model 调用 LLM
    });

大多数场景不需要手动管理凭证,ModelRegistry 内部自动处理:

java 复制代码
// 一行搞定:自动读取环境变量,自动创建凭证 + 模型
Model model = ModelRegistry.resolve("dashscope:qwen-max");

// 等价于手动:
// 1. DashScopeCredential.fromEnv() → apiKey
// 2. DashScopeChatModel.builder().apiKey(apiKey).modelName("qwen-max").build()

3. 模型接入层

io.agentscope.core.modelAgentScope 2.0模型接入层 ,提供统一的 LLM 调用抽象。

核心设计理念:

  • 接口统一 :所有模型通过 Model 接口接入,对上层 Agent 透明
  • 基类复用ChatModelBase 封装流式调用、错误处理等通用逻辑
  • Builder 模式 :每个模型提供 Builder,支持链式配置
  • 全局注册ModelRegistry 支持按名称解析模型(如 "dashscope:qwen-max"

类图:

text 复制代码
Model (interface)                     ModelRegistry (static)
    │ stream(msgs, tools, options)        │ register(name, model)
    │ getModelName()                      │ resolve("dashscope:qwen-max")
    │                                     │ registerFactory(...)
    ▼
ChatModelBase (abstract)
    │ stream() → Generator pipeline (retry/config merge)
    │ doStream() --- 子类实现
    │
    ├── DashScopeChatModel        ← 通义千问
    ├── OpenAIChatModel           ← OpenAI 兼容
    ├── AnthropicChatModel        ← Claude
    ├── GeminiChatModel           ← Google Gemini
    └── OllamaChatModel           ← 本地 Ollama

工具类:
    GenerateOptions     ← 生成参数(temperature/maxTokens/thinking...)
    ExecutionConfig     ← 执行策略(超时/重试/退避)
    ToolSchema          ← 工具 Schema(name/description/parameters)
    ToolChoice (interface)
    ChatResponse        ← 模型响应(content/usage/finishReason)
    ChatUsage           ← Token 用量(input/output/total)
    EndpointType        ← DashScope 端点类型(AUTO/TEXT/MULTIMODAL)

3.1 Model 接口

所有模型实现的唯一入口。Agent 调用 model.stream(messages, tools, options) 获取 Flux<ChatResponse> 流式响应。

java 复制代码
public interface Model {
    Flux<ChatResponse> stream(
        List<Msg> messages,
        List<ToolSchema> tools,
        GenerateOptions options
    );
    String getModelName();
    default boolean supportsNativeStructuredOutput() { return false; }
}

3.2 ChatModelBase 抽象基类

内置了 ExecutionConfig 驱动的重试/超时/退避管道,子类只需实现 doStream()

java 复制代码
public abstract class ChatModelBase implements Model {
    // 模板方法:处理 GenerateOptions 合并 + ExecutionConfig 重试/超时
    public final Flux<ChatResponse> stream(...);

    // 子类实现:真正的 HTTP/gRPC 调用
    protected abstract Flux<ChatResponse> doStream(
        List<Msg> messages, List<ToolSchema> tools, GenerateOptions options);
}

3.3 模型实现类

模型 Builder 关键参数
DashScopeChatModel 通义千问(Qwen) apiKey, modelName, enableThinking, enableSearch, endpointType
OpenAIChatModel OpenAI / 兼容 API apiKey, baseUrl, modelName
AnthropicChatModel Claude apiKey, modelName
GeminiChatModel Google Gemini apiKey, modelName
OllamaChatModel 本地 Ollama baseUrl, modelName

构建 DashScopeChatModel 示例:

java 复制代码
DashScopeChatModel model = DashScopeChatModel.builder()
    .apiKey("sk-xxx")                    // 必填
    .modelName("qwen-max")               // 模型名
    .endpointType(EndpointType.AUTO)     // AUTO / TEXT / MULTIMODAL
    .enableThinking(true)                // 启用思考模式(qwen-plus/qwen-max)
    .enableSearch(false)                 // 启用联网搜索
    .stream(true)                        // 是否流式
    .defaultOptions(GenerateOptions.builder()
        .temperature(0.7)
        .maxTokens(2000)
        .build())
    .proxy(ProxyConfig.http("proxy:8080"))
    .build();

3.4 GenerateOptions 生成参数

每次模型调用可覆盖的参数,Builder 支持所有主流参数:

java 复制代码
GenerateOptions options = GenerateOptions.builder()
    .temperature(0.7)            // 温度
    .topP(1.0)                   // Top-P 采样
    .maxTokens(4096)             // 最大输出 token
    .maxCompletionTokens(2048)   // 最大完成 token(OpenAI 风格)
    .topK(50)                    // Top-K 采样
    .seed(42L)                   // 随机种子
    .thinkingBudget(1000)        // 思考预算(Claude/Qwen)
    .reasoningEffort("medium")   // 推理强度(OpenAI o1)
    .frequencyPenalty(0.1)       // 频率惩罚
    .presencePenalty(0.1)        // 存在惩罚
    .parallelToolCalls(true)     // 并行工具调用
    .cacheControl(true)          // Prompt 缓存
    .executionConfig(ExecutionConfig.builder()
        .timeout(Duration.ofSeconds(60))
        .maxAttempts(3)
        .build())
    .toolChoice(...)             // 工具选择策略
    .responseFormat(...)         // 结构化输出格式
    .build();

3.5 ExecutionConfig 执行策略

控制模型调用的超时、重试和退避

java 复制代码
ExecutionConfig config = ExecutionConfig.builder()
    .timeout(Duration.ofSeconds(60))     // 单次调用超时
    .maxAttempts(3)                      // 最大重试次数(含首次)
    .initialBackoff(Duration.ofMillis(100))  // 初始退避
    .maxBackoff(Duration.ofSeconds(10))      // 最大退避
    .backoffMultiplier(2.0)              // 退避倍增因子
    .retryOn(e -> isRetryableError(e))   // 自定义重试判断
    .build();

内置常量:

  • MODEL_DEFAULTS:模型调用默认策略(3 次重试,60s 超时,指数退避)
  • TOOL_DEFAULTS:工具执行默认策略(1 次,30s 超时)
  • RETRYABLE_ERRORS:内置可重试错误判断(5xx、超时、限流等)

3.6 ChatResponse 模型响应

java 复制代码
ChatResponse response = ChatResponse.builder()
    .id("chatcmpl-xxx")               // 响应 ID
    .content(List.of(TextBlock...))    // ContentBlock 列表
    .usage(ChatUsage.builder()         // Token 用量
        .inputTokens(156)
        .outputTokens(89)
        .build())
    .finishReason("stop")             // stop / length / tool_calls
    .metadata(Map.of(...))            // 额外元数据
    .build();

3.7 ChatUsage Token 用量

java 复制代码
public class ChatUsage {
    int getInputTokens();     // 输入 token
    int getOutputTokens();    // 输出 token
    int getTotalTokens();     // 总 token = input + output
    double getTime();         // 耗时(秒)
}

3.8 ModelRegistry 模型注册中心

全局静态注册表,支持按字符串名称解析模型:

java 复制代码
// 手动注册
ModelRegistry.register("my-model", myModelInstance);

// 注册工厂(延迟创建)
ModelRegistry.registerFactory("provider:", modelName -> { ... });

// 按名称解析(自动识别 provider:model 格式)
Model model = ModelRegistry.resolve("dashscope:qwen-max");
// → 自动找到 DashScopeChatModel,从环境变量 DASHSCOPE_API_KEY 读取密钥

// 内置支持的 provider:
//   dashscope: → DashScopeChatModel       (DASHSCOPE_API_KEY)
//   openai:    → OpenAIChatModel          (OPENAI_API_KEY)
//   anthropic: → AnthropicChatModel       (ANTHROPIC_API_KEY)
//   gemini:    → GeminiChatModel          (GEMINI_API_KEY)
//   ollama:    → OllamaChatModel          (OLLAMA_BASE_URL)

HarnessAgent 中可以直接用字符串指定模型:

java 复制代码
HarnessAgent.builder()
    .model("dashscope:qwen-max")    // ModelRegistry 自动解析
    .build();

3.9 ToolSchema 工具 Schema

工具定义传给 LLMJSON Schema

java 复制代码
ToolSchema schema = ToolSchema.builder()
    .name("get_weather")
    .description("获取城市天气")
    .parameters(Map.of(
        "type", "object",
        "properties", Map.of(
            "city", Map.of("type", "string", "description", "城市名称")
        ),
        "required", List.of("city")
    ))
    .build();

3.10 EndpointType 端点类型

DashScope 有三种端点模式:

枚举值 说明
AUTO 自动选择(默认)
TEXT 纯文本端点
MULTIMODAL 多模态端点(支持图片/文件)

3.11 使用示例

直接使用 Model

java 复制代码
DashScopeChatModel model = DashScopeChatModel.builder()
    .apiKey(System.getenv("DASHSCOPE_API_KEY"))
    .modelName("qwen-plus")
    .stream(true)
    .build();

List<Msg> messages = List.of(
    Msg.builder().role(MsgRole.USER)
        .content(List.of(TextBlock.builder().text("你好").build()))
        .build()
);

model.stream(messages, List.of(), GenerateOptions.builder()
        .temperature(0.7).maxTokens(1000).build())
    .subscribe(response -> {
        response.getContent().forEach(block -> {
            if (block instanceof TextBlock text) {
                System.out.print(text.getText());
            }
        });
    });

通过 ModelRegistry 使用:

java 复制代码
// 一行解析(自动读取环境变量)
Model model = ModelRegistry.resolve("dashscope:qwen-max");

// 或手动注册
ModelRegistry.register("my-qwen",
    DashScopeChatModel.builder().apiKey("sk-xxx").modelName("qwen-plus").build());
Model model = ModelRegistry.resolve("my-qwen");

HarnessAgent 中使用:

java 复制代码
// 方式 1:传字符串,ModelRegistry 自动解析
HarnessAgent.builder()
    .model("dashscope:qwen-max")
    .build();

// 方式 2:传 Model 实例
HarnessAgent.builder()
    .model(DashScopeChatModel.builder().apiKey("sk-xxx").modelName("qwen-plus").build())
    .build();

自定义重试策略:

java 复制代码
ExecutionConfig retryConfig = ExecutionConfig.builder()
    .maxAttempts(5)
    .initialBackoff(Duration.ofSeconds(1))
    .maxBackoff(Duration.ofSeconds(30))
    .backoffMultiplier(2.0)
    .retryOn(e -> e.getMessage().contains("rate_limit"))
    .build();

// 注入到 ReActAgent
ReActAgent.builder()
    .model(model)
    .modelExecutionConfig(retryConfig)
    .build();
相关推荐
dozenyaoyida1 小时前
AI与大模型新闻日报 | 2026-06-12
人工智能·ai·大模型·新闻
Blb1236541 小时前
技术解析-固体绝缘材料表面电阻率测试
人工智能·功能测试·制造·材料工程
云淡风轻~窗明几净1 小时前
角谷猜想的任意算法测试
数据结构·人工智能·算法
SaaS_Product1 小时前
同步盘操作教程:如何自动同步文件
人工智能·云计算·saas·onedrive
Z-D-K1 小时前
考验AI的“自我和意识“-AI对《红楼梦》后40回的改写(21)
人工智能·ai·aigc·交互·agi
CIO_Alliance1 小时前
API激增时代,如何用iPaaS实现API全生命周期治理
人工智能·ai·ipaas·系统集成·企业ai化转型
云烟成雨TD1 小时前
Agent Scope Java 2.x 系列【5】智能体抽象层
java·人工智能·agent
黎茗Dawn1 小时前
CNN、RNN与Self-Attention:定义、原理、复杂度与对比-AI轮回基本原理复习3
人工智能·rnn·cnn
Angelina_Jolie1 小时前
DiCLIP:用扩散模型激活CLIP的密集知识,弱监督语义分割新SOTA
人工智能