Lingoose框架实战:构建智能客服工单处理AI工作流

news2026/5/18 10:48:49
1. 项目概述从“Lingo”到“Goose”一个AI应用编排框架的诞生如果你最近在折腾大语言模型应用尤其是想把OpenAI、Anthropic这些API的能力整合到自己的业务流程里那你大概率已经体会过那种“胶水代码”的烦恼了。今天要聊的这个项目——henomis/lingoose就是来解决这个问题的。它不是一个具体的AI应用而是一个用于编排和构建复杂AI工作流的Python框架。名字很有意思“Lingo”是行话、语言的意思暗指大语言模型“Goose”是大雁象征着编排和引导。合起来Lingooose就是“引导语言模型”非常形象。简单来说lingoose想做的事就是让你像搭积木一样把提示词工程、多个LLM调用、条件判断、工具调用、记忆管理这些环节串联起来形成一个稳定、可测试、可维护的AI应用流水线。我自己在尝试将客服问答升级为能查知识库、能调内部API的智能助手时就深受散乱代码之苦。直到用了这类编排框架才感觉真正上了轨道。Lingoose就是这类框架中一个值得关注的新选择它设计清晰对Python开发者相当友好。2. 核心设计哲学为何需要“编排”框架在深入代码之前我们得先搞清楚为什么简单的requests.post调用API不够用非得引入一个框架这源于生产级AI应用的两个核心痛点复杂性和可靠性。2.1 从单次问答到复杂工作流最初的AI应用可能就是用户输入一个问题你拼接一段提示词Prompt发给GPT然后返回结果。但真实的业务场景要复杂得多多步骤推理用户问“总结昨天销售额最高的产品并给出改进建议”。这需要先“查询数据库”获取数据再“分析数据”找出最高项最后“生成建议”。每一步都可能需要调用一次LLM。条件分支根据用户的提问意图是咨询、投诉还是查询订单需要走不同的处理流程。比如查询订单需要调订单系统API咨询产品需要查知识库。工具调用LLM本身不会算术、不能查数据库。需要定义“工具”函数让LLM在需要时决定调用哪个工具并解析出参数由框架去执行。记忆与上下文多轮对话中需要记住之前的对话历史并在合适的时机选择性地放入上下文以避免token超限。如果你用原生代码硬写很快就会陷入if-else嵌套、状态变量满天飞、错误处理冗长的泥潭。代码难以阅读更难以测试和修改。2.2 Lingoose的解决方案声明式编排Lingoose采用了声明式的编排思想。你不需要详细写出每一步的控制流而是声明你有哪些“组件”如LLM、提示词模板、工具以及它们之间大致的连接关系。框架的运行时引擎会负责调度和执行。这带来了几个关键优势可读性工作流像流程图一样清晰新同事也能快速理解业务逻辑。可复用性定义好的组件如一个精心调优的提示词模板可以在多个工作流中复用。可测试性你可以对单个组件如一个工具函数进行单元测试也可以模拟LLM的返回来测试整个工作流的逻辑。可维护性当需要更换LLM提供商、调整步骤顺序时修改点非常集中。3. 核心概念与组件拆解要玩转Lingoose得先理解它定义的几个核心抽象。这些概念是构建一切工作流的基石。3.1 基石LLM与提示词首先是LLM类它是对不同大模型供应商OpenAI, Anthropic, Google等的抽象。在Lingoose中配置LLM非常简单通常只需要一个API Key和模型名称。from lingoose.llm import OpenAILike llm OpenAILike( modelgpt-4o-mini, api_keyyour-api-key, base_urlhttps://api.openai.com/v1 # 也支持兼容OpenAI API格式的本地模型 )比LLM更重要的是Prompt。Lingoose鼓励使用模板化的提示词而不是在代码里用f-string硬拼接。这利用了Jinja2模板引擎。from lingoose import Prompt system_prompt Prompt(你是一位专业的{{ domain }}领域助手。) user_prompt Prompt(请用{{ style }}的风格回答以下问题{{ question }})在运行时你可以传入一个字典来渲染这些模板context {domain: 金融, style: 简洁明了, question: 什么是复利} rendered_user_prompt user_prompt.render(**context)这样做的好处是提示词变成了可以独立管理和版本化的文本文件而不是埋在代码里的字符串。3.2 灵魂链与工作流单个提示词调用LLM称为一个Runnable可运行单元。但lingoose的核心威力在于将多个Runnable组合起来。Chain链这是最基础的组合方式代表一系列顺序执行的步骤。上一步的输出可以作为下一步的输入。比如“生成大纲 - 扩展章节 - 润色文本”就是一个三步骤的链。Flow工作流这是更高级的抽象一个Flow可以包含多个Chain并且支持条件分支和并行执行。你可以把它想象成一个有向无环图Runnable是节点数据流是边。Lingoose提供了直观的API或DSL来定义这种图结构。3.3 关键扩展工具与记忆Tool工具这是让LLM连接外部世界和获取新能力的桥梁。你只需要用装饰器定义一个普通的Python函数Lingoose就能自动将其转化为LLM可以理解和调用的工具。from lingoose import tool tool def get_weather(city: str) - str: 根据城市名获取当前天气。 Args: city: 城市名称例如“北京”。 # 这里实现调用真实天气API的逻辑 return f{city}的天气是晴25摄氏度。框架会自动为这个函数生成符合OpenAI Function Calling格式的描述。当LLM认为需要调用工具时它会输出一个特殊的结构化响应框架会截获这个响应执行对应的工具函数并将结果作为新的上下文再次喂给LLM。Memory记忆用于管理对话历史。简单的有ConversationBufferMemory保存所有历史复杂的有ConversationSummaryMemory定期总结长历史以节省token、VectorStoreRetrieverMemory将历史存入向量数据库按相关性检索。记忆对象通常会被自动注入到提示词的上下文中。4. 实战构建一个智能客服工单分类与处理流水线光说不练假把式。我们用一个接近真实的场景——智能客服工单自动分类与预处理来演示如何用Lingoose构建一个完整的工作流。场景描述用户提交一段文字工单。系统需要1. 判断工单类型技术问题、账单咨询、账号申诉2. 根据类型提取关键实体信息如订单号、错误代码3. 根据类型和提取的信息生成一个标准化的处理摘要并推荐分配给哪个部门。4.1 第一步定义工具与LLM首先我们定义两个可能用到的工具。一个是查询内部订单系统的模拟另一个是查询知识库FAQ的。from lingoose import tool from typing import Optional tool def query_order_system(order_id: str) - Optional[dict]: 根据订单号查询订单详细信息。 Args: order_id: 订单编号。 Returns: 包含订单状态、金额、创建时间的字典若订单不存在则返回None。 # 模拟数据 mock_data { ORD-12345: {status: 已发货, amount: 299.00, created_at: 2023-10-27}, ORD-67890: {status: 处理中, amount: 150.50, created_at: 2023-10-28} } return mock_data.get(order_id) tool def search_knowledge_base(keywords: list[str], category: str all) - list[str]: 在知识库中搜索相关解决方案。 Args: keywords: 关键词列表。 category: 分类如‘billing’‘technical’。 Returns: 匹配的解决方案摘要列表。 # 模拟搜索 all_articles [ 如何重置密码前往登录页点击‘忘记密码’链接。, 账单 discrepancy 处理流程请提供订单号和具体差异描述。, API 接口超时错误请检查网络并确认 endpoint 地址正确。 ] # 简单模拟关键词匹配 result [] for article in all_articles: if any(kw in article for kw in keywords): result.append(article) return result[:2] # 返回最多两条然后初始化我们的LLM。这里使用OpenAI的模型。from lingoose.llm import OpenAI import os llm OpenAI(modelgpt-4o-mini, api_keyos.getenv(OPENAI_API_KEY))4.2 第二步构建分类与提取链我们创建一个Chain它包含两个连续的动作1. 分类2. 信息提取。这里我们用到了PromptTemplate它比基础的Prompt功能更强可以绑定LLM并直接运行。from lingoose import Chain, PromptTemplate from lingoose.schema import Message # 1. 分类提示词模板 classify_prompt PromptTemplate( llmllm, template 你是一个客服工单分类AI。请将以下用户工单内容分类到唯一最合适的类别中。 可选类别 - TECHNICAL: 产品使用、技术错误、API问题、bug报告。 - BILLING: 费用疑问、退款申请、发票问题、订阅变更。 - ACCOUNT: 登录问题、账号安全、资料修改、注销申请。 用户工单内容 {{ ticket_content }} 请只输出类别名称不要输出任何其他文字。 ) # 2. 信息提取提示词模板 (其内容依赖于分类结果) def create_info_extractor_prompt(ticket_type: str): 根据工单类型动态创建信息提取提示词。 extraction_guidelines { TECHNICAL: 请提取以下信息如果存在1. 具体的错误信息或代码。 2. 涉及的产品或功能模块。 3. 问题发生的步骤。, BILLING: 请提取以下信息如果存在1. 订单号或交易号。 2. 涉及的具体金额。 3. 用户的诉求退款、对账、修改账单等。, ACCOUNT: 请提取以下信息如果存在1. 账号标识用户名、邮箱。 2. 遇到的具体问题无法登录、密码错误、账号被锁。 3. 用户希望的操作。 } guideline extraction_guidelines.get(ticket_type, 请提取关键事实信息。) return PromptTemplate( llmllm, templatef 根据以下工单内容和指定的提取要求提取结构化信息。 工单分类{ticket_type} 提取要求{guideline} 用户工单内容 {{{{ ticket_content }}}} 请以清晰的键值对格式输出提取到的信息。例如 错误代码: 404 Not Found 产品模块: 支付网关 ) # 构建链先分类再提取 classification_chain Chain( steps[ classify_prompt, # 这里需要一个“路由器”根据上一步的结果动态选择下一个Prompt。 # 在Lingoose中这通常通过一个自定义的Runnable或使用Flow的Conditional分支来实现。 # 为了示例清晰我们稍后在Flow中展示更优雅的做法。 ] )注意上面的classification_chain展示了一个难点下一步的提示词依赖于上一步的输出。在简单的Chain中处理这种动态性比较麻烦。这正是Flow要解决的痛点。我们稍后重构。4.3 第三步使用Flow构建动态工作流Flow才是lingoose处理复杂逻辑的舞台。我们重新设计这个流程为一个Flow。from lingoose import Flow from lingoose.schema import TextArtifact # 用于在节点间传递数据 # 定义Flow的节点函数 def classify_node(state: dict) - dict: 分类节点。 ticket state[ticket_content] message classify_prompt.invoke({ticket_content: ticket}) # 假设LLM正确返回了类别字符串 state[ticket_type] message.content.strip() return state def extract_info_node(state: dict) - dict: 信息提取节点。 ticket state[ticket_content] ticket_type state[ticket_type] prompt create_info_extractor_prompt(ticket_type) message prompt.invoke({ticket_content: ticket}) state[extracted_info] message.content return state def generate_summary_node(state: dict) - dict: 生成处理摘要节点。 ticket_type state[ticket_type] extracted state[extracted_info] summary_prompt PromptTemplate( llmllm, template 你是一名客服主管。请根据以下信息生成一份给处理团队的工作摘要。 工单类型{{ type }} 提取到的关键信息 {{ info }} 请生成一段话的摘要包括 1. 问题核心。 2. 已掌握的关键线索。 3. 建议分配的处理小组技术组、财务组、客满组。 ) message summary_prompt.invoke({type: ticket_type, info: extracted}) state[summary] message.content return state # 构建并运行Flow ticket_processing_flow Flow( nodes{ classify: classify_node, extract: extract_info_node, summarize: generate_summary_node, }, edges[ (classify, extract), (extract, summarize), ] ) # 运行Flow initial_state {ticket_content: 我的订单ORD-12345一直显示已发货但一周了都没收到货请帮忙查一下物流并退款。} final_state ticket_processing_flow.run(initial_state) print(f工单分类: {final_state[ticket_type]}) print(f提取信息:\n{final_state[extracted_info]}) print(f处理摘要:\n{final_state[summary]})这个Flow的结构非常清晰三个节点线性执行。每个节点接收一个状态字典修改后再传出。edges定义了执行顺序。4.4 第四步集成工具调用与条件判断现在我们升级流程。如果分类是BILLING且提取到了订单号则自动调用query_order_system工具获取订单详情并将其融入摘要中。我们需要修改extract_info_node和generate_summary_node并在它们之间加入一个条件判断节点决定是否调用工具。from lingoose import tool_node # 这是一个便捷函数用于将工具包装成Flow节点 # 1. 将工具函数转化为Flow节点 query_order_node tool_node(query_order_system) search_kb_node tool_node(search_knowledge_base) # 2. 定义条件判断函数 def should_query_order(state: dict) - str: 决定下一步是查询订单还是继续生成摘要。 if state.get(ticket_type) BILLING and ORD- in state.get(extracted_info, ): # 这里应该用更严谨的正则从extracted_info里提取订单号为简化示例我们假设它存在。 # 我们临时从原始工单内容中简单查找订单号仅用于演示。 import re match re.search(rORD-\d, state[ticket_content]) if match: state[potential_order_id] match.group(0) return yes_query_order # 这个字符串用于路由 return no_query_order # 3. 修改generate_summary_node使其能接收工具查询结果 def generate_summary_with_data_node(state: dict) - dict: 生成处理摘要节点增强版。 ticket_type state[ticket_type] extracted state[extracted_info] order_detail state.get(order_detail, 无额外订单数据。) summary_prompt PromptTemplate( llmllm, template 你是一名客服主管。请根据以下信息生成一份给处理团队的工作摘要。 工单类型{{ type }} 提取到的关键信息 {{ info }} 订单系统查询结果 {{ order_detail }} 请生成一段话的摘要包括 1. 问题核心。 2. 已掌握的关键线索和系统数据。 3. 建议分配的处理小组技术组、财务组、客满组及初步处理建议。 ) message summary_prompt.invoke({type: ticket_type, info: extracted, order_detail: order_detail}) state[summary] message.content return state # 4. 构建更复杂的Flow advanced_flow Flow( nodes{ classify: classify_node, extract: extract_info_node, decision: should_query_order, # 条件判断节点 query_order: query_order_node, # 工具调用节点 summarize: generate_summary_with_data_node, }, edges[ (classify, extract), (extract, decision), # 条件边根据decision节点的返回值路由 (decision, query_order, {condition: lambda state: state.get(__decision_result) yes_query_order}), (decision, summarize, {condition: lambda state: state.get(__decision_result) no_query_order}), (query_order, summarize), # 查询订单后再去生成摘要 ] ) # 注意上面的condition写法是概念示意。实际中Lingoose可能有更专门的ConditionalRouter组件。 # 运行Flow前需要确保状态中有工具调用所需的参数。 # 假设我们从potential_order_id中提取了订单号并赋值给状态。 def prepare_for_tool(state: dict) - dict: 在调用工具节点前准备参数。 if potential_order_id in state: # 将订单号赋值给工具调用约定的输入键名通常由工具函数参数名决定 state[order_id] state[potential_order_id] return state # 需要在decision和query_order之间插入这个准备节点...实操心得在实际使用中动态路由和工具调用的参数传递是编排框架最需要仔细设计的地方。Lingoose提供了多种方式来实现例如使用RunnableBranch来处理条件逻辑或使用RunnableLambda来包装自定义函数进行状态转换。关键是要保持每个节点的功能纯粹输入输出明确。5. 调试、测试与部署考量构建了一个复杂的工作流后如何确保它按预期运行这就涉及到调试、测试和最终部署。5.1 交互式调试与跟踪对于AI应用调试不只是看代码有没有报错更要看LLM的输入输出是否符合预期。Lingoose通常与LangSmithLangChain的官方调试平台深度集成但开源版本也提供了基本的日志跟踪。一个最实用的调试方法是在关键节点打印状态def debug_node(state: dict) - dict: 一个用于调试的节点打印当前状态。 print(f[DEBUG] Node: {state.get(__node_name)}) print(f State keys: {list(state.keys())}) # 谨慎打印内容可能包含长文本 if ticket_content in state: print(f Ticket preview: {state[ticket_content][:100]}...) if ticket_type in state: print(f Type: {state[ticket_type]}) return state # 然后你可以把这个debug_node插入到Flow的任何两个节点之间。更高级的做法是利用框架的on_event回调或追踪器TracerAPI在LLM调用、工具调用等事件发生时记录详细信息包括消耗的token数、耗时、请求和响应的具体内容。5.2 单元测试与集成测试测试AI应用有其特殊性因为LLM的输出是非确定性的。策略如下Mock LLM响应在单元测试中绝对不要调用真实API。使用unittest.mock库来模拟llm.invoke方法返回你预设的答案。这可以测试你的流程逻辑是否正确。from unittest.mock import patch, AsyncMock def test_classify_node(): with patch(your_module.llm.invoke, new_callableAsyncMock) as mock_invoke: # 模拟LLM返回“BILLING” mock_invoke.return_value Message(contentBILLING) initial_state {ticket_content: test ticket} result_state classify_node(initial_state) assert result_state[ticket_type] BILLING mock_invoke.assert_called_once() # 确保LLM被调用了一次测试工具函数像测试普通Python函数一样测试你的tool函数确保其逻辑正确边界情况处理得当。集成测试谨慎进行对于整个Flow可以针对少数几个精心设计的、有确定预期答案的输入用例进行测试。例如一个明确包含订单号的账单问题工单应该被分类为BILLING并且触发订单查询。这类测试运行慢、消耗token应作为CI/CD中的少数验收测试。5.3 性能优化与生产部署当工作流投入生产你需要考虑异步执行如果工作流中有多个可以并行执行的节点例如同时查询多个外部APILingoose支持异步节点可以显著降低整体延迟。确保你的节点函数定义为async def并使用asyncio.gather来执行。错误处理与重试LLM API调用可能失败。在生产Flow中必须为LLM调用和外部工具调用添加重试逻辑通常使用指数退避和优雅降级。Lingoose的Runnable配置中通常可以设置重试参数。速率限制与成本控制监控每个工作流运行的token消耗和API调用次数。可以为不同的LLM模型设置不同的速率限制。在Flow的关键节点加入成本估算和预警逻辑。部署为服务最终这个Python的Flow需要被封装成一个服务。常见的做法是使用FastAPI构建一个HTTP端点。将Flow实例化为一个全局对象在API请求中传入输入参数执行Flow并返回结果。注意处理好并发请求下的状态隔离。from fastapi import FastAPI from pydantic import BaseModel app FastAPI() # 假设ticket_processing_flow是已经定义好的全局Flow对象 class TicketRequest(BaseModel): content: str app.post(/process_ticket) async def process_ticket(request: TicketRequest): initial_state {ticket_content: request.content} try: final_state await ticket_processing_flow.arun(initial_state) # 使用异步运行 return { success: True, type: final_state.get(ticket_type), summary: final_state.get(summary) } except Exception as e: # 记录日志返回用户友好的错误信息 return {success: False, error: 工单处理失败}6. 常见陷阱与进阶技巧在深度使用Lingoose或类似框架后我总结了一些容易踩坑的地方和对应的解决思路。6.1 提示词工程中的陷阱幻觉与格式错误LLM可能不按你要求的格式输出。比如你要求“只输出类别名称”它可能还是会加上“类别是”。解决方案在提示词中使用更强烈的分隔符和示例Few-Shot Prompting。例如请严格按以下格式输出 ###类别### [这里是类别名称] ###结束###然后在代码中使用正则表达式或字符串解析来提取###类别###和###结束###之间的内容。上下文过长当记忆ConversationBufferMemory或检索到的文档很大时容易超出模型的上下文窗口。解决方案使用ConversationSummaryMemory定期总结或使用VectorStoreRetrieverMemory只检索最相关的几条历史。对于长文档先做分割和摘要再喂给LLM。6.2 工作流设计中的陷阱状态污染Flow中每个节点都修改同一个状态字典。如果某个节点意外添加或修改了一个键可能会影响后面不相关的节点。解决方案建立清晰的“状态契约”文档规定每个节点允许读取和写入哪些键。在节点函数开头可以复制一份需要的输入状态避免直接修改原字典的所有部分。循环依赖与无限循环如果工作流设计不当比如工具调用结果又触发同一个工具调用可能导致无限循环。解决方案为工具调用设置最大重试次数或深度限制。在Flow设计时仔细检查边的指向确保没有形成环除非是故意的递归循环并明确设置了终止条件。6.3 性能与成本优化技巧缓存LLM响应对于内容固定、结果确定的提示词例如将用户问题分类到固定的几个类别其LLM响应可以缓存起来。可以使用langchain.cache与Lingoose兼容配合SQLite或Redis对相同的提示词输入直接返回缓存结果大幅节省成本和延迟。流式输出如果工作流的最终输出是直接返回给用户的文本考虑使用LLM的流式响应。这可以让用户更快地看到首个token提升体验。在FastAPI中你可以返回一个StreamingResponse。并行化独立节点仔细分析你的Flow图。如果node A和node B互不依赖它们的输出都只供给node C那么A和B可以并行执行。使用asyncio.create_task或框架提供的并行构造来加速。6.4 与其他系统的集成Lingoose构建的工作流最终要融入更大的技术栈。与后端业务逻辑集成工具函数tool是你连接现有业务系统的桥梁。在这里调用你的gRPC服务、数据库ORM、消息队列生产者等。确保工具函数有完善的错误处理和日志记录。与前端/客户端集成对于长耗时的复杂工作流不要让其阻塞HTTP请求。可以采用“提交任务 - 返回任务ID - 客户端轮询结果”的异步模式。使用Celery、Dramatiq或RQ等任务队列来管理Flow的执行。监控与可观测性在生产环境你需要监控每个工作流的成功率、平均耗时、token消耗分布、工具调用失败率等。将Lingoose的追踪事件发送到像PrometheusGrafana或Datadog这样的监控系统。这能帮你快速定位瓶颈是某个LLM调用慢还是某个外部工具API不稳定。从最初的简单脚本到引入Lingoose这样的编排框架再到考虑生产环境的方方面面构建一个健壮的AI应用确实是一个系统工程。它迫使你以更结构化、更模块化的方式思考问题而这恰恰是软件工程的核心。开始可能会觉得框架有些重但一旦业务逻辑复杂起来你会发现前期在设计和抽象上的投入会在后期的维护、扩展和调试中得到十倍百倍的回报。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2620732.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…