黑马大模型RAG与Agent智能体实战教程LangChain提示词——53、Agent智能体——Agent项目Agent创建(react_agent.py)

教程:https://www.bilibili.com/video/BV1yjz5BLEoY

代码:https://github.com/shangxiang0907/HeiMa-AI-LLM-RAG-Agent-Dev

云开发平台:https://hzh.sealos.run

文章目录

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_idfetch_external_data 若只依赖模型「自觉」带参数,存在被诱导越权访问的风险。生产上通常要把「当前用户身份」从鉴权层注入,工具只认服务端上下文,而不是纯靠 LLM 填参数。

8. 与工程化清单的缺口

概览里提到配置、日志模块等:该类没有暴露配置项(模型名、温度、max_tokens)、没有健康检查/预热、没有对接 app.py 的统一接口(同步/异步、SSE 格式)。若全局复用 chat_model,还要确认厂商 SDK 在多线程/多协程下的并发安全策略。

9. 依赖与 API 稳定性

create_agentstream(..., 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

实现上与原先示例的对应关系

  1. 包内导入 :使用 zhisaotong_agent.*(与 middleware.pyfactory.py 一致),模型通过 get_chat_model() 获取(工厂未导出名为 chat_model 的全局变量)。
  2. 工具列表 :使用 agent_tools.TOOLS_LIST,顺序与原先手写列表一致,避免以后改工具时两处不同步。
  3. context :每次 execute_stream 新建 {"report": False},避免多请求并发时 report 标记互相污染(不改变调用方式,仍是内部 stream(..., context=...))。
  4. 健壮性(不改变方法签名) :当 latest_message.content 不是 str(例如部分模型的块列表)时,用 str(content).strip() 再输出,避免原写法对非字符串 content 调用 .strip() 报错。

自检

  • 已通过 py_compilefrom 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%,仍有提升空间。建议定期清理机器人传感器,保持其灵敏度,可进一步提高覆盖率
- 考虑到您每日需要加水一次,建议检查水箱是否有轻微渗漏,或者考虑升级至大容量水箱配件

总体而言,您的扫地机器人使用状况良好,清洁效果优秀。通过上述针对性的保养措施,可以延长设备使用寿命并维持高效清洁性能。
相关推荐
云和数据.ChenGuang5 小时前
langchain安装过程中的故障bug
人工智能·langchain·bug·langsmith·langchain-core
zbdx不知名菜鸡6 小时前
langchain与langgraph 有什么区别?
人工智能·深度学习·langchain·langgraph
怕浪猫7 小时前
第5章 输出解析:让模型返回结构化数据
langchain·llm·ai编程
链上杯子17 小时前
《2026 LangChain零基础入门:用AI应用框架快速搭建智能助手》第8课(完结篇):小项目实战 + 部署 —— 构建网页版个人知识库 AI 助手
人工智能·langchain
飞Link1 天前
LangChain Core 架构深度剖析与 LCEL 高阶实战
人工智能·架构·langchain
沉下去,苦磨练!1 天前
langchain调用大模型
langchain
于过1 天前
AgentMiddleware is All You Need
人工智能·langchain·llm
勇往直前plus1 天前
大模型开发手记(十三):langchain skills(下):构建skills架构agent实战
langchain