Files
zk-data-agent/README.md
T
2026-05-11 20:26:06 +08:00

771 lines
21 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.
# ZK Data Agent
ZK Data Agent 是基于 `claw-code-agent` 改造的团队通用 Agent 工作台。
它不是一个单点数据工具,也不是只会聊天的 Web UI。这个项目的核心目标是把“通用 Agent 能力”稳定下来:让 Agent 能理解任务、选择 Skill、调用 Tools、读写文件、执行 Python、保留会话、展示工具链路,并把团队反复使用的工作经验沉淀成可维护的能力包。
数据开发、线上挖掘、ELK 查询、数据工场 SQL 查询,都是已经通过 Skill 和 Tools 落地的子能力。
## 这个项目解决什么
团队日常有很多任务不只是“问模型一句话”:
- 要读文件、查日志、跑 SQL、分析线上数据。
- 要生成中间结果、落盘文件、继续追问和修正。
- 要把某类任务的经验固化下来,下一次让 Agent 按同样的方法做。
- 要让用户看到 Agent 做了什么、调用了什么工具、文件生成在哪里。
- 要让多人共用一套平台,而不是每个人本地各跑一份零散脚本。
ZK Data Agent 做的是这层通用底座。业务能力通过 Skill 和 Tools 逐步沉淀。
## 核心设计
### Agent Loop
Agent 每轮对话不是一次性生成文本,而是一个循环:
```text
用户输入
-> 组装系统提示词、Skill 提示词、会话上下文、工具定义
-> 模型决定直接回复或返回 tool_calls
-> 后端执行对应 tool handler
-> 工具结果写入会话
-> 下一轮模型继续判断
-> 直到输出最终回复、等待用户 review 或被取消
```
这个循环让 Agent 可以边观察、边执行、边修正,而不是只能一次性回答。
### Skill
Skill 是“经验层”。它用 `SKILL.md` 描述某类任务应该怎样做、什么时候需要用户确认、可以调用哪些工具、产物应该放在哪里。
项目级 Skill 统一放在:
```text
skills/<skill-name>/SKILL.md
```
Skill 适合承载:
- 工作流程
- 业务边界
- review 门禁
- 工具调用经验
- 输入输出格式约定
- 常见错误和注意事项
Skill 不应该写成大段不可执行代码。稳定、强格式、可复用的能力应该下沉到 Tool。
### Tools
Tools 是“执行层”。工具负责稳定地做事情,例如读写文件、执行 Python、查询 parquet、转换 records、导出 JSONL。
主要位置:
```text
src/agent_tools.py
src/agent_tool_specs/
src/data_agent_records.py
src/data_agent_inputs.py
src/data_agent_router_sessions.py
```
工具适合承载:
- 强格式转换
- 数据校验
- 路径归一
- 线上数据读取
- 账号级 Python 执行环境
- 需要审计和约束的外部调用
原则是:不要长期让 Agent 手写易错脚本来完成稳定流程。能工具化的,尽量工具化。
### 会话工作区
每个用户、每个会话都有独立目录:
```text
.port_sessions/accounts/<account_id>/sessions/<session_id>/
input/ 用户输入文件
scratchpad/ 临时脚本、中间分析、草稿
output/ 最终产物
session.json 会话历史
```
会话工作区是这个项目和普通聊天机器人很不一样的地方。Agent 的产物不是散落在项目根目录,而是跟随当前会话保存,方便回看、下载和继续追问。
### Review 门禁
一些任务不能让 Agent 一步到位,例如:
- 数据生成目标还不清楚。
- 标签边界存在歧义。
- 线上候选需要人工抽样确认。
- 输出格式会影响训练、评测或对外交付。
这类流程要通过 Skill 和 Tool 实现 review 门禁。目标、计划、候选样本、最终导出都应该分阶段展示给用户确认。
### 可观测性
Web UI 会展示:
- 当前模型和上下文状态
- Skill 列表和启用状态
- 工具调用过程
- 总结版思考阶段
- 历史会话
- 当前会话输入/输出文件
- 后台运行和刷新恢复状态
目标是让用户知道 Agent 正在做什么,而不是只看到一个黑盒回复。
## 和 Claude Code 的区别
这个项目继承了 Claude Code 类工具的基本思路:Agent 可以读写文件、执行工具、维护上下文,并围绕一个工作区完成任务。
但当前项目的定位更偏团队内部 Agent 平台:
| 维度 | Claude Code 类工具 | ZK Data Agent |
|------|--------------------|---------------|
| 使用形态 | 个人本地 CLI/IDE 工作流为主 | 团队共享 Web 服务 |
| 任务范围 | 代码开发为核心 | 通用任务底座,数据开发只是能力之一 |
| 能力沉淀 | 个人 prompt、命令、脚本较多 | 项目级 Skill + Tools 统一管理 |
| 文件空间 | 通常围绕当前代码仓库 | 每个用户/会话独立 `input/scratchpad/output` |
| 可观测性 | 终端输出为主 | Web UI 展示工具链路、活动、文件、历史 |
| Python 执行 | 常用 shell 自行管理 | 优先 `python_exec`,走账号级环境和工具约束 |
| 人工确认 | 通常是权限批准或终端交互 | 更强调业务 review:目标、计划、样本、导出 |
| 内部系统 | 需要用户自行接脚本 | 可以通过 Skill/Tools 接 ELK、SQL、线上数据 |
因此,它不是要替代 Claude Code 的个人编码体验,而是把 Agent 变成团队可共享、可扩展、可治理的工作台。
## 能力目录
### 通用 Agent 能力
当前底座已经支持:
- OpenAI 兼容模型调用
- Web UI 多会话管理
- 模型选择
- Skill 发现和会话级启用
- 工具调用展示
- 文件输入和会话产物管理
- 后台 run 状态和刷新恢复
- 总结版思考过程展示
- Python 执行和包安装工具
- 用户级 systemd 部署
### 数据开发能力
Skill`product-data`
适用于从产品定义、标签规则、手写边界或示例 query 生成数据集。
典型流程:
```text
输入定义/规则/样例
-> 抽取 generation goal
-> 用户 review
-> 生成 generation plan
-> 用户确认数量、标签、边界、路径
-> 生成 dataset draft text
-> 转换为 canonical records
-> 校验
-> 导出 records.jsonl
```
默认最终产物:
```text
当前会话/output/records.jsonl
```
### 线上挖掘能力
Skill`online-mining`
适用于从线上 router session 中按 query 特征、domain、设备、日期等条件挖掘候选样本。
典型流程:
```text
需求/badcase/标签定义
-> 构造挖掘策略
-> profile 数据
-> search 候选
-> sample 抽样 review
-> 策略调整
-> 候选转换为 canonical records
-> 导出 records.jsonl
```
默认线上数据路径:
```text
/data/online_data/router_session_parquet/date=YYYYMMDD/
```
重要分支:
- 如果用户要“直接把线上候选作为样本”,只做转换,不生成新 query。
- 如果用户明确要“补充生成/扩写类似 case”,才切换到数据生成链路。
### 评测修复能力
Skill`eval-repair`
用于评测错误分析、错误类型归纳和后续补数流程。目前主要是流程占位和约定沉淀,工具还会继续补齐。
### 日志查询能力
Skill`elk-fetch`
用于按 request id 查询小米内网 ELK 日志,覆盖 NLP 主链路、拒识、免唤醒、小米汽车 OneTrack 等场景。
原则:
- 通过 `python_exec` 执行 skill 内脚本。
- 不让 Agent 直接用 `bash python ...` 绕过工具链路。
### 数据工场 SQL 能力
Skill`data-factory-sql`
用于通过 Kyuubi HTTP API 执行 SQL、轮询状态并下载 CSV 结果。
适用于:
- 用户直接给 SQL。
- 用户要求“跑个 SQL”“数据工场查一下”。
- Agent 基于表结构和字段说明生成 SQL 草稿,再请求用户确认后执行。
## 团队公约
### 空间公约
业务任务默认在当前会话空间内工作:
```text
input/ 用户上传或指定的输入材料
scratchpad/ 临时脚本、中间文件、抽样缓存
output/ 最终交付文件
```
约定:
- 最终产物优先写入当前会话 `output/`
- 临时脚本和中间文件写入当前会话 `scratchpad/`
- 数据 records 默认导出到逻辑路径 `output/records.jsonl`,工具会自动路由到当前会话 output。
- 不要把业务任务产物写到项目根目录的 `output/``tasks/``src/``skills/`
- 读取外部数据可以用明确路径,但写入外部路径前需要用户明确确认。
- 平台源码目录默认只读。只有用户明确要求开发平台功能时,才修改 `src/``frontend/``skills/``scripts/` 等项目文件。
### Skill 公约
项目级 Skill 统一放在:
```text
skills/<skill-name>/SKILL.md
```
Skill 是可以独立维护、独立安装、被 Agent 读取和执行的能力包。它不只是 prompt,也不只是脚本,而是某类任务的“能力入口”:可以包含流程、知识、脚本、配置和模板,但必须清楚说明边界。
#### 适合做成 Skill 的内容
当前项目里的 Skill 大致分为四类:
| 类型 | 代表 | 适合承载 |
|------|------|----------|
| 流程编排型 | `product-data``online-mining``eval-repair` | 分阶段流程、review 门禁、工具调用顺序、产物规范 |
| 工具封装型 | `elk-fetch``data-factory-sql` | 外部系统调用脚本、CLI 参数、依赖说明、返回格式 |
| 知识增强型 | `model-iteration/knowledge/*`,后续标签知识 Skill | 标签定义、边界规则、案例、决策依据 |
| 混合工程型 | `model-iteration` | 复杂工程闭环:流程 + 知识 + 脚本 + 配置 |
判断一件事放在哪里:
- **Skill**:告诉 Agent 怎么做、什么时候停、读哪些知识、如何组织流程。
- **Knowledge / references**:放大段业务知识、规则、案例和字段说明。
- **Scripts**:放可重复、确定性、容易写错的执行逻辑。
- **Tools**:放平台级、强约束、需要长期稳定维护的能力,例如 records 转换、校验、线上 parquet 检索。
#### 推荐目录结构
```text
skills/<skill-name>/
SKILL.md 必须,Agent 触发和执行该能力的入口
README.md 可选,给维护者看的说明
scripts/ 可选,确定性脚本或 CLI
knowledge/ 可选,业务知识、标签规则、案例
references/ 可选,长文档、字段说明、API 说明
assets/ 可选,模板、静态资源
config.yaml 可选,默认参数
```
不建议提交:
- `__pycache__/`
- `.venv/`
- 临时运行结果
- 用户私有 token、key、cookie
- 大体积产物或线上原始数据
#### SKILL.md frontmatter
`SKILL.md` frontmatter 至少包含:
```yaml
---
name: skill-name
description: 简短说明这个 skill 做什么,尽量覆盖触发关键词。
when_to_use: 说明什么场景应该触发,包含用户常见说法。
aliases: optional-alias
allowed_tools: read_file, write_file, python_exec
---
```
字段约定:
- `name`:短横线命名,稳定、可读,例如 `online-mining``data-factory-sql`
- `description`:面向模型召回,说明能力范围和典型触发词。
- `when_to_use`:面向模型决策,说明什么场景应该使用。
- `aliases`:兼容旧名字、团队口头叫法。
- `allowed_tools`:列出该 Skill 合理使用的工具,避免能力越界。
命名建议:
- 用“能力名”而不是项目临时代号,例如 `model-iteration` 优于 `zk-model`
- 工具封装型可以用系统名,例如 `elk-fetch``data-factory-sql`
- 知识型可以用知识域名,例如 `label-master`
- 不要用过泛的名字,例如 `helper``tools``data`
维护规则:
- 用中文写主要流程说明,方便团队后续维护。
- Skill 写“怎么做”和“什么时候停下来问用户”。
- 不要把稳定格式转换、校验、复杂查询长期写在 Skill 里,应沉淀为 Tool。
- Skill 如果依赖脚本,脚本放在该 Skill 目录下,并通过 `python_exec` 调用。
- 新增业务 Skill 后,可以在 Web UI Skill 列表中按会话启用或关闭。
#### SKILL.md 内容结构
推荐顺序:
```text
1. 这个 Skill 解决什么问题
2. 输入假设
3. 必要工作流
4. 需要用户 review 的门禁
5. 输出目录和产物约束
6. 可用脚本或知识文件
7. 常见错误和禁止事项
```
如果 `SKILL.md` 超过几百行,优先拆分:
- 长业务规则放 `knowledge/`
- 长 API/字段说明放 `references/`
- 可执行逻辑放 `scripts/`
- `SKILL.md` 只保留导航、流程和关键门禁
#### 脚本型 Skill 约定
脚本型 Skill 典型如 `elk-fetch``data-factory-sql``model-iteration`
约定:
- Python 脚本优先放在 `scripts/`,少量历史 Skill 可保留根目录脚本,但新 Skill 优先使用 `scripts/`
- Agent 调用脚本优先使用 `python_exec`,不要让模型直接 `bash python xxx.py`
- 依赖缺失时使用 `python_package` 安装到账号级 Python 环境。
- 脚本参数要稳定,输出尽量给 JSON 或结构化摘要,方便 Agent 继续分析。
- 不要在脚本里硬编码 API key、token、个人路径。优先读取环境变量或用户 home 下配置。
- 长耗时脚本必须考虑超时、分页、采样或断点,不要默认全量扫描。
脚本调用示例:
```json
{
"script_path": "skills/example/scripts/run_task.py",
"args": ["--input", "xxx"],
"timeout_seconds": 120,
"max_output_chars": 20000
}
```
#### 知识型 Skill 约定
知识型 Skill 适合承载标签体系、业务规则、字段定义、案例库。
约定:
- `SKILL.md` 只写“什么时候读哪些知识文件”。
- `knowledge/` 下按主题拆文件,文件名语义化。
- 每个知识文件开头写清楚适用范围。
- 不要把所有知识一次性塞进 `SKILL.md`
- 面向标签、路由、复杂度等判断时,鼓励输出“候选、依据、排除项、不确定点”,不要过早封装成黑盒单步分类。
例如后续中控标签知识可以先设计为:
```text
skills/label-master/
SKILL.md
knowledge/
agents.md
functions.md
complex_rules.md
boundary_cases.md
examples.md
scripts/
build_index.py
```
#### 外部 Skill 仓库安装约定
允许同事把能力打包为独立 git 仓库维护,再安装到本项目:
```text
skills/<skill-name>/
```
安装或迁移时需要检查:
- 是否有合法 `SKILL.md` frontmatter。
- skill 名是否符合项目命名风格。
- 是否包含不该提交的缓存、运行产物、私钥、token。
- 脚本是否能通过 `python_exec` 调用。
- 依赖是否写清楚,缺包时能通过 `python_package` 安装。
- 输出目录是否遵守当前会话 `output/` / `scratchpad/` 公约。
- 高风险动作是否有用户确认门禁。
外部仓库可以保留自己的 README,但真正影响 Agent 行为的是 `SKILL.md`
#### 高风险动作门禁
Skill 中只要涉及下面动作,必须先展示计划并等待用户确认:
- 批量修改训练数据或标签定义。
- 提交训练、部署模型、启动 CML job。
- 写入外部路径或覆盖已有产物。
- 推送 git、改远端配置。
- 导出包含敏感线上字段的数据。
用户明确说“开始评测”“查一下”“分析一下”时,可以执行只读分析;不要自动升级成训练、部署或批量改数据。
### Tool 公约
工具是稳定执行边界。
约定:
- 强格式输出必须工具化,例如 canonical records、JSONL 导出、数据校验。
- 需要持久化状态的 review 流程应由工具记录 pending/confirmed 状态。
- Python 分析优先用 `python_exec`
- 缺 Python 包时用 `python_package`
- 除非没有专用工具,否则不要让 Agent 通过 `bash` 绕过已有工具。
### Python 公约
Agent 执行 Python 优先使用:
```text
python_exec
python_package
```
原因:
- 可以进入账号级 Python 环境。
- 可以把临时脚本和输出放在当前会话 scratchpad。
- Web UI 能看到工具调用过程。
- 后续更容易加超时、取消、审计和资源限制。
### Git 公约
不要提交:
- `.env.deploy`
- `.venv/`
- `.port_sessions/`
- `router_session_parquet/`
- 用户数据、模型输出、临时任务产物
可以提交:
- `skills/` 下经过确认的项目级 Skill
- `src/` 下稳定工具和运行时代码
- `frontend/app/` 下 Web UI 代码
- `scripts/``deploy/` 下部署维护脚本
- README 中面向团队维护的约定
## 系统组成
```text
frontend/app/ Next.js Web UI
backend/ FastAPI Web 后端
src/ Agent runtime、提示词、工具实现、会话持久化
skills/ 项目级 Skill,使用 SKILL.md 定义
scripts/ 本地启动、服务器部署、systemd 启动脚本
deploy/systemd/ 用户级 systemd service 模板
.port_sessions/ 本地/服务端运行数据,禁止提交
.env.deploy 本机私有部署配置,禁止提交
```
前端负责账号、会话列表、模型选择、对话流式展示、活动面板和会话文件面板。
后端负责 Agent loop、OpenAI 兼容模型调用、工具执行、run 状态、会话持久化和数据开发工具。
## 本地开发启动
首次准备 Python 依赖:
```bash
pyenv install 3.10.14
pyenv local 3.10.14
python -m venv .venv
.venv/bin/python -m pip install --upgrade pip setuptools wheel
.venv/bin/python -m pip install -e .
```
准备前端依赖:
```bash
cd frontend/app
npm install
```
本地启动 Web UI
```bash
bash scripts/start-webui.sh
```
默认地址:
```text
前端:http://127.0.0.1:3000
后端:http://127.0.0.1:8765
```
`scripts/start-webui.sh` 会优先读取 `.env.deploy`,也可以直接使用当前 shell 里的环境变量:
```bash
export OPENAI_API_KEY="..."
export OPENAI_BASE_URL="http://model.mify.ai.srv/v1"
export OPENAI_MODEL="xiaomi/mimo-v2-flash"
```
停止本地 Web UI
```bash
kill $(cat .port_sessions/webui-frontend.pid) $(cat .port_sessions/webui-backend.pid)
```
## 部署和更新
### 首次部署
推荐把应用部署在用户目录,不需要把代码放到 `/opt`
```bash
git clone git@git.n.xiaomi.com:wuyang6/zk-data-agent.git "$HOME/zk-data-agent" || true
bash "$HOME/zk-data-agent/scripts/install-from-git.sh"
```
首次部署会:
- 拉取 `main` 分支。
- 交互式生成 `.env.deploy`
- 必要时请求 sudo 安装 Ubuntu 系统依赖。
- 用 pyenv 准备 Python `3.10.14`
- 创建项目 `.venv`
- 安装前端依赖并构建。
- 安装并启动用户级 systemd 服务。
`.env.deploy` 会保存:
```text
OPENAI_API_KEY
OPENAI_BASE_URL
OPENAI_MODEL
OPENAI_TIMEOUT_SECONDS
CLAW_BACKEND_HOST
CLAW_BACKEND_PORT
CLAW_FRONTEND_HOST
CLAW_FRONTEND_PORT
CLAW_API_URL
CLAW_NPM_BIN
CLAW_NPX_BIN
CLAW_NODE_BIN
CLAW_NODE_BIN_DIR
```
其中 Node.js 相关路径会在部署时自动记录,供 systemd 后端/前端服务以及飞书 MCP 等 Node 生态能力使用。该文件包含敏感信息,只保存在部署机器本地,权限设置为 `600`,并已被 `.gitignore` 忽略。
### 日常更新
已经完成首次部署后,普通代码更新使用:
```bash
cd "$HOME/zk-data-agent"
bash scripts/update-server-fast.sh
```
如果改动包含依赖、systemd 模板或部署脚本,使用完整部署脚本:
```bash
bash scripts/deploy-ubuntu.sh
```
部署指定分支:
```bash
bash scripts/deploy-ubuntu.sh main
```
强制覆盖服务器工作区:
```bash
bash scripts/deploy-ubuntu.sh main --force
```
### 服务管理
部署脚本会安装两个用户级 systemd 服务:
```text
zk-data-agent-backend
zk-data-agent-frontend
```
查看状态:
```bash
systemctl --user status zk-data-agent-backend
systemctl --user status zk-data-agent-frontend
```
查看日志:
```bash
journalctl --user -u zk-data-agent-backend -f
journalctl --user -u zk-data-agent-frontend -f
```
重启服务:
```bash
systemctl --user restart zk-data-agent-backend zk-data-agent-frontend
```
停止服务:
```bash
systemctl --user stop zk-data-agent-backend zk-data-agent-frontend
```
如果机器要求用户退出 SSH 后服务仍保持运行,可由管理员执行:
```bash
loginctl enable-linger <username>
```
## 环境要求
Ubuntu 部署建议:
- `git`
- `bash`
- `curl`
- `systemd`
- `pyenv`
- Python `3.10.14`
- Node.js `20``22`
- `npm`
首次安装如果缺 Python 编译依赖,可以执行:
```bash
bash scripts/deploy-ubuntu.sh --bootstrap-system
```
`--bootstrap-system` 会使用 `sudo apt-get` 安装系统依赖;应用代码、虚拟环境、前端依赖、运行数据和 systemd 用户服务仍然位于当前用户目录。
## 开发验证
后端基础校验:
```bash
.venv/bin/python -m compileall src backend
```
前端校验:
```bash
cd frontend/app
npm run lint
npx tsc --noEmit
npm run build
```
提交前建议确认:
```bash
git status --short
git diff --check
```
## 常见问题
### Web UI 能打开,但模型调用失败
先检查 `.env.deploy`
```bash
cat .env.deploy
```
重点确认:
- `OPENAI_API_KEY`
- `OPENAI_BASE_URL`
- `OPENAI_MODEL`
- `OPENAI_TIMEOUT_SECONDS`
然后看后端日志:
```bash
journalctl --user -u zk-data-agent-backend -f
```
### systemd 服务找不到 npm
重新执行完整部署脚本:
```bash
bash scripts/deploy-ubuntu.sh
```
脚本会把当前可用的 `npm` 路径写入 `.env.deploy`,避免用户级 systemd 读取不到 zsh/nvm 环境。
### 新增 Skill 后前端看不到
项目级 Skill 放在:
```text
skills/<skill-name>/SKILL.md
```
确保 frontmatter 至少包含 `name``description``when_to_use`。Web UI 会通过 `/api/claw/skills` 读取 Skill 列表。
### Agent 产物没有出现在“聊天中的文件”
最终产物必须写入当前会话 `output/`。数据 records 推荐使用数据工具导出到逻辑路径:
```text
output/records.jsonl
```
工具会自动路由到当前会话 output 目录。