多客科技 发表于 2025-9-4 06:44

Spring AI Observability可观测性

作者:微信文章
Spring AI Observability可观测性

Spring AI非常好用,但是也经常有人问
• 这个工具调用传的什么参数,为什么返回值不对• 究竟从知识库检索到了哪些内容,模型怎么回答的不符合预期

等等这些问题

当一个框架越成熟,也就意味着,我们越无法了解其内部的运行情况。幸好的是Spring AI提供了可观测性(Observability)支持,为开发者了解框架内部运行情况提供了可能。

本篇我们就来通过可观测性,实现工具调用、知识库检索的日志打印。
什么是可观测性

可观测性在Spring Framework 6 和 Spring Boot 3 中正式推出,可观测性是指:

检查系统的输出,以更好地理解系统的内部工作原理

通过指标、日志、分布式追踪之间的相互关联性,赋予开发者推理系统状态的能力,以便调试应用程序中的异常和延迟

本篇仅通过日志实现可观测性,指标、分布式追踪详细内容,大家请从 Spring 框架文档获取
准备

搭建SpringBoot项目、添加SpringAI依赖、配置Open AI参数,请大家直接看Spring AI入门这篇。

因为众所周知的原因,我们不能直接访问国外网站。如果有需要Open AI 代理地址,请关注公众号,点击菜单apikey 免费获取!

添加依赖,以通过SpringBoot自动配置启用可观测性
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>原理

添加spring-boot-starter-actuator 依赖后,项目启动会创建 ObservationRegistry 实例,然后自动将Spring管理的所有 ObservationHandler 实例添加到 ObservationRegistry 的配置类中。当我们使用Observation实例监控我们代码时,符合Observation.Context 的handle实现类会被执行。

Observation 执行监控示例(示例中自行创建registry并添加handle实例 ):
// 创建 ObservationRegistry
ObservationRegistry registry = ObservationRegistry.create();
// 注册 ObservationHandler
registry.observationConfig().observationHandler(new MyHandler());

// 创建Observation 并执行监测
Observation.createNotStarted("user.name", registry)
      .contextualName("getting-user-name")
      .lowCardinalityKeyValue("userType", "userType1") // let's assume that you can have 3 user types
      .highCardinalityKeyValue("userId", "1234") // let's assume that this is an arbitrary number
      .observe(() -> log.info("Hello")); // this is a shortcut for starting an observation, opening a scope, running user's code, closing the scope and stopping the observation工具调用

当模型选择调用工具时,系统并不会有任何输出,开发人员无法得知模型的具体动作,不利于调试和优化。

在Spring AI ToolCalling 中,我们通过@Tool注解创建了获取当前时间、设定闹钟两个工具,下面我们就来打印模型调用工具的具体内容:

首先创建ToolCallingObservationHandler:
@Component
public class ToolCallingObservationHandler implements ObservationHandler<ToolCallingObservationContext> {
    private static final Logger logger = LoggerFactory.getLogger(ToolCallingObservationHandler.class);

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void onStop(ToolCallingObservationContext context) {
      try {
            logger.info("\n tool calling completion: \n 工具定义:{} \n 请求参数:{} \n 响应内容:{}", objectMapper.writeValueAsString(context.getToolDefinition()), context.getToolCallArguments(), context.getToolCallResult());
      } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
      }
    }

    @Override
    public boolean supportsContext(Observation.Context context) {
      return context instanceof ToolCallingObservationContext;
    }
}
重写方法还有onStart()、onEvent()、onError()等,大家自行选择在哪个生命周期进行自定义处理即可。

创建工具调用controller
@RestController
@RequestMapping("/tool")
public class ToolCallingController {

    private final ChatClient chatClient;

    ToolCallingController(ChatClient.Builder chatClientBuilder) {
      this.chatClient = chatClientBuilder.build();
    }

