10_Agent的使用OverAllState和RunnableConfig

视频版:space.bilibili.com/2012289471 源码:github.com/yinqqm/spri...

基础调用

通过call方法实现基础调用,返回的是AssistantMessage,也就是模型输出的消息。就是普通的调用和接收响应信息。

获取完整状态

基本使用:

java 复制代码
public void test8() throws GraphRunnerException {
        // ★ 关键:通过 Map 传入自定义状态(messages/input 之外的都是自定义状态)
        Map<String, Object> inputs = new HashMap<>();
        inputs.put("input", "帮我写一首诗");           // 预留关键字:用户输入
        inputs.put("messages", Messageutils.convertToMessages("帮我写一首诗"));
        inputs.put("custom_key", "这是我在test8中设置的值");   // ★ 自定义状态
        inputs.put("user_role", "admin");              // ★ 自定义状态
        inputs.put("session_id", "sess_001");          // ★ 自定义状态
        inputs.put("request_count", 0);                // ★ 自定义状态

        ChatModel chatModel = CreateChatClient.createDashScopeChatModel();
        ReactAgent getAllState = ReactAgent.builder()
                .model(chatModel)
                .name("get_all_state")
               // .instruction("你是一个助手,请根据用户输入完成任务。")
                .build();
        Optional<OverAllState> result =  getAllState.invoke(inputs);
        if (result.isPresent()) {
            OverAllState overAllState = result.get();
            Optional<Object> messages = overAllState.value("messages");
            // 访问自定义状态
            Optional<Object> customData = overAllState.value("custom_key");
            if (customData.isPresent()) {
                System.out.println("获取设置的custom_key:" + customData);
            }
            System.out.println("完整状态:" + overAllState);
        }
    }

它的作用:

OverAllState 作为基于图的流水线处理管道中跨节点共享数据的中央容器 。 它支持键值对数据存储,并为每个 key 配置自定义更新策略 (KeyStrategy), 允许灵活的合并或替换逻辑。此类是可序列化的,适用于持久化、检查点或跨节点通信。

⚠️ 警告: 这个类不是线程安全的,在并发场景需要同步。

核心字段:

java 复制代码
public final class OverAllState implements Serializable {

    /** ★ 核心数据存储:所有状态值的实际存放位置 */
    private final Map<String, Object> data;

    /** ★ 键策略映射:每个 key 对应一个更新策略 */
    private final Map<String, KeyStrategy> keyStrategies;

    /** ★ 长期记忆存储:用于跨执行周期的持久化 */
    private Store store;

    /** ★ 默认输入键名 */
    public static final String DEFAULT_INPUT_KEY = "input";

    /** ★ 删除标记常量 */
    public static final Object MARK_FOR_REMOVAL = new Object();
}

实际使用讲解:

实际使用场景:智能客服 + 用户画像注入

场景描述

假设你有一个智能客服 Agent,需要:

  1. 传入用户基本信息(VIP等级、偏好语言等)
  2. 传入当前订单号(用于工具查询)
  3. 在工具中读取这些自定义状态
  4. 最终从 OverAllState 中验证所有状态

最终回复:

diff 复制代码
🤖 Agent 最终回复:
尊敬的VIP客户张三您好!

关于您的订单 ORD-20260525-8899 的查询结果如下:
📦 订单状态:已发货
🚚 物流公司:顺丰速运 SF1234567890  
📅 预计送达:2026-05-27

商品明细:
- MacBook Pro 16寸 x 1台 = ¥19,999

使用配置

基本使用:

它是每次agent调用call方法执行时传入的。表示它是在agent真正执行的时候给定的参数。

ini 复制代码
AssistantMessage response = agent.call("你的问题", runnableConfig);

通过RunnableConfig来实现的,它的主要作用是:

会话记忆, 为不同的用户区分上下文,通过threadId来实现的。

java 复制代码
 /**
     * 使用配置,测试threadId实现不同用户之间使用不同的上下文信息
     */
    @Test
    public void test9() throws GraphRunnerException {
        ChatModel chatModel = CreateChatClient.createDashScopeChatModel();
        ReactAgent agent = ReactAgent.builder()
                .name("runnable_config")
                .model(chatModel)
                .saver(new MemorySaver())
                .build();
        //通过RunnableConfig 传递运行时配置
        String threadId123 = "thread_123";
        String threadId456 = "thread_456";
        RunnableConfig runnableConfig123 = RunnableConfig.builder()
                .threadId(threadId123)
                .build();
        RunnableConfig runnableConfig456 = RunnableConfig.builder()
                .threadId(threadId456)
                .build();
        agent.call("我叫123",runnableConfig123);
        agent.call("我叫456",runnableConfig456);


        AssistantMessage response123 = agent.call("我叫什么?",runnableConfig123);
        System.out.println("runnableConfig123:"+response123.getText());
        AssistantMessage response456 = agent.call("我叫什么?",runnableConfig456);
        System.out.println("runnableConfig456:"+response456.getText());

    }

存放不可变数据

通过metadata 来是实现。它是在运行期是不可变的。可以为Interceptor和tool提供参数。

在interceptor中获取:

