1. 簡介

第一週詢問「誰說什麼會執行」。第二週的主題是誰決定接下來要執行的內容。第三週的主題是跑步後留下的痕跡。本週對話即將結束,問題是哪些內容會留存下來。結果顯示,內容類型決定了內容的去向。
如果發生錯誤,系統會將相關內容移至「封存」區。塔樓會記錄所有內容,而檔案管理員 Vesper 則在底層的桌子旁。夜間燈籠會熄滅,你去問問看。
她很健談,一個月後,她也很高興能與您見面。
記錄不是記憶體。
這句話就是整個實驗室的內容。這項計畫分為四個階段,每個階段都代表塔樓的一層:
rung | 地板 | 記憶內容 | 什麼原因導致 |
1 | 桌子和地板 | 這次造訪 |
|
2 | 二樓,你的抽屜 | 這位訪客 |
|
3 | 塔樓三樓 | 說了什麼 | Vertex AI Memory Bank |
4 | 第四層樓 (本季) | 整個山谷 | BigQuery |
每個階梯都是因為下一個階梯有東西掉落。

您已經知道檔案管理員的五種遺忘方式,因為您在支援服務電話中都經歷過:
她說的話 | 發生錯誤 | |
~~1~~ | ~~Could you give me that reference again?~~ | ~~在單一對話中忘記~~ - 第三週修正了這個問題 |
~~2~~ | ~~I've transferred you. 請從頭開始。~~ | ~~the history died with the process~~ — week three fixed this too |
3 | 歡迎!今天需要什麼協助呢? | 給上個月有未結案件的人 |
4 | 請描述損壞情形。 | 她上次看的是燈籠 |
5 | 我們從未見過這種情況。 | 本季有 31 人提出要求 |
第三行是本週。這項作業會以三種不同方式失敗,分別是新的造訪 (第 2 章)、紙條上沒有行的句子 (第 3 章),以及僅存在於程序中的封存 (第 4 章),每種方式都是一個章節。第四行留給您:look(),archive/agent.py是她讀取相片上的標記。第五行是第 5 章,為選填。
你不需要第 1 到第 3 週的資料。代理是具備指令和幾項工具的模型。本週的其餘內容不言自明。
您將撰寫三行,每一行都是記憶體概念:
該行 | 說明 |
| 狀態是由程式碼寫入,而非對話 |
| 前置字串為生命週期 |
| 召回政策 - 檔案未儲存 |
您已經有一行可供閱讀的內容 (寫入政策 await ctx.add_events_to_memory(...)),而第 3 章會說明該政策的作用,然後您再寫入使用該政策的程式碼。
另外兩個步驟完全不是編輯作業:您建構塔樓 (代管 Memory Bank 的 Agent Engine),而相同的程式碼會自行連線至塔樓;您載入資料倉儲 (BigQuery),在資料倉儲上鋪設圖表,並將兩個受控查詢 (一個依據意義,一個依據連線) 交給同一個代理程式。
每個章節都會執行相同的迴圈,而這也是您在自己的代理程式中使用的迴圈:讀取程式碼 → 撰寫程式碼行 → 在塔樓中觀看。不會先執行任何中斷的項目,也不會重新啟動任何項目,更不會有任何 Ctrl+C 項目:系統會在下一則訊息中擷取所有編輯內容,而連線至伺服器塔台的檔案中,每項要求都會重新讀取一行。高塔是重新繪製的圖案:它會讀取您編輯的相同檔案,並有三個按鈕:「🌙」結束當天、「🗓」開始下一次造訪、「🔥」忘記您。您在程式碼和終端機中執行的所有其他操作。
這兩個位置永遠不會變更工作:分頁 1 是終端機,分頁 2 是封存。工作台 (adk web) 只會在第 1 章出現一次,用於查看原始工作階段狀態,之後就不會再用到。下方每個 👉 都會說明是哪種。👉💻 是分頁 1,👉🖥 是分頁 2,👉🔬 是工作台。👉📖 是「開啟檔案並讀取」,沒有任何變更,而 👉✏️ 是編輯的步驟。如果步驟要求你對 Vesper 說些什麼,下方方塊中會顯示確切訊息,請直接複製。如果某個章節的標題結尾是「— read only」,則不需要輸入、貼上或點選任何內容:其中的程式碼已在存放區中執行,並列印供您閱讀。
Vesper 門上的句子是頂端的句子。本週的結尾句是整個賽季第四週的結尾:
事實和偏好設定應分別儲存在不同商店。
2. 🧰 設定
- 內容:指向專案或貼上金鑰、安裝,並證明工具鍊為綠色。
- 原因:這裡不會啟動任何項目。每個伺服器都會在需要該伺服器的步驟之前啟動,因此開啟畫面時,您會知道哪個指令擁有該畫面。
- 方式:一個用於建立專案的指令碼、一個用於安裝並指向 Vertex AI 的指令碼,以及一個用於讀取程式碼並告知您所在位置的預先檢查指令碼。
本實驗室的所有內容都會在 Cloud Shell 中執行,其中已安裝 Python、uv 和 gcloud,且您可以使用自己的憑證,透過 Vertex AI 存取 Gemini。本實驗室中沒有任何 API 金鑰,也不需要在筆電上安裝任何項目。
本實驗室無法提供已啟用計費功能的 Google Cloud 專案。步驟 1 會提供可支付費用的帳戶;步驟 4 則會將該帳戶轉換為專案,或選取您在第一週、第二週或第三週建立的 Agent Valley 專案。請依序執行這些步驟,因為步驟 4 之後的每個步驟都會讀取步驟 4 確定的專案。
1. 取得含帳單的帳戶 (約 1 分鐘)
🌐 請務必先完成這項操作。使用已啟用帳單功能的 Google 帳戶登入。任何這類帳戶都可以。如果沒有,請開始免費試用,這樣您就會有帳單帳戶,這也是步驟 4 的必要條件。
2 · 開啟 Cloud Shell (約 1 分鐘)
🌐 點選 Google Cloud 控制台頂端的「啟用 Cloud Shell」,也就是標題中的終端機形狀圖示。

