框架版本: Spring AI 1.1.2(spring-ai-starter-model-openai
项目路径org.springframework.ai.chat.model.ChatResponse

一、对象结构总览

二、逐层详解(同步调用)

2.1 chatResponse ChatResponse(最外层)

package org.springframework.ai.chat.model;

public class ChatResponse {

    /** 生成结果(通常只有一个,流式会返回多个片段) */
    private Generation result;

    /** 响应元信息(包含 Usage) */
    private ChatResponseMetadata metadata;
}

2.2   result  Generation(结果层)

public class Generation {

    /** AI 输出的消息对象 */
    private AssistantMessage output;

    /** 生成的元信息(如结束原因) */
    private GenerationMetadata metadata;
}

2.3  output AssistantMessage(消息层)

public class AssistantMessage {

    /** AI 返回的文本内容 */
    private String text;

    /** 消息的其他属性(元数据等) */
    private Map<String, Object> properties;
}

2.4   properties GenerationMetadata(生成元信息)

public class GenerationMetadata {

    /** 结束原因:stop / length / content_filter / null */
    private String finishReason;
}

2.5  metadata ChatResponseMetadata(响应元信息)

public class ChatResponseMetadata {

    /** Token 用量统计 */
    private Usage usage;

    /** 模型名称 */
    private String model;
}

2.6  usage Usage(Token 用量)

public class Usage {

    /** 输入(提示词)消耗的 Token 数 */
    private Integer promptTokens;

    /** 输出(生成内容)消耗的 Token 数 */
    private Integer completionTokens;

    /** 总 Token 数 = promptTokens + completionTokens */
    private Integer totalTokens;
}

三、流式响应(Flux)差异

流式调用时,Flux<ChatResponse> 会返回多个 ChatResponse 对象,每个片段的特征如下:

阶段 result output.text usage
中间片段 非 null,有内容 当前增量文本片段 通常 null
最后一个有内容的片段 非 null,有内容 最后的文本增量 可能包含完整用量
结束空包(终止标记) null null 完整用量(部分实现)

注意事项

  • 流式中间片段的 usage 通常为 null只有在最后一个有效包或空终止包中才包含完整用量
  • 需要判断 getResult() == null 或 getOutput() == null 来跳过空终止包
  • finishReason 在流式中间包中通常为 null,仅在最后包中才有值

四、代码中的使用

4.1 非流式(call()

ChatResponse aiResponse =
    chatClient.prompt(prompt).call().chatResponse();
// 获取 AI 回复文本
String content = aiResponse.getResult().getOutput().getText();

// 获取 Token 用量
Integer promptTokens     = aiResponse.getMetadata().getUsage().getPromptTokens();
Integer completionTokens = aiResponse.getMetadata().getUsage().getCompletionTokens();
Integer totalTokens      = aiResponse.getMetadata().getUsage().getTotalTokens();

// 获取结束原因
String finishReason = aiResponse.getResult().getMetadata().getFinishReason();

4.2 流式(stream()

Flux<ChatResponse> flux =
    chatClient.prompt(prompt).stream().chatResponse();
flux.flatMap(chatResponse -> {

    // 跳过空终止包(最后一个空 chunk)
    if (chatResponse.getResult() == null
        || chatResponse.getResult().getOutput() == null) {
        return Flux.empty();
    }

    // 获取当前增量文本
    String chunk = chatResponse.getResult().getOutput().getText();

    // 获取 Token 用量(仅在有值时不 null)
    Usage usage = chatResponse.getMetadata().getUsage();
    if (usage != null) {
        Integer promptTokens = usage.getPromptTokens();
        Integer completionTokens = usage.getCompletionTokens();
    }

    return Flux.just(chunk);
});

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