Spring Ai Alibaba Graph实现五大工作流模式

发布于:2025-06-25 ⋅ 阅读:(16) ⋅ 点赞:(0)

Spring Ai Alibaba Graph实现五大工作流模式

概述

building-effective-agents
一文中,Anthropic将"智能体系统"(agentic systems),从架构层面分为 “工作流”(workflows)和 “智能体”(agents):

工作流(Workflow):通过预定义代码路径来协调大语言模型(LLMs)和工具的系统。
智能体(Agent):与之相反,这类系统中的大语言模型可动态指导自身流程及工具使用,自主掌控任务完成。

本文主要讨论的是使用Spring Ai Alibaba Graph实现五种基本工作流。

技术实现

采用的技术栈如下:

Spring AI

Spring Boot

Java 17+

Spring AI Alibaba Graph

spring-ai-alibaba-graph核心概念

1.StateGraph(状态图/工作流图) 定义整个工作流的主类。 支持添加节点(addNode)、边(addEdge、addConditionalEdges)、条件分支、子图等。 可校验图结构,最终编译为 CompiledGraph 以供执行。

2.Node(节点) 表示工作流中的单个步骤(如模型调用、数据处理等)。 支持异步节点,可封装大模型调用或自定义逻辑。

3.Edge(边) 表示节点之间的转移关系。 支持条件分支(根据状态决定下一个节点)。

4.OverAllState(全局状态) 可序列化的全局状态对象,贯穿整个工作流。 支持按 key 注册不同的合并/更新策略(如替换、合并等)。 用于数据传递、断点续跑、人工干预等。

5.CompiledGraph(已编译图) StateGraph 的可执行版本。 负责实际的节点执行、状态流转、结果流式输出。 支持中断、并行节点、检查点等高级特性。

官网文档

工作流模式

1. 链式工作流(Chain Workflow)

实现提示词链式处理,将任务分解为一系列 LLM 调用,每个步骤处理前一步的输出。适用于可清晰拆分为固定子任务的场景。如下架构图所示:

在这里插入图片描述

使用场景:

具有明确顺序步骤的任务

愿意用延迟换取更高准确性

每个步骤依赖前一步输出

应用案例

数据转换管道

多步骤文本处理

结构化步骤的文档生成

实现

链式工作流(Chain Workflow)如上架构图所示,流程节点包括步骤节点(LLM CALL)和程序检测节点(Gate非必须)。下面示例流程包含4个步骤,
其中step1和step2之间有个检测节点,检测通过继续流程,否则流程结束。

节点定义:

//分步骤处理节点
static class StepNode implements NodeAction {

    private final ChatClient client;
    private final String systemPrompt;
    private final String inputKey;
    private final String outputKey;

    StepNode(ChatClient client, String systemPrompt, String inputKey, String outputKey) {
      this.client = client;
      this.systemPrompt = systemPrompt;
      this.inputKey = inputKey;
      this.outputKey = outputKey;
    }

    @Override
    public Map<String, Object> apply(OverAllState state) {
      String text = (String) state.value(inputKey).orElse("");
      // 调用 LLM
      ChatResponse resp = client.prompt().system(systemPrompt).user(text).call()
          .chatResponse();
      String stepResult = resp.getResult().getOutput().getText();
      return Map.of(outputKey, stepResult);
    }
}

//程序检测节点 programmatic checks非必须
static class GateNode implements NodeAction {

