从零搭建可观测 ReAct 智能客服 Agent:支持订单查询、库存检索与对话自动邮件归档(完整 3000 字实战教程)

📅 2026/7/3 12:16:20
从零搭建可观测 ReAct 智能客服 Agent:支持订单查询、库存检索与对话自动邮件归档(完整 3000 字实战教程)
摘要随着大模型 AI 技术普及传统关键词问答机器人已无法满足电商客服复杂业务需求。基于 ReActReasonAct推理 行动范式的 AI 智能体能够模拟人类思考流程自主判断任务、调用外部工具、记录完整决策链路解决传统 AI “黑盒不可解释” 的行业痛点。本文基于原生 Python 实现一套轻量化电商智能客服 Agent无需依赖 LangChain 等重型框架内置订单 / 内存数据库查询、对话历史存储、QQ 邮箱自动归档完整对话三大核心功能配套全链路决策日志可视化模块开发者可直观查看 AI 每一轮思考、动作、参数与执行结果适合 AI 入门学习者、课程设计与小型电商业务原型开发。本文完整覆盖环境部署、模块分层拆解、代码逐行解析、功能测试、踩坑排错、拓展优化六大板块附可直接运行完整源码全文约 3000 字。关键词AI AgentReAct 范式智能客服Python 自动化邮件可观测日志工具调用一、项目背景与需求分析1.1 传统客服机器人现存痛点市面上绝大多数简易问答机器人存在三大致命缺陷决策黑盒不可追溯AI 如何理解用户问题、为何调用某工具、参数如何生成完全隐藏出现业务错误时无法定位问题功能单一无工具联动仅能固定问答无法对接订单、库存等业务数据更不具备自动化归档、通知能力会话数据丢失无留存多轮对话结束后用户交互记录无法自动导出人工复盘需要手动复制全部聊天内容效率极低。针对以上问题本文设计一套轻量化智能客服 Agent完整覆盖四大核心需求遵循标准 ReAct 闭环流程Thought思考推理→ Action工具调用→ Observation工具返回结果循环执行模拟人类客服思考逻辑内置电商业务工具集订单信息查询、商品库存检索采用内存字典模拟数据库开箱即用无需安装 MySQL全链路可观测决策日志独立日志管理模块完整存储每一轮对话的思考文本、执行动作、入参、返回结果会话结束一键打印全部决策链路对话自动邮件归档用户输入关键词 “发邮件”系统自动抓取本轮全部多轮对话记录格式化后通过 QQ 邮箱 SMTP 协议发送至指定收件箱实现会话自动留存。1.2 技术栈选型说明本项目全部采用轻量组件无重型框架依赖兼容本地 Python、Kaggle Notebook、Colab 等云运行环境基础语言Python3.12语法简洁、第三方库生态完善数据存储dataclasses 结构化存储决策日志实体Python 字典模拟业务数据库与对话内存缓存邮件自动化yagmail 封装 SMTP 协议简化 QQ 邮箱发信逻辑一行代码完成邮件构建与发送标准库time、typing用于类型注解与模拟接口请求延迟无额外依赖。二、系统整体架构分层设计项目采用四层低耦合模块化架构各模块职责完全隔离可单独替换、新增功能架构自上而下分为四层分层架构总览交互层Chat 交互入口chat_loop多轮对话循环持续接收用户输入调度 Agent 核心引擎会话结束输出完整决策日志核心层ServiceAgent 智能体引擎ReAct 流程调度中枢负责意图识别、工具分发、对话历史缓存、日志写入串联全部业务流程能力层CustomerServiceTools 工具集封装三大业务工具 —— 订单查询、库存检索、QQ 邮件发送内置模拟业务数据库与邮箱配置观测层DecisionLogger 日志管理器独立可观测模块定义标准化决策记录实体提供日志存储、全链路可视化打印功能。模块通信逻辑用户输入 → ServiceAgent.think () 意图推理 → 判断执行工具 / 直接回复 → 调用 Tools 工具获取结果 → 写入决策日志与对话历史 → 返回客服回复至交互层触发 “发邮件” 指令时自动读取全部对话缓存拼接为邮件正文调用发信工具。三、环境部署与前置配置3.1 第三方库安装项目仅依赖yagmail邮件库打开终端 / Notebook 单元格执行安装命令python运行# 适配云Notebook精准安装避免环境错位 import sys !{sys.executable} -m pip install yagmail --user -i https://pypi.tuna.tsinghua.edu.cn/simpleKaggle 环境注意带--user参数安装的库存储在临时用户目录重启内核会丢失每次启动会话需重新执行安装代码全局安装可移除--user参数。3.2 QQ 邮箱授权码获取邮件发送必备代码无法直接使用 QQ 登录密码登录 SMTP 服务器必须开启 POP3/IMAP 服务并生成 16 位授权码操作步骤浏览器打开mail.qq.com登录发件 QQ 账号页面右上角「设置」→ 顶部切换「账户」标签下滑找到POP3/IMAP/SMTP服务点击开启完成短信 / 扫码安全验证验证通过后点击「生成授权码」复制页面展示的 16 位字母 数字组合妥善保存仅显示一次丢失需重新生成。3.3 邮箱配置参数替换在CustomerServiceTools类初始化方法中修改三处邮箱配置python运行self.sender_mail 你的QQ账号qq.com # 发件QQ邮箱 self.auth_code 你的QQ邮箱授权码 # 16位授权码 self.receiver_mail 你的QQ账号qq.com # 接收对话记录的目标邮箱四、核心模块代码逐行解析4.1 观测层DecisionLogger 可观测决策日志模块4.1.1 DecisionRecord 日志实体使用dataclass定义标准化日志存储结构固定 5 类核心字段统一存储每一轮 Agent 完整决策信息解决日志格式混乱、字段缺失问题python运行dataclass class DecisionRecord: round_id: int # 对话轮次区分多轮会话 thought: str # AI完整思考推理文本解决黑盒问题 action: str # 执行动作标识工具名/reply_direct action_params: Dict # 工具调用入参字典用于调试参数错误 observation: str # 工具执行返回结果客服回复文本每一次用户交互都会生成一条DecisionRecord对象存入日志列表永久缓存至会话结束。4.1.2 DecisionLogger 日志管理类提供两大核心方法add_record()接收本轮全部决策数据实例化日志实体并存入列表visualize()格式化遍历全部日志分层打印轮次、思考、动作、参数、返回结果清晰展示 AI 完整推理链路便于开发调试与业务复盘。python运行class DecisionLogger: def __init__(self): self.records: List[DecisionRecord] [] # 写入单轮决策记录 def add_record(self, round_id: int, thought: str, action: str, params: Dict, observation: str): rec DecisionRecord(round_id, thought, action, params, observation) self.records.append(rec) # 可视化打印全链路日志 def visualize(self): print(\n Agent 完整思考-行动决策链路 ) for item in self.records: print(f\n【第{item.round_id}轮】) print(f 思考(Thought): {item.thought}) print(f⚙️ 行动(Action): {item.action}) print(f 参数(Params): {item.action_params}) print(f 观察(Observation): {item.observation}) print()4.2 能力层CustomerServiceTools 业务工具集本模块封装全部外部能力包含模拟内存数据库、三大业务工具、统一工具路由分发器新增异常捕获机制避免单一工具报错导致整个 Agent 程序崩溃。4.2.1 模拟内存业务数据库采用 Python 字典存储订单、库存数据无需部署 MySQL、SQLite运行无额外依赖python运行# 订单库键订单号值订单详情字典 self.order_db { O1001: {status: 已发货, goods: 无线鼠标, num: 2}, O1002: {status: 待发货, goods: 机械键盘, num: 1} } # 库存库键商品名称值库存数量 self.stock_db { 无线鼠标: 156, 机械键盘: 23 }4.2.2 三大业务工具详解query_order 订单查询工具接收订单号入参匹配订单库返回格式化订单文本无匹配项返回未查询到提示添加time.sleep(0.2)模拟真实数据库接口网络延迟。query_stock 库存查询工具接收商品名称检索库存字典返回剩余库存无商品默认库存为 0。send_email 对话归档邮件工具基于 yagmail 连接 QQ 邮箱 SMTP 服务器捕获全部异常授权码错误、端口拦截、网络失败区分成功 / 失败返回提示文本邮件主题固定为【智能客服 Agent 完整对话记录】正文为格式化多轮对话历史。4.2.3 统一工具路由分发 run_tool通过action动作名称匹配对应工具函数新增工具仅需新增elif分支拓展性极强完全遵循开闭设计原则。4.3 核心层ServiceAgent 智能体 ReAct 引擎本模块是项目核心完整实现标准 ReAct 推理行动闭环新增对话历史内存缓存负责意图识别、流程调度、数据持久化内存级。4.3.1 初始化变量说明python运行def __init__(self): self.tools CustomerServiceTools() # 实例化工具集 self.logger DecisionLogger() # 实例化日志管理器 self.round 0 # 全局对话轮次计数器 self.dialog_history [] # 多轮对话历史缓存列表dialog_history列表存储每一轮「用户输入 客服回复」字典触发发邮件指令时自动遍历拼接邮件正文。4.3.2 think () 意图识别推理模块本项目采用轻量化关键词匹配实现意图识别适合入门演示生产环境可直接替换为大模型 LLM 调用仅需重写本函数返回thought、action、params三元组整体架构无需改动适配 LangChain、OpenAI、本地开源大模型等各类方案。 意图匹配规则同时包含 “订单” 与 “O1001”调用订单查询工具同时包含 “库存” 与 “机械键盘”调用库存检索工具包含关键词 “发邮件”读取全部对话历史拼接正文调用邮件发送工具无匹配关键词动作标记reply_direct返回兜底提示文本。4.3.3 run_agent 单轮 ReAct 闭环流程标准三步执行逻辑调用think()完成意图推理获取思考文本、执行动作、工具入参判断动作类型工具调用则执行run_tool直接回复则赋值兜底文本获取观测结果客服回复将本轮全部决策数据写入日志管理器同时将用户提问、客服回复存入对话历史缓存最终返回回复文本至交互层。4.4 交互层chat_loop 多轮对话交互入口提供命令行交互式会话界面循环接收用户输入输入quit关键字终止会话会话结束后自动调用日志可视化方法打印全部轮次完整 AI 决策链路便于复盘调试。 交互提示预先展示可用指令示例降低使用门槛支持无限轮次连续对话上下文独立缓存互不干扰。五、项目功能完整测试演示5.1 基础业务查询测试用户输入帮我查询一下订单O1001AI 思考用户想要查询 O1001 订单调用 query_order 工具传入订单号 O1001客服回复订单 O1001商品无线鼠标数量 2状态已发货用户输入机械键盘库存还有多少AI 思考用户询问机械键盘库存调用 query_stock 工具客服回复商品【机械键盘】当前库存23 件5.2 对话自动归档邮件测试连续执行两轮业务查询后用户输入关键词发邮件系统自动执行以下流程读取dialog_history缓存中全部两轮对话记录格式化拼接轮次、用户提问、客服回复作为邮件正文调用send_email工具连接 QQ SMTP 服务器发送完整会话记录至配置邮箱控制台返回发送成功提示收件 QQ 邮箱接收标题为【智能客服 Agent 完整对话记录】的邮件包含全部聊天内容。5.3 会话结束日志可视化输入quit退出对话循环程序自动打印完整 ReAct 决策链路每一轮清晰展示 AI 思考过程、调用工具、传入参数、工具返回结果彻底解决 AI 黑盒调试难题。六、常见报错与排坑解决方案6.1 ModuleNotFoundError: No module named yagmail问题根源云 NotebookKaggle/Colab多 Python 环境隔离--user安装库重启内核丢失本地多版本 Python 解释器错位。 解决方案采用精准安装代码绑定当前运行 Python 解释器python运行import sys !{sys.executable} -m pip install yagmail -i https://pypi.tuna.tsinghua.edu.cn/simple安装完成后重启 Notebook 内核再执行导入代码云环境临时方案删除 yagmail 依赖替换模拟邮件函数无需第三方库。6.2 邮件发送失败授权码错误区分 QQ 登录密码与 16 位授权码配置必须填写网页邮箱生成的授权码修改 QQ 密码后旧授权码自动失效需重新登录mail.qq.com生成确认网页端 POP3/IMAP/SMTP 服务处于开启状态。6.3 Kaggle 云环境邮件发送超时Kaggle 免费会话外网防火墙拦截 QQ 邮箱 465 SMTP 端口无法建立连接两种解决方案切换本地 Python 环境运行邮件发送功能临时替换模拟邮件函数仅演示流程不真实发信。6.4 输入 “发邮件” 无触发邮件工具检查think()意图匹配逻辑用户输入必须完整包含 “发邮件” 三字大小写无区分文字拆分、同义词无法匹配可拓展关键词列表优化匹配规则。七、项目拓展优化方向生产级升级思路7.1 意图识别升级对接大模型 LLM当前采用关键词匹配仅适用于演示场景生产环境可替换think()函数调用 GPT、通义千问、Llama 等大模型由模型自主输出 Thought、Action、Params 三元组支持自然语言模糊提问、复杂多步骤任务拆解。7.2 持久化数据存储业务数据库内存字典替换为 SQLite/MySQL实现订单、库存数据永久保存日志与对话记录将 DecisionLogger 日志、dialog_history 对话历史写入 JSON 文件或数据库会话结束不丢失支持长期数据复盘。7.3 新增业务工具拓展遵循现有工具路由架构新增退款申请、物流查询、优惠计算、工单生成等电商工具仅需新增工具函数与elif匹配分支无需改动 Agent 核心流程。7.4 前端页面封装基于 Gradio/Streamlit 封装 Web 可视化界面替代命令行input()交互实现网页端聊天、一键导出对话邮件、在线查看 AI 决策日志可部署至服务器对外提供服务。7.5 安全容错增强增加输入过滤拦截恶意注入文本工具调用参数校验避免空参数、非法订单号引发程序异常邮箱配置分离为独立配置文件硬编码敏感授权码避免代码泄露安全风险。八、总结本文基于原生 Python 从零实现一套遵循 ReAct 范式的轻量化可观测智能客服 Agent彻底解决传统问答机器人 “黑盒不可调试、功能单一、会话无法自动归档” 三大痛点。项目采用分层模块化低耦合架构代码易读、易拓展、易部署无需重型 AI 框架依赖兼顾入门学习与小型业务原型落地需求。核心创新点在于独立的全链路决策日志观测模块将 AI 每一步思考、工具调用行为完整可视化降低 Agent 开发调试门槛同时创新整合对话历史自动邮件归档功能满足电商客服会话留存、人工复盘的实际业务需求。文中完整覆盖环境部署、代码拆解、功能测试、排错、生产级拓展全部流程配套可直接运行完整源码适合 AI Agent 初学者、高校课程设计、小型电商自动化客服原型开发参考。随着大模型技术持续落地基于 ReAct 工具调用的智能体将成为行业主流开发方案本项目可作为学习 Agent 底层运行逻辑的基础实战案例。全文总字数3028附录项目完整可运行源码python运行import time import yagmail from typing import Dict, List, Any from dataclasses import dataclass # ---------------------- 1. 决策日志实体 ---------------------- dataclass class DecisionRecord: round_id: int # 对话轮次 thought: str # Agent思考内容 action: str # 执行动作工具名 action_params: Dict # 工具入参 observation: str # 工具返回结果 class DecisionLogger: 决策日志管理器用于可视化思考过程 def __init__(self): self.records: List[DecisionRecord] [] def add_record(self, round_id: int, thought: str, action: str, params: Dict, observation: str): rec DecisionRecord(round_id, thought, action, params, observation) self.records.append(rec) def visualize(self): 可视化打印完整思考行动链 print(\n Agent 完整思考-行动决策链路 ) for item in self.records: print(f\n【第{item.round_id}轮】) print(f 思考(Thought): {item.thought}) print(f⚙️ 行动(Action): {item.action}) print(f 参数(Params): {item.action_params}) print(f 观察(Observation): {item.observation}) print() # ---------------------- 2. 工具集订单、库存、真实邮件发送 ---------------------- class CustomerServiceTools: 客服可用工具库 def __init__(self): # 【核心配置区必须修改为你自己的信息】 self.sender_mail 你的QQ账号qq.com # 发件人QQ邮箱 self.auth_code 你的QQ邮箱授权码 # 网页mail.qq.com生成的授权码 self.receiver_mail 你的QQ账号qq.com # 接收对话记录的邮箱 # # 模拟业务数据库 self.order_db { O1001: {status: 已发货, goods: 无线鼠标, num: 2}, O1002: {status: 待发货, goods: 机械键盘, num: 1} } self.stock_db { 无线鼠标: 156, 机械键盘: 23 } def query_order(self, order_no: str) - str: 工具1查询订单 time.sleep(0.2) if order_no in self.order_db: info self.order_db[order_no] return f订单{order_no}商品{info[goods]}数量{info[num]}状态{info[status]} else: return f未查询到订单号 {order_no} def query_stock(self, product_name: str) - str: 工具2查询库存 time.sleep(0.2) stock self.stock_db.get(product_name, 0) return f商品【{product_name}】当前库存{stock}件 def send_email(self, receiver: str, content: str) - str: 工具3真实QQ邮箱发送捕获异常防崩溃 try: # 连接QQ邮箱SMTP服务器 mail_client yagmail.SMTP( userself.sender_mail, passwordself.auth_code, hostsmtp.qq.com ) # 发送邮件 mail_client.send( toreceiver, subject【智能客服Agent完整对话记录】, contentscontent ) return f✅ 对话记录邮件发送成功收件人{receiver} except Exception as err: return f❌ 邮件发送失败错误详情{str(err)} # 工具路由分发器 def run_tool(self, tool_name: str, params: Dict[str, Any]) - str: if tool_name query_order: return self.query_order(params[order_no]) elif tool_name query_stock: return self.query_stock(params[product_name]) elif tool_name send_email: return self.send_email(params[receiver], params[content]) else: return f不存在工具{tool_name} # ---------------------- 3. Agent核心思考-行动-观察闭环 ---------------------- class ServiceAgent: def __init__(self): self.tools CustomerServiceTools() self.logger DecisionLogger() self.round 0 # 新增存储全部对话历史 self.dialog_history [] def think(self, user_input: str) - tuple[str, str, Dict]: 意图识别模块规则匹配可替换大模型LLM self.round 1 user_text user_input.strip() if 订单 in user_text and O1001 in user_text: thought 用户想要查询O1001订单调用query_order工具传入订单号O1001 action query_order params {order_no: O1001} elif 库存 in user_text and 机械键盘 in user_text: thought 用户询问机械键盘库存调用query_stock工具 action query_stock params {product_name: 机械键盘} elif 发邮件 in user_text: thought 用户请求发送全部对话记录邮件调用send_email工具把历史对话作为邮件正文 action send_email # 拼接完整对话记录作为邮件内容 mail_content 本次智能客服完整对话记录 \n for idx, item in enumerate(self.dialog_history, 1): mail_content f\n【第{idx}轮】\n用户{item[user]}\n客服{item[reply]}\n params { receiver: self.tools.receiver_mail, content: mail_content } else: thought 无法识别用户需求无需调用工具返回兜底提示 action reply_direct params {} return thought, action, params def run_agent(self, user_message: str) - str: 单次完整思考-执行-记录闭环 thought, action, params self.think(user_message) if action reply_direct: obs 暂时无法识别您的请求请提供订单号/商品名称或输入发邮件发送全部对话记录 else: obs self.tools.run_tool(action, params) # 写入决策日志 self.logger.add_record( round_idself.round, thoughtthought, actionaction, paramsparams, observationobs ) # 保存本轮用户提问客服回复到对话历史 self.dialog_history.append({ user: user_message, reply: obs }) return obs def chat_loop(self): 交互式多轮对话入口 print( 智能客服Agent已启动) print(使用指令示例) print(1. 查询O1001订单) print(2. 机械键盘库存还有多少) print(3. 发邮件自动把所有对话记录发送到邮箱) print(输入 quit 退出对话\n) while True: user_msg input(用户) if user_msg.lower() quit: break reply self.run_agent(user_msg) print(f客服回复{reply}\n) # 退出后打印完整决策链路 self.logger.visualize() # ---------------------- 4. 程序入口 ---------------------- if __name__ __main__: agent ServiceAgent() agent.chat_loop()完整的结果呈现