🌐 點選「Open Editor」(開啟編輯器) (含鉛筆的開啟資料夾圖示)。這時會開啟 Cloud Shell 編輯器,左側顯示檔案總管,每當步驟標示為 👉✏️ 時,您就會在這裡作業。

🌐 如果系統在今天任何時間提示您授權,請點選「授權」繼續操作。
🌐 在編輯器中開啟終端機,也就是分頁 1,除非另有說明,否則每個 👉💻 步驟都會在此執行。「分頁 2」是「封存」,您會在第 1 章中開啟這個分頁,就在需要這個分頁的步驟之前。如果終端機尚未顯示在畫面底部,請依序點選「View」→「Terminal」開啟:

🌐 確認目前登入的帳戶,應該是步驟 1 中的帳戶:
gcloud auth list
3. 取得實驗室 (約 1 分鐘)
💻 複製存放區 - 這是封存存放區,不是第一週、第二週或第三週的存放區:
cd ~
git clone https://github.com/cuppibla/agent-valley-archive
cd agent-valley-archive
4. 建立專案,或重複使用前幾週的專案 (約 2 分鐘)
💻 一個指令碼會找出您的帳單帳戶、在該帳戶中建立專案,並將 Cloud Shell 指向該專案。如果您已完成第一週、第二週或第三週的課程,系統會先找出 Agent Valley 專案,並提供重複使用該專案的選項。請選取「是」,這樣就不必考慮第二個計費專案:
cd ~/agent-valley-archive
./setup_project.sh
👀 預期會看到所選帳單帳戶的 ✓、所建立或重複使用的專案 ✓,以及類似以下的結尾:
cd ~/agent-valley-archive
Project ready: agent-valley-4271
Next: ./setup_codelab.sh
agent-valley-4271 是您的專案 ID,您的專案 ID 會有不同的數字。當中會發生四件事:
帳單 | 如果有的話,系統會採用最新的 | |
project | 尋找您已擁有的 Agent Valley 專案 (第一週、第二週或第三週),並提供重複使用該專案的選項;否則會建立 | |
選取 | 會將 ID 寫入 | |
等待時間 | 輪詢,直到專案實際獲准放送為止,最多兩分鐘 | |
🌐 控制台中現在有相同的專案,其 ID 位於資訊主頁的「Project info」(專案資訊) 資訊卡中:

5 · 安裝並指向 Vertex AI (~3 分鐘)
💻 安裝 uv、匯出將 ADK 傳送至 Vertex AI 的三個變數,然後執行設定:
cd ~/agent-valley-archive
curl -LsSf https://astral.sh/uv/install.sh | sh
source ~/.local/bin/env
export GOOGLE_GENAI_USE_VERTEXAI=TRUE
export GOOGLE_CLOUD_PROJECT=$(gcloud config get project)
export GOOGLE_CLOUD_LOCATION=global
./setup_codelab.sh
$(gcloud config get project) 有要傳回的內容,因為步驟 4 已設定。這也是步驟 4 先執行的原因。
setup_codelab.sh 具有等冪性,可安全地重複執行任意次數。這項功能會依序執行下列五項操作:
api | 讀取專案步驟 4 選取內容,並在該專案上啟用 | |
uv env |
| |
基地 | 在 | |
.env | 寫入實驗室讀取的變數 ( | |
模型檢查 | 會對 Gemini 進行一次實際呼叫,因此不良專案會在設定時失敗,而不是在章節內稍後失敗 | |
6 · 證明是綠色 (約 1 分鐘)
💻 執行預檢 - 每個勾號都是實際探測,而非猜測:
cd ~/agent-valley-archive
uv run python scripts/preflight.py
👀 預檢會向模型提出一個問題,驗證您的憑證是否有效,檢查封存檔的套件是否就位,然後讀取您的程式碼並列印本週進度列:
cd ~/agent-valley-archive
desk ▢ the slip · write_down writes nothing chapter 1 · EDIT ONE
floor 1 ✓ the file · SqliteSessionService chapter 1, read only
floor 2 ▢ the drawer · CASE = "case" chapter 2 · EDIT TWO
floor 3 ✓ what was said · closing time files the day chapter 3, read only
floor 3 ▢ the asking · recall never looks chapter 3 · EDIT THREE
floor 3 ▢ the tower · InMemoryMemoryService chapter 4 · built, not edited
floor 3 ✓ the rules · USER_PREFERENCES, LANTERN_CONTEXT chapter 4, read only
其中三項已勾選。這些是您只會閱讀的內容。三行是您撰寫的內容,一行是您建構的塔。您隨時可以在實驗室中再次執行預檢,系統會讀取檔案而非檢查清單,因此可顯示您目前的位置。
3. Session、State、SqliteSessionService
- 什麼 - 寫一行;啟動工作台一次,然後觀察滑動填入;然後在塔中也是如此;然後閱讀它為何能存活一晚。
- 原因:首先,記憶體不會自行記憶任何內容。有人會寫出這種東西。
- 如何 -
agent.py中的一行,然後不變更任何其他內容。
編輯一
👉📖 開啟 archive/agent.py 並找到 write_down。請閱讀以下內容:
case = dict(tool_context.state.get(CASE, {}))
if case.get(field):
return {"already_written": {field: case[field]}}
case[field] = value
# 👉 EDIT ONE — chapter 1. She heard you. Nothing was written. Delete the
# "# " in front of the next line, then save — the slip is session state,
# and state is written by code, never by the conversation:
# tool_context.state[CASE] = case
return {"written": {field: value}}
函式會在本機 dict 中建構單據,然後傳回該單據,而本機 dict 會隨著呼叫而終止。照原樣執行這項操作,Vesper 就能完美地聽到你的聲音:四個 write_down 呼叫會觸發,每個呼叫都會回應 "written",且工作階段狀態會保持空白,因為沒有任何內容傳送至該狀態。她聽到你的心聲了。未寫入任何內容。
👉✏️ 仍在 archive/agent.py 內,在 write_down 中:刪除一行前面的 #,也就是 # 和後方的空格。變更前:
case[field] = value
# 👉 EDIT ONE — chapter 1. She heard you. Nothing was written. Delete the
# "# " in front of the next line, then save — the slip is session state,
# and state is written by code, never by the conversation:
# tool_context.state[CASE] = case
return {"written": {field: value}}
變更後:
case[field] = value
# 👉 EDIT ONE — chapter 1. She heard you. Nothing was written. Delete the
# "# " in front of the next line, then save — the slip is session state,
# and state is written by code, never by the conversation:
tool_context.state[CASE] = case
return {"written": {field: value}}
。
紙條會填入
👉💻 啟動工作台。這是您在實驗室中唯一一次開啟這個視窗,也是唯一會以原始 JSON 格式顯示工作階段狀態的視窗:
cd ~/agent-valley-archive
uv run adk web . --allow_origins="*"
👉🔬 開啟工作台,然後選取「Web Preview」→「Preview on port 8000」(網頁預覽按鈕是 Cloud Shell 右上方的眼睛和視窗圖示)。選取「封存」,然後在輸入任何內容前,按一下左側面板中的「狀態」。
👀 空白。目前沒有人說話。
👉🔬 現在請在同一則訊息中說出以下內容:
Hi! My lantern keeps going out at night. My case number is k7f2, and there's a little q7 stamped on the base.
👀 四個 write_down 晶片會觸發 - 點選一個並讀取 JSON:"written": {"no": "k7f2"}。現在再次點選「狀態」。

case {"no": "k7f2", "item": "lantern", "mark": "q7",
"symptom": "keeps going out at night"}
👀 空白,然後在同一則訊息中填滿。這就是她記得的內容,而且不會單獨顯示。您撰寫的程式碼會寫入該行。這就是整個機制:一個寫入 tool_context.state 的簡單函式,以及一項指令,告訴她每當訪客說出符合紙條上某行內容的話時,就使用該函式。
👉🔬 問她:
What's my case number?
👀 k7f2. 她照著紙條唸出內容,如果沒有 EDIT ONE,她會要求你提供支援清單中的第一行,也就是某個對話中的一行。
這兩道防線是紙本表單:四條短線,每條線各寫一次。這些指標比您想像的更重要。如果沒有這些限制,模型會發現可以將整段對話倒入 symptom,而第 3 章 (整章的重點是單據上沒有該項的欄位) 會悄悄停止成立。商店形狀是由撰寫商店形狀的程式碼強制執行,或不強制執行。
現在前往高塔
👉💻 工作台已完成,您可以讓工作台繼續執行,或關閉工作台的分頁;實驗室的其餘部分位於「封存」中。開啟第二個終端機分頁 (分頁 2 - Archive):
cd ~/agent-valley-archive
bash valley.sh
👉🖥 依序點選「網頁預覽」→「變更通訊埠」開啟封存檔,輸入 3440,然後點選「變更並預覽」。3440 不在 Web Preview 的快速清單中 (預設為 8080),因此您必須手動設定一次。依序按下「開始」▶ 和「封存」。你已抵達門口。選擇來訪者 (姓名和物種),然後進入。

👀 一棟建築物。Vesper 位於一樓的辦公桌,你可以在這裡與他對話。她上方有第一層、第二層、第三層和黑暗的閣樓。四個階梯代表四層樓。你的寵物會坐在底層,因為你只爬了這麼高。圖旁邊的欄位會列出各樓層目前有哪些商店,與簡介中的表格相同,順序也一樣。右側沒有任何按鈕。
👉🖥 將這四項內容貼到對話下方的方塊中 (必須是這則訊息),然後按下 Enter 鍵:
Hi! My lantern keeps going out at night. My case number is k7f2, and there's a little q7 stamped on the base.

👀 看著書桌。系統會逐行在繪圖上和旁邊的「紙條」下方寫入紙條內容。工具和狀態都相同:高塔只是繪製 write_down 寫入的內容,而且在實驗室的其餘部分也會繼續這麼做。
她記得一整晚 - 僅供閱讀
你輸入的內容和實際內容
該行 | 說明 | 儲存位置 |
| 工作階段狀態:由程式碼寫入,由指令讀取 | 桌面 · |
| 工作階段儲存區:檔案中的造訪記錄,而非程序 | 一樓 · |
這個鈴聲會響一次,而且在關門時間後仍會響。下次造訪時不會保留。
4. 使用者狀態
- 什麼 - 一個月後再回來,收據就不見了。五個角色,而且會跟著你。
- 為什麼:工作階段就是一次造訪。下一次造訪是新的工作階段,且從未見過上一個工作階段。
- 「How」一共有五個字元,因此
state.py的長度為 5。


👉🖥 按下 🗓 一個月後。這是同一位訪客的新工作階段,就像第 3 週的「發起新對話」一樣。
歡迎來到封存內容頁面。你今天想做什麼呢?
👉🖥 看著塔樓。一樓還有另一本書,這次是《The Great Gatsby》。二樓的抽屜是空的。桌上的紙條是空白的。

👀 原因:系統會將收據寫入工作階段狀態,而工作階段就是這次造訪。變更造訪次數、變更工作階段。由於未提供任何資訊,因此沒有任何內容轉移。最後一次的造訪記錄仍保留在檔案中 (也就是一樓的第一本書),但收據是根據一次性造訪的金鑰所寫。
編輯 2
👉✏️ 開啟 archive/state.py。找出 👉。變更前:
# 👉 EDIT TWO — chapter 2. Five characters. A key with no prefix lives for one
# visit; `user:` follows the visitor into every visit after this.
CASE = "case"
變更後:
CASE = "user:case"
。不重新啟動:Archive 會在每則訊息中重新匯入程式碼。
👉🖥 再次貼上相同的四個項目,也就是這段訊息:
Hi! My lantern keeps going out at night. My case number is k7f2, and there's a little q7 stamped on the base.
👉🖥 接著再次按下一個月後的按鈕 (與先前相同)。

👀 二樓的抽屜上寫著你的名字,裡面有四個欄位。桌上的紙條還是那四行字,你走進來時,紙條就從抽屜裡拿出來了。你的寵物已升上一層樓。每次造訪時都使用相同金鑰,且只有一個值:這就是前置字串的用途。
前置字串為生命週期。
前置字串 | 存活時間 | 哪個樓層 |
(無) | 這次造訪 | 辦公桌 |
| 該訪客的每次造訪 | 二樓,你的抽屜 |
| 所有人,永久 | 四樓部分區域 |
| 這回合就好,甚至不用爬樓梯 | — |
一張桌子,四個抽屜。本章將介紹其中一項。
她現在認識你
👉🖥 這是全新的通話,你尚未說過任何話。問她:
What did I bring in last time?
👀 我記下你帶進來的是燈籠,案件編號為 k7f2。該裝置標示為 q7,你提到裝置會在夜間持續關機。這段文字的每個字都是從抽屜中取出,而非來自對話。這次造訪只有一則訊息,且該訊息未命名。這就是使用者層級狀態的用途:訪客說話前,系統就會在每次造訪時提供 user: 金鑰。
抽屜只能容納紙條上的四行文字,你說的任何話 (你嘗試了什麼、你為什麼在意、你是否想要新的) 都沒有記錄,一個月後就會消失。導覽匣跨越月份。但句子不會。第 3 章會說明這項功能。
你輸入的內容和實際內容
該行 | 說明 | 儲存位置 |
| 前置字元是生命週期,也就是與訪客範圍相同的金鑰,而非與造訪範圍相同 | 二樓 · |
這個階段觸及一位訪客。抽屜會跟著你移動,但對話不會。
5. InMemoryMemoryService
- 什麼:讀取檔案當天的行,寫入詢問的行;然後是結束時間和一個問題。
- 為什麼:這張紙條是表單。表單會顯示您提供的行。人們不會逐行說話,而記錄他們說的內容只是記憶的一半。
- 如何:朗讀
file;一行recall;然後一個 🌙、一個 🗓、一個問題。

她回家的路程 (僅供參考)
系統不會記住已填寫的欄位
該行會將日期放在時間軸上。不會從中扣除任何金額。如果沒有人查看,滿滿一架卡片和空架子一樣沒用,而程式碼發布時,沒有人會查看:recall,也就是在每個問題上 Vesper 之前執行的節點,不會向塔樓詢問任何問題。無法在適當時間回憶起的儲存內容並非記憶,而是記錄。「看」是另一半,由你撰寫。
編輯三:提問
👉📖 在 archive/agent.py 中,找出 recall,也就是 file 上方的函式。這是純函式節點,會在每個問題上先執行 Vesper,而不是由模型決定何時要搜尋,因此即使找不到任何內容,也會顯示結果。請閱讀以下內容:
if query.strip():
try:
# 👉 EDIT THREE — chapter 3. Filed is not remembered: the cards are on
# the shelf and nobody is looking at them. Delete the "# " in front
# of the next line, then save:
# found = await ctx.search_memory(query)
pass
except ValueError:
# no memory service wired on this runner — degrade, do not crash
pass
👉✏️ 仍在 archive/agent.py 內,在 recall 中:刪除一行前面的 #,也就是 # 和後方的空格。變更前:
try:
# 👉 EDIT THREE — chapter 3. Filed is not remembered: the cards are on
# the shelf and nobody is looking at them. Delete the "# " in front
# of the next line, then save:
# found = await ctx.search_memory(query)
pass
except ValueError:
變更後:
try:
# 👉 EDIT THREE — chapter 3. Filed is not remembered: the cards are on
# the shelf and nobody is looking at them. Delete the "# " in front
# of the next line, then save:
found = await ctx.search_memory(query)
pass
except ValueError:
將 pass 留在原處,因為 found 已在上方設為 None,因此現在不會執行任何動作。
。不必重新啟動。
兩行程式碼,兩項政策,其中一項是您編寫的。寫入政策會決定要保留哪些資料,以及保留時間 (關閉時間、整天)。回想政策會決定何時要回想,以及回想的內容 (每個問題、問題本身)。ADK 會提供動詞 (add_events_to_memory、search_memory),並排除政策。這才是正確的拆分方式,因此您有權撰寫要求。
打烊時間
👉🖥 說出紙條上沒有的內容。一則或三則訊息:
I read by it at night, so night is exactly when I need it.
I've tried hanging it higher. No change.
I don't want a new one — it was a gift.

👉🖥 然後按下 🌙 今天的內容到此結束。

👀 看著書桌。你說的三件事從滑梯上起飛,然後漂浮上去,最後降落在三樓。在列出塔樓的資訊卡下方,會顯示你傳送的每則訊息,並標示 quote,以及你逐字逐句的句子,上方則會顯示「在此過程中」。降落前,桌上的燈會一直亮著。
一個月後,她知道
👉🖥 按下 🗓 一個月後,然後詢問:
What have I already tried?
👀 你試過將攝影機掛高一點,但沒有幫助。她知道。收據上沒有這類資訊,因此櫃員無法回答這個問題;recall找到卡片後,將資訊寫入 ctx.state["recalled"],並按照指示操作。其中一行是差異。
而這一切都是她想像出來的
查看機箱旁邊的卡片下方:在此程序中。目前記憶體是 InMemoryMemoryService,也就是 bash valley.sh 內的字典,而且與該程序存續時間完全相同。今晚關閉塔樓,明天再開啟:書本在第一層,抽屜在第二層,第三層是黑色的。案件已儲存在檔案中。你說的內容會保留在程序中,但程序已消失。
持續性並非記憶體。
第三層樓目前有兩個問題:一是正在處理中,二是您自己的話,也就是引言,而非事實。下一章會修正這兩項問題,完全不需要任何程式碼。
你讀取、撰寫的內容和內容類型
該行 | 說明 | 儲存位置 |
| 寫入政策 - 一整天,在關閉時間 | 三樓 · 記憶體服務 |
| 回憶政策 - 每個問題,在她回答之前 |
|
這個層級會擷取所說內容,並以您自己的話儲存在某個程序內的字典中。這兩半都是錯誤的,下一章會完全不使用程式碼,修正這兩個問題。
6. MemoryBank
- 內容:一個指令碼會建構 Memory Bank;您已有的兩行程式碼會開始將事實寫入 Memory Bank,並讀取這些事實。
- 原因:記憶體服務是服務。封存位置是部署決策,而非代理程式決策,因此您可以在不變更代理程式的情況下變更封存位置。
- 如何:執行
make_tower.py、說出三句話、按下 🌙、按下 🗓,然後提出一個問題。然後唯讀查看寫入和讀取作業。
建造高塔
第 3 章的 3 樓是 bash valley.sh 內的 Python 字典。Memory Bank 是該層樓的管理版本:它位於專案的 Agent Engine 執行個體中,會保留從當天提煉出的事實,而非句子,並根據意義而非共用字詞尋找事實。您不必將 Vesper 部署至 Agent Engine 即可使用,即使執行個體未部署任何內容,仍會代管 Memory Bank,而這正是指令碼建構的內容:無人居住的塔樓,唯一的工作是保管卡片。
👉💻 在分頁 1 (約 1 分鐘):
cd ~/agent-valley-archive
uv run python scripts/make_tower.py
👀 預期:
building the tower in YOUR_PROJECT / us-central1 — about a minute...
built, with the two topics in archive/topics.py configured on it.
resource: projects/.../locations/us-central1/reasoningEngines/6792...
AGENT_ENGINE written to .env
Next — nothing to restart. The Archive reads .env on every message:
look at floor three — under the cards it now says Memory Bank.
(adk web, if you use it: --memory_service_uri "agentengine://projects/.../reasoningEngines/6792...")
一次 SDK 呼叫 (agent_engines.create()) 和一行寫入 .env 的內容。Archive 會在每次要求時重新讀取該檔案,因此不需要重新啟動。
觀看運作方式
👉🖥 查看三樓,高塔會在幾秒內自行重新繪製。「卡片」下方現在顯示「Memory Bank」,且書架是空的:第 3 章的三個引文正在處理中,但這不是處理程序。再次說出這三句話,可以一次說完,也可以分三次說:
I read by it at night, so night is exactly when I need it.
I've tried hanging it higher. No change.
I don't want a new one — it was a gift.
👉🖥 按下 🌙 今天的內容到此結束。現在關閉時間約為八秒,塔正在擷取資料。然後看看三樓。

👀 這些卡片並非你的句子。他們會說「我晚上會用燈籠看書,但燈籠會一直熄滅」和「我已經試過把燈籠掛高一點了」,每則訊息都會標示日期 fact。蒸餾。輸入的內容是對話。結果是事實。
👉🖥 一個月後🗓,再次拜訪她 (這是新的拜訪,因此對話中不會再出現您剛才說的任何內容),並問她這個問題 (與卡片內容完全無關):
Should I just get a different lamp?
👀 你提到這是禮物,因此不想更換燈籠,而且你已嘗試將燈籠掛高。這張卡片上的每個字都來自於她,而且只有她才能知道:這次拜訪是舊訊息。相似度搜尋。塔羅牌的意義與問題中的字詞相符,但字詞不同。問題中是「燈」和「不同」,資訊卡中則是「燈籠」和「取代」。現在已不在程序中:今晚關閉塔台,明天就會有卡片,因為卡片位於 Agent Engine,而非 bash valley.sh。
寫入和讀取 - 僅限讀取
被遺忘權

👉🖥 按下訊息方塊下方的「🔥 forget me」。
👀 三層樓的燈光熄滅,一層樓的燈光未熄滅:
所持內容 | 後 🔥 | |
三樓,卡片 | 她記得的內容,也就是 Memory Bank 從你的造訪記錄中擷取的資訊 | 不復存在, |
二樓的抽屜 |
| 已清除 |
辦公桌、紙條 | 本次就診的病歷副本 | 已清除 |
一樓,書籍 | 造訪本身,即每次造訪時的單一工作階段 | 未觸碰,計數不會移動 |
這些書籍是記錄:記錄了拜訪的日期和內容。這些卡片和抽屜就是記憶,代表她從這些訪視中學到的事物,並帶到下一次訪視。被遺忘權要求是針對記憶,也就是從某人身上衍生的事實,以及隨之而來的狀態。是否要一併刪除記錄,是基於稽核追蹤記錄或支援記錄等其他原因而做出的決定。本實驗室刻意保留記錄,讓您親眼見證兩者分離:記錄和記憶不同,忘記其中一項不會影響另一項。這是從另一側看到的 Vesper 門上句子。
ADK 記憶體抽象層具有 add_events_to_memory 和 search_memory。無法刪除。忘記是管理動作,而非代理程式動作,因此會存在於應用程式 (原始用戶端上的 archive/tower.py 和 memories.delete) 中,模型不會意外存取。代理程式是否會忘記資訊,與是否會記住資訊一樣,都是由您設計。
您建構及讀取的內容,以及這些內容的用途
該項目 | 說明 | 儲存位置 |
| 記憶體服務 (以服務形式):部署決策,不在代理程式內 | Agent Engine 上的 Vertex AI Memory Bank |
| 相同的 |
|
| 系統可能會保留的內容 (在撰寫時決定,而非在提示中決定) |
|
🔥 → | 忘記是應用程式動作;ADK 的記憶體 API 沒有刪除 |
|
這個階段會根據所說內容進行調整。一天過去了,事實也隨之產生,但經過主題的限制,書本始終沒有離開一樓。
7. GraphRAG
選用。
- 內容:一個指令碼會將山谷的過往載入 BigQuery、在資料倉儲內部生成嵌入項目,並在資料表上鋪設圖表,而不會移動任何資料列;然後向 Vesper 提出兩個問題,Vesper 有兩個受控查詢:一個用於查詢相似的聲音,一個用於查詢相關內容。
- 為什麼 - 聲音相似不等於已連線。向量會找出要搜尋的位置;圖表會找出附加的內容;答案則必須包含走過的路徑。
- 做法:
bash scripts/season.sh一次。本章節的其他內容僅供參考。
Vesper 的塔樓範圍僅限於您,(app_name, user_id) 施工時也是如此。其他人的造訪記錄並非她的記憶,再怎麼努力搜尋也不會改變這點。這些是山谷的財產,山谷將其存放在倉庫中。本季有 31 位訪客回報夜間 Q7 燈籠熄滅的問題,其中一位訪客找到了原因。本章會載入該倉庫,並將兩個修正後的查詢傳遞至該倉庫。
圖表 RAG
RAG 是「先檢索,再生成」:找出正確的記錄,交給模型,讓模型根據這些記錄回覆。一般 RAG 是依相似度檢索,也就是嵌入問題,然後提取最接近的記錄。這項功能會找出聽起來像問題的內容,也就是第 4 章的塔樓停止的位置。圖形 RAG 會在邊緣 (倉庫中已有的鍵) 之後新增第二個擷取步驟,從找到的任何相似項目擷取附加的項目。這兩個步驟分別回答不同的問題,本章會引導您提出這兩個問題:
點選 [下一步] | 回答的問題 | 做法 | 本章 |
相似度 | 應該在哪裡查看相關資訊? | 嵌入問題, |
|
遍歷 | 與此相關的內容為何? |
|
|
代別 | 我該如何向訪客說明? | 模型,並將路徑做為引用來源 | 她的答案 |
開始執行
這些季別會以純 CSV 格式出貨 season/(訪客、項目、要求、修正、季別),就像支援系統匯出這些資料一樣。一個指令碼就能將資料一路帶進資料倉儲,而這也是本章中唯一執行的項目。
👉💻 在分頁 1 中 (約三分鐘;它會列印每個步驟,並在第一個失敗的步驟停止):
cd ~/agent-valley-archive
bash scripts/season.sh
👀 結束時,塔樓的第四層會亮起,旁邊的圖例會顯示「開放」。
建構內容 - 唯讀
她如何閱讀內容 - 僅供閱讀
問她
👉🖥 四樓已開放。請她以訪客身分提出要求:
Has anyone else had a q7 lantern go out at night?

👀 她回覆了,另外三十一人也回覆了,大多數人表示火焰很小,一小時後就熄滅了。Marlow 發現蠟燭芯浸得不夠深,而答案的最後一行就是路徑。這是她的輸出內容,請閱讀,但不要傳回給她:
mark q7 → 31 visits this season → 10 different things said → the wicks in the q7 batch were dipped too shallow — they drown in the oil and starve in an hour
路徑就是引文。其中的每個躍點都是圖表中的邊,而邊就是金鑰,因此任何人都可以再次走訪,並取得相同的 31。任何人皆無法再次進行相似度評估。如果她在路徑前表示資料列是透過三個聯結傳回,因為專案沒有圖表預留空間,這就是專案版本拒絕 GRAPH_TABLE 的原因,資料列和路徑相同。
👉🖥 現在請將標記排除在外,傳送以下內容:
Has anyone else had a lantern that keeps dying once the sun is down?
👀 她得到相同的三十一分,路徑也相同。改變的是路徑:season_search 先跑,找到五位相似的訪客 (每位都攜帶 q7),然後才走。「類似」並非連線,而是要尋找的內容。
載入的內容和用途
該項目 | 說明 | 儲存位置 |
| 倉庫:含有名稱和類型的資料欄 |
|
| 相似度步驟 - 應查看的位置 |
|
| 遍歷步驟:連結的內容;表格會變成節點和箭頭 |
|
| 她唯一能走的道路,而這條路就是引文 |
|
幾十位訪客並非購買倉庫的理由。本章節的重點是查詢的形狀,而非規模。將這個圖表放大一千倍,MATCH 也不會改變。
8. 關閉
三條線、一座塔、一個倉庫,共四層樓。沒有重新啟動任何項目。
階梯 | 你所做的動作 | 購買的商品 |
ONE |
| 任何滑動:狀態是由程式碼所寫 |
二 |
| 跟隨訪客的導覽匣 |
歸檔 |
| 說過的話、保留的內容 |
三 |
| 保留的內容、要求的事項 - 系統不會記住檔案 |
塔 |
| 蒸餾塔,並在夜間存活 |
規則 |
| 只保留應保留的內容 |
賽季 |
| 其他人的造訪記錄 (依意義和連結) |
每個零件的更換情形
ADK 2 | 您會改寫的內容 | 以及費用 |
| 聊天迴圈旁的 dict,自行封存至磁碟 | 模型無法讀取,而您會撰寫履歷和鎖定 |
| 使用者資料表,以及每次輪流的聯結 | 每次都要決定金鑰的歸屬位置 |
| 傾印轉錄稿的 Cron,以及決定何時查看的模式 | 它會傾印,不會蒸餾,而且您永遠不會看到未查看的時間 |
| 向量儲存區、擷取提示、合併工作,以及提示中的「請勿記住瑣事」 | 三項服務,且這項規則會持續生效,直到模型認為情況有異為止 |
| 匯出、嵌入其他位置、圖形資料庫、同步工作,以及模型撰寫 SQL | 資料會離開資料倉儲以供解讀,而當顧客執行 |
三個問題,在第一個「是」之後停止
- 明天還重要嗎?否 → 不保留任何內容。這項功能會隨著對話開始和結束。
- 函式可以檢查嗎?是 → 導覽匣。程式碼會寫入,每個回合都會讀取,且任何句子都無法變更。
- 其他情況 → 塔樓。從對話內容中擷取資訊,在需要時提供,並根據後續對話內容修正。
單一句子
記錄不是記憶體。記憶記錄包含兩項決定:要保留哪些內容,以及何時查看。內容類型則決定了內容要放在哪個樓層。
事實和偏好設定應分別儲存在不同商店。
👀 每個樓層都亮著燈。畫面頂端會顯示你的熟人。護照上會蓋上「封存」戳記,第五週則會開放夜市。屆時 Nix 會即時大聲朗讀舞台上的內容,而塔樓所知的一切都會跟著你。