Files
chenlin 0d986f60bd
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
feat: release v1.0.2 LeKiwi 语言控制与网站嵌入
集成服务器托管模型、自然语言移动与有界抓放、内置 LeKiwi URL 导入和双摄像头;同步部署契约与指定域名 iframe 白名单,保留原有物理安全、会话及调用预算防护。

更新 npm 包及锁文件版本、CHANGELOG 与发布文档。提交前 typecheck、120 项定向前端测试和 44 项后端测试通过(3 项可选跳过);真实 v2 云模型抓放仍待单独验收,不包含运行密钥或构建产物。
2026-09-24 15:29:49 +08:00

179 lines
22 KiB
Markdown
Raw Permalink 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.
# LeKiwi 语言控制与物理基线
## 当前版本:语言控制 v2(已部署,真实模型待验收)
网站已发布 `20260924T065821Z-language-v2`,公网非付费验证 3/3 通过;没有将部署/加载成功视为真实模型推理成功。[发布及回滚记录](lekiwi-language-v2-release.md)。
本地/网站统一为「控制台 → 机器人语言控制」,只保留预设、指令、执行/停止与简短状态。先点击**载入预设场景**,再输入:
- `把方块搬到 B 区`(A `[0.257,0.45,0.128]`,B `[0.257,0.75,0.128]`)。
- `把方块搬到 (0.25,0.50) 米`,或 `搬到 X=0.25 Y=0.50 Z=0.128`。
- 仍支持 `前进0.5米`、`左转90度`、`停止`。停止无需模型。
**坐标约定**:世界坐标、米、Z 向上;XY 根据真实支撑面补 Z,XYZ 的 Z 是方块中心而非台面。目标台允许输入的连续范围(不代表每个点都已做物理成功率评估)X `[0.237,0.277]`、Y `[0.365,0.865]`,Z `0.128`;另保留源台支撑区域。支持米/厘米/毫米,但不接受任意空间点、悬空目标、未知对象或相对坐标。单次持物搬运距离 `0.08–1 m`。底盘需处于预设净空走廊 X `[-0.06,0.04]` / Y `[-0.12,0.95]`、初始航向误差 ≤0.15 rad,超出时明确拒绝而非通用导航。
只有“载入预设”会重建场景;执行不重置方块、不移动支撑台,支持从上次放置后的实测位置再次搬运。空工作台点击加载可校验并导入内置机器人;替换其他工程需确认。地图/RL 和双摄像头保留。旧面板的配置、mock、单技能/导出按钮已移除;诊断通过只读 `robot-task-result` 事件采集,不提供仿真写句柄。旧 v1 物理/API 夹具保留,不代表旧产品界面仍存在。
### 分层实现
- **LLM 任务层**:`/command` 解析受限意图与目标,`/plan` 给出带前置条件的合法技能链。两次请求共用 run/scene 身份与预算;后端配置模型,见 [本地启动](../decision_server/README.md)。没有服务时明确报错,不转 mock。
- **Jev 监督层**:`TaskSupervisor` 消费一次多问题请求中的 Choice(合法切换)、Noul(allow/deny/uncertain)、Score(离散等级)。等级 poor/partial/good/excellent 映射 0/25/75/100,unavailable 不评分;它是**最近技能边界**的模型意见,不是概率或终局物理成功。为减少调用,本轮不增加可选终局评分请求。
- **执行层**:`TaskPlanner` 根据实测状态计算停靠位并以 scratch IK 预检;`PickPlaceExecutor` 复用限速伺服/技能与物理证据,添加收臂/接近阶段。正常夹爪—台面接触仅在指定抓放阶段、底盘速度 ≤0.03 m/s、总力 ≤20 N 时允许;其他外部碰撞停止。这是仿真阈值,不是实机安全认证。
- **底层**:原 MuJoCo 位置/速度伺服与唯一 `SimulationSession` 时钟,不引入 ROS2/MoveIt2,不瞬移物体、不焊接吸附。等待模型冻结物理,迟到响应、取消和硬安全不能被模型覆盖。
### 本轮精简验收
- 主工作台真实 WASM+同源网关+**假 HTTP 模型上游**连续两次成功:B 区有效搬运 **0.728882 m**、误差 **7.54 mm**;自由坐标有效搬运 **0.241201 m**、误差 **8.92 mm**。每任务 2 次 LLM / 14 次 Jev(含意图审核),Score=75 来自明确假上游,不是真实模型能力证明。证据:`build/e2e/lekiwi-language/`。
- 20 个停靠位/高度 scratch IK 检查与真实夹爪锁开失败用例通过;锁开为 `empty_grasp`、搬运 0、成功 false。证据:`build/e2e/lekiwi-language-safety/`。
- 原 v1 种子 0 基线通过,搬运 0.593793 m;网站构建移动/转向/停止两用例通过。证据:`build/e2e/lekiwi-language-v1-regression/`、`build/e2e/lekiwi-language-website-smoke/`。
- 定向前端 13 文件 / 83 测试通过;Python 29 项中 28 通过、1 个既有可选项跳过;typecheck、定向 lint、双构建通过(保留大 chunk 提示);未跑全仓/训练/多种子耐久。实现验收未读取真实密钥、未调用真实 LLM/Jev;随后已按用户要求部署,沿用服务器凭据,公网仅做非付费验证。真实模型需后续用服务器配置明确授权验收,不能引用下方历史结果当作 v2 通过。
## 以下为 v1 历史记录(旧界面与旧验收)
当时计划 **10/10 已完成**。自动回归、物理故障与真实双 API 回合已通过;用户明确确认以 **DeepSeek `deepseek-flash` + OpenRouter `typesafe/jev-1.13` 的主工作台真实抓放**作为最终验收,不再要求本次订阅推理回合。仅仿真,不控制实机。
ChatGPT 隔离官方登录已确认成功,未发现隔离 HOME 中的 `auth.json`,没有读取全局登录。订阅浏览器用例在模型请求前因选择器未匹配而中止(已为协议/型号下拉框补充显式可访问名称);用户随后要求结束验收,因此**未运行订阅推理**,不能宣称订阅抓放成功。该临时会话已关闭,LLM/Jev 请求均为 0。记录:`build/lekiwi-agent/subscription-login-only.json`;失败用例保留于 `build/e2e/lekiwi-agent-subscription-first/`。
## 网站模式补充
网站版不再填写本机地址或服务令牌。在“模型设置”中填写自己的 DeepSeek/OpenRouter LLM API_KEY/型号与独立 Jev OpenRouter API_KEY;也可选 ChatGPT 订阅,走官方设备码登录。订阅网络/账号不可用时明确提示,不自动转付费 API。网站暂不开放 RL 训练和调参,本地模式继续保留。
网站生产构建已通过真实同源后端/假 HTTP 上游与双浏览器隔离测试,并完成一次显式 mock 的真实 WASM 抓放与证据导出;这不是此次云端真实 API/订阅推理验收。后续真实验收需用户提供测试凭据/完成官方登录。见 [网站部署](website-deployment.md)。
## 主工作台使用
1. 导入 A ZIP,在 URDF 对话框选择 `lekiwi-v1`,然后打开「控制台 → LeKiwi 智能抓放」。缺资产会报错,不下载/替换机器人。
2. 点击「加载 A 任务场景」,初始为显式 mock(不调用 API)。开始、任务级暂停/继续、单技能步进、停止、重置和证据导出都在同一主视口。全局暂停/隐藏/拖动会取消任务,不等同于可继续的任务级暂停。
3. 目标可在暂停后用米制 X/Y 编辑;首版范围 X `[0.237,0.277]`、Y `[0.565,0.665]`,Z 固定 `0.128`。修改后开始会重新载入方块/支撑台并启动新回合,不复用旧计划。范围编辑仍属受限实验,不等于已验证任意位置。
4. 真实模式先启动本机服务,再展开「模型连接与官方订阅登录」,输入服务终端显示的临时令牌。仅连接/读取配置不推理;测试连接和开始真实任务可能计费。选 API 或官方 Codex 均需显式保存型号/协议,不自动换模型。修改草稿后禁止继续使用旧付费连接运行/测试,保存后才重新启用;保存会刷新两角色的服务配置。
```bash
source .venv/bin/activate
npm run decision-server -- --openrouter-env .env --deepseek-env .env
# 另一个终端:npm run dev
```
这两个可选参数只按授权读取根 `.env` 的 OpenRouter Jev 与 DeepSeek key,固定 `typesafe/jev-1.13` / `deepseek-flash`;不是订阅登录失败后的自动回退。也可不传参数,在界面临时输入自己的 API 配置;换 URL 必须重新输入密钥。Codex 需固定 0.147.0,可在界面发起官方登录、取消、退出、刷新账号/可见型号/官方配额;CLI/门禁/账号任一步不可用都明确报错。
界面展示计划、当前技能、Jev 判断、双指力/支撑/搬运历史、调用数、墙钟/仿真时间、服务报告 token/部分费用。证据导出不包含密钥、服务令牌或认证地址;重置前请先导出当前回合。地图草稿与后台训练作业保留,进入 RL 则重新载入 RL 场景。
首个主工作台 mock 端到端测试通过:真实文件导入 → 单技能暂停 → 继续 → 独立物理成功 → JSON 导出 → 场景重置。证据:`build/e2e/lekiwi-agent-workbench-first/`;初版截图发现支撑台因默认碰撞组被隐藏,已显式放入可见组,碰撞仍保留;修复后主视口同一完整回合复测通过,截图与证据保存在 `build/e2e/lekiwi-agent-workbench-step9/`。生产构建已核对不含 `mobile.html`,保留 `tuning.html`;`/physics/mobile.html`、两变体 RL/ONNX 底层不删除。
## 第 10 步:真实回合、故障与回归
### 真实双 API(不是 mock 或订阅)
主视口已完成两次真实 API 回合,均为 **1 次规划 + 11 次 Jev 判断**,无回退、无网络自动重试。最新证据位于 `build/e2e/lekiwi-agent-final-gates/` 下的 `live-physical-evidence.json` 与 `live-workbench.png`:
- 仿真 **47.220 s**;任务墙钟 **73.271 s**,等待模型不推进仿真。
- 有效持物底盘平移 **0.593727 m**;目标误差 **0.007689 m**。
- 最终两指力均为 0,目标台支撑成立,末端撤离 **0.093133 m**。
- DeepSeek 最新报告 input/output **916/1101 tokens**,未报告费用,**不能记为 0**。
- Jev 11 次累计 input/output **15351/2194 tokens**,报告费用 **$0.000644742**;这不是包含 DeepSeek 的完整账单。
首次浏览器连接尝试在发起推理前失败:原生 `fetch` 被作为类成员调用触发 `Illegal invocation`。已改为使用全局 receiver,并增加单元回归。失败保留于 `build/e2e/lekiwi-agent-live-first/`,修复后首轮保留于 `build/e2e/lekiwi-agent-live-second/`,未用最后一次成功覆盖失败。
真实用例必须显式 opt-in;普通 CI 不读取 `.env` 或调用模型。测试服务在生产预算之外进一步限制为 **总计 1 次 LLM / 12 次 Jev**,临时服务令牌不写证据,关闭后销毁临时状态目录:
```bash
LEKIWI_LIVE_API=1 PLAYWRIGHT_HTML_OPEN=never npx playwright test \
-c web_platform/playwright.agent.config.ts lekiwi.agent.live.spec.ts \
--output build/e2e/lekiwi-agent-live-new
```
### 真实 WASM 故障(模型选择为显式 mock)
`build/e2e/lekiwi-agent-faults-final/` **10/10** 通过:
| 注入 | 实际结果 |
| ------------------------------ | ------------------------------------------------------------------------ |
| 夹爪持续锁开 | 3 次 `empty_grasp`,最多恢复 2 次,42.007 s 停止 |
| 一次空抓后移除故障 | 恢复 1 次,61.219 s 完成真实抓放 |
| 实际 IK 目标偏移 20 mm | 3 次 `alignment_timeout`,最多恢复 2 次 |
| 已搬运 12 cm 后渐进开爪 | `lost_grasp`,无重试,清除有效搬运历史 |
| 肩关节驱动锁定 | `joint_stall`,3.291 s 停止,无重试 |
| 驱动器目标突跳(模拟超速故障) | 首个 1 ms 子步检测 `joint_velocity` 后停止 |
| 轮驱动锁定 | `navigation_timeout`,40.004 s 停止,无重试 |
| 真实 scratch IK 求解不可达目标 | `unreachable`,未发出对应运动目标 |
| 两个受限目标角点 | `[.237,.565,.128]` / `[.277,.665,.128]` 均真实成功;非区域内全部位姿保证 |
注入只在非生产物理夹具中修改执行器输出或 IK 输入;不通过写物体 qpos、焊接或假反馈实现结果。恢复时从实测臂/夹爪位置重新初始化目标,避免故障解除后旧内部目标造成跳变。臂卡住保护采用版本化阈值:跟踪误差 ≥0.14 rad、实测速度 <0.02 rad/s 持续 0.75 s;不把正常夹爪接触阻挡当作臂卡住。
### 生命周期、资源与保留功能
- 最终 agent 门禁 **18/18**:原规则 5 种子、mock 5 种子、同一时钟基线、5 个迟到响应场景、8 次资源循环及上述真实 API。故意忽略 abort 的 mock 规划在任务暂停/全局暂停/停止/外力交互/模型重载后交付,真实 WASM 控制、qpos、时间均未变化,Jev 调用为 0。
- 8 次 A 全模型与 IK 加载释放:逐一核验 model、live data、scratch data、两 Jacobian buffer、接触 force buffer 共 48 个原生句柄均已删除。heap 容量为 **1143.19 → 1367.56 → 1567.75 MiB**,后 6 次保持稳定;不是保证 heap 缩小或无限次无泄漏。
- 主视口 mock、单技能、继续、成功、导出、重置、编辑目标后新 run、新源方块与旧计划失效通过:`build/e2e/lekiwi-agent-workbench-final/`。
- 从暂停中的 agent 场景切入真实 RL 训练、上传快照、导入 ONNX、继续训练通过;服务器的 `*.training.xml` 明确不含 `__agent_`:`build/e2e/lekiwi-agent-to-rl/`。短训练不是抓放收敛证明。
- 原主工作台/地图/调参/通用外控 **92 通过、6 个既有可选用例跳过**;完整 LeKiwi 原套件 **20/20**;两模型物理/ORT **2/2**。目录分别为 `lekiwi-agent-existing-workbench`、`lekiwi-agent-regression`、`lekiwi-agent-mobile-regression`。
- 最新 LeRobot 60 s / 30 Hz:1800 动作、57.596 s 仿真、RTT P95 27.593 ms、max 312.842 ms,超时/丢请求为 0;未放宽 500 ms 门槛。
- Vitest **129 文件 / 608 测试**、typecheck、TS/Python lint、生产 build 通过。决策服务 **28 项**(25 常规 + 3 单独启用的真实 CLI 离线门禁);训练服务 126 项中 102 通过/24 可选跳过;控制桥 16/16;隔离 MuJoCo 3.11 移动操作 Python 7/7。
最终汇总与 43 个关键源码文件的 SHA-256 位于 `build/lekiwi-agent/final-verification.json`。源码/证据扫描未匹配到根 `.env` 两个已授权角色的真实 API key(不打印密钥值或其指纹)。最新两机器人训练快照还通过原生 MuJoCo 3.11 的 12 步对照:A 的 qpos 最大误差约 `5.67e-9`,bundle 约 `3.09e-6`,不声称长轨迹逐位相同。
全仓格式检查仍仅被四个原有文件阻塞:两份 `.pytest_cache/README.md` 与 `contracts/fixtures/{mobile-golden,mobile-motion-v2-golden}.json`,未擅自改写。真实账号配额不足/型号推理资格与订阅回合仍未验证;本次用户已接受该边界,不阻塞已完成的 API 验收。将来验证订阅需重新建立隔离会话,不使用现有全局 Codex 登录代替,也不回退到 API 付费。
## 已验证的 A 基线
资产固定为 `build/lekiwi/lekiwi-v1.zip` / `lekiwi-v1`,不是 Link1–Link4 bundle。完整轮网格与性能边界见 [网格说明](lekiwi-mesh-compatibility.md)。
`contracts/lekiwi-pick-place-v1.json` 冻结了当前空旷平地任务:36 mm 方块、110 mm 支撑面、两个支撑台沿 Y 相隔 600 mm、5 个 ±2 mm 的小扰动种子。不是任意桌面高度、任意物体位姿、障碍导航或广泛随机化的成功率。
- `PickPlaceScene.ts` 在任务专属场景中组合物体/目标/支撑台,保留旧 RL 契约及其 EEF site;新增 `__agent_tcp` 是经 CAD 指端位置标定的抓取点。
- `LeKiwiIK.ts` 用独立 scratch `MjData`、`mj_jacSite`、阻尼最小二乘求解五臂轴的位置和竖直接近方向,不假设能满足任意六维姿态。明确释放 scratch 和 Jacobian buffers。
- `DeterministicBaseline.ts` 只发限位、限速/限加速度的执行器目标;不自行建物理循环、不调用模型、不使用 RL 的 `manual=true/hasLifted` 绕过训练门控、不修改物体 qpos、无焊接/吸附。
- `PhysicalEvidence.ts` 每物理步汇总两侧分别与物体的接触法向力、支撑、速度和位姿;同一侧多个凸包不能冒充两侧。结合试抬和相对稳定验证抓持,只累计抓持有效期间的底盘平移。放置同时要求历史搬运、目标误差、释放、撤离和持续支撑;重复/冻结观测不能累加稳定时间。
真实 WASM 5/5 结果:每回合约 47.24 秒仿真时间、持物平移 0.5938 m、最大臂/夹爪关节速度约 0.5801 rad/s;最终误差约 8 mm、无指面接触、支撑成立、末端撤离超过 9 cm。原生 MuJoCo 曾先行完成一次标定探索,不把该探索替代浏览器验收。
```bash
npx playwright test -c web_platform/playwright.agent.config.ts --output build/e2e/lekiwi-agent-baseline
```
证据在各用例的 `physical-evidence.json` / `governed-baseline.json`。它们包含 50 Hz 控制级轨迹;评估器和速度保护在 1 ms 物理子步运行。没有 RL 训练收敛或真实模型调用的声明。
## 契约与控制边界
- `contracts/lekiwi-agent-v1.schema.json`:有界具名 SI 观测、计划、Jev 选择/分类/诊断、技能结果;观测明确标注 `mujoco-ground-truth`,非视觉识别。
- `protocol.ts` 使用本版本 schema 的有限子集校验器,拒绝未知字段/对象/技能、非有限数字、越界坐标、跳过物理前置阶段与循环计划。模型文本不变成代码或文件路径。
- `RequestGate.ts` 对 run/scene/sequence/plan/request 标识逐项校验,取消、替换和超时立即拒绝;提供者忽略 AbortSignal 也不能把迟到结果重新交付。
- `SimulationSession` 新增 `agent` 所有者。写入能力只在当前票据对应的同步物理回调或安全保持中有效;网络回调直接写入会被拒绝。等待期间冻结并丢弃墙钟积压,暂停/reset/控制切换/重载使旧能力失效。
- 带动态方块的场景不能冒充“唯一浮动根”的 LeRobot 外控模型;agent 使用现有移动操作环境进行绑定/安全保持,并独占原 `SimulationSession` 物理时钟,不启动第二个 `RobotManager`。真实 agent 所有者路径已经完成一轮同一基线。
步骤 8 的单元门禁已在第 10 步复跑;最新数量、真实回合、物理故障及残余边界见上文,不把 mock、真实 API 和订阅证据混用。
## 第 8 步:有界异步闭环
`AgentTaskController` 编排 LLM → Jev → 已验证的本地技能 → 物理观测。Promise 只能填充邮箱,在下一次 `SimulationSession` 同步写入窗口应用;等待时冻结物理,旧响应、暂停/取消、重载后不可继续执行。支持任务级暂停/继续/单技能步进,区别于全局暂停取消任务。
- ungated `DeterministicBaseline` 保留冻结基线;gated 模式逐技能等待授权,重新检查停车、TCP/物体对齐、双指力、试抬、运输历史、支撑和释放。
- 每技能最多 2 次恢复、每回合 2 次重规划/3 次 LLM/60 次 Jev,20 分钟墙钟及原 70 秒仿真期限;取消请求也计入前端次数,服务端另有并发/小时限额。重规划不能重置恢复计数或搬运历史。
- 只允许源位置附近、仍被支撑且静止的空抓/对齐失败重新开爪、对齐和抓取。滑落、关节超速、不可达、底盘异常等硬失败立即保持/停止,不询问模型放行。LLM 要求重规划时,Jev 的重试建议只能升级为重规划,不能直接重试。
- `DecisionClient` 仅访问本机网关;取消同时 abort HTTP 和指定服务端请求,取消先于 POST 到达也留下有界拒绝记录。凭据不写浏览器存储,无真实 API → mock 降级。`MockDecisionProvider` 只供显式测试模式。
- Jev 的 `secure` 与本地证据矛盾即拒绝;搬运要求双方一致。最终成功仍由 `PickPlaceEvaluator` 决定,不采信模型或技能的自报结果。
`build/e2e/lekiwi-agent-step8/`:11/11 真实 WASM 用例通过(5 个原始基线、5 个 mock 决策闭环、1 个 agent 所有权基线)。mock 闭环每回合 1 次规划、11 次判定,47.217–47.221 秒仿真、持物平移 0.59371–0.59375 m,释放/支撑/撤离均通过。此批**未调用真实模型**。单元测试覆盖有限恢复/重规划、预算、硬停、非法选择、401/超时、过期响应和物理成功否决;后续真实物理故障结果见第 10 步。
## 第 7 步:模型服务与单请求验证
新增 `decision_server/`,配置、接口、安全限制、费用及真实单请求证据见 [服务说明](../decision_server/README.md)。OpenRouter Jev 和经用户确认的 DeepSeek `deepseek-flash` 早期均用合成契约输入完成真实单请求;这些早期探针本身不是完整回合,后续真实主视口回合见第 10 步。
Codex 已实现官方 stdio 的登录/取消/退出、账号/模型/额度、结构化规划与中断;固定 0.147.0,独立临时 HOME、仅会话 OAuth。当前 5 个可见模型在匹配目录的受限配置下,均通过空工具表与 4 类强行工具调用拒绝测试;真实 stdio 假推理也验证了最终结构化计划和线程释放。真实 ChatGPT 隔离登录后来已确认成功;订阅推理未运行,未冒充通过。
### 早期探测记录(保留失败与改进过程)
本机为 `codex-cli 0.147.0`。使用独立临时 `HOME/CODEX_HOME/cwd`、清理后的进程环境和回环假 Responses 服务,未读用户已有登录、未登录、未调用真实模型或消耗 API 额度:
1. 单独关闭 shell、unified exec、多 agent、插件,并设 read-only/never approval,仍会暴露 `update_plan`、`request_user_input`、`apply_patch`、`view_image`。**不能以 read-only 声称禁工具。**
2. 再关闭 `tools.update_plan.enabled`、`tools.experimental_request_user_input.enabled`、`features.view_image`,并使用与 0.147.0 匹配的模型目录将 `apply_patch_tool_type` 设为 null,离线请求的 `tools` 为空。
3. 假服务强行注入 `apply_patch` 调用,CLI 返回 `unsupported custom tool call: apply_patch`,未生成探针文件。
这段早期实验本身不是订阅登录或真实可用模型证明。探针使用的 `gpt-5.4` 在该目录标为隐藏/退役,**不可把它作为默认可用订阅模型**。后续实现已结合官方 `account/read` / `model/list`、匹配版本目录与逐模型门禁,保持现有登录隔离;失败时明确不可用且不得转收费 API。当前默认/API 提供者是用户显式授权的选择,不是 Codex 静默回退。
离线原始证据及探针副本位于 `build/lekiwi-agent/codex-capability/`;临时源码路径只是实验用途,不能作为生产服务启动入口。
Sources:
- [Codex 0.147.0 配置 schema](https://raw.githubusercontent.com/openai/codex/rust-v0.147.0/codex-rs/core/config.schema.json)
- [版本匹配的模型目录](https://github.com/openai/codex/blob/rust-v0.147.0/codex-rs/models-manager/models.json)