  @Override
  public Map<String, Object> apply(OverAllState state) {
    //一些程序性的检测,如果未通过流程结束
    Map<String, Object> checkResultMap = new HashMap<>();
    checkResultMap.put("checked", "pass");
    // checkResultMap.put("checked",fail);
    return checkResultMap;
  }
}
流程编排
public StateGraph chainGraph(ChatModel chatModel) throws GraphStateException {

    ChatClient client = ChatClient.builder(chatModel).defaultAdvisors(new SimpleLoggerAdvisor())
        .build();
    OverAllStateFactory factory = () -> {
      OverAllState s = new OverAllState();
      s.registerKeyAndStrategy("inputText", new ReplaceStrategy());
      s.registerKeyAndStrategy("step1Text", new ReplaceStrategy());
      s.registerKeyAndStrategy("step2Text", new ReplaceStrategy());
      s.registerKeyAndStrategy("step3Text", new ReplaceStrategy());
      s.registerKeyAndStrategy("result", new ReplaceStrategy());
      return s;
    };
    // Step 1
    String step1System = """
        Extract only the numerical values and their associated metrics from the text.
        Format each as'value: metric' on a new line.
        Example format:
        92: customer satisfaction
        45%: revenue growth""";
    // Step 2
    String step2System = """
        Convert all numerical values to percentages where possible.
        If not a percentage or points, convert to decimal (e.g., 92 points -> 92%).
        Keep one number per line.
        Example format:
        92%: customer satisfaction
        45%: revenue growth""";
    // Step 3
    String step3System = """
        Sort all lines in descending order by numerical value.
        Keep the format 'value: metric' on each line.
        Example:
        92%: customer satisfaction
        87%: employee satisfaction""";
    // Step 4
    String step4System = """
        Format the sorted data as a markdown table with columns:
        | Metric | Value |
        |:--|--:|
        | Customer Satisfaction | 92% | """;
    StateGraph graph = new StateGraph("ChainGraph", factory.create());
    graph.addNode("step1", node_async(new StepNode(client, step1System, "inputText", "step1Text")));
    graph.addNode("gate", node_async(new GateNode()));
    graph.addNode("step2", node_async(new StepNode(client, step2System, "step1Text", "step2Text")));
    graph.addNode("step3", node_async(new StepNode(client, step3System, "step2Text", "step3Text")));
    graph.addNode("step4", node_async(new StepNode(client, step4System, "step3Text", "result")));
    graph.addEdge(START, "step1");
    graph.addEdge("step1", "gate")
        .addConditionalEdges("gate", edge_async(t -> {
              String checked = (String) t.value("checked").orElse("fail");
              return checked;
            }),
            Map.of("pass", "step2", "fail", END));
    graph.addEdge("step2", "step3");
    graph.addEdge("step3", "step4");
    graph.addEdge("step4", END);
    // 可视化
    GraphRepresentation representation = graph.getGraph(Type.PLANTUML,
        "chain flow");
    System.out.println("\n=== Chain UML Flow ===");
    System.out.println(representation.content());
    System.out.println("==================================\n");

    return graph;
  }

上述例子在step1和step2中间加了一个gate节点,模拟在2个结点之前做一个检测,如果复合条件继续下一个节点,否则流程结束。UML图如下:

在这里插入图片描述

完整代码:Chain Workflow

并行化工作流(Parallelization Workflow)

支持多个 LLM 操作的并发处理,包含两种关键变体:
分块(Sectioning): 将任务拆分为可并行运行的独立子任务
投票(Voting): 多次执行同一任务以获取多样化输出。架构图如下:

在这里插入图片描述

使用场景:

处理大量相似但独立的任务

需要多个独立视角的任务

处理任务处理速度,并且任务可并行

应用案例

文档批量处理
多视角内容分析
并行验证检查

实现

并行化工作流(Parallelization Workflow)如上架构图所示,流程节点包括并行节点(LLM CALL)和结果合并节点(Aggregator)。下面示例实现一个文本情感分析和
关键字提取的流程,流程中包含节点SentimentAnalysisNode(情感分析),KeywordExtractionNode(关键字提取),结果合并(Aggregator)。

节点定义:
//情感分析节点
static class SentimentAnalysisNode implements NodeAction {

  private final ChatClient client;

  private final String key;

  public SentimentAnalysisNode(ChatClient client, String key) {
    this.client = client;
    this.key = key;
  }

