Files
auto_agent/README.md
T

446 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Agent Web Chat
基于 LangGraph 的多模态对话 Agent,支持文本、图片、音频、多种类型文件输入,具备屏幕截图、浏览器控制、RAG 知识库、数据库查询、本地文件获取等工具调用能力。
## 快速开始
### 1. 克隆仓库并进入项目目录
```bash
git clone <your-repo-url>
cd Agent
Windows:
bash
python -m venv myenv
.\myenv\Scripts\activate
macOS / Linux:
bash
python -m venv myenv
source myenv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
pip install -e .
gedit .env
必须填写的变量:
LLM_BASE_URL – 大模型 API 基础地址
LLM_API_KEY – API 密钥
LLM_MODEL – 模型名称(如 Qwen/Qwen2.5-72B-Instruct)
TTS_BASE_URL – 文本转语音服务地址(可选,若不使用音频回复可不填)
ASR_BASE_URL – 语音识别服务地址(可选)
RAG_BASE_URL – RAG 嵌入与重排序服务地址(可选)
# 启动 Web 对话服务(推荐)
# 确保在 Agent 目录下,且 PYTHONPATH 包含 src 目录
cd ./Agent
export PYTHONPATH=src:$PYTHONPATH # Linux/macOS
# 或 Windows PowerShell: $env:PYTHONPATH="src;$env:PYTHONPATH"
uvicorn web.server:app --host 0.0.0.0 --port 8765
# (可选)通过 Cloudflare Tunnel 暴露公网
cloudflared tunnel --url http://localhost:8765
# 进入项目目录并提交代码(Windows 下路径为 .\Agent\)
✅ 推送到公司
powershell
# 进入项目目录
cd Agent
# 暂存所有修改
git add .
# 提交修改(请替换双引号里的内容为实际说明)
git commit -m "修改内容的说明"
# 默认推送到公司
git push
🌐 推送到个人 GitHub
powershell
# 进入项目目录
cd Agent
# 暂存所有修改
git add .
# 提交修改(请替换双引号里的内容为实际说明)
git commit -m "修改内容的说明"
# 显式指定推送到个人仓库 (minor)
git push minor master
###循环检测
用户输入 → runtime.py 重置循环状态
→ graph.invoke 开始执行
│
├─ agent 节点 (nodes.py / call_model)
│ ├─ _build_reflection_prompt()
│ │ ├─ check_and_record_todolist_progress() ← todolist 停滞检测
│ │ │ └─ 10轮无进展 → 注入反思提示:"请反思当前卡点..."
│ │ │
│ │ └─ build_loop_reflection_prompt()
│ │ └─ detect_repeated_tool_calls() ← 连续相同工具检测
│ │ └─ 连续3次 → 注入反思提示:"你已连续多次调用同一工具..."
│ │
│ └─ LLM 调用(带反思提示引导)
│
├─ routing 节点 (routing.py / should_continue)
│ └─ should_force_end()
│ └─ 连续5次相同工具+相同参数 → 返回 END,强制终止
│
└─ 图结束后 (runtime.py / execute_agent)
└─ 检测到强制终止 → 向前端输出:
"检测到异常循环,工具 `xxx` 已连续调用 5 次..."
---
## 提示词工程文档
本 Agent 系统的提示词采用**分层架构**,按作用域和注入时机分为四个层级。以下逐一说明。
### 一、架构总览
```
┌─────────────────────────────────────────────────┐
│ Layer 1: 系统级提示词 (System Prompt) │
│ 作用于整个会话,定义 Agent 角色与核心行为准则 │
│ 文件: system_prompt.py / agent_config.json │
├─────────────────────────────────────────────────┤
│ Layer 2: 工具描述提示词 (Tool Description) │
│ 随工具定义注入,指导 LLM 如何正确调用工具 │
│ 文件: gui_tool.py / tool.py / tool_rag.py 等 │
├─────────────────────────────────────────────────┤
│ Layer 3: 运行时注入提示词 (Runtime Injection) │
│ 每轮 ReAct 循环动态拼接到消息列表 │
│ 文件: system_prompt.py / loop_detector.py │
├─────────────────────────────────────────────────┤
│ Layer 4: 内部模型提示词 (Internal Model Prompt) │
│ 工具内部调用子模型时使用,用户不可见 │
│ 文件: gui_tool.py (_build_batch_prompt) │
└─────────────────────────────────────────────────┘
```
---
### 二、Layer 1 — 系统级提示词
#### 2.1 MAIN_SYSTEM_PROMPT(Agent 模式)
**位置:** `agent/memory/system_prompt.py` → `MAIN_SYSTEM_PROMPT`
**作用:** Agent 模式的顶层系统提示词,定义 Agent 的身份和全局行为准则。
**核心规则:**
| 规则 | 目的 |
|------|------|
| 优先理解用户意图,高效完成任务 | 确立目标导向 |
| 对图片/音频直接使用多模态能力分析,不调用无关工具 | 防止误调用截图/OCR |
| 截图返回后必须基于实际结果推进,严禁凭空编造 | 防止幻觉 |
| **同一页面的 GUI 操作必须合并为一次 gui_tool 调用** | 减少延迟,避免单步执行 |
| 不确定是否需要工具时优先不调用 | 防止过度工具调用 |
| 复杂任务主动使用 todo_list 规划并跟踪进度 | 确保多步任务可追踪 |
**设计要点:**
- 第 8 行从"优先考虑动作序列"升级为"**必须**合并",并明确"严禁逐个单步调用",以对抗 ReAct 循环天然倾向于单步执行的问题。
- 第 6 行"基于实际结果继续推进"是为了让模型把截图当作真实的视觉反馈,而非想象屏幕状态。
---
#### 2.2 PLAN_MODE_PROMPT(Plan 模式)
**位置:** `agent/memory/system_prompt.py` → `PLAN_MODE_PROMPT`
**作用:** 当 `agent_mode == "plan"` 时替换 MAIN_SYSTEM_PROMPT,强制 Agent 先规划后执行。
**核心规则:**
- 收到用户请求后**第一步必须调用 todo_list** 进行任务拆解
- 步骤拆解必须详尽,覆盖完整流程
- 规划完成后立即开始执行,不等待用户确认
- 每完成一步调用 todo_list 标记进度
---
#### 2.3 Agent 级 system_prompt
**位置:** `agent/core/agent_config.json`
```json
"system_prompt": "你是一个多模态助手...你的默认行为是优先调用工具解决用户问题。"
```
**作用:** 当 `agent_config.json` 中配置了 `system_prompt` 时,会作为额外的行为准则注入。当前版本的指令较为简略,主要作为兜底。
---
#### 2.4 其他专用 System Prompt
| Prompt | 用途 | 特点 |
|--------|------|------|
| VISION_SYSTEM_PROMPT | 图像理解子 Agent | 要求客观描述、不臆测、多图编号 |
| DB_SYSTEM_PROMPT | 数据库查询子 Agent | 只允许 SELECT/WITH,强调安全底线 |
| SUMMARY_SYSTEM_PROMPT | 摘要子 Agent | 压缩至 20%-30%,保留关键信息 |
| TEAM_MODE_PROMPT | Team 模式占位 | 当前未实现,告知用户使用 Agent 模式 |
---
### 三、Layer 2 — 工具描述提示词
工具描述提示词直接定义在工具类的 `description` 属性中,随 LangChain 工具绑定注入到 LLM 上下文。
#### 3.1 gui_tool 描述
**位置:** `agent/tools/gui_tool.py` → `GUITool.description`
**结构:**
```
GUI 自动化工具。通过截图视觉定位桌面元素...
↓
【type 使用说明】type 支持 element_description 自动聚焦输入框
↓
【网页滚动提示】推荐用 hotkey space 代替 scroll 滚轮
↓
【下拉框处理策略】直接使用 type 动作,系统自动匹配选项
↓
示例:登录表单 actions 列表
```
**设计要点:**
- **type 操作说明:** 强调 `element_description` 参数可让 type 自动完成"定位→点击→输入",无需额外 click。这是减少动作数量的关键设计。
- **网页滚动提示:** 引导模型使用 `hotkey space`(空格键即 Page Down)而非 `scroll` 滚轮,因为浏览器中滚轮定位不准确。
- **下拉框处理:** 精简为一步 `type`,去掉了之前的两步 fallback 策略(点击→方向键→回车),减少不必要的操作。
- **登录表单示例:** 提供一个多 action 的 one-shot 示例,示范如何将两个 type 操作合并到一个 gui_tool 调用中。
---
#### 3.2 todo_list 描述
**位置:** `agent/tools/tool.py` → `TodoList.description`
**关键指令:**
- **步骤粒度要求:** 同一页面/界面的连续操作合并为一条步骤,用"并"连接
- 包含正例(推荐)和反例(禁止)的对比
- Plan 模式下为必须调用,Agent 模式下按需
**示例:**
```
推荐:"点击搜索框,输入XXX并点击搜索"(合并了点击、输入、搜索)
禁止:"1.点击搜索框 2.输入文字 3.点击搜索"(过于细碎)
```
---
### 四、Layer 3 — 运行时注入提示词
这类提示词在每轮 ReAct 循环中动态拼接到消息列表,作为 synthetic HumanMessage 注入,不会被记录到前端消息历史。
#### 4.1 REFLECTION_PROMPT(反思提示)
**位置:** `agent/memory/system_prompt.py` → `REFLECTION_PROMPT`
**注入时机:** 每轮 ReAct 循环(除首轮外),由 `nodes.py` 的 `_build_reflection_prompt()` 构建并注入。
**结构:**
```
【请先在你的回复中尽可能简短地输出你的反思...】
1. 分析上一轮执行结果
2. GUI 未命中 → 重新估算坐标重试
3. 操作成功 → 进行下一步
4. 调用工具或回复用户
【gui_tool 批量调用规则 - 务必遵守】
同一页面的连续操作必须合并为一次 gui_tool 调用
严禁拆分多次调用——会造成严重延迟
仅页面跳转/加载后才分步调用
```
**设计要点:**
- 前 4 条建立"观察→反思→行动"的思维链模式
- **第 5 条是关键补充:** 明确告知模型在做"下一步"计划时,如果同一页面有多个操作,必须打包成一个 gui_tool 调用。这是对抗 ReAct 循环"做一步看一步"惯性的核心机制。
- 仅当需要等页面跳转/加载后才能确定后续操作时,才允许分步,给了模型合理的例外判断空间。
---
#### 4.2 PLAN_FIRST_CALL_PROMPT(Plan 模式首轮注入)
**位置:** `agent/memory/system_prompt.py` → `PLAN_FIRST_CALL_PROMPT`
**注入时机:** Plan 模式下的首轮调用,在 `call_model` 中检测到 `agent_mode == "plan" && is_first_call` 时注入。
**核心指令:**
- **立即调用 todo_list** 进行任务拆解
- **合并同类操作:** 同一页面的连续操作合并为一条步骤
- 包含三个正例和一个反例的详细示范
---
#### 4.3 反循环反思提示
**位置:** `agent/core/loop_detector.py` → `build_loop_reflection_prompt()`
**注入时机:** 当检测到循环风险时,拼接到 REFLECTION_PROMPT 之后。
**两级响应:**
| 级别 | 触发条件 | 响应 |
|------|----------|------|
| Level 1 (警告) | 连续 3 次调用同一工具且参数相同 | 注入反思提示:"你已经连续 N 次调用工具...请反思当前策略" |
| Level 1 (警告) | TodoList 停滞 10 轮无进展 | 注入反思提示:"TodoList 已有 N 轮没有进展...考虑调整计划" |
| Level 2 (终止) | 连续 5 次调用同一工具且参数相同 | 强制结束图执行,向前端输出错误报告 |
**设计要点:**
- 两级响应机制避免误杀——先警告引导模型自我纠偏,纠偏失败再强制终止
- 循环检测阈值可通过 `env_config.json` 中的 `LOOP_DETECT_*` 配置项热更新
---
#### 4.4 截图反馈注入
**位置:** `agent/core/nodes.py` → `process_tool_artifact()`
**注入时机:** 每次 gui_tool 返回 artifact(截图)后。
**注入内容:** `[图片数据] + "上面是工具返回的截图。"`
**作用:** 将截图作为视觉反馈注入对话上下文,让多模态 LLM 看到执行后的屏幕状态,实现闭环的视觉推理。
---
### 五、Layer 4 — 内部模型提示词
#### 5.1 批量坐标定位 Prompt
**位置:** `agent/tools/gui_tool.py` → `_build_batch_prompt()`
**调用链:** `_run()` → `_collect_grounding_queries()` → `_batch_ground_elements()` → `_build_batch_prompt()`
**作用:** 将一次截图中需要定位的所有元素,批量发送给视觉定位模型,一次性返回所有坐标。
**结构:**
```
You are a visual grounding model for desktop GUI control.
↓
=== OUTPUT FORMAT (STRICT) ===
每行一对坐标: (<x>, <y>)
↓
=== ONE-SHOT EXAMPLE ===
4 个 query → 4 行坐标的完整示例
↓
=== NOW YOUR TURN ===
实际需要定位的元素列表
↓
=== RULES ===
7 条严格的输出格式规则
```
**设计要点:**
- **One-shot 示例**是核心: 用一个完整的 4 元素定位示例纠正模型的输出格式偏好,防止输出 JSON、Markdown 或其他非预期格式。
- **规则 7** 特别强调"按顺序生成坐标",确保 action 顺序与坐标顺序一一对应。
- 使用的模型为 `_get_gui_llm()` 获取的 GUI 专用模型(如有配置),否则回退到主模型。
---
### 六、提示词注入流程
#### 6.1 Agent 模式标准流程
```
用户输入
│
▼
[MAIN_SYSTEM_PROMPT] ← 作为 SystemMessage,会话开始时注入
│
▼
┌─ ReAct 循环 ────────────────────────────────────┐
│ │
│ call_model 节点 │
│ ├─ 首轮: 直接调用 LLM │
│ └─ 后续: 注入 [REFLECTION_PROMPT] │
│ + [TodoList 状态] │
│ + [反循环警告(如有)] │
│ │ │
│ ▼ │
│ LLM 决策 → 调用 tool(带 [Tool Description]) │
│ │ │
│ ▼ │
│ tools 节点 → 执行工具 │
│ │ │
│ ▼ │
│ process_tool_artifact 节点 │
│ └─ gui_tool 返回 → 注入截图 + "上面是截图" │
│ │ │
│ ▼ │
│ routing → 继续/结束 │
│ │
└──────────────────────────────────────────────────┘
```
#### 6.2 Plan 模式特殊流程
```
用户输入
│
▼
[PLAN_MODE_PROMPT] ← 替换 MAIN_SYSTEM_PROMPT
│
▼
首轮 call_model:
注入 [PLAN_FIRST_CALL_PROMPT]
→ LLM 调用 todo_list 生成步骤规划
│
▼
后续 call_model:
注入 [REFLECTION_PROMPT] + [TodoList 状态]
→ LLM 按规划逐步执行
```
---
### 七、关键设计决策
| 决策 | 原因 | 实现方式 |
|------|------|----------|
| **动作序列优先于单步** | 单步调用每个 action 都经过一轮 LLM→截图→LLM 循环,N 个 action 需要 2N+1 次 LLM 调用。序列化后 N 个 action 只需 2 次 LLM 调用(1 次定位 + 1 次决策) | MAIN_SYSTEM_PROMPT + REFLECTION_PROMPT 双重强调 |
| **下拉框仅用 type** | 两步策略(type→键选 fallback)会增加不必要的 action 数量,type 本身即可完成下拉匹配 | gui_tool 描述中精简为单句 |
| **截图作为视觉闭环** | 让 LLM 看到真实屏幕状态而非猜测,是 GUI 自动化可靠性的基础 | process_tool_artifact 自动注入截图 |
| **反思提示每轮注入** | 让模型形成"观察→分析→行动"的习惯,减少盲目操作和幻觉 | REFLECTION_PROMPT 作为 synthetic HumanMessage |
| **循环检测两级响应** | 先警告引导,再强制终止,避免误杀同时防止无限循环 | loop_detector.py 的 warn→end 机制 |
| **坐标定位批量化** | N 个元素的坐标定位只需 1 次子模型调用,而非 N 次 | _batch_ground_elements + _build_batch_prompt |
| **One-shot 示例纠正格式** | 视觉定位模型容易输出 JSON/Markdown/解释文字,one-shot 强制纯坐标格式 | _build_batch_prompt 中的 4 行坐标示例 |
| **trajectory_rounds 短期记忆过滤** | 多轮 GUI 操作后上下文过长,仅保留最近 3 轮工具返回结果 | _filter_short_term_memory() |
#### 连接远程服务器
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -p 60007 minor123@semi-ai.tech
#### 本地端口映射
ssh -fN -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -L 8901:127.0.0.1:8901 -L 8902:127.0.0.1:8902 -L 8903:127.0.0.1:8903 minor123@semi-ai.tech -p 60007
ssh -fN -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -L 8903:127.0.0.1:8903 minor123@semi-ai.tech -p 60007
# 查看状态码(200表示健康)
curl.exe -o nul -s -w "%{http_code}\n" http://localhost:8901/health
curl.exe -o nul -s -w "%{http_code}\n" http://localhost:8902/health
curl.exe -o nul -s -w "%{http_code}\n" http://localhost:8903/health
curl -o /dev/null -s -w "%{http_code}\n" http://localhost:8901/health
curl -o /dev/null -s -w "%{http_code}\n" http://localhost:8902/health
curl -o /dev/null -s -w "%{http_code}\n" http://localhost:8903/health
(email、sendfile)
今天和昨天有什么邮件
发封邮件给19553226590@163.com,内容就是我桌面的图片"C:\Users\86166\Desktop\风景\8.png"
(websearch、terminal、sendfile)
查一下济南和青岛近10年的GDP并画个图表
(gui、browser、human_interaction、改成英文)
进行以下gui任务,严格按照我的指令操作:
1、打开https://erpdemo.fanpusoft.com/main.aspx#
2、进行登录(账号密码调用human_interaction工具来问我)
3、点击销售管理
4、点击新增客户
5、在新增客户界面输入:
客户名称:minor;客户类别:零售商;公司地址:中国·青岛;公司简介:大狗叫叫叫;联系人姓名:叮咚鸡;
点击性别选项:女;部门:抽象部;生日:2004-07-09;
6、点击客户档案并连按两次空格(用来下滑到网页底部)
7、点击批量上传
8、在弹出的文件选择器的文件名输入框中输入"C:\Users\86166\Desktop\风景\8.png"并回车
9、输入跟进日期:2026-07-16
10、点击保存
11、点击确定