1.建议实现自定义拦截器建议要将流式(StreamAroundAdviosr)和非流式(CallAroundAdviosr)一起实现
自定义 Advisor 步骤
1)选择合适的接口实现,实现以下接口之一或同时实现两者(更建议同时实现):
- CallAroundAdvisor:用于处理同步请求和响应(非流式)
- StreamAroundAdvisor:用于处理流式请求和响应
public class MyCustomAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {
}
2)实现核心方法
对于非流式处理 (CallAroundAdvisor),实现 aroundCall 方法:
@Override
public AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {
AdvisedRequest modifiedRequest = processRequest(advisedRequest);
//在方法之前要执行的准备,处理请求(前置处理)
AdvisedResponse response = chain.nextAroundCall(modifiedRequest);
//相当于切面方法,要增强的原始方法,在这里是下一个链的Adviosr或者AI
return processResponse(response);
//执行之后的响应(后置处理)
}
对于流式处理 (StreamAroundAdvisor),实现 aroundStream 方法:
@Override
public Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain) {
//处理请求
AdvisedRequest modifiedRequest = processRequest(advisedRequest);
//调用链中的下一个Advisor或者AI并处理流式响应
return chain.nextAroundStream(modifiedRequest)
.map(response -> processResponse(response));
}
3.实例:实现日志输出自定义拦截器,Re2自定义拦截器
最佳实践
1)保持单一职责:每个 Advisor 应专注于一项特定任务
2)注意执行顺序:合理设置getOrder()值确保 Advisor 按正确顺序执行
3)同时支持流式和非流式:尽可能同时实现两种接口以提高灵活性
4)高效处理请求:避免在 Advisor 中执行耗时操作
5)测试边界情况:确保 Advisor 能够优雅处理异常和边界情况
6)对于需要更复杂处理的流式场景,可以使用 Reactor 的操作符:
7)可以使用 adviseContext 在 Advisor 链中共享状态:
advisedRequest = advisedRequest.updateContext(context -> {
context.put("key", "value");
return context;
});
Object value = advisedResponse.adviseContext().get("key");
2.结构化输出
结构化输出转换器(Structured Output Converter)是 Spring AI 提供的一种实用机制,用于将大语言模型返回的文本输出转换为结构化数据格式,如 JSON、XML 或 Java 类,这对于需要可靠解析 AI 输出值的下游应用程序非常重要。