Spring AI Advisor:一行代码解决 AI 应用"面条代码"

别再每次调用 AI 都写重复的鉴权、日志、敏感词检测代码了------Spring AI Advisor 给你一条可复现的路,把横切逻辑像乐高一样拆装。

先附上一张Spring AI Advisor架构图

先给结论

Spring AI Advisor 是一个可插拔的请求/响应增强机制,通过责任链模式组合多个横切关注点,让 AI 应用的横切逻辑管理变得简单优雅。

为什么需要 Advisor

没有 Advisor 时,每次调用都要写一堆重复代码:

java 复制代码
public String callAI(String input) {
    if (!authService.check(input)) return "无权限";
    if (containsSensitiveWords(input)) return "敏感内容";
    List<ChatMessage> history = memoryService.getHistory();
    ChatResponse response = model.call(new Prompt(input, history));
    logger.info("调用AI:输入={},输出={}", input, response);
    memoryService.save(input, response);
    if (checkOutput(response)) return "输出有风险";
    return response.getContent();
}

有 Advisor 后,业务代码回归干净:

java 复制代码
ChatClient chatClient = ChatClient.builder(chatModel)
    .defaultAdvisors(
        new AuthAdvisor(),
        new SensitiveWordAdvisor(),
        new MessageChatMemoryAdvisor(chatMemory),
        new MyLoggerAdvisor()
    )
    .build();

String answer = chatClient.prompt().user("你好").call().content();

Advisor 的核心原理

1. 责任链模式

  • 前置处理:按 Order 值升序执行(值小先执行)
  • 后置处理:按 Order 值降序执行(后进先出)
  • 短路机制:某个 Advisor 可以直接返回,不继续调用模型

2. 短路能力

java 复制代码
public class SensitiveWordAdvisor implements CallAroundAdvisor {
    @Override
    public AdvisedResponse aroundCall(AdvisedRequest req, CallAroundAdvisorChain chain) {
        for (String word : blockedWords) {
            if (req.userText().contains(word)) {
                AssistantMessage rejection = new AssistantMessage("抱歉,内容不合规,无法回答。");
                ChatResponse chatResponse = new ChatResponse(List.of(new Generation(rejection)));
                return AdvisedResponse.from(chatResponse).advisorContext(req.advisorContext()).build();
            }
        }
        return chain.nextAroundCall(req);
    }
}

3. 自定义 Advisor 四步

  1. 同时实现 CallAroundAdvisor + StreamAroundAdvisor
  2. 重写 aroundCall/aroundStream
  3. 设置 getOrder()
  4. 返回唯一 getName()

实战案例:RAG + Advisor

java 复制代码
@Service
public class KnowledgeService {
    private final ChatClient chatClient;

    public KnowledgeService(ChatClient.Builder builder, VectorStore vectorStore) {
        this.chatClient = builder
            .defaultSystem("请基于提供的上下文信息回答问题,上下文不足就明确说明,不要编造。")
            .defaultAdvisors(
                new QuestionAnswerAdvisor(vectorStore),
                new AuthAdvisor(),
                new MyLoggerAdvisor()
            )
            .build();
    }

    public String ask(String question) {
        return chatClient.prompt().user(question).call().content();
    }
}

踩坑清单

Order 排序

java 复制代码
new MyLoggerAdvisor(),         // Order=0,最外层
new SecurityAdvisor(),         // Order=10,安全检查
new RagAdvisor(vectorStore),    // Order=50,RAG 检索增强
new MemoryAdvisor(chatMemory)   // Order=100,最靠近模型

流式处理

java 复制代码
// 错误:对每个 token 触发
chain.nextAroundStream(request).doOnNext(this::afterProcess)

// 正确:聚合完整响应
new MessageAggregator().aggregateAdvisedResponse(
    chain.nextAroundStream(request), this::logAfter)

避免耗时操作

Advisor 同步执行,别在链里做外部 API 调用或复杂计算。

不适用的情况

  1. 需要异步处理时,Advisor 是同步的
  2. 复杂并行场景,责任链是串行的
  3. 性能敏感场景,多个 Advisor 会增加调用开销
相关推荐
第十人i1 小时前
Pi 1.0 正式发布:原生 MCP + Pi Durable,终端编程代理的重大升级
ai编程·pi
交付一线的ZLycan2 小时前
我用AI coding给旧手表(华米Amazfit GTR4)写了个番茄代办App
ai编程
晚安code2 小时前
Gemini 4 Argon 价格与用途:和 GPT-6、Claude 怎么选
ai编程
StrangeXin2 小时前
做AI项目,为什么我提议成立一个委员会
ai编程
Maynor9962 小时前
6张商品图→17秒带货短视频:开源12个Claude Skills,配音、字幕花字、BGM本地一条命令出片
ffmpeg·ai编程·claude·电商·agent skills
奈落243 小时前
【RAG 深度修炼】专栏 · 第 9 期(收官):安全专题与生产 Checklist 总集——从能跑的 Demo 到睡得着觉的生产系统
大数据·网络·人工智能·安全·ai编程
空心木偶☜4 小时前
A2A2A(多智能体协作)
开发语言·python·ai·ai编程
搬砖的小码农_Sky14 小时前
AI Agent:如何处理Claude Code 最近版本(2026年更新)引入的模型上下文限制
人工智能·windows·ai·ai编程