扫地机器人智能客服 Agent

基于 LangChain ReAct 框架构建的扫地机器人 / 扫拖一体机器人智能客服系统,支持知识库问答、天气适配查询、用户个性化使用报告生成等功能,并通过中间件机制实现动态提示词切换与全链路日志监控。


目录


项目概览

本项目是一个面向扫地机器人领域的垂直智能客服 Agent,核心能力包括:

  • 知识库问答(RAG):将产品手册、选购指南、维护保养、故障排除等文档向量化存储,支持语义检索后结合 LLM 生成精准回答。
  • 环境适配查询:自动获取用户所在城市与实时天气,判断环境对机器人使用的影响。
  • 个性化使用报告:根据用户 ID 和月份,从外部 CSV 数据中检索使用记录,生成结构化 Markdown 报告并给出保养建议。
  • 动态提示词切换:通过中间件机制,在报告生成场景下自动将主提示词切换为专业报告提示词。
  • 全链路日志:记录每次工具调用、模型调用的详细信息,同时输出到控制台和日志文件。

项目结构

Agent-test/
├── config.py                     # 全局配置入口(路径、日志格式)
├── .env                          # API Key 配置(不提交到版本库)
│
├── config/                       # YAML 配置文件
│   ├── rag.yml                   # 模型名称与接口地址
│   ├── chroma.yml                # 向量库参数(分块、存储路径等)
│   ├── prompts.yml               # 提示词文件路径映射
│   └── agent.yml                 # 外部数据文件路径
│
├── model/
│   └── factory.py                # 模型工厂(ChatModel / EmbeddingModel)
│
├── rag/
│   ├── vector_store.py           # 向量库管理(加载文档、增量存储、检索)
│   └── rag_summarize.py          # RAG 链(检索 + LLM 总结)
│
├── agent/
│   ├── react_agent.py            # ReAct Agent 入口
│   └── tools/
│       ├── agent_tools.py        # 7 个 Agent 工具定义
│       └── middleware.py         # 3 个中间件(工具监控、模型前置日志、动态提示词)
│
├── prompts/
│   ├── main_prompt.txt           # 主客服提示词
│   ├── rag_summarize_prompt.txt  # RAG 总结提示词
│   └── report_prompt.txt         # 报告生成提示词
│
├── utils/
│   ├── config_handler.py         # YAML 配置加载
│   ├── logger_handler.py         # 日志初始化
│   ├── prompt_handler.py         # 提示词文件读取
│   ├── file_handler.py           # 文档加载(txt/pdf)与 MD5 工具
│   └── path_tool.py              # 绝对路径工具
│
├── data/
│   ├── *.txt / *.pdf             # 知识库文档(产品问答、维护、选购等)
│   └── external/
│       └── records.csv           # 用户使用记录(用户ID、月份、清洁数据)
│
├── chroma_db/                    # ChromaDB 持久化目录(运行后自动生成)
│   └── md5.txt                   # 已处理文档的 MD5 记录(增量更新用)
│
└── logs/                         # 运行日志(运行后自动生成)

核心模块说明

1. 模型工厂 model/factory.py

使用抽象基类 BaseModel 统一管理模型初始化,子类分别实现 Chat 模型和 Embedding 模型。

class ChatModel(BaseModel):      # 对话模型,默认 DeepSeek
class EmbeddingModel(BaseModel): # 向量模型,默认 text-embedding-3-large

API Key 从 .env 文件读取,模型名称和接口地址从 config/rag.yml 读取,两端解耦,切换模型只需改 YAML,切换 Key 只需改 .env

模块末尾直接导出单例:

chat_model = ChatModel().generator()
embedding_model = EmbeddingModel().generator()

其他模块直接 from model.factory import chat_model 使用即可。


2. 向量数据库与 RAG

rag/vector_store.py — VectorStore

管理 ChromaDB 向量库的全生命周期:

  • 初始化:读取 config/chroma.yml 中的 collection 名、存储路径、分块参数,创建 Chroma 实例和 RecursiveCharacterTextSplitter
  • 增量加载 load_document()
    1. 创建 loading.lock 锁文件防止并发重复加载。
    2. 遍历 data/ 目录下所有允许类型(txt/pdf)的文件。
    3. 计算文件 MD5,与 chroma_db/md5.txt 中已记录的哈希比对,已处理的文件跳过,实现增量更新。
    4. 读取文档 → 分块 → 写入向量库 → 记录 MD5。
  • 获取检索器 get_retriever():返回 top-k 语义检索器(k 由配置决定,默认 3)。