  @Override
  public Map<String, Object> apply(OverAllState state) throws Exception {
    String text = (String) state.value(key).orElse("");
    // 调用 LLM
    ChatResponse resp = client.prompt().user("情感分析: " + text).call()
        .chatResponse();
    String sentiment = resp.getResult().getOutput().getText();
    return Map.of("sentiment", sentiment);
  }

}

//关键字提取节点
static class KeywordExtractionNode implements NodeAction {

  private final ChatClient client;

  private final String key;

  public KeywordExtractionNode(ChatClient client, String key) {
    this.client = client;
    this.key = key;
  }

  @Override
  public Map<String, Object> apply(OverAllState state) throws Exception {
    String text = (String) state.value(key).orElse("");
    ChatResponse resp = client.prompt().user("提取关键字: " + text).call()
        .chatResponse();
    String kws = resp.getResult().getOutput().getText();
    return Map.of("keywords", List.of(kws.split(",\\s*")));
  }

}
//并行结果合并节点
static class AggregatorNode implements NodeAction {

  @Override
  public Map<String, Object> apply(OverAllState state) {
    String sent = (String) state.value("sentiment").orElse("unknown");
    List<?> kws = (List<?>) state.value("keywords").orElse(List.of());
    return Map.of("analysis", Map.of("sentiment", sent, "keywords", kws));
  }

}

流程编排
   public StateGraph parallelGraph(ChatModel chatModel) throws GraphStateException {
    ChatClient client = ChatClient.builder(chatModel).defaultAdvisors(new SimpleLoggerAdvisor())
        .build();
    OverAllStateFactory factory = () -> {
      OverAllState s = new OverAllState();
      s.registerKeyAndStrategy("inputText", new ReplaceStrategy());
      s.registerKeyAndStrategy("sentiment", new ReplaceStrategy());
      s.registerKeyAndStrategy("keywords", new ReplaceStrategy());
      s.registerKeyAndStrategy("aggregator", new ReplaceStrategy());
      return s;
    };
    StateGraph graph = new StateGraph("Parallel Flow", factory.create())
        // 注册节点
        .addNode("sentiment", node_async(new SentimentAnalysisNode(client, "inputText")))
        .addNode("keyword", node_async(new KeywordExtractionNode(client, "inputText")))
        .addNode("aggregator", node_async(new AggregatorNode()))
        // 构建并行边:使用单条边携带多目标
        .addEdge(START, "sentiment")
        .addEdge(START, "keyword")
        // 限制:sentiment/keyword 并行后必须合并到同一节点
        .addEdge("sentiment", "aggregator")
        .addEdge("keyword", "aggregator")

        .addEdge("aggregator", END);

    // 可视化
    GraphRepresentation representation = graph.getGraph(GraphRepresentation.Type.PLANTUML,
        "parallel  flow");
    System.out.println("\n=== Parallel  UML Flow ===");
    System.out.println(representation.content());
    System.out.println("==================================\n");

    return graph;
  }

UML图如下:

在这里插入图片描述

完整代码:Parallel Workflow

路由工作流(Routing Workflow)

路由对输入进行分类,并将其定向到专门的后续任务。架构图如下:

在这里插入图片描述

使用场景:

输入具有明确类别的复杂任务
不同输入需要专门处理
可准确分类的任务

应用案例

客户支持工单路由
内容审核系统
基于复杂度的查询优化

实现

路由工作流(Routing Workflow)如上架构图所示,流程节点包括路由节点(LLM Router)负责任务分类选择后续专门处理节点,和专门LLM处理节点(LLM CALL)。
下面示例实现客服问题处理流程,流程接受到问题经过路由节点(LlmCallRouterNode)处理,大模型给出选择的后续任务处理节点(SelectionLlmNode),专门任务处理节点
有三种:账单问题处理,技术问题处理,一般问题处理(默认)。

节点定义:
  //选择的专门任务处理节点
static class SelectionLlmNode implements NodeAction {

  private final ChatClient client;

  public SelectionLlmNode(ChatClient client) {
    this.client = client;
  }

