AI Agent实战路线图:ReAct、提示词与记忆系统协同设计

发布时间:2026/6/21 18:02:48
AI Agent实战路线图:ReAct、提示词与记忆系统协同设计 1. 这不是“学完就能造出Claude”的速成课而是一份真实踩过坑、调过参、上线过三个Agent项目的万字实操地图“AI Agent万字学习路线”这个标题听起来像知识付费的钩子但我要说清楚它既不是教你怎么背诵ReAct论文里的公式也不是罗列一堆“必须学LangChain、必须看LlamaIndex文档”的清单。我带团队落地过电商客服Agent、金融投顾辅助Agent和本地政务问答Agent从0到1跑通全链路——真正卡住90%人的从来不是“不知道该学什么”而是“学了之后不知道哪块该深挖、哪块可以跳过”“调试时连日志都看不懂”“上线后Token爆炸式增长成本直接翻三倍”。这篇路线图就是把这三年里我们拆解过的27个真实Agent系统、复现过的14种主流架构、压测过的8类记忆策略全部摊开在你面前。核心关键词——AI Agent、ReAct、提示词工程、上下文工程、记忆系统——每一个都不是孤立概念ReAct不是魔法咒语是推理与行动耦合的约束范式提示词工程不是写得越长越好而是要匹配模型底层的attention机制上下文工程不是堆token而是设计信息流动的“管道”记忆系统更不是简单存数据库而是决定Agent能否形成“经验”的关键神经突触。如果你正卡在“看了十篇教程还是不会写一个能记住用户偏好的聊天机器人”或者“用LangChain搭出来的东西一问多轮就崩”又或者“面试被问‘ReAct和Chain-of-Thought本质区别’答得模棱两可”那这份路线图就是为你写的。它不承诺“30天成为专家”但能确保你每投入1小时都精准打在真实项目最痛的关节上。2. 学习路线设计逻辑为什么必须按“问题域”而非“技术栈”来组织2.1 拒绝“工具先行”的陷阱LangChain不是银弹而是手术刀很多初学者一上来就猛啃LangChain文档结果学完RouterChain、SQLDatabaseChain、VectorStoreRouterChain回头写个“帮用户订咖啡”的Agent发现连“用户说‘再来一杯’时该复用上次地址还是问新地址”都处理不了。问题出在哪——把框架当目的而非解决具体问题的工具。我带的第一个Agent项目需求是“自动回复淘宝商家后台的售后消息”团队初期也想直接套LangChain的ConversationChain。结果上线三天客服投诉率飙升模型把“已发货”误判为“未发货”把“退差价”理解成“全额退款”。根本原因ConversationChain默认的记忆机制只保留最近几轮对话而售后场景中用户第一句说“订单号12345”第三句才说“要退差价”中间夹着物流查询。LangChain的Memory模块没做上下文裁剪策略直接把整段对话塞进prompttoken爆表不说关键信息还被稀释。后来我们砍掉所有高级Chain手写了一个极简状态机用Redis存订单ID→状态映射用正则提取关键字段只把“订单ID当前状态用户最新意图”喂给模型。效果立竿见影准确率从62%升到91%。所以本路线图的第一原则所有工具学习必须绑定到明确的问题场景。LangChain值得学但不是学“怎么调用API”而是学“它的BufferMemory为什么在长对话中失效”“它的ConversationSummaryMemory如何触发摘要摘要质量受哪些参数影响”。同样LlamaIndex不是用来炫技的而是当你需要让Agent“读懂公司200页PDF产品手册并回答细节问题”时才去深挖它的DocumentLoader分块策略、NodeParser的语义分割逻辑、以及QueryEngine如何平衡检索精度与响应速度。2.2 架构演进不是线性升级而是问题复杂度驱动的自然分叉网络热词里总在刷“最新架构”但现实是没有所谓“最新最好”只有“当前问题最适配”。我们三个上线项目用的完全是不同代际的架构电商客服Agent2022年纯ReAct模式。用户问“我的订单还没发货”Agent先调用get_order_status(order_id)工具拿到返回{status: packed, warehouse: shanghai}再生成回复“您的订单已在上海仓打包完成”。这里ReAct的价值是强制解耦思考Reasoning阶段只决定“需要什么信息”行动Acting阶段只执行工具调用避免模型自己“脑补”物流状态。金融投顾Agent2023年ReAct 记忆增强。用户问“对比A基金和B基金的近一年波动率”Agent不仅要查数据还要记住用户风险偏好比如之前说过“不能接受单日跌幅超2%”在回复中主动加一句“B基金近一周最大回撤达3.2%可能超出您的承受范围”。这时单纯ReAct不够必须引入外部记忆系统——我们用PostgreSQL存用户画像用向量库存历史咨询记录每次推理前先用用户ID检索相关记忆片段拼接到prompt中。政务问答Agent2024年ReAct 上下文工程 Token优化闭环。用户问“低保申请需要什么材料”答案分散在民政、人社、卫健三个部门的政策文件中。如果直接把三份PDF全文喂给模型token轻松破万成本高且易丢重点。我们改用“分层上下文注入”第一层用RAG召回最相关条款如《低保认定办法》第5条第二层用规则引擎提取材料清单身份证、收入证明等第三层用轻量级LLMPhi-3对条款做口语化转述。整个流程token消耗降低67%响应时间从8秒压到1.2秒。看到没架构选择不是跟风而是被问题倒逼出来的。所以本路线图不按“LangChain→AutoGen→CrewAI”这种工具顺序排而是按“单轮任务→多轮状态管理→跨源知识整合→高并发低延迟”四个问题域展开。每个域里你会同时看到ReAct、提示词工程、上下文工程、记忆系统的协同工作方式——这才是真实世界的样子。2.3 技术选型背后的硬约束成本、延迟、可控性三者不可兼得所有教程都告诉你“用OpenAI API最省事”但真实业务中这三个词像三座大山成本一个日活1万的客服Agent若每轮对话平均消耗3000 tokenGPT-4-turbo调用费约$0.03/次日成本$300月成本近万元。而我们的政务Agent用Qwen2-7B量化版本地部署单次推理成本≈$0.0002降幅150倍。延迟金融场景要求“用户提问后1秒内给出风险提示”。OpenAI API P95延迟常达2.3秒而本地部署的Phi-3模型P95延迟仅0.4秒。我们曾为抢这1秒放弃GPT-4的强推理能力改用小模型规则兜底。可控性医疗Agent必须保证“绝不编造药品剂量”。OpenAI模型存在幻觉风险而我们用Llama-3-8B微调后在测试集上幻觉率从12%降至0.8%代价是开发周期延长3周。所以路线图里每个技术点都会标注它的“约束代价”比如学ReAct时我会告诉你“标准ReAct模板在长上下文下token效率低需配合动态截断策略”学提示词工程时会强调“指令越复杂模型遵循率越低实测超过5条指令时第3条被忽略概率达34%”。这不是泼冷水而是帮你建立技术决策的坐标系——当你面对“用云服务还是自建模型”的选择时心里有杆秤。3. 核心模块深度解析从原理到避坑每一行代码都有来处3.1 ReAct不是“思考行动”四字真言而是对抗模型幻觉的防御协议ReActReasoning Acting常被简化为“先想后做”但它的真正价值在于构建人机协作的信任边界。我见过太多Agent因过度自信导致事故某教育Agent被问“牛顿第三定律公式”它没调用物理知识库直接生成Fma这是第二定律还加了一句“此公式由艾萨克·牛顿于1687年提出”——完全正确但答错了问题。这就是典型的“幻觉自信”。ReAct的精妙之处在于用结构化输出强制模型暴露思考过程。标准ReAct prompt包含三要素Thought明确声明“我需要知道X才能回答Y”Action调用指定工具输入严格格式化参数Observation接收工具返回的原始数据不做任何加工看一个真实案例用户问“上海今天空气质量如何”错误做法无ReAct“上海今日空气质量优PM2.5浓度为12μg/m³。”模型凭训练数据“猜”的实际可能重度污染正确ReAct流程Thought: 我需要查询上海实时空气质量数据应调用get_air_quality(cityShanghai)工具。Action:get_air_quality(cityShanghai)Observation:{city: Shanghai, aqi: 156, level: 重度污染, pm25: 128}Thought: 观察到AQI为156属于重度污染PM2.5为128μg/m³。Final Answer: 上海今日空气质量为重度污染PM2.5浓度为128μg/m³。这里的关键是Observation环节的不可篡改性。工具返回什么模型就必须原样接收不能“觉得128太高改成110”。我们曾用Python装饰器强制校验def tool_call_validator(func): def wrapper(*args, **kwargs): result func(*args, **kwargs) # 强制返回JSON格式且必须含指定字段 assert isinstance(result, dict) and aqi in result and level in result return result return wrapper这个小技巧让幻觉率下降82%。但ReAct也有硬伤Action调用失败时模型容易陷入死循环。比如get_air_quality接口超时返回空模型可能反复重试同一Action。我们的解法是加“失败熔断”在Thought中嵌入失败计数器Thought: 尝试获取空气质量数据第3次失败切换至备用方案...备用方案可以是查缓存、返回通用话术或转人工。提示ReAct不是万能的它最适合“有明确工具边界”的场景。对于开放性创作如写诗ReAct反而束缚创造力。判断标准很简单如果问题答案能被某个API或数据库100%确定就用ReAct如果答案需要主观权衡如“推荐一首适合雨天听的歌”就用Chain-of-Thought。3.2 提示词工程超越“角色设定”直击模型attention机制的底层博弈网上90%的提示词教程还在教“你是一个资深律师”这就像给汽车贴“我是法拉利”贴纸——不改变性能。真正的提示词工程是研究模型如何分配注意力权重。以Qwen2-7B为例其attention层对prompt开头和结尾的token赋予更高权重中间部分易被稀释。我们做过实验将关键指令放在prompt末尾模型遵循率比放在开头高27%。实战中我们总结出三条反直觉原则原则一指令必须原子化且用动词开头错误写法“请扮演客服友好、专业、快速回复用户问题不要编造信息”问题4个形容词模糊模型无法量化“友好”“不要编造”是负面指令attention机制更关注正面动作。正确写法提取用户问题中的实体人名、订单号、日期查询订单系统获取状态若状态为“已发货”回复包含物流单号若状态为“未发货”回复预计发货时间所有回复必须基于查询结果禁止添加未验证信息原则二示例Few-shot必须覆盖边界case新手常给3个完美示例但真实场景充满噪声。我们要求示例必须包含正常case用户说“订单12345还没发货” → 查状态 → 回复预计时间模糊case用户说“那个快递” → 提取订单号失败 → 回复“请提供订单号”冲突case用户说“取消订单”但系统显示“已签收” → 触发客诉流程原则三动态提示词优于静态模板固定prompt在多轮对话中必然失效。我们的解决方案是“提示词编译器”# 根据对话状态动态组装prompt def build_prompt(history, user_input, memory_context): base_prompt 你是一个电商客服Agent... # 注入记忆用户历史投诉记录、偏好语言风格 if memory_context.get(complaint_count, 0) 2: base_prompt 用户是高敏感客户请用更谨慎措辞 # 注入上下文当前订单状态、物流节点 if history[-1].get(order_status) delivered: base_prompt 注意用户刚签收可能询问售后 return base_prompt f\n用户最新输入{user_input}这个编译器让提示词从“静态文本”变成“活的状态机”也是我们Agent能记住用户偏好的技术基础。3.3 上下文工程不是“堆更多token”而是设计信息流动的“神经突触”“上下文工程”这个词很玄其实就干一件事控制哪些信息在何时以何种精度进入模型视野。很多人以为“把用户历史对话全塞进去”就是好上下文结果token爆表模型反而找不到重点。我们用“三层上下文漏斗”解决这个问题层级内容长度更新频率技术实现L1即时上下文当前对话的最近3轮含用户最新输入≤512 token每轮更新直接拼接L2记忆上下文用户画像风险偏好、常用地址、高频问题答案缓存≤256 token用户首次交互时加载Redis哈希表L3知识上下文RAG召回的1-3个最相关知识片段≤1024 token每次query触发向量相似度检索关键创新在L2和L3的协同当用户问“推荐基金”L2提供“用户风险等级稳健型”L3提供“债券型基金近一年收益数据”模型无需再从海量文本中自行提取直接做决策。我们实测这种分层结构使有效信息密度提升3.8倍token消耗降低41%。但分层带来新问题L2/L3内容如何可信我们采用“双校验机制”时效校验所有记忆数据带TTLTime-To-Live用户画像TTL30天过期自动刷新来源校验知识片段必须标注来源如“《2024年公募基金白皮书》P23”模型回复中强制引用方便审计注意上下文工程最大的坑是“过度依赖RAG”。某政务Agent曾把所有政策文件扔进向量库结果用户问“低保申请材料”RAG召回《残疾人保障法》全文因“保障”一词相似度高。后来我们加入“领域过滤器”先用规则识别问题领域民政/人社/卫健再限定RAG检索范围召回准确率从58%升至92%。3.4 记忆系统从“数据库存”到“经验沉淀”Agent的进化核心很多人把记忆系统等同于“把对话存进MySQL”这是致命误解。真正的记忆系统要让Agent具备从经验中学习的能力。我们三个项目记忆系统演进如下V1电商客服键值存储。Key用户IDValue最近3次咨询主题。作用检测重复问题如用户第三次问“怎么退货”自动推送图文指南链接。缺点无法泛化用户换说法就失效。V2金融投顾向量记忆关系图谱。除存对话外还提取实体基金名称、风险指标和关系“用户A认为基金B波动大”构建成Neo4j图谱。当新用户问“类似基金B的产品”系统不仅查相似基金还查“和用户A有相同风险偏好的其他用户推荐了什么”。这实现了从“记事本”到“经验库”的跨越。V3政务问答记忆蒸馏反馈闭环。每天凌晨系统扫描所有对话日志用轻量模型TinyBERT蒸馏出高频问题-答案对自动更新知识库同时收集用户点击“有用/无用”反馈调整记忆权重。上线半年冷启动问题新政策发布后首周咨询解决率从31%升至79%。技术实现上我们坚持“内存持久化”双层设计短期记忆用Redis Stream存实时对话流支持按用户ID、时间范围快速回溯长期记忆用ChromaDB存向量化记忆支持语义搜索关键记忆用PostgreSQL存结构化数据用户ID、风险等级、偏好地址保证强一致性最实用的经验是记忆系统必须有“遗忘机制”。我们设置三条遗忘规则用户主动说“忘记刚才的对话”立即清空其L1/L2记忆连续3次对话无关联自动降权L2记忆权重知识类记忆如政策条款超过有效期如法规修订自动标记为“待审核”这避免了Agent越用越“固执”比如老政策废止后还继续推荐。4. 实操路径从零开始搭建一个可运行的微信AI Agent4.1 环境准备避开国产模型部署的9个深坑要落地微信Agent必须本地部署模型避免API合规风险。我们选Qwen2-7B-Int4量化版理由中文理解强、7B参数适合4090显卡、Int4量化后显存占用8GB。但部署过程充满陷阱坑1CUDA版本错配Qwen2-7B要求CUDA 12.1但Ubuntu 22.04默认装CUDA 11.8。强行安装会破坏系统。解法用Docker隔离环境FROM nvidia/cuda:12.1.1-base-ubuntu22.04 RUN apt-get update apt-get install -y python3-pip COPY requirements.txt . RUN pip3 install -r requirements.txt坑2transformers版本冲突HuggingFace transformers 4.40对Qwen2支持不完善必须锁定4.38.2pip install transformers4.38.2 accelerate bitsandbytes坑3tokenizer加载失败Qwen2的tokenizer_config.json中chat_template字段缺失导致apply_chat_template报错。手动补全chat_template: {% for message in messages %}{{|im_start| message[role] \n message[content] |im_end| \n}}{% endfor %}{% if add_generation_prompt %}{{|im_start|assistant\n}}{% endif %}坑4微信消息体编码微信服务器发送的XML消息含中文Python默认utf-8解码会乱码。必须在Flask路由中强制指定app.route(/wechat, methods[POST]) def wechat(): data request.get_data().decode(utf-8) # 关键 # 解析XML...坑5长文本截断策略微信单条消息上限2000字符但Agent回复可能超长。我们用“智能分段器”先用正则识别段落\n\n、列表-、标题##优先在段落间断开避免割裂句子每段末尾加“[继续]”提示用户点击后触发下一段坑6消息去重微信服务器可能因网络问题重发同一消息。我们在Redis中用SETNX加锁lock_key fmsg_lock:{msg_id} if redis_client.set(lock_key, 1, ex30, nxTrue): # 处理消息 process_message(msg) else: # 重复消息丢弃 pass坑7会话状态管理微信无session机制必须用OpenID作为会话ID。但用户可能换设备登录导致状态丢失。解法首次交互时用OpenID手机号用户授权后获取生成唯一session_idsession_id存RedisTTL7天用户换设备时通过手机号找回session坑8Token消耗监控每条消息必须记录input_token/output_token用于成本分析。我们用tiktoken库import tiktoken enc tiktoken.get_encoding(qwen) input_tokens len(enc.encode(prompt)) output_tokens len(enc.encode(response)) redis_client.hincrby(token_stats, input, input_tokens) redis_client.hincrby(token_stats, output, output_tokens)坑9错误降级模型崩溃时不能返回空白。我们设三级降级LLM异常 → 调用规则引擎if-else匹配关键词规则引擎无匹配 → 返回预设FAQ如“请描述具体问题”FAQ也失效 → 转人工并记录“降级事件”供后续优化这些坑我们踩了两周才填平。现在把完整Docker Compose配置放出来version: 3.8 services: agent: build: . ports: - 5000:5000 environment: - MODEL_PATH/models/Qwen2-7B-Instruct-AWQ - REDIS_URLredis://redis:6379/0 depends_on: - redis redis: image: redis:7-alpine command: redis-server --save 60 1 --loglevel warning4.2 核心Agent构建手写ReAct引擎不依赖LangChainLangChain的ReActChain封装太深调试时日志像黑盒。我们手写轻量引擎核心就三个函数Step 1Thought生成def generate_thought(model, prompt): # 强制输出格式Thought: text\nAction: tool_name(args)\nObservation: full_prompt f你是一个ReAct Agent。请严格按以下格式输出 Thought: 你需要思考的步骤 Action: 工具名(参数) Observation: 留空等待工具返回 Prompt: {prompt} response model.generate(full_prompt, max_new_tokens256) # 正则提取Thought thought_match re.search(rThought:\s*(.*?)(?:\n|$), response) return thought_match.group(1).strip() if thought_match else Step 2Action执行与校验TOOLS { get_order_status: lambda order_id: db.query(SELECT status FROM orders WHERE id?, order_id), search_policy: lambda keyword: rag_search(keyword, top_k2) } def execute_action(action_str): try: # 安全执行只允许预定义工具 match re.match(r(\w)\((.*?)\), action_str) if not match: raise ValueError(Invalid action format) tool_name, args match.groups() if tool_name not in TOOLS: raise ValueError(fTool {tool_name} not allowed) # 参数解析简单场景用eval生产环境用ast.literal_eval args_list [x.strip().strip(\) for x in args.split(,)] result TOOLS[tool_name](*args_list) return {success: True, data: result} except Exception as e: return {success: False, error: str(e)}Step 3Observation注入与终局判断def run_react_loop(user_input, session_id): history get_memory(session_id) # 从Redis读L1/L2记忆 prompt build_prompt(history, user_input) # 调用3.2节的编译器 for step in range(5): # 最大5步防死循环 thought generate_thought(model, prompt) # 判断是否终局Thought含Final Answer即停止 if Final Answer in thought: final_answer thought.split(Final Answer:)[-1].strip() save_memory(session_id, user_input, final_answer) # 写入记忆 return final_answer # 否则执行Action action_match re.search(rAction:\s*(\w\(.*?\)), thought) if not action_match: break # 无Action退出 action_str action_match.group(1) result execute_action(action_str) # 构建Observation obs fObservation: {json.dumps(result)} prompt f\n{thought}\n{action_str}\n{obs} return 抱歉我暂时无法处理这个问题请稍后再试。这个引擎只有200行代码但胜在透明每一步Thought、Action、Observation都可打印日志调试时一眼定位问题。比如发现某次Thought是“我需要查询订单状态”但Action却是get_user_info(12345)立刻知道是prompt没约束好工具名。4.3 微信集成从消息接收、处理到回复的端到端链路微信公众号开发需配置服务器URL和Token这部分官方文档很清晰。我们聚焦三个关键实操点点1消息加解密微信要求消息体AES加密很多教程用过时的pycrypto库。实测pycryptodome更稳from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad def decrypt_msg(encrypted_msg, encoding_aes_key, app_id): key base64.b64decode(encoding_aes_key ) cipher AES.new(key, AES.MODE_CBC, key[:16]) decrypted unpad(cipher.decrypt(base64.b64decode(encrypted_msg)), AES.block_size) # 验证AppID xml_content decrypted.decode(utf-8) if app_id not in xml_content: raise ValueError(AppID mismatch) return xml_content点2多轮对话状态保持微信消息无session但我们用OpenID时间戳生成会话IDdef get_session_id(from_user, timestamp): # 10分钟内同一用户视为同一会话 minute_key int(timestamp / 600) return f{from_user}_{minute_key}这样即使用户间隔9分钟发两条消息也能关联上下文。点3富媒体消息构造微信支持图文、卡片、小程序消息。我们用模板消息提升体验def send_template_message(openid, template_id, data): # data格式{first: {value: 您好}, keyword1: {value: 订单12345}} payload { touser: openid, template_id: template_id, data: data } resp requests.post( https://api.weixin.qq.com/cgi-bin/message/template/send, params{access_token: get_access_token()}, jsonpayload ) return resp.json()当用户问“我的订单”我们不再只文字回复而是发模板消息标题“订单12345状态”副标题“已发货”详情栏显示物流单号、预计到达时间、一键联系客服按钮。最后把整个流程串起来微信服务器POST消息到/wechatFlask路由解密、验签、解析XML提取FromUserName用户OpenID、Content消息文本调用run_react_loop(content, get_session_id(FromUserName, timestamp))将Agent回复封装成XMLPOST回微信服务器我们压测过单台4090服务器Qwen2-7B并发处理12路微信消息P95延迟1.8秒完全满足客服场景。5. 常见问题与排查技巧实录那些文档里不会写的血泪教训5.1 ReAct调试为什么Thought总是“我想调用工具”却不执行Action这是最高频问题。表面看是模型没输出Action实则是Thought阶段已被干扰。我们整理出四大根因及解法现象根因排查方法解决方案Thought含“我需要...”但无Action行Prompt中指令位置不佳模型注意力被分散打印完整prompt检查指令是否在开头/结尾将Action指令移到prompt末尾加粗强调**Action:**Thought正确Action参数格式错误如get_order(12345少右括号模型对括号闭合不敏感日志中捕获Action字符串用正则校验格式在execute_action中加括号匹配校验失败则重试Thought和Action都正确但Observation为空工具函数抛异常未被捕获在execute_action中加try-catch打印完整traceback用logging.exception()记录异常避免静默失败多轮后Thought突然变模糊如“我不知道该做什么”L1上下文过长关键信息被冲刷检查history长度打印最近3轮内容实施动态截断保留最近2轮当前输入其余存L2记忆独家技巧在Thought中强制要求“写出下一步Action的完整字符串”。例如Thought: 下一步应调用get_order_status工具参数为订单号12345完整Action字符串是get_order_status(12345)这利用了模型对“复述”任务的高准确率大幅提升Action生成稳定性。5.2 提示词失效为什么昨天好用的prompt今天就胡言乱语提示词不是一劳永逸的。我们建立“提示词健康度监控”每日统计prompt遵循率模型按指令执行的比例、幻觉率答案与事实不符的比例、响应时长设置阈值遵循率85%或幻觉率5%时自动告警常见失效场景及对策场景1模型版本升级Qwen2-7B从v1.0升级到v1.1后原prompt中“请用中文回复”失效模型开始混用英文。解法在prompt开头加|im_start|system\n你必须严格使用中文回复禁止使用任何英文单词|im_end|利用Qwen的system角色强制约束。场景2用户输入噪声用户发语音转文字“订个咖fie”模型误判为“咖啡”。解法在prompt中加纠错指令Thought: 用户输入“订个咖fie”可能是“咖啡”的语音识别错误应尝试“咖啡”“咖妃”“咖非”等变体查询场景3领域术语漂移政务Agent中“低保”在2023年指“最低生活保障”2024年新政策称“基本生活救助”。解法在L3知识上下文中为术语添加版本标签{term: 低保, definition: 基本生活救助, version: 2024Q1, source: 民政部2024年第1号公告}模型回复时自动引用最新版本定义。5.3 记忆系统故障为什么Agent突然“失忆”记忆失效往往不是代码bug而是数据流断裂。我们用“记忆链路追踪”定位写入侧检查save_memory函数是否被调用在函数入口加logging.info(fSaving memory for {session_id})若无日志检查run_react_loop末尾是否漏掉调用存储侧检查Redis连接和key过期# 进入Redis CLI redis-cli -h your-redis-host KEYS memory:* # 查看是否存在记忆key TTL memory:user123 # 查看剩余TTL读取侧检查get_memory是否返回空打印session_id确认是否与写入时一致OpenID大小写敏感检查Redis DB编号是否写入db0却从db1读取血泪教训我们曾因Redis密码含特殊字符在连接字符串中未转义导致redis://:passwordhost:6379被解析成hostpass所有记忆写入失败。解法URL编码密码redis://:pass%40wordhost:6379。5.4 Token爆炸为什么一次简单问答消耗8000 tokenToken失控是成本杀手。我们用“token火焰图”定位热点