java 复制代码
    public void test10() throws GraphRunnerException {

        ChatModel chatModel = CreateChatClient.createDashScopeChatModel();
        ReactAgent agent = ReactAgent.builder()
                .name("model_interceptor_agent")
                .model(chatModel)
                .interceptors(new DynamicPromptInterceptor()).build();
        //通过runnableConfig指定配置信息
        RunnableConfig runnableConfig = RunnableConfig.builder().addMetadata("user_role", "expert").build();
        AssistantMessage assistantMessage = agent.call("介绍一下Spring boot的自动注入原理。", runnableConfig);
        System.out.println(assistantMessage.getText());
    }
python 复制代码
public class DynamicPromptInterceptor extends ModelInterceptor {
    @Override
    public ModelResponse interceptModel(ModelRequest request, ModelCallHandler handler) {
        // 基于上下文构建动态 system prompt
        String userRole = (String) request.getContext().getOrDefault("user_role", "default");
        String dynamicPrompt = switch (userRole) {
            case "expert" -> """
                    你正在与技术专家对话。
                    - 使用专业术语
                    - 深入技术细节""";
            case "beginner" -> """
                    你正在与初学者对话。
                    - 使用简单语言
                    - 解释基础概念""";
            default -> "你是一个专业的助手,保持友好和专业。";
        };

        SystemMessage enhancedSystemMessage;
        if (request.getSystemMessage() == null) {
            enhancedSystemMessage = new SystemMessage(dynamicPrompt);
        } else {
            enhancedSystemMessage = new SystemMessage(request.getSystemMessage().getText() + dynamicPrompt);
        }

        ModelRequest modified = ModelRequest.builder(request)
                .systemMessage(enhancedSystemMessage)
                .build();
        return handler.call(modified);
    }

在Tool中获取

java 复制代码
public void test11() throws GraphRunnerException {

        //创建tool 类
        ToolCallback searchTool = FunctionToolCallback.
                builder("search", new SearchTool()).description("通过给定的参数查询线上新闻并返回结果") //定义工具描述,提供给模型的使用指南
                .inputType(SearchToolInput.class).build();

        ChatModel chatModel = CreateChatClient.createDashScopeChatModel();
        ReactAgent metaDataTool = ReactAgent.builder()
                .name("meta_data_tool")
                .model(chatModel)
                .tools(searchTool)
                .build();

        //创建RunnableConfig
        RunnableConfig runnableConfig = RunnableConfig.builder()
                .addMetadata("call_tool", "yes")
                .build();

        AssistantMessage assistantMessage = metaDataTool.call("今天发生了什么新闻", runnableConfig);

        System.out.println(assistantMessage.getText());

    }

SearchTool的定义

java 复制代码
public class SearchTool implements BiFunction<SearchToolInput, ToolContext, String> {
    @Override
    public String apply(SearchToolInput query, ToolContext toolContext) {
        String callTool = (String) toolContext.getContext().getOrDefault("call_tool", "N");
        System.out.println("get data from mateData:"+callTool);


        //mock 搜索web
        return """
                    习近平就推动哲学社会科学高质量发展作出重要指示
                    习近平同美国总统特朗普在中南海小范围会晤
                    【微镜头·中美元首在北京举行会谈】"让2026年成为中美关系继往开来的历史性、标志性年份"
                    武汉票价最贵火车发车:20999元起
                    """;
    }
}

总结

OverAllState RunnableConfig
定义 全局状态,业务数据 运行时配置,系统的环境配置信息
包含的数据 input:用户的提问message:模型响应的结果其他自定义的key:用户自定义保存的信息 threadId:区分会话metadata:在运行时不可变,可以用来配置系统变量和环境参数等。
获取和使用 在Hooks中获取,后面会讲解Hooks的使用。 在interceptor中,通过ModelRequest.getContext().get()或getOrDefault()获取。在Tool中,通过ToolContext.getContext().get()或getOrDefault()获取。
可变性 可以变的,每个节点都可以读取它,并且它的key有对应的update strategy 更新策略。 通常只读,不可变。
相关推荐
神奇小汤圆1 小时前
一条命令让你这辈子彻底解决"LF will be replaced by CRLF"(建议收藏)
后端
会编程的土豆1 小时前
Go 里的 error 接口 + 假 nil(超级重点)
开发语言·后端·golang
西安邮电大学1 小时前
Kafka保证消息顺序性
java·后端·kafka
贺国亚1 小时前
RAG 检索增强 · 向量库与 Chunking
后端·面试
晓杰'2 小时前
从0到1实现Balatro游戏后端(5):得分计算与单局结算流程实现
后端·typescript·node.js·游戏开发·项目实战·nestjs·webscoket
减瓦2 小时前
Jackson 自定义反序列化器的类型不匹配陷阱
java·后端
HLAIA光子2 小时前
计网面试躲不掉的三连问:OSI七层、HTTPS握手、REST还是RPC
后端·网络协议
JAVA社区2 小时前
Java高级全套教程(九)—— SpringCloud超详细实战详解
java·开发语言·后端·spring cloud·面试·职场和发展
yspwf2 小时前
Electron/Node 本地集成 C#/.NET,node-api-dotnet
后端