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 会增加调用开销
相关推荐
小虎AI生活12 小时前
给豆包和 Claude 派活总返工?把测试用例搬进提示词,前置验收清单一次交差
aigc·ai编程
abckingaa13 小时前
AI时代代码Review瓶颈分析
人工智能·ai编程·1024程序员节
楚国的小隐士14 小时前
从审核员到监工:AI正在重写评价体系,也重写人的价值
ai·编程·ai编程·哲学·马列主义
金銀銅鐵14 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
孔令飞16 小时前
工具分享:OneX AI 工具安装、配置及功能介绍
云原生·go·ai编程
Tangyuewei16 小时前
AI 编程后,越来越不会码了
人工智能·ai编程
slacker-kian16 小时前
[工程]:智能招聘--一个可组装的人才智能推荐系统
ai·ai编程·向量数据库·1024程序员节·相似性搜索·人力推荐系统
文谦南宁AI普工17 小时前
用 250 行纯标准库,给 Agent 造一道能验的出站门
aigc·agent·ai编程
我是小邵17 小时前
1024 特辑:我写过的 Skill,正在变成 AI 编程的基础设施
人工智能·agent·ai编程·skill·知识沉淀·协作·开发者工具
lugiax17 小时前
开着 Auto Mode 通宵让 AI 敲代码,为什么早上醒来还是卡在半夜?
ai编程·claude