  @Override
  public Map<String, Object> apply(OverAllState state) {
    String inputText = (String) state.value("inputText").orElse("");
    String selectionLlm = (String) state.value("selectionLlm").orElse("");
    String result = client.prompt().system(availableRoutes.get(selectionLlm).toString())
        .user(inputText).call().chatResponse().getResult().getOutput()
        .getText();
    return Map.of("result", result);
  }
}

//大模型问题分类路由节点
static class LlmCallRouterNode implements NodeAction {

  private final ChatClient client;
  private final String inputTextKey;

  public LlmCallRouterNode(ChatClient client, String inputTextKey) {
    this.client = client;
    this.inputTextKey = inputTextKey;
  }

  @Override
  public Map<String, Object> apply(OverAllState state) {
    String inputText = (String) state.value(inputTextKey).orElse("");
    String selectorPrompt = String.format("""
        Analyze the input and select the most appropriate support team from these options: %s
        First explain your reasoning, then provide your selection in this JSON format:

        \\{
            "reasoning": "Brief explanation of why this ticket should be routed to a specific team.
                        Consider key terms, user intent, and urgency level.",
            "selection": "The chosen team name"
        \\}

        Input: %s""", availableRoutes.keySet(), inputText);

    LlmRoutingResponse llmRoutingResponse = client.prompt(selectorPrompt).call()
        .entity(LlmRoutingResponse.class);
    Map<String, Object> selectionLlmMap = new HashMap<>();
    selectionLlmMap.put("selectionLlm", llmRoutingResponse.selection);
    return selectionLlmMap;
  }
}

public record LlmRoutingResponse(String reasoning, String selection) {

}
流程编排
  private static Map<String, Object> availableRoutes = new HashMap<>();

  static {
    availableRoutes.put("billing", "You are a billing specialist. Help resolve billing issues...");
    availableRoutes.put("technical",
        "You are a technical support engineer. Help solve technical problems...");
    availableRoutes.put("general",
        "You are a customer service representative. Help with general inquiries...");
  }
  
  public StateGraph routingGraph(ChatModel chatModel) throws GraphStateException {
    ChatClient client = ChatClient.builder(chatModel).defaultAdvisors(new SimpleLoggerAdvisor())
        .build();
    OverAllStateFactory factory = () -> {
      OverAllState s = new OverAllState();
      s.registerKeyAndStrategy("inputText", new ReplaceStrategy());
      s.registerKeyAndStrategy("selectionLlm", new ReplaceStrategy());
      return s;
    };

    StateGraph graph = new StateGraph("ParallelDemo", factory.create())
        // 注册节点
        .addNode("routing", node_async(new LlmCallRouterNode(client, "inputText")))
        .addNode("billing", node_async(new SelectionLlmNode(client)))
        .addNode("technical", node_async(new SelectionLlmNode(client)))
        .addNode("general", node_async(new SelectionLlmNode(client)))
        // 构建并行边:使用单条边携带多目标
        .addEdge(START, "routing")
        .addConditionalEdges("routing", AsyncEdgeAction.edge_async(new EdgeAction() {
          @Override
          public String apply(OverAllState state) {
            String selection = (String) state.value("selectionLlm").orElse("");
            return selection;
          }
        }), Map.of("billing", "billing", "technical", "technical", "general", "general"))
        .addEdge("billing", END)
        .addEdge("technical", END)
        .addEdge("general", END);

    // 可视化
    GraphRepresentation representation = graph.getGraph(GraphRepresentation.Type.PLANTUML,
        "Routing  flow");
    System.out.println("\n=== Routing  UML Flow ===");
    System.out.println(representation.content());
    System.out.println("==================================\n");

    return graph;
  }

UML图如下:

在这里插入图片描述

完整代码:Routing Workflow

Orchestrator-Workers

Orchestrator-Workers 工作流中,一个中心LLM动态分解任务,将它们委托给工作LLM,并综合它们的结果。它与并行化工作流(Parallelization Workflow)最大区别在于,
它分解的任务数量不固定。架构图如下:

在这里插入图片描述

使用场景:

子任务无法预先预测的复杂任务
需要不同方法或视角的任务
需要自适应问题解决的场景

应用案例

复杂代码生成任务
多源研究任务
自适应内容创作

实现

Orchestrator-Workers如上架构图所示,流程节点包括编排节点(Orchestrator)负责任务拆解,工作节点(LLM CALL),结果合并节点(Synthesizer)。
下面示例实现写作工作流,用户输入写作的主题,编排节点拆解成子任务,并启动并行流程执行子任务,最后Synthesizer节点合并结果。

节点定义
  //编排节点
static class OrchestratorNode implements NodeAction {
  private final ChatClient client;
  OrchestratorNode(ChatClient client) {
    this.client=client;
  }
  @Override
  public Map<String, Object> apply(OverAllState state) throws GraphStateException {
    String DEFAULT_ORCHESTRATOR_PROMPT = """
        Analyze this task and break it down into 2-3 distinct approaches:

        Task: {task}

        Return your response in this JSON format:
        \\{
        "analysis": "Explain your understanding of the task and which variations would be valuable.
                     Focus on how each approach serves different aspects of the task.",
        "tasks": [
        	\\{
        	"type": "formal",
        	"description": "Write a precise, technical version that emphasizes specifications"
        	\\},
        	\\{
        	"type": "conversational",
        	"description": "Write an engaging, friendly version that connects with readers"
        	\\}
        ]
        \\}
        """;
    String text = (String) state.value("inputText").orElse("");
    OrchestratorResponse orchestratorResponse = client.prompt()
        .user(u -> u.text(DEFAULT_ORCHESTRATOR_PROMPT)
            .param("task", text))
        .call()
        .entity(OrchestratorResponse.class);
    //任务拆改后,批量并行执行子任务
    OverAllStateFactory factory = () -> {
      OverAllState s = new OverAllState();
      s.registerKeyAndStrategy("inputText", new ReplaceStrategy());
      s.registerKeyAndStrategy("result",new AppendStrategy());
      s.registerKeyAndStrategy("outputText",new ReplaceStrategy());
      return s;
    };
    StateGraph stateGraph = new StateGraph(() -> factory.create());
    for (int i = 0; i < orchestratorResponse.tasks.size(); i++) {
      stateGraph.addNode("task"+i,node_async(new TaskCallLlmNode(client,orchestratorResponse.tasks.get(i))))
          .addEdge(START,"task"+i)
          .addEdge("task"+i,END);

    }
    // 可视化
    GraphRepresentation representation = stateGraph.getGraph(GraphRepresentation.Type.PLANTUML,
        "orchestrator task  flow");
    System.out.println("\n=== Orchestrator Task  UML Flow ===");
    System.out.println(representation.content());
    System.out.println("==================================\n");
    CompileConfig compileConfig = CompileConfig.builder().saverConfig(SaverConfig.builder().build()).build();
    Map<String, Object> taskResults = stateGraph.compile(compileConfig).invoke(Map.of("inputText", text)).get().data();
    ArrayList result =(ArrayList) taskResults.get("result");
    return Map.of("taskResult",result);
  }
}

//工作处理节点
static class WorkerLlmNode implements NodeAction {
  private ChatClient client;
  private Task task;
  String DEFAULT_WORKER_PROMPT = """
      Generate content based on:
      Task: {original_task}
      Style: {task_type}
      Guidelines: {task_description}
      """;

  public WorkerLlmNode(ChatClient client,Task task) {
    this.client = client;
    this.task=task;
  }

  @Override
  public Map<String, Object> apply(OverAllState state) throws Exception {
    String taskDescription = (String) state.value("inputText").orElse("");
    String result = client.prompt()
        .user(u -> u.text(DEFAULT_WORKER_PROMPT)
            .param("original_task", taskDescription)
            .param("task_type", task.type())
            .param("task_description", task.description()))
        .call()
        .content();
    return Map.of("result", result);
  }
}
//结果合并节点
static class SynthesizerNode implements NodeAction {