rag/rag_summarize.py — RagSummarize

将检索与生成串联为一条 LangChain 链:

PromptTemplate → (可选打印调试) → chat_model → StrOutputParser

rag_summarize(input) 方法:

  1. 调用检索器获取 top-k 相关文档片段。
  2. 将文档片段拼接为带编号的 context 字符串。
  3. 注入 {input}{context} 到提示词模板,调用链返回总结文本。

提示词约束模型严格基于参考资料回答,不编造内容,仅输出纯文本。


3. Agent 工具 agent/tools/agent_tools.py

共 7 个工具,通过 @tool 装饰器注册:

工具名 入参 功能
rag_summarize input(检索词) 从向量库检索相关资料并总结
get_weather city(城市名) 返回指定城市天气(当前为 Mock)
get_user_location user 随机返回用户所在城市(当前为 Mock)
get_uesr_id user 随机返回用户 ID(当前为 Mock)
get_uesr_time user 随机返回当前月份,格式 YYYY-MM(当前为 Mock)
get_external_data user_id, user_time 从 CSV 中检索用户指定月份的使用记录
fill_context_for_report 触发中间件,将运行时上下文 report 标记为 True

get_external_data 使用懒加载模式,首次调用时将整个 CSV 解析为嵌套字典 { user_id: { month: {...} } } 并缓存到模块级变量,后续调用直接读内存。

fill_context_for_report 本身不做任何业务逻辑,仅作为信号工具——当 Agent 调用它时,monitor_tool 中间件捕获到此调用并将 request.runtime.context['report'] 置为 True,触发后续的提示词切换。


4. 中间件 agent/tools/middleware.py

三个中间件挂载到 Agent 的执行链路上:

monitor_tool@wrap_tool_call

每次工具调用前后均会执行:

  • 调用前记录工具名和入参(INFO 级别)。
  • 执行工具,捕获异常并记录错误日志。
  • 调用成功后,若工具名为 fill_context_for_report,将 request.runtime.context['report'] 置为 True
log_before_model@before_model

在每次模型调用前执行:

  • INFO 级别记录当前消息条数。
  • DEBUG 级别记录最后一条消息的类型和内容(截断显示)。
report_prompt_switch@dynamic_prompt

每次生成提示词之前自动触发:

  • 读取 request.runtime.context['report'] 标志。
  • 若为 True,加载 prompts/report_prompt.txt 作为系统提示词。
  • 否则加载 prompts/main_prompt.txt(默认客服提示词)。

这三个中间件共同实现了工具监控 → 状态感知 → 动态提示词注入的完整链路。


5. ReAct Agent agent/react_agent.py

class ReactAgent():
    def __init__(self):
        self.agent = create_agent(
            model=chat_model,
            system_prompt=None,          # 提示词由 dynamic_prompt 中间件动态注入
            tools=[...],                 # 7 个工具
            middleware=[...],            # 3 个中间件
        )

    def execute_stream(self, input):
        # 以流式方式执行,逐块 yield 输出
  • system_prompt=None:主提示词完全由 report_prompt_switch 中间件在运行时动态决定,无需硬编码。
  • stream_mode='values':每次 yield Agent 状态中最新一条消息的内容。
  • context={'report': False}:初始化运行时上下文,确保首次提示词切换逻辑正常工作。

入口示例

agent = ReactAgent()
for chunk in agent.execute_stream("扫地机器人在我所在的地区的气温下如何保养"):
    print(chunk, end="", flush=True)

6. 配置系统

所有配置分离到 config/ 目录下的 YAML 文件,通过 utils/config_handler.py 统一加载:

文件 内容
config/rag.yml 对话模型名/URL、Embedding 模型名/URL
config/chroma.yml ChromaDB collection 名、持久化路径、top-k、数据目录、分块参数
config/prompts.yml 三个提示词文件的相对路径
config/agent.yml 外部 CSV 数据文件路径

config.py 是全局入口,定义各 YAML 的绝对路径及日志格式,其他模块通过 config_handler 获取已解析的字典对象。


7. 提示词

文件 用途 关键约束
prompts/main_prompt.txt 主客服系统提示词 ReAct 思考框架、7 个工具使用规范、报告生成固定调用链约束
prompts/rag_summarize_prompt.txt RAG 总结提示词 严格基于参考资料、纯文本输出、不编造
prompts/report_prompt.txt 报告生成提示词 Markdown 格式输出、给出保养建议、不直接输出原始查询数据