    @RequestMapping("/time")
    public String time(String userInput) {
      String content=this.chatClient.prompt()
                .tools(newDateTimeTools())
                .user(userInput)
                .call()
                .content();
      return content;
    }
}
浏览器请求:http://localhost:8080/tool/time?userInput=现在几点了,我们看一下打印日志
2025-08-29T22:13:25.471+08:00INFO 64415 --- c.s.l.c.ToolCallingObservationHandler    :
tool calling completion:
工具定义:{"name":"getCurrentDateTime","description":"Get the current date and time in the user's timezone","inputSchema":"{\n\"$schema\" : \"https://json-schema.org/draft/2020-12/schema\",\n\"type\" : \"object\",\n\"properties\" : { },\n\"required\" : [ ],\n\"additionalProperties\" : false\n}"}
请求参数:{}
响应内容:"2025-08-29T22:13:25.467503+08:00"
这样,我们就可以很清楚的看到工具调用的相关数据。
RAG检索

当使用Spring AI 提供的RetrievalAugmentationAdvisor以实现开箱即用RAG检索时,仅需要一行代码,即可完成RAG的接入,但同时也意味着无法直观的监视RAG数据。

下面我们通过Observability来实现RAG的可观测性。

向量库及数据我们直接使用之前RAG篇的内容,具体请看:Spring AI RAG检索增强生成。

创建RAGObservationHandle实现ObservationHandler
@Component
public class RAGObservationHandle implements ObservationHandler<VectorStoreObservationContext> {

    private static final Logger logger = LoggerFactory.getLogger(RAGObservationHandle.class);

    public void onStop(VectorStoreObservationContext context) {
      logger.info("------------------- rag查询到的数据: start ------------------------");
      context.getQueryResponse().forEach(result -> {
            // 这里截取一下,避免打印太多数据
            logger.info(" rag查询到的数据: {}", result.getText().substring(0, 30));
      });
      logger.info("------------------- rag查询到的数据: end ------------------------");
    }

    @Override
    public boolean supportsContext(Observation.Context context) {
      return context instanceof VectorStoreObservationContext;
    }
}
创建RAG 调用接口
@RestController
@RequestMapping(value = "/rag")
public class RagController {
    private final ChatClient chatClient;
    private final VectorStore vectorStore;

    public RagController(ChatClient.Builder chatClientBuilder, VectorStore vectorStore) {
      this.chatClient = chatClientBuilder.build();
      this.vectorStore = vectorStore;
    }

    @RequestMapping("/qa")
    public String qa(String userInput) {
      return chatClient.prompt()
                .advisors(newQuestionAnswerAdvisor(vectorStore))
                .user(userInput)
                .call()
                .content();
    }
}浏览器访问:http://localhost:8080/rag/qa?userInput=都考哪些科目,查看控制台打印


为了方便查看,这里仅截取了30个字符。Spring AI支持

SpringAI 内置了部分handler,当项目启动时,SpringBoot自动配置监测到相关配置,会创建内置handle实例,交给Sprint管理。

支持的handle配置有
# 打印模型prompt日志
spring.ai.chat.observations.log-prompt=true
# 打印模型完成内容
spring.ai.chat.observations.log-completion=true
# 打印模型错误日志
spring.ai.chat.observations.include-error-logging=true
# 打印图片生成prompt
spring.ai.image.observations.log-prompt=true
# 打印向量查询结果
spring.ai.vectorstore.observations.log-query-response=true下面以添加了spring.ai.chat.observations.log-completion=true为例,当请求完成后,控制台打印如下:


Sprig AI提供的默认handle大多仅返回了简单的内容,并没返回相关的元数据,大家可以根据需求自行实现。
最后

利用 Spring AI 的可观测性功能,通过观察日志,可以了解到工具调用、RAG其内部数据流转情况,方便了我们对应用的调试、记录。另外,Spring AI在很多地方都预留了观察入口,当有需要时,可以查看是否有依赖相应模块的Observation包,自行接入即可。

文章源码、Open AI代理地址、免费api-key请关注公众号免费获取。
页: [1]
查看完整版本: Spring AI Observability可观测性