  @Override
  public Map<String, Object> apply(OverAllState state) throws Exception {
    Object result = state.value("result").orElse("");
    return Map.of("outputText", result);
  }
}

流程编排:
  @Bean
  public StateGraph orchestratorGraph(ChatModel chatModel) throws GraphStateException {
    ChatClient client = ChatClient.builder(chatModel).defaultAdvisors(new SimpleLoggerAdvisor())
        .build();
    OverAllStateFactory factory = () -> {
      OverAllState s = new OverAllState();
      s.registerKeyAndStrategy("inputText", new ReplaceStrategy());
      s.registerKeyAndStrategy("taskResult", new ReplaceStrategy());
      return s;
    };
    StateGraph graph = new StateGraph("OrchestratorGraph", factory.create())
        // 注册节点
            .addNode("orchestrator",node_async(new OrchestratorNode(client)))
            .addNode("synthesizer",node_async(new SynthesizerNode()))
        .addEdge(START, "orchestrator")
       .addEdge("orchestrator","synthesizer")
        .addEdge("synthesizer",END);

    // 可视化
    GraphRepresentation representation = graph.getGraph(GraphRepresentation.Type.PLANTUML,
        "orchestrator  flow");
    System.out.println("\n=== Orchestrator  UML Flow ===");
    System.out.println(representation.content());
    System.out.println("==================================\n");

    return graph;
  }

UML图如下:

在这里插入图片描述

子任务并行流程,任务数量动态

在这里插入图片描述

完整代码:Orchestrator Workflow

评估-优化工作流(Evaluator-Optimizer)

在评估-优化工作流中,一个LLM调用生成响应,而另一个调用在循环中提供评估和反馈。架构如下
在这里插入图片描述

使用场景:

存在明确评估标准时
迭代优化能带来可衡量价值时
任务受益于多轮批判时

应用案例

代码审查与改进
内容质量优化
翻译精修
复杂搜索任务

实现

评估-优化工作流(Evaluator-Optimizer)如上架构图所示,流程节点包括内容生成节点(Orchestrator),评估反馈节点(EvaluateNode)。
下面示例实现代码生成工作流,用户输入要生成的代码描述,生成内容节点(GeneratorNode)生成代码,然后评估反馈节点(EvaluateNode)生成反馈和是否达标,如果不符合要求
继续生成内容,一直循环知道评估通过。