提示词中对报告生成有强约束:Agent 必须按照 get_uesr_id → get_uesr_time → fill_context_for_report → get_external_data 的固定顺序调用工具,不得跳步。


8. 日志系统

utils/logger_handler.py 封装了标准 logging

  • 控制台:INFO 级别及以上实时输出。
  • 文件:DEBUG 级别及以上写入 logs/agent_<时间戳>.log,每次启动创建新文件。
  • 日志格式:时间 - logger名 - 级别 - 文件名:行号 - 消息

模块末尾导出单例 logger,各模块 from utils.logger_handler import logger 直接使用。


数据说明

知识库文档 data/

存放扫地机器人相关的 txt/pdf 文档,当前包含:

  • 扫地机器人100问.pdf / 扫地机器人100问2.txt
  • 扫拖一体机器人100问.txt
  • 故障排除.txt
  • 维护保养.txt
  • 选购指南.txt

首次运行时 VectorStore.load_document() 会自动将上述文档分块并写入 ChromaDB。后续再次运行时通过 MD5 比对跳过已处理文件,data/ 目录新增文档后无需额外操作,下次启动自动增量入库

外部使用记录 data/external/records.csv

字段:用户ID, 特征, 清洁效率, 耗材, 对比, 时间

包含用户 ID 1001~10102025-012025-12 的逐月使用记录,覆盖面积特征、清洁覆盖率、耗材寿命、横向对比等维度。


快速开始

1. 安装依赖

pip install langchain langchain-openai langchain-chroma langchain-text-splitters python-dotenv pyyaml

2. 配置 API Key

在项目根目录创建 .env 文件:

CHAT_API_KEY=your_chat_api_key
EMBEDDING_API_KEY=your_embedding_api_key

3. 配置模型(可选)

编辑 config/rag.yml,修改模型名称和接口地址:

chat_model_name: "deepseek-chat"
chat_model_url: "https://api.deepseek.com/v1"

embedding_model_name: "text-embedding-3-large"
embedding_model_url: "https://your-embedding-api/v1"

4. 初始化向量库

首次使用前需要将知识库文档写入向量数据库:

python rag/vector_store.py

执行后 chroma_db/ 目录下会生成持久化数据,md5.txt 记录已处理文件的哈希。

5. 运行 Agent

python agent/react_agent.py

默认执行一条测试问题:扫地机器人在我所在的地区的气温下如何保养

如需集成到其他入口,直接实例化并调用:

from agent.react_agent import ReactAgent

agent = ReactAgent()
for chunk in agent.execute_stream("帮我生成本月的使用报告"):
    print(chunk, end="", flush=True)

配置说明

配置项 文件 说明
chat_model_name config/rag.yml 对话模型 ID
chat_model_url config/rag.yml 对话模型 API 地址(OpenAI 兼容格式)
embedding_model_name config/rag.yml 向量模型 ID
embedding_model_url config/rag.yml 向量模型 API 地址
collection_name config/chroma.yml ChromaDB 集合名
persist_directory config/chroma.yml ChromaDB 持久化目录
k config/chroma.yml RAG 检索返回文档数(top-k)
chunk_size config/chroma.yml 文本分块大小(字符数)
chunk_overlap config/chroma.yml 分块重叠大小
data_path config/chroma.yml 知识库文档目录
allow_type config/chroma.yml 允许的文档类型列表
external_data_path config/agent.yml 用户使用记录 CSV 路径

主要流程图

普通问答流程

用户提问
   └─> ReactAgent.execute_stream()
         └─> report_prompt_switch 加载 main_prompt
               └─> LLM 思考 → 决定调用工具
                     ├─> rag_summarize(知识库检索+总结)
                     ├─> get_user_location → get_weather(天气查询)
                     └─> LLM 整合信息 → 生成回答 → 流式输出

报告生成流程

用户请求报告
   └─> ReactAgent
         └─> LLM 识别报告意图
               ├─> get_uesr_id(获取用户ID)
               ├─> get_uesr_time(获取当前月份)
               ├─> fill_context_for_report
               │     └─> monitor_tool 中间件: context['report'] = True
               ├─> get_external_data(读取CSV使用记录)
               └─> report_prompt_switch 检测到 report=True
                     └─> 切换为 report_prompt → LLM 生成 Markdown 报告
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