当前位置: 首页 > news >正文

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

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;}@Overridepublic Map<String, Object> apply(OverAllState state) {String text = (String) state.value(inputKey).orElse("");// 调用 LLMChatResponse 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 {@Overridepublic 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 1String 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 satisfaction45%: revenue growth""";// Step 2String 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 satisfaction45%: revenue growth""";// Step 3String step3System = """Sort all lines in descending order by numerical value.Keep the format 'value: metric' on each line.Example:92%: customer satisfaction87%: employee satisfaction""";// Step 4String 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;}@Overridepublic Map<String, Object> apply(OverAllState state) throws Exception {String text = (String) state.value(key).orElse("");// 调用 LLMChatResponse 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;}@Overridepublic 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 {@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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: %sFirst 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() {@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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 {@Overridepublic Map<String, Object> apply(OverAllState state) throws Exception {Object result = state.value("result").orElse("");return Map.of("outputText", result);}
}
流程编排:
  @Beanpublic 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;}@Overridepublic 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;}@Overridepublic 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 {@Overridepublic 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

相关文章:

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

Spring Ai Alibaba Graph实现五大工作流模式 概述 在 building-effective-agents 一文中,Anthropic将"智能体系统"(agentic systems),从架构层面分为 “工作流”&#xff08;workflows&#xff09;和 “智能体”&#xff08;agents&#xff09;&#xff1a; 工作流…...

基于单片机的语音控制设计(论文)

摘要 自然语音作为人机交互在目前得以广泛的应用以及极大的发展前景。该设计介绍了基于非指定人语音芯片LD3320的语音控制器结构及其实现语音控制的方法。该语音控制器利用STM32F103C8T6单片机作为主要控制器&#xff0c;控制芯片对输入的进行语音识别并处理&#xff0c;根据语…...

【网络安全】从IP头部看网络通信:IPv4、IPv6与抓包工具 Wireshark 实战

从IP头部看网络通信&#xff1a;IPv4、IPv6与抓包工具 Wireshark实战 在网络安全分析和数据通信的世界中&#xff0c;一切都始于“数据包”。数据包是网络上传输的基本单位&#xff0c;而数据包的结构与内容&#xff0c;正是我们理解网络行为的核心。本文将带你深入了解 IP 协…...

计算机组成原理笔记(公众号版本)

1.MAR&#xff0c;存储单元和PC位数之间的关系 我们的MAR位数取决于我们的存储单元的个数&#xff1b; PC位数也是取决于我们的存储单元的个数&#xff1b; 假设我们是64个存储单元&#xff0c;我们的这个MAR实际上就是6位&#xff0c;因为这个2的6次方等于我们的64吗&#…...

CPM基本原理

CPM&#xff08;连续相位调制&#xff0c;Continuous Phase Modulation &#xff09;是一种恒包络&#xff0c;信号相位随时间连续变化的调制技术 。其优势显著&#xff0c;连续相位特性&#xff0c;频谱效率高&#xff0c;对带外辐射抑制好&#xff1b;相位平滑过渡&#xff0…...

浅谈开源在线客服系统与 APP 集成的技术方案与优劣势

在为移动端 App 接入在线客服系统的过程中&#xff0c;我经历了长时间的技术选型探索。最初&#xff0c;我也曾被一些“技术理想主义”选项所吸引&#xff0c;比如让用户自己研发界面我提供 API 以获得最高自由度&#xff0c;或集成 SDK 以追求原生体验。然而&#xff0c;随着项…...

AutoGPT,自主完成复杂任务

AutoGPT是一个开源的AI Agent项目&#xff0c;它的核心目标是让AI能够自主完成复杂任务&#xff0c;而不仅仅是回答单个问题。简单来说&#xff0c;它让AI具备了"自主思考和行动"的能力。 1. AutoGPT的核心概念 什么是AI Agent&#xff1f; AI Agent&#xff08;智…...

基于Qt C++的影像重采样批处理工具设计与实现

摘要 本文介绍了一种基于Qt C++框架开发的高效影像重采样批处理工具。该工具支持按分辨率(DPI) 和按缩放倍率两种重采样模式,提供多种插值算法选择,具备强大的批量处理能力和直观的用户界面。工具实现了影像处理的自动化流程,显著提高了图像处理效率,特别适用于遥感影像处…...

Qt Windows平台调用ffmpeg动态库

本文基于QT6.8实测验证。 一、下载预编译库‌ 从官方或第三方源获取FFmpeg的Windows动态库&#xff08;Shared版本&#xff09;&#xff0c;解压后需包含以下目录&#xff1a; bin   DLL文件&#xff08;运行时依赖&#xff09;include   头文件lib   .lib或.dll.a链接…...

猿人学js逆向比赛第一届第十三题

一、分析请求 通过分析请求得知&#xff0c;本题目的参数为yuanrenxue_cookie&#xff0c;因为题目中中明说了是动态cookie&#xff0c;所以可以先删除这个cookie然后下脚本断点&#xff0c;简单分析看一下页面执行的js代码逻辑。 在经过这段代码的时候很明显的可以看到这里的有…...

React性能优化精髓之一:频繁setState导致滚动卡顿的解决方案

在开发一个 List 页面时&#xff0c;我们遇到了一个典型的React性能问题&#xff1a;页面在滚动时出现明显卡顿。这个问题的调试过程充满了误判和重新思考&#xff0c;最终发现了一个重要的性能优化原则。 问题现象 我们有一个监控仪表盘页面&#xff0c;包含多个图表组件。用…...

JavaScript 事件常用属性

一、事件对象基础 在事件处理函数中&#xff0c;浏览器会自动传入一个 event 对象&#xff0c;它包含了与事件相关的所有信息。 element.addEventListener(click, function(event) {// event 是事件对象 }); 二、常见事件属性 属性名 类型 描述 type String 事件类…...

配置自己的NTP 服务器做时间同步

✅ 推荐方案&#xff1a;使用 chrony 搭建 NTP 服务器&#xff08;适用于 CentOS 7/8/9&#xff09; chrony 是 CentOS 推荐的 NTP 实现&#xff0c;精度高、资源占用低、同步快&#xff0c;默认在 CentOS 8 中取代了 ntpd。 &#x1f527; 一、安装 chrony sudo yum install…...

基于深度学习的双色球智能预测系统:从原理到实现

需要源码的小伙伴可以在这里直接下载&#xff1a;基于深度学习的双色球智能预测系统&#xff1a;从原理到实现&#xff08;完整代码训练数据&#xff09;可直接运行-预测&#xff09;资源-CSDN下载可直接运行&#xff0c;包括完整的训练测试数据&#xff0c;让你的双色球更准&a…...

STM32[笔记]--4.嵌入式硬件基础

4.嵌入式硬件基础 4.1认识上官二号开发板 主控芯片:STM32F103C8T6高速晶振:8M低速晶振:32.768kLED:5颗KEY:3个 主控芯片内部的资源如下项目介绍内核Cortex-M3Flsah64K*8bitSRAM20K*8bitGPIO37个GPIO,分别为PA0-PB15,PC13-PC15,PD0-PD1ADC2个12bitADC合计12了通道,外部通…...

Springboot项目中使用手机号短信验证码注册登录实现

文章目录 1. 功能概述2. 技术栈3. 实现步骤3.1 短信服务集成3.2 创建短信工具类3.3 验证码生成和存储3.4 控制器实现发送短信验证码手机号+验证码注册短信验证码登录3.5 服务层实现4. 前端实现4.1 API层4.2 手机号注册页面5. 最佳实践6. 总结本文将介绍如何在Spring Boot应用中…...

Python的GUI库选择指南(深度拓展)

前文我们分析了python的GUI库&#xff0c;有很多&#xff0c;面向应用场景也不尽相同&#xff0c;如何在使用过程中&#xff0c;选择合适的GUI库呢&#xff1f;可以查看&#xff1a;python有哪些常用的GUI&#xff08;图形用户界面&#xff09;库及选择指南-CSDN博客 初学者推…...

Kubernetes生命周期管理:深入理解 Pod 生命周期

云原生学习路线导航页&#xff08;持续更新中&#xff09; kubernetes学习系列快捷链接 Kubernetes架构原则和对象设计&#xff08;一&#xff09;Kubernetes架构原则和对象设计&#xff08;二&#xff09;Kubernetes架构原则和对象设计&#xff08;三&#xff09;Kubernetes控…...

JVM(12)——详解G1垃圾回收器

G1&#xff08;Garbage-First&#xff09;垃圾回收器。它是现代 Java 应用中默认的垃圾回收器&#xff08;自 JDK 9 起&#xff09;&#xff0c;旨在提供一个高性能、可预测停顿时间&#xff08;低延迟&#xff09;的解决方案&#xff0c;尤其适合大内存&#xff08;多GB甚至TB…...

Matplotlib vs Seaborn:选择与区别

相同点 都是Python数据可视化库&#xff1a;两者都用于创建统计图形和图表 基于Python生态系统&#xff1a;都与NumPy、Pandas等科学计算库良好集成 开源免费&#xff1a;两者都是开源项目&#xff0c;可自由使用 支持多种图表类型&#xff1a;都能创建折线图、柱状图、散点…...

TCP/UDP协议深度解析(一):UDP特性与TCP确认应答以及重传机制

&#x1f50d; 开发者资源导航 &#x1f50d;&#x1f3f7;️ 博客主页&#xff1a; 个人主页&#x1f4da; 专栏订阅&#xff1a; JavaEE全栈专栏 前言 在网络通信的世界里&#xff0c;传输层协议如同交通规则&#xff0c;决定了数据包如何从源头抵达目的地。其中UDP和TCP就…...

Linux线程概念及常用接口(1)

目录 1. Linux线程概念 什么是线程 线程的优点 线程的缺点 线程异常 线程用途 2. Linux进程VS线程 进程和线程 关于进程线程的问题 3. Linux线程控制 POSIX线程库 创建线程 线程ID及进程地址空间布局 线程终止 线程等待 为什么需要线程等待&#xff1f; 4. 分离线程 1. Linux线…...

Qt+OPC开发笔记(三):OPC客户端订阅特点消息的Demo

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/148868209 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…...

《美化生活》投稿简介

《美化生活》杂志是国家新闻出版署批准的正规期刊&#xff0c;是面向全国发行的文学艺术刊。本刊坚持“传播新理念&#xff0c;交流新经验”办刊方针&#xff0c;坚持“指导消费、丰富生活、美化心灵、雅俗共赏”的宗旨&#xff0c;以其丰富的内容&#xff0c;融学术性与技术性…...

如何为虚拟机上的 Manjaro Linux启用 VMware 拖放功能

如果你的Manjaro 发行版本是安装在 VMware Workstation Player 上使用的 &#xff0c;而且希望可以通过拖放功能将文件或文件夹从宿主机复制到客户端的Manjaro 里面&#xff0c;那么可以按照以下的步骤进行操作&#xff0c;开启拖放功能。 在 VMware 虚拟机上安装 Manjaro 后&…...

VIVADO导出仿真数据到MATLAB中进行分析

VIVADO导出仿真数据到MATLAB中进行分析 目录 前言 一、导出仿真数据需要编写的RTL代码 二、MATLAB读入txt文件中的数据 三、需要注意的点 总结 前言 在使用 Xilinx Vivado 进行 FPGA 开发时&#xff0c;如何将 RTL 仿真生成的数据导出&#xff0c;进行进一步分析与可视化&…...

Harmony状态管理@Event

ArkUI Event装饰器&#xff1a;实现子组件向父组件通信的规范方式 概述 Event装饰器是ArkUI框架中用于规范组件间通信的重要工具&#xff0c;特别是在需要子组件向父组件请求更新Param变量的场景下。它通过回调机制实现数据的双向同步&#xff0c;是组件化开发中不可或缺的一…...

算力服务器选型

算力服务器选型需结合应用场景、算力需求及扩展性&#xff0c;核心要素如下&#xff1a; 应用定位&#xff1a; AI 训练 / 推理&#xff1a;优先高算力 GPU&#xff08;如 NVIDIA A100、H100&#xff0c;或 RTX4090&#xff09;&#xff0c;搭配多核 CPU&#xff08;如 Intel …...

基于目标驱动的分布式敏捷开发

研究结论 风险对项目目标的影响 时间目标&#xff1a;需求管理不当&#xff08;如需求优先级不明确、多产品负责人需求冲突&#xff09;、架构变更导致的返工、跨站点协调问题&#xff08;如第三方依赖、通信基础设施不足&#xff09;是影响项目时间的主要风险因素。质量目标&…...

大数据在UI前端的应用拓展:用户行为分析的深度挖掘

hello宝子们...我们是艾斯视觉擅长ui设计、前端开发、数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩! 在当今数字化时代&#xff0c;大数据已成为推动各行业发展的核心动力之一。对于 UI 前端而言&…...

elk+filebeat收集springboot项目日志

目录 步骤 1: 安装和配置Elasticsearch 步骤 2: 安装和配置Logstash&#xff08;可选&#xff09; 步骤 3: 安装和配置Filebeat 步骤 4: 安装和配置Kibana 要使用ELK&#xff08;Elasticsearch, Logstash, Kibana&#xff09;堆栈和Filebeat来收集Spring Boot项目的日志&am…...

华为云Flexus+DeepSeek征文 | 华为云MaaS平台上的智能客服Agent开发:多渠道融合应用案例

华为云FlexusDeepSeek征文 | 华为云MaaS平台上的智能客服Agent开发&#xff1a;多渠道融合应用案例 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 总有一行代码&#xff0c;能点亮万千星辰。 &#x1f50d; 在技术的宇宙中&#xff0c;我愿做永不…...

SQL关键字三分钟入门:UPDATE —— 修改数据

在数据库操作中&#xff0c;除了添加新记录外&#xff0c;我们还需要经常修改已有的记录。例如&#xff1a; 更新用户的个人信息&#xff1b;调整订单的状态&#xff1b;更改产品的价格。 这时候就需要用到 SQL 中非常基础但极其重要的关键字 —— UPDATE&#xff01; 它是用…...

用Rust写平衡三进制加法器

1、三进制加法器的发展 最初的平衡三进制加法是采用了三选一结构(github原文)&#xff0c;这位大佬也很厉害&#xff0c;他是硬件都弄了出来的&#xff0c;也写了虚拟机&#xff0c;甚至用这三态多路复用器弄出了可以存状态的硬件&#xff0c;但我没有去看了&#xff0c;因为当…...

【AI时代速通QT】第三节:Linux环境中安装QT并做测试调试

目录 引言 一、Linux QT开发环境的核心要素 1.1 编译器&#xff08;g&#xff09;与构建工具&#xff08;make&#xff09; 1.2 搞定 OpenGL 依赖 二、核心步骤——安装 Qt Creator 2.1 获取官方在线安装器 2.2 赋予文件执行权限 2.3 运行图形化安装向导 三、Linux上创…...

论文阅读:2025 arxiv Qwen3 Technical Report

https://arxiv.org/pdf/2505.09388 https://www.doubao.com/chat/9918384373236738 文章目录 论文翻译Qwen3技术报告摘要1 引言 论文翻译 Qwen3技术报告 Qwen团队 摘要 在这项工作中&#xff0c;我们介绍了Qwen模型家族的最新版本Qwen3。Qwen3包含一系列大型语言模型&…...

Vue3+el-table-v2虚拟表格大数据量多选功能详细教程

Vue3el-table-v2虚拟表格大数据量多选功能详细教程 本教程基于 Element Plus 组件库的 el-table-v2&#xff08;假设你使用虚拟滚动表格&#xff09;&#xff0c;实现大数据量场景下的多选功能&#xff0c;并包含了全选、反选、已选行展示、清除选择等完整交互。 一、项目背景与…...

开源跨平台的轻量 C# 编辑器

NetPad一个基于.NET 开源、跨平台的 C# 编辑器&#xff0c;目的是创建一个开源的、支持 Web 的跨平台替代方案&#xff0c;从而为开发者提供便利的编程环境并为非 Windows 环境下的开发者提供一个可替代 LINQPad 的实用工具。它以.NET SDK 作为基础运行时环境&#xff0c;利用E…...

QT多线程

使用多线程的好处 假如当前窗口要进行一段非常复杂的逻辑处理&#xff0c;在单线程的情况下&#xff0c;是无法操控界面UI的&#xff0c;点击界面UI没有响应。此时就要用到多线程。 注意&#xff1a; 1、默认的线程在Qt中称之为窗口线程&#xff0c;也叫主线程&#xff0c;负…...

了解公共部门中的数据网格:支柱、架构和示例

作者&#xff1a;来自 Elastic Elastic Platform Team 想想那些像公共健康记录、城市规划模型等项目背后的所有数据。政府机构一直在产生大量数据。当数据分散在云平台、本地系统或像卫星和应急响应中心这样的专业环境中时&#xff0c;情况变得更加复杂。找到信息变得困难&…...

关于一维数组和字符串的详细讲解(从属于GESP三级)

本章内容 一维数组基础 字符串基础 就像打磨一串符号&#xff0c;每个位置都要精准对待&#xff0c;才能串起完整的风景。坚持下去&#xff0c;小细节终将成就大格局。 一、⼀维数组基础 1 &#x1f4da; 定义 典型写法 说明 易错/拓展 int a[5]; 编译期长度常量&#x…...

【驱动设计的硬件基础】PCI和PCI-E

打开电脑主机&#xff0c;你会看到主板上一排长短不一的插糟&#xff1a;矮胖的 PCI 插糟还插着古老的声卡&#xff0c;旁边细长的 PCI-E 插糟则牢牢卡住显卡、高速网卡等核心设备。这些看似普通的插糟&#xff0c;其实是计算机硬件沟通的 "高速公路"&#xff0c;承载…...

【学习记录】Git Base使用-免密连接代码仓库

github&#xff08;JL765&#xff09;和gitee&#xff08;JL765/git-test01&#xff09;都可以用于管理代码 在windows中&#xff0c;可以通过Git Base软件&#xff08;Git - Downloading Package&#xff09;和仓库进行连接 下载略过 github登录 ssh -T gitgithub.com # 成…...

android脱糖

前言 另外一篇相关文章&#xff1a;https://androidblog.blog.csdn.net/article/details/148574130 通过sourceCompatibility 和targetCompatibility可以实现低版本写代码高版本输出&#xff08;详情可查看我的另一篇文件中的&#xff1a;验证各种Java版本 > 一、纯Java项…...

DVWA Brute Force漏洞深度分析与利用指南

DVWA简介 DVWA&#xff08;Damn Vulnerable Web Application&#xff09;是一个基于PHP/MySQL的脆弱性Web应用平台&#xff0c;专为安全专业人员设计&#xff0c;用于测试技能和工具。它包含十大安全模块&#xff0c;其中Brute Force&#xff08;暴力破解&#xff09;是最基础…...

Docker 报错“x509: certificate signed by unknown authority”的排查与解决实录

目录 &#x1f527;Docker 报错“x509: certificate signed by unknown authority”的排查与解决实录 &#x1f4cc; 问题背景 &#x1f9ea; 排查过程 步骤 1&#xff1a;确认加速器地址是否可访问 步骤 2&#xff1a;检查 Docker 是否真的使用了镜像加速器 步骤 3&…...

采用ArcGIS10.8.2 进行插值图绘制

一、最终成果图展示 二、软件下载 链接: 百度网盘 请输入提取码 密码:azay 三、软件安装 1、在安装之前需要关闭电脑的防火墙及杀毒软件 设置-隐私和安全性-Windows安全中心-防火墙和网络保护 2、软件解压 (1)【ArcGIS_Desktop_1082_180......】“以管理员身份运行”…...

国产安路FPGA纯verilog视频图像去雾,基于暗通道先验算法实现,提供5套TD工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目国产安路FPGA相关方案推荐本博主已有的图像处理方案 3、设计思路框架工程设计原理框图输入Sensor之-->GC0308摄像头输入Sensor之-->OV7725摄像头输入Sensor之--…...

利用大型语言模型增强边缘云 AI 系统安全性

大家读完觉得有帮助及的关注和点赞&#xff01;&#xff01;&#xff01; 抽象 随着边缘计算和云系统在 AI 驱动应用中的广泛应用&#xff0c;如何在确保数据隐私的同时保持高效性能已成为一个紧迫的安全问题。本文提出了一种基于联邦学习的数据协作方法&#xff0c;以提高边缘…...

微信小程序中 rpx与px的区别

在微信小程序中的rpx比px方便的多 <!--pages/welcome/welcome.wxml--> <!--rpx替换px--> <image style"width:200rpx;height: 200rpx"src"/images/avatar/3.png"></image> <text>你好&#xff0c;冻梨</text> <but…...