lazyBoy/docs/agent-experience.md

126 lines
9.4 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.

# AI 使用體驗
[← 回到 README](../README.zh-TW.md)
這份文件記錄 LazyBoy 怎麼讓「AI 用電腦」這件事變得跟人一樣順,以及背後的取捨。
三個主題其實是同一件事:系統如果把 AI 使用電腦當成一系列無狀態的請求AI 就必須每輪重新
交代自己在哪裡、在做什麼,界面也只能用輪詢去猜現在發生了什麼。
| 主題 | 一句話 | 細節 |
| --- | --- | --- |
| 任務長度 | 沒有輪數額度,只有偵測鬼打牆的保險絲 | [輪次政策](./operations.md#任務跑多久輪次政策) |
| 容器內終端機 | 一台活的 tmux人和 AI 看同一個 shell | [終端機](./operations.md#容器內終端機) |
| 聊天即時性 | 事件推送,輪詢只是兜底 | 本文件下面 |
## 輪數不是額度,是偵錯工具
### 交代一次,持續執行
清楚的工作指令直接開工,不預設要求使用者確認計畫。模型請求不設 60 秒總時限,也不定時發送等待提示。首次動作最多補上一句開工說明,之後只在重要階段、改變方法或遇到阻礙時簡短回報;一般工具呼叫不逐一播報。實際發生模型重試時更新同一個狀態位置,新的輸出會清除提示。
Worker 在模型與工具等待期間,每 10 秒更新背景心跳並延長執行租約,不產生聊天訊息。綠點以最近 30 秒內的心跳為依據,失去心跳時前端不能用舊的串流文字覆蓋失聯狀態。綠點表示 worker 存活,不聲稱任務已有進展。真實的供應商錯誤仍會進入恢復流程;使用者仍能停止或接管。
一般任務也採用 goal 的交付原則完成子步驟或說「做好了」不會直接結束必須核對完整目標後明確宣告完成。普通的「做不到無法完成」會進入自行診斷而非直接要求使用者接手。模型須自行選擇除錯方法說明實際嘗試與結果後繼續登入、2FA、拼圖驗證、缺少必要資訊或授權才交給使用者。
偵測到方法打轉時,系統先要求換方法,保留原目標和工具歷史。同一段沒有進展的恢復最多提供兩次改道機會,相同失敗不能重新算一次;新的成功狀態變更才結束這段恢復。最後的保險上限仍有效。恢復耗盡會記為失敗並說明具體障礙,不標成完成。成功工具操作會重設連續空談次數,避免長任務累積幾次進度說明就被停止。執行中補充訊息會併入原任務,不必使用 `/goal`,也不另開一個工作搶同一台電腦。
以前一個 run 固定 40 輪,等於假設所有任務一樣長:洗資料這種事情做不完,但也不會因此變成
錯誤,只是被腰斬。現在的正常結局是**把事情做完**(模型提出驗證,或明白說它卡在哪裡),會
被停下來的只有鬼打牆:同一個會改變狀態的動作連做六次、同一個錯誤連錯八次、連續十四個動作
全部失敗。觀察、等待、輪詢不算重複動作,所以等一個長 build、等下載、輪詢佇列都不會被打斷。
設計上要記住兩件事:
- 提示(「你已經做同一件事三次了」)永远不會停掉任務,只有重複到像故障才會暫停,暫停也是停在
現況、按「繼續」接下去,不重來。
- 保險絲(`budget_exhausted`)代表迴圈失控,是故障不是成績;它照樣可以續跑,但值得去看執行記錄。
純聊天仍然是 4 輪上限:那是避免模型在閒聊裡燒額度,跟任務長度無關。
## 任務狀態與交付
一般工作以 `report_task` 記錄重要進展、改採的方法、必要資訊與完成結果。回覆中提到
captcha 或說「做好了」不會改變工作狀態。完成回報必須列出已完成項目、驗證依據、空的
待辦清單與全部交付檔案;後端會檢查檔案範圍、存在、大小及讀取權限。這能驗證交付物
可取得,內容是否充分符合目標仍依賴模型提供的核對證據,並非自動判定所有事實正確。
`GET /api/sessions/{id}/task` 回傳該對話各助理最新任務、回報與心跳到期時間,沿用對話
權限檢查。狀態列區分排隊、處理、恢復、等人、完成、未完成與停止。綠點表示有效心跳;
電腦是否開機另行呈現。心跳、模型重試和逐次工具動作不新增聊天訊息;重要回報才進對話,
技術紀錄留在執行詳情。排隊及舊串流文字不能把助理冒充成在線。
交付回報通過後直接完成,不額外等待一輪模型回覆;完整核對證據留在可展開的詳情。
`request_takeover` 可指定登入、驗證或授權原因。介入卡只要求當下的人類步驟,交還後以
原 run 接續,重新取得畫面並附上先前工作紀錄,不要求再打一遍「繼續」。
成果卡沿用工作區預覽與下載;舊回覆仍可閱讀,未驗證的舊路徑不會補標成已交付。
一般介面以對話、成果及助理設定為主。助理設定最上方直接呈現完整頭像編輯器,
下方可編輯工作內容與工作指示。記憶、帳號與服務集中在設定,環境選擇、套件安裝及技能匯入收進進階入口。
既有會議模式偏好及獨立電腦設定保留,不搬動帳號或工作區資料。
回歸驗證:`tests/task-experience.test.mjs` 在獨立 API、資料庫及模擬模型下驗證一次交辦、
失敗改道與接手後原任務接續;不能拿它當作第三方網站或真實模型的成功率保證。
## 終端機是一台活的 tmux
`shell` 透過 Cua 在共用 VNC 桌面上開啟有名稱的終端機。相同 `session` 保留工作目錄、
環境變數與背景工作;`keys: "C-c"` 會在該終端機送出中斷,`reset` 會換成乾淨的登入 shell。
輸出以桌面截圖回傳。模型必須確認提示字元已回來才能輸入下一條命令;省略 `command`
即可再次查看,長輸出可以透過 Cua 捲動終端機。`wait_ms` 預設 1000、上限 10000
等待結束不會終止命令。終端機若被關閉,下次呼叫會重新開啟,已關閉 shell 的環境不會還原。
檔案列出、分頁讀取與寫入也使用這個可見終端機。所有這些工具都需要視覺模型與桌面控制鎖。
## 聊天是推送,不是輪詢
事件早就寫進 `events` 表,也有 SSE 端點,但兩端都在猜:伺服器每 750 ms 掃一次資料庫,瀏覽器
每 2 秒重刷一次全部狀態(訊息、電腦狀態、螢幕、技能、心跳一起打)。所以一個回覆最快也要兩輪
輪詢才被看見。
現在的管線:
1. 寫事件的事實不變——`events` 表仍然是順序與重放的依據(游標是 `threads.next_event_seq`
斷線重連用 `Last-Event-ID` 從資料庫重放,不會漏也不會重複)。
2. 提交之後往進程內的 wake channel 敲一下(`WakeBus`。SSE 端點不再固定間隔輪詢,而是等敲;
敲不到時(多副本、讀者落後)以 5 秒兜底輪詢補上。
3. 瀏覽器用 `EventSource` 訂閱 `/api/sessions/{id}/events`,事件在 120 ms 的窗口裡合流,
一回合變動只刷新一次。
實測(本機 loopback、丟棄式資料庫、同一台機器
| 事件 | 以前 | 現在 |
| --- | --- | --- |
| 自己發的訊息出現在畫面 | 最多 2 秒 | 送出去後約 25 ms |
| 「思考中」指示出現 | 最多 2 秒 | 約 32 msworker 也被敲醒,不再等 200 ms 定時器) |
| 模型回覆出現 | 寫入後最多 2.75 秒 | 寫入後約 25 ms模型本身要幾秒是另一回事 |
順帶把浪費掉的工作拿掉:分頁藏在後面時不再刷新(回到前景立刻補一次),心跳從 2 秒改成
60 秒——一次心跳買的是 15 分鐘控制租約、避免 10 分鐘閒置暫停60 秒是很寬的餘裕。
**壞了會怎樣。** SSE 被 proxy 擋住或斷線,瀏覽器察覺後自動回到 2 秒輪詢,等於退回以前的行為,
不會變成不更新伺服器端事件順序仍然只以資料庫為準wake 不見得可靠,只是慢。
自己量一次:
```bash
curl -N -b cookies.txt http://127.0.0.1:3101/api/sessions/<id>/events
# 另開一個終端機送訊息,看事件幾毫秒後出現在這條串流裡
```
長任務還有一層上下文保險絲:舊的網頁快照會收成摘要,最新畫面保持完整。這不是另開一個模型做壓縮,而是避免 70 輪 DOM 把 128k 窗口塞爆。細節見 [模型上下文](./operations.md#模型上下文)。
## 已知取捨
- 一般聊天可串流文字;工作任務採安靜執行,只顯示重要進展與最終交付。狀態與心跳獨立更新,
不以逐字輸出或工具播報充當進度。
- 電腦狀態(執行中/暫停、誰在控制)沒有自己的事件,只能靠兜底輪詢更新,`LIVE_POLL_MS` 目前是 4 秒;
桌面畫面本身是即時串流,只有狀態列會慢幾秒。要真正事件化得把 `computers` 的狀態變更也寫進
`events`(狀態是 bot 層、事件是執行緒層,要先決定寫到哪條執行緒)。
- 滑鼠停在頭像上看到的執行記錄泡泡,開啟時仍是輪詢(它只在滑鼠停留時開啟,量很小)。
- wake channel 是單進程的。多副本部署時,其他副本靠 5 秒安全輪詢追上;真要横向擴充應改用
Postgres `LISTEN/NOTIFY`
- 持久終端機需要桌面映像檔裡的 `tmux`;舊映像檔會退回一次性 shell`docker compose build computer`
之後就有了。
- 容器執行檔仍以 uid 1000、限制環境變數的方式進入容器持久化的是 shell 狀態,不是憑證。