AI应用的幂等性工程2026:让LLM任务在失败重试时不出错

news2026/5/4 6:41:22
LLM应用在生产环境中面临着普通软件没有的挑战同一个任务被重复执行时可能产生副作用发两次邮件、创建重复记录、扣两次款。幂等性设计是解决这个问题的工程答案。—## 问题的本质LLM应用的非确定性传统软件的幂等性设计已有成熟方案。但LLM应用增加了新的复杂度1.长时间运行的任务LLM的生成过程可能耗时30秒甚至更长网络超时概率更高2.有副作用的工具调用Agent调用API发送邮件、修改数据库、调用支付接口时失败重试会造成重复执行3.多步骤工作流前几步成功但最后一步失败重启会重新执行已完成的步骤4.不确定性输出即使是相同的输入LLM可能生成不同的决策导致幂等性更难保证—## 幂等性的三个层次### 层次一API层幂等性基础确保同一个HTTP请求被多次发送不会产生重复效果pythonimport hashlibimport jsonimport asynciofrom datetime import datetime, timedeltafrom typing import Optional, Callable, Anyimport redis.asyncio as aioredisfrom fastapi import FastAPI, Header, HTTPExceptionfrom pydantic import BaseModelclass IdempotencyManager: API幂等性管理器 def __init__(self, redis_url: str, ttl_hours: int 24): self.redis None self.redis_url redis_url self.ttl ttl_hours * 3600 async def initialize(self): self.redis await aioredis.from_url( self.redis_url, encodingutf-8, decode_responsesTrue ) def _key(self, idempotency_key: str) - str: return fidempotency:{idempotency_key} async def check_and_lock(self, key: str) - Optional[dict]: 检查幂等键 - 如果不存在锁定并返回None允许执行 - 如果存在且已完成返回缓存的结果 - 如果存在且进行中返回processing状态 redis_key self._key(key) # 使用SET NX原子操作避免竞争条件 locked await self.redis.set( f{redis_key}:lock, processing, nxTrue, # 只在不存在时设置 exself.ttl ) if not locked: # 已有请求在处理或已完成 result await self.redis.get(redis_key) if result: return json.loads(result) # 正在处理中 return {status: processing, message: 请求正在处理中请稍后查询结果} return None # 允许继续执行 async def store_result(self, key: str, result: dict): 存储执行结果 redis_key self._key(key) result[completed_at] datetime.now().isoformat() await self.redis.setex( redis_key, self.ttl, json.dumps(result, ensure_asciiFalse) ) async def mark_failed(self, key: str, error: str): 标记失败释放锁允许重试 # 删除lock允许重新尝试 await self.redis.delete(f{self._key(key)}:lock)# FastAPI中的使用app FastAPI()idempotency IdempotencyManager(redis://localhost:6379)app.post(/ai/generate-report)async def generate_report( request: dict, idempotency_key: str Header(None, aliasIdempotency-Key)): 幂等的AI报告生成接口 if not idempotency_key: # 无幂等键直接执行不做幂等保护 return await _do_generate_report(request) # 检查是否重复请求 cached await idempotency.check_and_lock(idempotency_key) if cached: return cached # 返回缓存结果或处理中状态 try: result await _do_generate_report(request) await idempotency.store_result(idempotency_key, result) return result except Exception as e: await idempotency.mark_failed(idempotency_key, str(e)) raiseasync def _do_generate_report(request: dict) - dict: 实际生成报告的逻辑 # ... LLM调用逻辑 pass—### 层次二工具调用幂等性关键当Agent需要调用有副作用的外部工具时幂等性最为关键pythonfrom functools import wrapsfrom typing import Callabledef idempotent_tool(tool_id_fn: Callable None): 工具调用幂等性装饰器 def decorator(func: Callable): wraps(func) async def wrapper(*args, **kwargs): # 生成工具调用的唯一ID if tool_id_fn: call_id tool_id_fn(*args, **kwargs) else: # 默认基于函数名参数的hash key_data f{func.__name__}:{json.dumps(args, defaultstr)}:{json.dumps(kwargs, defaultstr)} call_id hashlib.sha256(key_data.encode()).hexdigest()[:16] redis await aioredis.from_url(redis://localhost:6379) redis_key ftool_call:{call_id} # 检查是否已执行过 existing await redis.get(redis_key) if existing: print(f⚡ 工具 {func.__name__} 已执行过 (id{call_id})返回缓存结果) return json.loads(existing) # 执行工具 result await func(*args, **kwargs) # 缓存结果24小时 await redis.setex( redis_key, 86400, json.dumps(result, defaultstr) ) return result return wrapper return decorator# 使用示例idempotent_tool( tool_id_fnlambda order_id, **kw: fsend_order_email:{order_id})async def send_order_confirmation_email(order_id: str, email: str) - dict: 发送订单确认邮件 - 幂等版本 # 即使被调用多次邮件只会发送一次 await email_service.send( toemail, subjectf订单 {order_id} 确认, templateorder_confirmation ) return {sent: True, order_id: order_id, email: email}—### 层次三工作流检查点复杂任务对于多步骤的LLM工作流需要支持断点续跑pythonimport jsonfrom enum import Enumfrom dataclasses import dataclass, fieldclass StepStatus(Enum): PENDING pending RUNNING running COMPLETED completed FAILED faileddataclassclass WorkflowCheckpoint: 工作流检查点 workflow_id: str steps: dict field(default_factorydict) metadata: dict field(default_factorydict)class CheckpointedWorkflow: 支持检查点的工作流执行器 def __init__(self, workflow_id: str, redis_url: str): self.workflow_id workflow_id self.redis_url redis_url self.checkpoint_key fworkflow_checkpoint:{workflow_id} async def _load_checkpoint(self) - WorkflowCheckpoint: redis await aioredis.from_url(self.redis_url) data await redis.get(self.checkpoint_key) if data: d json.loads(data) return WorkflowCheckpoint(**d) return WorkflowCheckpoint(workflow_idself.workflow_id) async def _save_checkpoint(self, checkpoint: WorkflowCheckpoint): redis await aioredis.from_url(self.redis_url) await redis.setex( self.checkpoint_key, 7 * 86400, # 保存7天 json.dumps({ workflow_id: checkpoint.workflow_id, steps: checkpoint.steps, metadata: checkpoint.metadata }, ensure_asciiFalse) ) async def run_step( self, step_name: str, step_fn: Callable, *args, force_rerun: bool False, **kwargs ) - Any: 执行带检查点的单个步骤 checkpoint await self._load_checkpoint() # 如果步骤已完成且不强制重跑直接返回缓存结果 if not force_rerun and step_name in checkpoint.steps: step_data checkpoint.steps[step_name] if step_data[status] StepStatus.COMPLETED.value: print(f⏭️ 跳过已完成的步骤: {step_name}) return step_data[result] # 标记步骤开始 checkpoint.steps[step_name] { status: StepStatus.RUNNING.value, started_at: datetime.now().isoformat() } await self._save_checkpoint(checkpoint) try: # 执行步骤 result await step_fn(*args, **kwargs) # 标记完成 checkpoint.steps[step_name] { status: StepStatus.COMPLETED.value, result: result, completed_at: datetime.now().isoformat() } await self._save_checkpoint(checkpoint) return result except Exception as e: # 标记失败 checkpoint.steps[step_name] { status: StepStatus.FAILED.value, error: str(e), failed_at: datetime.now().isoformat() } await self._save_checkpoint(checkpoint) raise# 使用示例多步骤AI工作流async def run_analysis_workflow(workflow_id: str, document_url: str): workflow CheckpointedWorkflow(workflow_id, redis://localhost:6379) # 步骤1下载文档失败重试时不会重复下载 document await workflow.run_step( download_document, download_document, document_url ) # 步骤2AI分析失败重试时不会重复调用LLM节省费用 analysis await workflow.run_step( ai_analysis, analyze_with_llm, document ) # 步骤3发送报告失败重试时不会重复发送 await workflow.run_step( send_report, send_analysis_report, analysis, workflow_id ) return analysis—## 实用的幂等键生成策略pythonclass IdempotencyKeyGenerator: 幂等键生成工具 staticmethod def for_business_action(user_id: str, action: str, resource_id: str) - str: 业务操作的幂等键 return f{user_id}:{action}:{resource_id} staticmethod def for_content_hash(content: str) - str: 基于内容的幂等键相同内容只处理一次 return hashlib.sha256(content.encode()).hexdigest() staticmethod def for_time_window(action: str, window_minutes: int 60) - str: 时间窗口幂等键同一时间窗口内只执行一次 window int(time.time() / (window_minutes * 60)) return f{action}:{window} staticmethod def for_llm_request(model: str, messages: list) - str: LLM请求的幂等键 key_data f{model}:{json.dumps(messages, sort_keysTrue)} return hashlib.sha256(key_data.encode()).hexdigest()—## 最佳实践总结1.所有有副作用的工具调用都应该幂等发邮件、支付、发短信——没有例外2.为客户端提供幂等键接口允许客户端携带Idempotency-Keyheader进行重试3.区分安全和非安全操作GET请求天然幂等POST/PUT需要主动设计4.检查点粒度要合理太细会增加开销太粗意味着失败时重跑更多工作5.清理过期的幂等记录设置合理的TTL避免Redis无限增长幂等性是构建可靠LLM应用的基础工程能力在自动化程度越来越高的AI时代这一点的重要性只会越来越高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2580822.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;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…