跳到內容

在持久核心中探索資料

本指南說明如何讓代理只載入一次昂貴的資料,接著就它提出多個問題,而不必為每個問題都付一次載入的代價。

eval 工具執行的是持久直譯器。變數、匯入的模組與已載入的資料都會在多次呼叫之間保留。

一次性的 python -c 會為每個問題都付一次初始化成本。載入一個資料框架要花上幾秒與上百 MB;把它畫成圖卻只要幾毫秒。當每個問題的代價都是那次載入時,代理提出的問題就會比它該提的少——而每個答案又以文字形式回傳,它還得重新解析一遍。

載入 data/runs.csv,然後告訴我每個代理的 p95 耗時。

import pandas as pd
runs = pd.read_csv("data/runs.csv")
len(runs)

最後一個運算式會像 notebook 那樣被回顯,因此 len(runs) 不需 print 就會回報列數。

接著,在另一次呼叫中:

runs.groupby("agent")["duration_ms"].quantile(0.95).sort_values()

runs 仍處於已載入狀態。pandas 資料框架會以表格形式回傳,而不是以 repr 形式。

import matplotlib.pyplot as plt
runs.groupby("agent")["duration_ms"].mean().plot.bar()

圖形會在儲存格執行完畢後被擷取,並以影像形式回傳,由對話紀錄呈現出來。你看得到圖表,代理也看得到。

圖形在擷取後就會被關閉。未被回收的圖形也會被下一個儲存格重繪並再次送出,因此一次五個儲存格的會話會把第一張圖表送出五次。

那些你本來就會順手輸入的慣用寫法

標題為「那些你本來就會順手輸入的慣用寫法」的章節

這些寫法會被改寫成一般程式碼,而不是直接報錯:

你輸入的內容 會發生什麼事
%pip install x 執行 pip,然後清空模組快取,讓下一次 import 能看到它
%cd path os.chdir
!command 被擷取的子處理序
%%bash 把儲存格其餘部分當作 shell 指令碼執行
%%timeit 1000 次計時執行

其中真正要緊的是 %pip 的快取逐出:對一個已經匯入過的模組而言,把套件安裝進執行中的直譯器毫無作用,因此少了這一步,你剛安裝的版本就不是正在執行的版本。

paths = tool("find", {"pattern": "**/*.dart", "path": "lib"})
for path in paths.splitlines()[:100]:
contents = tool("read", {"path": path})
...

tool(name, args) 會重新進入代理自己的工具登錄表。這表示一個儲存格可以同時對上百個檔案展開作業,或透過 task 進行委派,而不必讓模型為每個項目各花掉一個回合。

橋接呼叫在尚未回傳期間會暫停儲存格的逾時計時。這份預算衡量的是無活動時間,而不是實際經過的時間——一個展開到子代理、等了四分鐘的儲存格並不算是卡住,而把它在展開途中終止,會失去整個核心的狀態。

eval(code: "…", reset: true, description: "Start a clean interpreter")

丟棄目前的直譯器,並啟動一個乾淨的直譯器。所有已載入的內容都會消失,而這正是重點。

對話有隔離艙時就在其中執行,否則在主機上執行。

由模型驅動、正在讀取不受信任儲存庫的持久直譯器,正是「僅限隔離艙執行」存在的理由:一次性的 bash 呼叫至少會結束,而核心是一個會記住狀態的 shell。

它不會為了做到這件事而啟動隔離艙——這和阻止機台分頁自動啟動的是同一條規則。如果你希望核心在隔離艙中執行,請先開啟該對話的 shell。參見給代理一台用於測試的機器。

  • 每個核心一次只能有一個儲存格。 兩個儲存格在同一個直譯器裡競速,就是兩個程式的兩半在同一個命名空間中交錯執行。
  • 輸出有上限。 處於列印迴圈中的儲存格會被截斷,而不會任它填滿情境視窗。
  • 每個儲存格最多四張影像。 繪圖迴圈可能在每次迭代都產生一張圖形,而每張影像都是承載它的那次請求中一筆很大的固定成本。
  • 核心會隨著執行一起終止。 對話結束後仍占著一個資料框架的核心就是一種洩漏。