feat: rebuild as multi-user web agent
This commit is contained in:
@@ -1,815 +1,116 @@
|
||||
# ZK Data Agent
|
||||
# K1412 Agent
|
||||
|
||||
ZK Data Agent 是基于 `claw-code-agent` 改造的团队通用 Agent 工作台。
|
||||
K1412 Agent is a multi-user web Agent built around two deliberately different
|
||||
experiences:
|
||||
|
||||
它不是一个单点数据工具,也不是只会聊天的 Web UI。这个项目的核心目标是把“通用 Agent 能力”稳定下来:让 Agent 能理解任务、选择 Skill、调用 Tools、读写文件、执行 Python、保留会话、展示工具链路,并把团队反复使用的工作经验沉淀成可维护的能力包。
|
||||
- **Chat** is fast, conversational, and uses Open WebUI's native tool loop.
|
||||
- **Work** is a long-running coding Agent whose loop, scheduler, context,
|
||||
memory, tools, and sub-agents are owned by this repository.
|
||||
|
||||
数据开发、线上挖掘、ELK 查询、数据工场 SQL 查询,都是已经通过 Skill 和 Tools 落地的子能力。
|
||||
A conversation may be upgraded from Chat to Work. The upgrade is intentionally
|
||||
one-way so that two independent Agent loops never compete for the same
|
||||
conversation state.
|
||||
|
||||
## 这个项目解决什么
|
||||
|
||||
团队日常有很多任务不只是“问模型一句话”:
|
||||
|
||||
- 要读文件、查日志、跑 SQL、分析线上数据。
|
||||
- 要生成中间结果、落盘文件、继续追问和修正。
|
||||
- 要把某类任务的经验固化下来,下一次让 Agent 按同样的方法做。
|
||||
- 要让用户看到 Agent 做了什么、调用了什么工具、文件生成在哪里。
|
||||
- 要让多人共用一套平台,而不是每个人本地各跑一份零散脚本。
|
||||
|
||||
ZK Data Agent 做的是这层通用底座。业务能力通过 Skill 和 Tools 逐步沉淀。
|
||||
|
||||
## 核心设计
|
||||
|
||||
### Agent Loop
|
||||
|
||||
Agent 每轮对话不是一次性生成文本,而是一个循环:
|
||||
## Architecture
|
||||
|
||||
```text
|
||||
用户输入
|
||||
-> 组装系统提示词、Skill 提示词、会话上下文、工具定义
|
||||
-> 模型决定直接回复或返回 tool_calls
|
||||
-> 后端执行对应 tool handler
|
||||
-> 工具结果写入会话
|
||||
-> 下一轮模型继续判断
|
||||
-> 直到输出最终回复、等待用户 review 或被取消
|
||||
browser
|
||||
|
|
||||
v
|
||||
Open WebUI (auth, RBAC, chat history, UI)
|
||||
|
|
||||
v
|
||||
Agent Runtime (model gateway + Work loop)
|
||||
|
|
||||
v
|
||||
Workspace Gateway (identity, policy, audit)
|
||||
|
|
||||
v
|
||||
one Docker workspace per Open WebUI user
|
||||
```
|
||||
|
||||
这个循环让 Agent 可以边观察、边执行、边修正,而不是只能一次性回答。
|
||||
Open WebUI is pinned and lightly patched. Its model picker is replaced by two
|
||||
product-level choices: `Chat / Work` and `轻度 / 中 / 高`. Provider URLs,
|
||||
provider model IDs, API keys, tool server settings, system prompts, and runtime
|
||||
parameters remain server-side.
|
||||
|
||||
### Skill
|
||||
The inference mapping is fixed:
|
||||
|
||||
Skill 是“经验层”。它用 `SKILL.md` 描述某类任务应该怎样做、什么时候需要用户确认、可以调用哪些工具、产物应该放在哪里。
|
||||
| Strength | Provider model |
|
||||
| --- | --- |
|
||||
| 轻度 | `ChatGPT-5.6:Luna` |
|
||||
| 中 | `ChatGPT-5.6:Terra` |
|
||||
| 高 | `ChatGPT-5.6:Sol` |
|
||||
|
||||
项目级 Skill 统一放在:
|
||||
## Local development
|
||||
|
||||
```text
|
||||
skills/<skill-name>/SKILL.md
|
||||
```
|
||||
1. Copy `.env.example` to `.env` and fill in the secret values. Never commit
|
||||
`.env`. Generate new values with `./scripts/init-secrets.sh`.
|
||||
2. Build the user workspace image:
|
||||
|
||||
Skill 适合承载:
|
||||
```bash
|
||||
docker compose --profile build-only build workspace-image
|
||||
```
|
||||
|
||||
- 工作流程
|
||||
- 业务边界
|
||||
- review 门禁
|
||||
- 工具调用经验
|
||||
- 输入输出格式约定
|
||||
- 常见错误和注意事项
|
||||
3. Start the stack:
|
||||
|
||||
Skill 不应该写成大段不可执行代码。稳定、强格式、可复用的能力应该下沉到 Tool。
|
||||
```bash
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
### Tools
|
||||
4. Open <http://localhost:3000>. New users register as `pending` and require
|
||||
approval by the bootstrap administrator.
|
||||
|
||||
Tools 是“执行层”。工具负责稳定地做事情,例如读写文件、执行 Python、查询 parquet、转换 records、导出 JSONL。
|
||||
The pasted provider credential from the planning conversation is intentionally
|
||||
not stored here. Rotate it and place the replacement only in the protected
|
||||
deployment `.env`.
|
||||
|
||||
主要位置:
|
||||
|
||||
```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 依赖:
|
||||
## Tests
|
||||
|
||||
```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 .
|
||||
python3 -m venv .venv
|
||||
.venv/bin/pip install -e '.[dev]'
|
||||
.venv/bin/pytest
|
||||
```
|
||||
|
||||
准备前端依赖:
|
||||
Run the complete local verification path, including the real Docker isolation
|
||||
test, with:
|
||||
|
||||
```bash
|
||||
cd frontend/app
|
||||
npm install
|
||||
./scripts/verify.sh
|
||||
```
|
||||
|
||||
本地启动 Web UI:
|
||||
Run the disposable six-service integration stack with a deterministic fake
|
||||
model provider and exercise registration approval, both Agent loops, workspace
|
||||
isolation, and the one-way mode upgrade with:
|
||||
|
||||
```bash
|
||||
bash scripts/start-webui.sh
|
||||
./scripts/verify-e2e.sh
|
||||
```
|
||||
|
||||
默认地址:
|
||||
The E2E stack and its test-only volumes are removed on exit. Set
|
||||
`E2E_KEEP_STACK=1` only when you need to inspect the running containers.
|
||||
|
||||
```text
|
||||
前端:http://127.0.0.1:3000
|
||||
后端:http://127.0.0.1:8765
|
||||
```
|
||||
|
||||
`scripts/start-webui.sh` 会优先读取 `.env.deploy`,也可以直接使用当前 shell 里的环境变量:
|
||||
Audit every finished service and workspace image, requiring consistent Python
|
||||
environments, zero known Python vulnerabilities, and zero fixable
|
||||
High/Critical image vulnerabilities, with:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY="..."
|
||||
export OPENAI_BASE_URL="http://model.mify.ai.srv/v1"
|
||||
export OPENAI_MODEL="tongyi/deepseek-v4-pro"
|
||||
./scripts/audit-images.sh
|
||||
```
|
||||
|
||||
停止本地 Web UI:
|
||||
## Deployment
|
||||
|
||||
```bash
|
||||
kill $(cat .port_sessions/webui-frontend.pid) $(cat .port_sessions/webui-backend.pid)
|
||||
```
|
||||
Production uses immutable `linux/amd64` images in
|
||||
`docker.k1412.top/wuyang/*`, an Unraid Compose Manager project, private
|
||||
service networking, and a single public HTTPS entry at
|
||||
`https://agent.k1412.top`.
|
||||
|
||||
## 部署和更新
|
||||
See [docs/architecture.md](docs/architecture.md) and
|
||||
[docs/security.md](docs/security.md).
|
||||
|
||||
### 首次部署
|
||||
## Open WebUI attribution
|
||||
|
||||
推荐把应用部署在用户目录,不需要把代码放到 `/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 服务。
|
||||
|
||||
如果要启用“平台账号 = Linux 用户”的托管工作区,需要使用 root/systemd system 服务部署:
|
||||
|
||||
```bash
|
||||
cd "$HOME/zk-data-agent"
|
||||
sudo -E env PATH="$PATH" bash scripts/deploy-ubuntu.sh main --system-service --enable-linux-accounts
|
||||
```
|
||||
|
||||
启用后:
|
||||
|
||||
- 平台注册/登录账号时会同步创建同名 Linux 用户。
|
||||
- 平台密码会同步设置为 Linux 用户密码。
|
||||
- Linux 用户允许 SSH 登录。
|
||||
- 本机托管工作区会使用 `/home/<account_id>/zk-agent/`。
|
||||
- `python_exec`、`python_package`、`bash` 会在对应 Linux 用户身份下执行。
|
||||
- Jupyter 远程工作区保持现有逻辑,不参与本机 Linux 用户隔离。
|
||||
|
||||
`.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_SERVICE_SCOPE
|
||||
CLAW_ENABLE_LINUX_ACCOUNTS
|
||||
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
|
||||
```
|
||||
|
||||
root/system 服务更新:
|
||||
|
||||
```bash
|
||||
sudo -E env PATH="$PATH" bash scripts/deploy-ubuntu.sh main --system-service --enable-linux-accounts
|
||||
```
|
||||
|
||||
部署指定分支:
|
||||
|
||||
```bash
|
||||
bash scripts/deploy-ubuntu.sh main
|
||||
```
|
||||
|
||||
强制覆盖服务器工作区:
|
||||
|
||||
```bash
|
||||
bash scripts/deploy-ubuntu.sh main --force
|
||||
```
|
||||
|
||||
### 服务管理
|
||||
|
||||
部署脚本默认安装用户级 systemd 服务;以 root 执行或指定 `--system-service` 时安装 system 级服务。服务名默认是:
|
||||
|
||||
```text
|
||||
zk-data-agent-backend
|
||||
zk-data-agent-frontend
|
||||
```
|
||||
|
||||
查看状态:
|
||||
|
||||
```bash
|
||||
systemctl --user status zk-data-agent-backend
|
||||
systemctl --user status zk-data-agent-frontend
|
||||
```
|
||||
|
||||
system 级服务使用:
|
||||
|
||||
```bash
|
||||
systemctl status zk-data-agent-backend
|
||||
systemctl status zk-data-agent-frontend
|
||||
```
|
||||
|
||||
查看日志:
|
||||
|
||||
```bash
|
||||
journalctl --user -u zk-data-agent-backend -f
|
||||
journalctl --user -u zk-data-agent-frontend -f
|
||||
```
|
||||
|
||||
system 级日志使用:
|
||||
|
||||
```bash
|
||||
journalctl -u zk-data-agent-backend -f
|
||||
journalctl -u zk-data-agent-frontend -f
|
||||
```
|
||||
|
||||
重启服务:
|
||||
|
||||
```bash
|
||||
systemctl --user restart zk-data-agent-backend zk-data-agent-frontend
|
||||
```
|
||||
|
||||
system 级重启使用:
|
||||
|
||||
```bash
|
||||
systemctl 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`
|
||||
- 启用 Linux 账号工作区时,还需要 `passwd`、`python3`、`python3-venv`,并要求服务以 root/systemd system 方式运行。
|
||||
|
||||
首次安装如果缺 Python 编译依赖,可以执行:
|
||||
|
||||
```bash
|
||||
bash scripts/deploy-ubuntu.sh --bootstrap-system
|
||||
```
|
||||
|
||||
`--bootstrap-system` 会使用 `sudo apt-get` 安装系统依赖;普通模式下应用代码、虚拟环境、前端依赖、运行数据和 systemd 用户服务仍然位于当前用户目录。启用 `--enable-linux-accounts` 后,账号工作区位于 `/home/<account_id>/zk-agent/`。
|
||||
|
||||
## 开发验证
|
||||
|
||||
后端基础校验:
|
||||
|
||||
```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 目录。
|
||||
The web service is derived from Open WebUI v0.9.6. Open WebUI's copyright,
|
||||
license, name, and user-facing attribution are retained. See
|
||||
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
||||
|
||||
Reference in New Issue
Block a user