Atoms平台通过服务端生成SHA-256指纹(user_id+session_id+标准化prompt+排序后model_list)实现多模型请求幂等,结合Redis原子锁与Promise缓存协同去重,并在结果聚合阶段按优先级选取首个成功响应。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

在Atoms平台中同时调用多个大模型(如GPT-4o、Claude-3.5、Qwen-Max)时,若用户快速重试、前端自动重调度或网关触发二次转发,极易造成同一语义请求被并发分发至多个模型实例,引发重复推理、Token重复计费、会话上下文错乱三重问题。
识别重复请求的唯一标识
Atoms不依赖客户端传入的随机ID,而是由服务端统一生成请求指纹。必须基于原始输入+调用链路特征生成,否则无法覆盖多模型并行场景。
取user_id + session_id + normalized_prompt(去除空格、换行、注释,标准化JSON字段顺序) + model_list.sort().join("|") 四元组拼接后做SHA-256哈希,得到32字节二进制指纹。
【model_list必须排序后拼接】否则gpt-4o|qwen-max与qwen-max|gpt-4o会被视为两个不同请求,导致幂等失效。
服务端请求锁与缓存协同
方法一:Redis原子锁 + Promise缓存双机制
请求到达时,先用Lua脚本执行SETNX命令尝试加锁,key为atoms:dedup:{fingerprint},过期时间设为max(model_timeout)+10s(如最长模型超时90s,则锁100s)。
加锁成功则继续调用各模型;加锁失败则立即返回303 See Other响应,Header中携带Location: /v1/dedup/wait?token={fingerprint},引导前端轮询等待结果。
方法二:内存级短时缓存(仅限单机部署)
使用LRUMap缓存最近5000个指纹及其Promise引用,TTL设为60秒。适用于开发环境或小流量Atoms实例,但【不可用于K8s多副本集群】,否则缓存不一致会导致幂等崩溃。
多模型结果聚合阶段去重
第一步:等待所有模型返回或超时,收集results = [{model: "gpt-4o", output: "...", status: "success"}, ...]
第二步:对每个result计算output_hash = sha256(trim(output)),剔除status === "error"且output_hash与其他成功结果相同的条目——这说明某模型因网络抖动返回了空响应,但其他模型已正确产出。
第三步:按预设优先级(如gpt-4o > claude-3.5 > qwen-max)选取首个status === "success"的结果作为最终输出,其余结果丢弃不入库。
第四步:向Redis发布事件PUBLISH atoms:dedup:done {fingerprint},唤醒所有等待该token的客户端连接。


