节点定义:
/**
   * 生成内容节点
   */
  static class GeneratorNode implements NodeAction {

    private final ChatClient chatClient;
    private final String generatorPrompt;

    public GeneratorNode(ChatClient chatClient, String generatorPrompt) {
      this.chatClient = chatClient;
      this.generatorPrompt = generatorPrompt;
    }

    public GeneratorNode(ChatClient chatClient) {
      this.chatClient = chatClient;
      this.generatorPrompt = DEFAULT_GENERATOR_PROMPT;
    }

    @Override
    public Map<String, Object> apply(OverAllState state) throws Exception {
      String task = (String) state.value("task").orElse("");
      String context = (String) state.value("context").orElse("");
      Generation generationResponse = chatClient.prompt()
          .user(u -> u.text("{prompt}\n{context}\nTask: {task}")
              .param("prompt", this.generatorPrompt)
              .param("context", context)
              .param("task", task))
          .call()
          .entity(Generation.class);
      System.out.println(
          String.format("\n=== GENERATOR OUTPUT ===\nTHOUGHTS: %s\n\nRESPONSE:\n %s\n",
              generationResponse.thoughts(), generationResponse.response()));
      return Map.of("context", generationResponse.response, "historyContext",
          generationResponse.response, "chainOfThought",
          generationResponse);
    }
  }

  /**
   * 评估内容节点
   */
  static class EvaluateNode implements NodeAction {


    private final ChatClient chatClient;
    private final String evaluatorPrompt;

    public EvaluateNode(ChatClient chatClient, String evaluatorPrompt) {
      this.chatClient = chatClient;
      this.evaluatorPrompt = evaluatorPrompt;
    }

    public EvaluateNode(ChatClient chatClient) {
      this.chatClient = chatClient;
      this.evaluatorPrompt = DEFAULT_EVALUATOR_PROMPT;
    }

    @Override
    public Map<String, Object> apply(OverAllState state) throws Exception {
      String context = (String) state.value("context").orElse("");
      String task = (String) state.value("task").orElse("");
      EvaluationResponse evaluationResponse = chatClient.prompt()
          .user(u -> u.text("{prompt}\nOriginal task: {task}\nContent to evaluate: {content}")
              .param("prompt", evaluatorPrompt)
              .param("task", task)
              .param("content", context))
          .call()
          .entity(EvaluationResponse.class);
      System.out.println(
          String.format("\n===评估输出 ===\n评估内容: %s\n\n反馈结果: %s\n",
              evaluationResponse.evaluation(), evaluationResponse.feedback()));
      //累计结果
      List<String> historyContext = (List<String>) state.value("historyContext").orElse("");
      StringBuilder newContext = new StringBuilder();
      newContext.append("Previous attempts:");
      for (String hc : historyContext) {
        newContext.append("\n- ").append(hc);
      }
      newContext.append("\nFeedback: ").append(evaluationResponse.feedback());
      return Map.of("evaluationType", evaluationResponse.evaluation, "context",
          newContext.toString());
    }

    /**
     * 根据评估解决,选择下一步EdgeAction
     */
    static class EvaluateEdgeAction implements EdgeAction {


      @Override
      public String apply(OverAllState state) throws Exception {
        Evaluation evaluationType = (Evaluation) state.value("evaluationType").orElse("");
        return evaluationType.name();
      }
    }

    public record EvaluationResponse(Evaluation evaluation, String feedback) {

      public enum Evaluation {
        PASS, NEEDS_IMPROVEMENT, FAIL
      }
    }

    public record Generation(String thoughts, String response) {

    }
  }
流程编排
 public StateGraph evaluatorOptimizerGraph(ChatModel chatModel) throws GraphStateException {
    ChatClient client = ChatClient.builder(chatModel).defaultAdvisors(new SimpleLoggerAdvisor())
        .build();
    OverAllStateFactory factory = () -> {
      OverAllState s = new OverAllState();
      //任务
      s.registerKeyAndStrategy("task", new ReplaceStrategy());
      //生成内容和思考内容,值覆盖
      s.registerKeyAndStrategy("context", new ReplaceStrategy());
      //生成的内容的历史记录List<String>
      s.registerKeyAndStrategy("historyContext", new AppendStrategy());
      //List<Generation>历史生成内容对象
      s.registerKeyAndStrategy("chainOfThought", new AppendStrategy());
      //评估结果类型
      s.registerKeyAndStrategy("evaluationType", new ReplaceStrategy());

      return s;
    };
    StateGraph graph = new StateGraph("EvaluatorOptimizerGraph", factory.create())
        // 注册节点
        .addNode("generator", node_async(new GeneratorNode(client)))
        .addNode("evaluator", node_async(new EvaluateNode(client)))
        .addEdge(START, "generator")
        .addEdge("generator", "evaluator")
        .addConditionalEdges("evaluator", AsyncEdgeAction.edge_async(new EvaluateEdgeAction()),
            Map.of("PASS", END, "NEEDS_IMPROVEMENT", "generator", "FAIL", END));

    // 可视化
    GraphRepresentation representation = graph.getGraph(GraphRepresentation.Type.PLANTUML,
        "evaluator-optimizer  flow");
    System.out.println("\n=== EvaluatorOptimizer  UML Flow ===");
    System.out.println(representation.content());
    System.out.println("==================================\n");

    return graph;
  }

UML图如下:

在这里插入图片描述

完整代码:Evaluator Workflow


网站公告

今日签到

点亮在社区的每一天
去签到