教程:https://www.bilibili.com/video/BV1yjz5BLEoY
代码:https://github.com/shangxiang0907/HeiMa-AI-LLM-RAG-Agent-Dev
文章目录
- Agent智能体-12、[Agent项目]Agent创建
-
- 介绍
- [→提示词:我现在要实现`@zhisaotong_agent/PROJECT_OVERVIEW.md` 中的`react_agent.py`,下面是一个已有实现,指出它在生产环境下的不足](#→提示词:我现在要实现
@zhisaotong_agent/PROJECT_OVERVIEW.md中的react_agent.py,下面是一个已有实现,指出它在生产环境下的不足) - ←AI回复
-
- [1. 对话形态与产品目标不匹配](#1. 对话形态与产品目标不匹配)
- [2. 流式输出语义过窄,容易丢内容或表现异常](#2. 流式输出语义过窄,容易丢内容或表现异常)
- [3. `stream_mode="values"` 的生产代价](#3.
stream_mode="values"的生产代价) - [4. 缺少请求级治理:超时、取消、重试、限流](#4. 缺少请求级治理:超时、取消、重试、限流)
- [5. `context` 与多租户隔离](#5.
context与多租户隔离) - [6. 可观测性不足](#6. 可观测性不足)
- [7. 安全与合规](#7. 安全与合规)
- [8. 与工程化清单的缺口](#8. 与工程化清单的缺口)
- [9. 依赖与 API 稳定性](#9. 依赖与 API 稳定性)
- →提示词:但是我不想改变对外接口,请在此前提下帮我实现代码
- ←AI回复
- 代码
Agent智能体-12、[Agent项目]Agent创建
介绍

→提示词:我现在要实现@zhisaotong_agent/PROJECT_OVERVIEW.md 中的react_agent.py,下面是一个已有实现,指出它在生产环境下的不足
py
from langchain.agents import create_agent
from model.factory import chat_model
from utils.prompt_loader import load_system_prompts
from agent.tools.agent_tools import (rag_summarize, get_weather, get_user_location, get_user_id,
get_current_month, fetch_external_data, fill_context_for_report)
from agent.tools.middleware import monitor_tool, log_before_model, report_prompt_switch
class ReactAgent:
def __init__(self):
self.agent = create_agent(
model=chat_model,
system_prompt=load_system_prompts(),
tools=[rag_summarize, get_weather, get_user_location, get_user_id,
get_current_month, fetch_external_data, fill_context_for_report],
middleware=[monitor_tool, log_before_model, report_prompt_switch],
)
def execute_stream(self, query: str):
input_dict = {
"messages": [
{"role": "user", "content": query},
]
}
# 第三个参数context就是上下文runtime中的信息,就是我们做提示词切换的标记
for chunk in self.agent.stream(input_dict, stream_mode="values", context={"report": False}):
latest_message = chunk["messages"][-1]
if latest_message.content:
yield latest_message.content.strip() + "\n"
if __name__ == '__main__':
agent = ReactAgent()
for chunk in agent.execute_stream("给我生成我的使用报告"):
print(chunk, end="", flush=True)
←AI回复
结合 PROJECT_OVERVIEW.md 里「toC 客服 + RAG + 使用报告」的定位,以及你们 middleware.py 里用 runtime.context["report"] 做场景切换的设计,这段 ReactAgent 在生产里主要会有下面这些不足(按影响面大致排序)。
1. 对话形态与产品目标不匹配
execute_stream 每次只构造一条 user 消息,没有会话历史、没有 session_id、没有把「当前登录用户 / 设备」等绑定进调用链。真实客服需要多轮澄清、追问和上下文延续,否则只能当「单次问答脚本」用,和概览里的全生命周期服务差距很大。
2. 流式输出语义过窄,容易丢内容或表现异常
只在对 latest_message.content 为真时 yield,会漏掉:工具调用阶段(无文本 content)、仅含 tool_calls 的 assistant 消息、多模态/结构化 content(list/dict)、以及分片流式里「空片段再拼字」的常见情况。
另外对每个片段做 strip() 再统一加 \n,可能破坏代码块/缩进,也可能和模型自带的换行不一致,造成前端展示抖动。
3. stream_mode="values" 的生产代价
每次 chunk 都是完整 state(含整条 messages),对话略长时 CPU/内存和网络压力会明显上升;高并发下更适合按产品需求选用更细粒度的 stream 模式,或在应用层做增量 diff,而不是全量 state 反复传。
4. 缺少请求级治理:超时、取消、重试、限流
没有对单次 stream 的超时与取消(用户离开页面、网关断开),也没有对模型/供应商错误的分层处理(429、5xx、内容审核)。生产上通常要把异常转成可展示的错误码/文案,并配合重试与熔断,避免拖垮实例。
5. context 与多租户隔离
虽然每次调用传了 context={"report": False},但生产上要明确:同一次请求内 从 False 到工具里改成 True 是合理的;不同请求之间 必须保证不会共享同一份可变 context(取决于框架是否在内部复用对象)。更稳妥的做法是每请求新建 dict,并在请求结束时视为废弃;若有长连接/WebSocket,还要定义何时重置 report 标记。
6. 可观测性不足
中间件里已有工具/模型前日志,但 execute_stream 没有把 trace_id / request_id / user_id 贯进日志与(如有)指标;排障时很难把一次用户会话和下游 RAG、工具调用串起来。
7. 安全与合规
缺少对输入长度、频率的限制;工具如 get_user_id、fetch_external_data 若只依赖模型「自觉」带参数,存在被诱导越权访问的风险。生产上通常要把「当前用户身份」从鉴权层注入,工具只认服务端上下文,而不是纯靠 LLM 填参数。
8. 与工程化清单的缺口
概览里提到配置、日志模块等:该类没有暴露配置项(模型名、温度、max_tokens)、没有健康检查/预热、没有对接 app.py 的统一接口(同步/异步、SSE 格式)。若全局复用 chat_model,还要确认厂商 SDK 在多线程/多协程下的并发安全策略。
9. 依赖与 API 稳定性
create_agent、stream(..., stream_mode="values", context=...) 与 LangChain/LangGraph 版本强相关;生产应锁版本并封装一层,避免升级后行为静默变化。
小结 :作为本地 demo 足够,但作为 toC 生产智能体,核心缺口是多轮会话与身份绑定 、流式协议与错误/取消治理 、可观测与上下文隔离 ,以及工具调用的授权模型 。若你接下来要实现正式的 react_agent.py,可以按上述几条列成接口需求(入参、历史消息、context 结构、SSE 事件类型)再落代码。
→提示词:但是我不想改变对外接口,请在此前提下帮我实现代码
←AI回复
已在仓库中新增 zhisaotong_agent/agent/react_agent.py,在不改动对外约定的前提下实现逻辑,说明如下。
对外接口(保持不变)
ReactAgent():仍无必填构造参数。execute_stream(self, query: str):仍只接收用户问题;仍按「有文本则strip()后加\n」逐段yield。
实现上与原先示例的对应关系
- 包内导入 :使用
zhisaotong_agent.*(与middleware.py、factory.py一致),模型通过get_chat_model()获取(工厂未导出名为chat_model的全局变量)。 - 工具列表 :使用
agent_tools.TOOLS_LIST,顺序与原先手写列表一致,避免以后改工具时两处不同步。 context:每次execute_stream新建{"report": False},避免多请求并发时report标记互相污染(不改变调用方式,仍是内部stream(..., context=...))。- 健壮性(不改变方法签名) :当
latest_message.content不是str(例如部分模型的块列表)时,用str(content).strip()再输出,避免原写法对非字符串content调用.strip()报错。
自检
- 已通过
py_compile与from zhisaotong_agent.agent.react_agent import ReactAgent导入测试。 - 若在本机执行
python -m zhisaotong_agent.agent.react_agent,仍需配置好 DashScope / RAG 等环境(与调用get_chat_model()、rag_summarize时一致)。
若你希望 from zhisaotong_agent.agent import ReactAgent 也能用,可以说一声,再在 agent/__init__.py 里补一行导出即可(不影响现有接口)。
代码
react_agent.py
py
"""
ReAct 智能体封装:组合模型、系统提示、业务工具与中间件,并提供流式执行入口。
对外保持稳定:
- ``ReactAgent()``:无必填构造参数;
- ``execute_stream(query: str)``:入参仅为用户问题字符串,按块产出字符串(与原有 strip + 换行语义一致)。
"""
from __future__ import annotations
from typing import Any, Iterator
from langchain.agents import create_agent
from zhisaotong_agent.agent.tools.agent_tools import TOOLS_LIST
from zhisaotong_agent.agent.tools.middleware import (
log_before_model,
monitor_tool,
report_prompt_switch,
)
from zhisaotong_agent.model.factory import get_chat_model
from zhisaotong_agent.utils.api_key import init_dashscope_api_key
from zhisaotong_agent.utils.prompt_loader import load_system_prompts
__all__ = ["ReactAgent"]
class ReactAgent:
"""基于 LangChain ``create_agent`` 的 ReAct 封装,供应用入口(如 app.py)调用。"""
def __init__(self) -> None:
self.agent = create_agent(
model=get_chat_model(),
system_prompt=load_system_prompts(),
tools=TOOLS_LIST,
middleware=[monitor_tool, log_before_model, report_prompt_switch],
)
def execute_stream(self, query: str) -> Iterator[str]:
input_dict: dict[str, Any] = {
"messages": [
{"role": "user", "content": query},
]
}
# 与原先一致:context 承载 runtime 标记;每次请求新建 dict,避免并发下 report 状态串扰
runtime_context: dict[str, Any] = {"report": False}
for chunk in self.agent.stream(
input_dict,
stream_mode="values",
context=runtime_context,
):
messages = chunk.get("messages")
if not messages:
continue
latest_message = messages[-1]
content = getattr(latest_message, "content", None)
if not content:
continue
if isinstance(content, str):
text = content.strip()
if not text:
continue
yield text + "\n"
else:
# 非字符串 content(如部分模型的块列表)时避免 .strip() 抛错,仍保持「有则输出」
text = str(content).strip()
if text:
yield text + "\n"
if __name__ == "__main__":
"""
自测:在项目根目录运行 ``python -m zhisaotong_agent.agent.react_agent``。
与 ``model.factory``、``rag.rag_service`` 等模块一致:仅在脚本入口加载 .env 并校验 Key。
覆盖两条业务路径:
- 非报告:常规问答,``runtime.context['report']`` 保持 False,``report_prompt_switch`` 使用系统提示词;
- 生成报告:触发 ``fill_context_for_report`` 后切换报告提示词并完成报告链路。
"""
_ok = init_dashscope_api_key()
if not _ok:
raise SystemExit("DASHSCOPE_API_KEY 未正确配置,无法运行 ReactAgent 自测。")
_agent = ReactAgent()
def _run_demo(_title: str, _query: str) -> None:
print(f"\n{'=' * 60}\n{_title}\n{'=' * 60}\n", flush=True)
for _chunk in _agent.execute_stream(_query):
print(_chunk, end="", flush=True)
print("\n", flush=True)
_run_demo(
"自测 1:非报告场景(常规问答;不应依赖「使用报告」专用提示词链路)",
"你好,扫地机器人尘盒一般多久清理一次?请简短回答。",
)
_run_demo(
"自测 2:报告场景(应走 fill_context_for_report / 外部数据等报告生成逻辑)",
"给我生成我的使用报告",
)
运行
bash
python -m zhisaotong_agent.agent.react_agent
结果
2026-03-25 06:42:18,572 - zhisaotong_agent.utils.api_key - INFO - api_key.py:49 - DashScope API Key 已成功加载并设置到环境变量。
============================================================
自测 1:非报告场景(常规问答;不应依赖「使用报告」专用提示词链路)
============================================================
你好,扫地机器人尘盒一般多久清理一次?请简短回答。
2026-03-25 06:42:18,759 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:150 - [log_before_model]即将调用模型,带有1条消息。
2026-03-25 06:42:22,511 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:108 - [tool monitor]执行工具:rag_summarize
2026-03-25 06:42:22,511 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:109 - [tool monitor]传入参数:{'query': '扫地机器人尘盒清理频率'}
2026-03-25 06:42:22,715 - zhisaotong_agent.rag.rag_service - INFO - rag_service.py:132 - RagSummarizeService 初始化完成。
2026-03-25 06:42:23,104 - zhisaotong_agent.rag.rag_service - INFO - rag_service.py:153 - 向量检索完成,query='扫地机器人尘盒清理频率', 命中文档数=3
2026-03-25 06:42:29,195 - zhisaotong_agent.rag.rag_service - INFO - rag_service.py:197 - RAG 总结调用成功,query='扫地机器人尘盒清理频率', answer_len=65
2026-03-25 06:42:29,195 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:113 - [tool monitor]工具rag_summarize调用成功
普通家庭建议每2-3天清理一次尘盒,宠物家庭或大户型建议每天清理;每次清扫完成后应及时倾倒尘盒垃圾,避免满溢、滋生细菌或产生异味。
2026-03-25 06:42:29,196 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:150 - [log_before_model]即将调用模型,带有3条消息。
普通家庭建议每2-3天清理一次尘盒,宠物家庭或大户型建议每天清理。每次清扫完成后应及时倾倒,避免满溢、滋生细菌或产生异味。
============================================================
自测 2:报告场景(应走 fill_context_for_report / 外部数据等报告生成逻辑)
============================================================
给我生成我的使用报告
2026-03-25 06:42:32,023 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:150 - [log_before_model]即将调用模型,带有1条消息。
我需要为您生成个人使用报告。首先,我需要获取您的用户ID和报告月份,然后调用相关工具来生成报告。
2026-03-25 06:42:34,632 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:108 - [tool monitor]执行工具:fill_context_for_report
2026-03-25 06:42:34,633 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:109 - [tool monitor]传入参数:{}
2026-03-25 06:42:34,633 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:113 - [tool monitor]工具fill_context_for_report调用成功
fill_context_for_report已调用
2026-03-25 06:42:34,636 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:150 - [log_before_model]即将调用模型,带有3条消息。
我需要获取您的用户ID和当前月份,以便生成您的使用报告。
2026-03-25 06:42:37,526 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:108 - [tool monitor]执行工具:get_user_id
2026-03-25 06:42:37,526 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:109 - [tool monitor]传入参数:{}
2026-03-25 06:42:37,526 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:113 - [tool monitor]工具get_user_id调用成功
1008
2026-03-25 06:42:37,527 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:150 - [log_before_model]即将调用模型,带有5条消息。
2026-03-25 06:42:38,759 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:108 - [tool monitor]执行工具:get_current_month
2026-03-25 06:42:38,760 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:109 - [tool monitor]传入参数:{}
2026-03-25 06:42:38,760 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:113 - [tool monitor]工具get_current_month调用成功
2025-04
2026-03-25 06:42:38,761 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:150 - [log_before_model]即将调用模型,带有7条消息。
现在我已获取到您的用户ID(1008)和当前月份(2025-04),接下来我将查询您在这个月的使用记录。
2026-03-25 06:42:43,144 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:108 - [tool monitor]执行工具:fetch_external_data
2026-03-25 06:42:43,144 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:109 - [tool monitor]传入参数:{'user_id': '1008', 'month': '2025-04'}
2026-03-25 06:42:43,147 - zhisaotong_agent.agent.tools.agent_tools - INFO - agent_tools.py:121 - 外部数据已加载,路径=/home/devbox/project/zhisaotong_agent/data/external/records.csv,用户数=10
2026-03-25 06:42:43,148 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:113 - [tool monitor]工具fetch_external_data调用成功
特征: 100㎡三居 | 三口之家 | 大理石
效率: 覆盖率:90%\n避障成功率:95%
耗材: 主刷寿命:剩余70天\n水箱加水:每日1次
对比: 大理石地面清洁效果优于同类10%
2026-03-25 06:42:43,149 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:150 - [log_before_model]即将调用模型,带有9条消息。
为了提供更专业的保养建议,我需要查询一些关于扫地机器人维护的专业知识。
2026-03-25 06:42:46,024 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:108 - [tool monitor]执行工具:rag_summarize
2026-03-25 06:42:46,024 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:109 - [tool monitor]传入参数:{'query': '大理石地面扫地机器人保养建议'}
2026-03-25 06:42:46,274 - zhisaotong_agent.rag.rag_service - INFO - rag_service.py:153 - 向量检索完成,query='大理石地面扫地机器人保养建议', 命中文档数=3
2026-03-25 06:42:48,214 - zhisaotong_agent.rag.rag_service - INFO - rag_service.py:197 - RAG 总结调用成功,query='大理石地面扫地机器人保养建议', answer_len=51
2026-03-25 06:42:48,214 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:113 - [tool monitor]工具rag_summarize调用成功
在大理石地面使用扫地机器人时,拖地后应及时清理机器人底部水渍,并每月对拖布支架进行除垢,防止水垢附着。
2026-03-25 06:42:48,215 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:150 - [log_before_model]即将调用模型,带有11条消息。
2026-03-25 06:42:52,138 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:108 - [tool monitor]执行工具:rag_summarize
2026-03-25 06:42:52,138 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:109 - [tool monitor]传入参数:{'query': '扫地机器人主刷更换周期和保养方法'}
2026-03-25 06:42:52,409 - zhisaotong_agent.rag.rag_service - INFO - rag_service.py:153 - 向量检索完成,query='扫地机器人主刷更换周期和保养方法', 命中文档数=3
2026-03-25 06:42:59,165 - zhisaotong_agent.rag.rag_service - INFO - rag_service.py:197 - RAG 总结调用成功,query='扫地机器人主刷更换周期和保养方法', answer_len=190
2026-03-25 06:42:59,165 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:113 - [tool monitor]工具rag_summarize调用成功
主刷更换周期和保养方法如下:
- 宠物家庭环境下,耗材更换周期缩短50%,每次清扫后需全面清理主刷,避免毛发结块。
- 每周拆卸清洗主刷(非防水款用干布擦拭),晾干后安装;长毛地毯使用后应立即清理主刷上的纤维,防止缠绕硬化。
- 每月检查主刷电机工作状态,确保无异常发热或异响,并拆解吸口组件清理内部杂物。
- 清理时注意保护滚刷两端轴承,避免进水、进灰导致卡顿。
2026-03-25 06:42:59,166 - zhisaotong_agent.agent.tools.middleware - INFO - middleware.py:150 - [log_before_model]即将调用模型,带有13条消息。
# 黑马程序员扫地机器人使用情况报告与保养建议
## 使用情况分析
根据您2025年4月的使用数据,您的扫地机器人在100㎡三居室、三口之家、大理石地面环境中表现如下:
- **清洁效率**:覆盖率高达90%,避障成功率达到95%,表明机器人能够有效覆盖大部分区域并成功避开障碍物
- **耗材状态**:主刷剩余寿命约70天,水箱需要每日加水一次
- **清洁效果**:在大理石地面上的清洁效果优于同类用户10%,说明您对机器人的使用和维护较为得当
## 个性化保养建议
### 针对大理石地面环境
- 每次拖地完成后,请及时清理机器人底部残留的水渍,防止水渍在大理石表面留下痕迹
- 建议每月对拖布支架进行除垢处理,避免水垢附着影响拖地效果
### 主刷维护建议
- 根据您家中有三口人的情况(非宠物家庭),主刷可按正常周期更换,当前剩余70天寿命属于正常范围
- 建议每周拆卸清洗主刷,由于您的地面为大理石(硬质地面),可使用干布擦拭即可
- 每月检查主刷电机工作状态,确保无异常发热或异响
- 清理主刷时注意保护滚刷两端轴承,避免进水、进灰导致卡顿
### 提升使用效率建议
- 您的覆盖率已达90%,仍有提升空间。建议定期清理机器人传感器,保持其灵敏度,可进一步提高覆盖率
- 考虑到您每日需要加水一次,建议检查水箱是否有轻微渗漏,或者考虑升级至大容量水箱配件
总体而言,您的扫地机器人使用状况良好,清洁效果优秀。通过上述针对性的保养措施,可以延长设备使用寿命并维持高效清洁性能。