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 会增加调用开销
相关推荐
wangruofeng4 小时前
1.17 万赞的 Claude 技能,源码只有 321 字节:拆解 Anthropic 内部疯传的 ELI5
aigc·ai编程·claude
Flynt4 小时前
从 Claude Code 切到 Pi 跑了一阵,聊聊真实体感
agent·ai编程·claude
潘高5 小时前
如何用AI做出高质量的PPT
ai编程
全栈弄潮儿6 小时前
先让 AI 出方案,再让它写代码:新手也能使用的设计习惯
aigc·openai·ai编程
long3166 小时前
封装(Encapsulation)
java·人工智能·ai·ai编程
zandy10117 小时前
AI编程工具技术测评2026:Kimi Code、Cursor等6款常见编程软件选型清单
ai编程
就叫飞六吧7 小时前
两道门:X-Frame-Options 和 SameSite 到底谁管什么
开发语言·chrome·ai编程
Web3_Basketball8 小时前
动手玩DeepSeek视觉版:多模态OCR实战代码
ai编程
飞哥数智坊9 小时前
我给 DeepSeek 看了两次截图,才发现 Vision 真正的价值
人工智能·ai编程·deepseek