Files
AgentLab/docs/zh-CN/development.md
T
ThearchyHelios 2714890d0d 文档重新梳理:README 精简成介绍和索引,细节按主题拆进 docs/zh-CN 与 docs/en(17 篇一一对应),英文文档不含中文
README.zh-CN.md / README.md 只留:这是什么、为什么用它、主要功能(按领域一行一条,链到文档)、快速开始、部署、文档索引、
开发与测试、许可(原文不动)。原来的每一节按读者和任务分到 17 篇主题文档:ask-data、workflows、evidence、
data-sources(新增:接入数据库、只读保证、上传表格、跨库合并、遮罩列)、data-catalog、tools(新增:工具、审批档位、
能力登记、端点、网络规则——它们管所有工作流,不只应用)、apps、evaluation-and-ledger、schedules(含通知)、deployment、
configuration、postgresql-and-scaling、identity-and-security、architecture、development、upgrade-notes(按时间倒序,
每波先写要做的事)、faq。删掉的只有模块名(api/copilot_gen.py、chat/drive.py、data/schema_view.py)、重复的话和
「以前…现在…」的叙述;操作步骤、命令、配置名、限制、权限边界都有归宿。中文是原文,英文按新的中文写;英文里界面文字
只写英文名,开头注明界面目前只有简体中文,中文占位符换成英文占位符,中文数字的例子改成不依赖中文的说法。
数据剖析可以同时剖析 2–3 张表(baf23998)收进 data-catalog。
新增 scripts/check-docs.py:英文文档(README.md、docs/en/**)不许有中日韩字符和全角符号(代码块也算),
README、docs/**、deploy/README.md 的相对链接和锚点都要通,docs/zh-CN 与 docs/en 文件一一对应、标题层级相同。
中文提示里指向 README 章节的地方改指新文档:cluster/guard.py、cluster/version.py、db/base.py 两处报错,
data/schema_view.py 文档串,.env.example 三处,scripts/prod.sh、scripts/test-postgres.sh,terms.ts 两处、
DataSourcesTab.tsx、check-manage.mjs 注释,deploy/README.md 三处链接。deploy/agentlab.env 未动。
验收:check-docs 0 问题(英文文档 18 个 0 处中文,相对链接 369 条 0 断链,18 对标题层级一致);相关后端测试
117 通过、7 跳过;tsc -b、check-copy 通过。
2026-10-21 10:23:26 +08:00

163 lines
12 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.
[English](../en/development.md) | 简体中文
# 开发
这篇讲本地开发:环境、启动、目录结构、依赖与锁文件、测试和检查脚本。给改代码的人看。系统为什么这样设计见[架构与设计决策](architecture.md)。
## 开发环境
- 需要 conda([miniforge](https://conda-forge.org/miniforge/) 即可)、Node 20+、pnpm。
- **不需要 Docker**:代码沙箱基于操作系统自带的隔离原语,可选升级到 microVM(见[配置](configuration.md#启用-microvm))。
- 不配 API Key 也能完整体验:内置的 Mock provider 会把编排链路完整走一遍(见[配置](configuration.md#模型接入))。
## 启动
```bash
conda env create -f environment.yml # 首次:创建 agentlab 环境并安装依赖
./scripts/dev.sh # 之后:一条命令启动前后端
```
- 打开 http://localhost:5273 。
- `dev.sh` 自动找 `agentlab` conda 环境,不存在时按 `environment.yml` 创建。要用别的环境名,设 `AGENTLAB_CONDA_ENV`。
- 端口:前端默认 5273、后端 8000,用 `AGENTLAB_WEB_PORT` / `AGENTLAB_PORT` 改。
- `--host`:前端监听所有网卡,启动时打印局域网地址,同一网络里的手机、别的电脑也能打开。后端仍只听 127.0.0.1,页面里的 `/api` 由前端开发服务器在本机转发。默认不开登录,只在信得过的网络里这样用(见[登录方式](identity-and-security.md#登录方式))。
- `--postgres`:应用库用 PostgreSQL,本机 docker 起一个开发用的库(见[和库一起起](postgresql-and-scaling.md#和库一起起))。
- 认不出的参数直接报错,`./scripts/dev.sh --help` 看用法。
- `dev.sh` 开着热重载:改一个后端文件就是一次服务重启,正在跑的运行显示中断,断点完好,可以接着跑(见[断点续跑](workflows.md#断点续跑))。
## 目录结构
```
backend/ FastAPI + LangGraph
app/engine/ 画布 JSON → StateGraph 的编译与执行
schema.py 图定义与静态校验
compiler.py 编译:节点包装、事件、重试、条件路由
runner.py 执行调度、事件总线、中断与恢复
issuance.py 出具契约:数字回指与三档判定
evidence.py 可点击证据:证据台账、引用标记、报告文档的切块与核对(纯函数)
judge.py 结论句裁判:预筛、成本上限、判定写回
governance.py 发布门禁:受管 lint 与证据门禁 G1–G5
autofix.py 发布前自动修复;upgrade.py 一键升级为可追溯结构
guards.py agent 护栏:重复调用、预算、上下文压缩
review.py 产出复核:事件流规则扫描 + 模型复核
expressions.py 模板插值 + AST 白名单表达式求值
nodes/ 各类节点的执行器(report.py 是报告撰写)
app/data/ 数据源接入:连接、SQL 守卫、结构探查、表格导入
app/providers/ 多模型接入与成本估算
app/sandbox/ microVM / Seatbelt / bubblewrap / 裸子进程四后端
app/tools/ 工具注册表、内置工具、MCP、自定义工具
app/memory/ 记忆、知识库、倒排索引、混合检索、文档解析
app/api/ REST + WebSocket(证据接口在 evidence.py)
frontend/ React 19 + React Flow + Zustand
src/canvas/nodeDefs.ts 节点元数据——属性面板、节点库、连接桩均由其驱动
src/canvas/routing.ts 连线走线:端口错开、走廊车道、长边绕行
src/run/decode.ts 事件流 → 人类可读步骤的唯一翻译层
src/run/EvidenceDoc.tsx 报告逐段渲染:数字、名字、原话都是可点的片段;EvidencePanel.tsx 是出处链
src/store/studio.ts 画布状态 + 事件流到高亮的映射
environment.yml conda 环境定义
scripts/dev.sh 一键启动
scripts/check-all.mjs 前端检查的总入口:分道并行跑全部 check-*.mjs,汇总成一张表
```
## 依赖与锁文件
- `backend/pyproject.toml` 写版本范围,`backend/requirements.lock` 写精确版本:后端全部依赖(含间接依赖、全部 extras)锁在测试跑过的那一套上,跨平台通用。
- `environment.yml` 装包时以锁文件为约束,所以换一台机器装到的也是同一套,不是当天的最新版。
- LangGraph / LangChain 一族在 `pyproject.toml` 里只放行到下一个小版本:引擎直接依赖它们的断点格式、interrupt / resume 和流式事件,这些在小版本里也改过行为。
- 断点格式本身在 `langgraph-checkpoint` 里(langgraph 只要求它 <5,所以单独卡住)。SQLite、PostgreSQL 两个断点库(`langgraph-checkpoint-sqlite`、`langgraph-checkpoint-postgres`)都按它读写;`copy-to-postgres` 能搬断点,也靠两边是同一版格式。
- `langgraph-checkpoint-postgres` 从 3.1.3 起要 `langgraph-checkpoint` 4.3,所以锁在 3.1.2;升级时三个一起动。
- aiosqlite 与 SQLAlchemy 同理:`db/base.py` 给 aiosqlite 打了补丁,连接池断开连接时会走到它。应用库换成 PostgreSQL 之后补丁照样打着,因为上传表格、手工登记的 SQLite 数据源还走 aiosqlite。
- `[postgres]` 里是应用库用 PostgreSQL 时要的:SQLAlchemy 这边走 asyncpg(和 `[db]` 里连业务库的是同一个包),断点库走官方的 `langgraph-checkpoint-postgres`,它只认 psycopg 3 和 `psycopg-pool`。psycopg 带 `[binary]`:wheel 里自带 libpq,镜像和本机都不用另装 PostgreSQL 客户端。
### 可选依赖
`environment.yml` 默认已经全部装上。单独补装时带上锁文件,版本才和测过的一致:
```bash
pip install -e 'backend[docs]' -c backend/requirements.lock # PDF / Word / PowerPoint / Excel 解析
pip install -e 'backend[db]' -c backend/requirements.lock # MySQL / PostgreSQL / Oracle 驱动
pip install -e 'backend[microvm]' -c backend/requirements.lock # microVM 沙箱
pip install -e 'backend[postgres]' -c backend/requirements.lock # 应用库用 PostgreSQL(asyncpg、psycopg 3、官方断点库)
pip install -e 'backend[dev]' -c backend/requirements.lock # pytest
```
### 升级依赖
升级依赖要主动做,改完跑一遍测试再提交:
```bash
./scripts/lock-deps.sh --upgrade-package langgraph # 升一个包(连带它必须跟着动的)
./scripts/lock-deps.sh --upgrade # 全部升到 pyproject 允许的最新
./scripts/lock-deps.sh # 只加了新依赖:补上它,已锁的不动
pip install -e 'backend[microvm,dev,db,docs,postgres]' -c backend/requirements.lock # 装到当前环境
```
重新生成锁文件需要 [uv](https://docs.astral.sh/uv/);装依赖本身只用 pip。
## 测试
```bash
# 后端:约 14300 个测试,-n auto 并行约 1–2 分钟
cd backend && env -u ANTHROPIC_API_KEY -u ANTHROPIC_BASE_URL -u ANTHROPIC_AUTH_TOKEN -u OPENAI_API_KEY \
python -m pytest -n auto
# 前端类型检查
cd frontend && npx tsc -b
# 应用库换成 PostgreSQL 跑同一套后端测试(起临时的 postgres:16 容器,跑完删掉)
PYTHON=$(conda run -n agentlab which python) ./scripts/test-postgres.sh
```
- pytest 前面的 `env -u` 不能省:没配 Key 的 provider 会退回环境变量里的密钥,启动时的 seed 也会拿它种一个 provider。环境里留着真密钥,测试就可能真的去调接口。
- PostgreSQL 和多进程的测试细节见 [PostgreSQL 与多进程](postgresql-and-scaling.md#测试)。
### 验收用的假外部系统
```bash
python scripts/fake-erp.py --port 8765
```
它可以切换「正常 / 写成功后超时 / 500 / 4xx」,用来验收写外部系统的各种结果;接口见脚本开头。
## 前端检查
```bash
# 43 项,默认 8 道并行。连 5273 / 8000,先起 ./scripts/dev.sh
node scripts/check-all.mjs
# 另起 2 套只给检查用的「后端 + vite」,各用一份数据拷贝,约 6.5 分钟;边改代码边跑也不被打断
CHECK_DATA_SRC=<数据目录> node scripts/check-all.mjs --stacks 2 --lanes 12
# 只跑某几项(名字去掉 check- 前缀)
node scripts/check-all.mjs evidence publish
```
- 完整输出写进 `/tmp/agentlab-checks/<时间>/`,终端只给汇总。并行时没过的,最后单独重跑一遍;重跑才过的单列成「偶发」。
- `--stacks` 每套拷一份数据、端口自动挑空闲的;后端不热重载、vite 不监听文件;跑完、出错或被中断都收干净。`--stacks` 只支持 SQLite。
- `scripts/e2e-check.mjs` 真发起一次运行(Mock,不花钱),会在库里留下记录,所以不在 check-all 里。
- `scripts/check-auth.mjs`(登录、按角色收起的导航、401 跳登录)要另起一套开着本地账号登录的服务单独跑,也不在 check-all 里。
`check-all` 的 43 项按 `scripts/check-all.mjs` 里 `ORDER` 的顺序排:
| 类别 | 检查 |
|---|---|
| 不开浏览器 | `tokens`(设计令牌的静态扫描)`copy`(界面文案)`trace`(运行态内核的纯函数)`decode`(事件翻译层) |
| 走线、组件与护栏 | `canvas-layout` `ui-kit` `guards` |
| 外壳、回答流与运行态 | `shell` `stream` `evidence`(可点击证据)`run-states`(节点卡)`canvas-fx`(画布表层) |
| 各页面 | `studio` `publish`(发布前检查与自动修复)`chat` `runs` `manage` `versions`(上传表格的版本)`catalog`(数据目录)`catalog-loop`(表助手、审阅队列、导出导入)`catalog-profile`(数据剖析的逐表任务)`catalog-changes`(变化、表详情的变化一节、定时维护、后台任务条)`ui`(端到端,连真数据) |
| 复核套件与导出 | `schedules`(定时任务)`compare`(运行对比)`verify`(双盲复算、反方审稿)`inquiry`(审批质询)`challenge`(反方审稿)`bundle`(可验证报告)`whatif`(数字推演)`report-export`(报告导出) |
| 评测与口径账本 | `evals`(题集、加题、发起与进度、结果、对比与 A/B、口径命中与重复度)`ledger`(证据里的「口径」一步、轮次摘要、出具与对账、可沉淀的问题) |
| 应用平台 | `apps`(应用页、印章、点数字看出处、入口校验、实例页)`inbox`(会签进度、超时、动作确认的哈希卡、核实)`app-editor`(应用编辑、派生、检查、发布时选处置、助手)`capabilities`(能力、端点、身份、通知、审计)`access-keys`(访问密钥)`share`(分享链接与 /s 页)`blueprint`(新建应用、蓝图卡片、试运行、发布摘要)`personal`(个人应用)`records`(记录列表)`files`(文件控件) |
### 三层验证的分工
- `check-decode` 守「翻译对不对」,`check-stream` 守「画出来对不对」,`check-ui` 守「整条路走得通不通」。三者可以各自通过、合起来却是坏的:例如 Step 字段全部正确,组件却把它渲染成一屏转义的 JSON。
- `check-canvas-fx` 守「事件对了但界面没跟上」:把脚本化的事件灌进 store(走的是页面上那一份 applyEvent / NodeCard / FlowEdge,只有事件来源是脚本),断言协作矩阵真的长出来了、并行度算对了、条形长度和耗时成正比、分支命中的出口被点亮、系统关了动效时光效确实不绘制。真跑一张多 agent 的图要连模型、要等十几秒,而且撞不上「三个人同时还在跑」那一瞬间,那样的检查会变成偶发失败。
- `check-canvas-layout` 单独守「图好不好看」里唯一能算的那部分:它把夹具图交给后端 `/api/copilot/layout` 排版,再直接 `import('/src/canvas/routing.ts')`,用页面上正在跑的那份走线代码算路径,然后按几何断言:没有两条线压在同一段上、没有线从别人的卡片中间穿过去、每条线的两端都接在节点边缘。连线叠成一团时,`check-ui` 和 `e2e-check` 一个字都不会说。
## 文档检查
```bash
python3 scripts/check-docs.py
```
它检查三件事:`README.md` 和 `docs/en/` 下不许出现中文字符和全角符号(代码块也算);`README.md`、`README.zh-CN.md`、`docs/` 下全部文档和 `deploy/README.md` 里的相对链接和锚点都要通;`docs/zh-CN/` 和 `docs/en/` 的文件一一对应、每一对的标题层级相同。改文档后跑一遍。