摘要:在构建 AI Agent 时,我们面临两大挑战:一是如何让 LLM 记住之前的对话(Chat Context),二是如何在复杂的业务流程中传递数据(Execution Context)。

Spring AI Alibaba 给出了一套完美的组合拳:利用 Advisor 责任链处理微观的 Prompt 上下文,利用 GraphRunnerContext 处理宏观的业务状态流转。本文将从架构设计到源码实战,揭秘这两大引擎是如何协同工作的。

引言:上下文工程的两个维度

在开发企业级 AI 应用时,“上下文(Context)”其实包含了两层含义,初学者往往容易混淆:

  1. 语义上下文 (Semantic Context):LLM 需要的 Prompt 背景信息。例如:历史聊天记录、RAG 检索到的文档、当前的时间地点。

  2. 执行上下文 (Execution Context):代码运行时的业务状态。例如:当前的任务 ID、重试次数、生成的草稿内容、用户 ID。

Spring AI Alibaba 通过两套机制分别解决这两个问题,并在 Graph(图) 引擎中将它们合二为一。

一、引擎一:Advisor 责任链 (微观·语义上下文)

这是 Spring AI Alibaba 实现“上下文工程”的核心底层机制。它基于 AOP(面向切面编程)思想,在 ChatClient 发起请求的前后进行拦截和注入。

核心原理

通过实现 RequestResponseAdvisor 接口,框架可以在 Prompt 发送给大模型之前,动态地“塞入”信息。

典型实现:

  1. 记忆注入 (MessageChatMemoryAdvisor)

    • 自动从 ChatMemory(内存/Redis)中读取历史对话。

    • 实现逻辑:SystemPrompt = SystemPrompt + "\nHistory:\n" + retrieveHistory()。

  2. 知识注入 (QuestionAnswerAdvisor)

    • 自动将用户的问题向量化,去 DashVector 检索文档。

    • 实现逻辑:UserPrompt = UserPrompt + "\nContext:\n" + vectorSearch(query)。

一句话总结:Advisor 负责把“剧本”写好,确保发给 LLM 的 Prompt 是丰满的。

二、引擎二:GraphRunnerContext (宏观·执行上下文)

这是 spring-ai-alibaba-graph 模块特有的机制。当 Agent 开始执行一个复杂的“图(Graph)”任务时,GraphRunnerContext 就是整个任务的运行时容器

核心职责

  1. 状态持有 (OverAllState):它持有一个全局共享的 Java 对象(State)。无论流程流转到哪个节点(Node),都能读写这个对象。这是 Agent 的“背包”。

  2. 流式通道 (Streaming):它提供了一个 StreamObserver,允许任何节点随时向前端推送数据(打字机效果),而不仅仅是等节点结束。

一句话总结:GraphRunnerContext 负责管理“舞台”,确保演员(Node)知道现在演到哪一出,手里拿着什么道具。

三、深度融合:GraphRunnerContext 如何驱动上下文工程?

最精彩的部分在于:GraphRunnerContext 中的数据,往往是 Advisor 构建 Prompt 的原材料。

让我们通过一个**“AI 论文润色 Agent”**的实战案例,看这两者是如何结合的。

场景描述

Agent 需要循环执行:写草稿 -> 评审 -> 修改 -> 再评审。
在这个过程中:

  • GraphRunnerContext 记录:当前的草稿内容、评审意见、迭代轮次。

  • Advisor 记录:用户最开始的要求(“要学术风”)、之前的对话历史。

代码实战

1. 定义全局状态 (State)

这是存放在 GraphRunnerContext 里的东西。

public class PaperState {
    private String topic;       // 论文主题
    private String content;     // 当前草稿
    private String comments;    // 评审意见
    // ... getters/setters
}
2. 编写节点 (WriterNode)

关键点来了:请注意看 state (来自 GraphRunnerContext) 是如何喂给 chatClient (触发 Advisor) 的。

public class WriterNode implements BiFunction<PaperState, GraphRunnerContext, NodeOutput<PaperState>> {

    private final ChatClient chatClient;

    public WriterNode(ChatClient.Builder builder) {
        // 配置 ChatClient,挂载 Advisor
        this.chatClient = builder
            .defaultSystem("你是一个学术论文写作专家。")
            // 【微观引擎】挂载记忆,让 AI 记住"我偏好简短句式"这种历史指令
            .defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory())) 
            .build();
    }

    @Override
    public NodeOutput<PaperState> apply(PaperState state, GraphRunnerContext context) {
        // 1. 【宏观引擎】从 GraphRunnerContext (State) 获取业务数据
        String currentContent = state.getContent();
        String comments = state.getComments();

        // 2. 构建动态 Prompt
        String promptText;
        if (currentContent == null) {
            promptText = "请写一篇关于 " + state.getTopic() + " 的摘要。";
        } else {
            // 将"执行上下文"中的评审意见,注入到 Prompt 中
            promptText = "请根据以下评审意见修改文章:\n" + comments + "\n\n原文章:\n" + currentContent;
        }

        // 3. 【融合调用】
        // chatClient 会自动触发 Advisor,把"历史对话"拼接到 promptText 后面
        // 同时,context (GraphRunnerContext) 负责向前端推送流式 Token
        String newContent = chatClient.prompt()
            .user(promptText)
            .stream() // 获取流
            .content()
            .map(token -> {
                // 利用 GraphRunnerContext 做实时输出
                context.publishStreamUpdate(token); 
                return token;
            })
            .collect(Collectors.joining()); // 拼成完整字符串

        // 4. 【状态回写】更新 GraphRunnerContext 中的 State
        state.setContent(newContent);
        
        return NodeOutput.of(state);
    }
}

四、架构总结:一张图看懂关系

我们可以把这套机制比喻为**“导演与演员”**:

  1. GraphRunnerContext (导演/场记)

    • 它拿着剧本(PaperState)。

    • 它知道上一场戏拍完了(Node A 结束),下一场该拍哪(Router)。

    • 它记录着关键道具(content, comments)的状态。

  2. Node (演员)

    • 它从导演手里接过剧本(state)。

    • 它开始表演(执行业务逻辑)。

  3. ChatClient + Advisor (演员的提词器/大脑)

    • 当演员需要说话(调用 LLM)时,提词器(Advisor)会自动把以前的台词(ChatMemory)和背景资料(RAG)显示出来,辅助演员生成高质量的台词(Response)。

核心结论

Spring AI Alibaba 的上下文工程之所以强大,是因为它实现了分层管理

  • 隐式上下文 (Implicit Context) 由 Advisor 自动管理(历史记录、文档检索)。开发者在写业务逻辑时基本无感。

  • 显式上下文 (Explicit Context) 由 GraphRunnerContext 显式管理(业务变量、流程状态)。开发者在 Node 之间明确传递。

正是这种“显隐结合”,让我们既能写出逻辑严密的业务流程(Graph),又能拥有善解人意的 AI 大脑(Advisor)。

欢迎关注、一起交流、一汽进步!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