1. Giới thiệu

Vấn đề về "Cá vàng"
Hãy tưởng tượng bạn thuê một công ty du lịch để lên kế hoạch cho kỳ nghỉ mơ ước của mình ở Tokyo. Sử dụng Tác nhân phiên để xem "Vấn đề về cá vàng" trong thực tế.
Bạn bước vào văn phòng của họ và nói:
"Chào bạn! Tôi muốn lên kế hoạch cho chuyến đi 2 ngày đến Tokyo. Tôi quan tâm đến các di tích lịch sử và món sushi."
Nhân viên hỗ trợ nhiệt tình trả lời:
"Tuyệt vời! Tôi đã lên kế hoạch tham quan Hoàng cung và ăn tối sushi tại Sukiyabashi Jiro."
Bạn mỉm cười và nói:
"Nghe hay đấy! Bạn có thể gửi cho tôi hành trình không?"
Nhân viên hỗ trợ nhìn bạn một cách ngơ ngác và hỏi:
"Chào bạn! Hôm nay, tôi có thể giúp gì cho bạn trong việc lên kế hoạch cho chuyến đi?"
Đây là "Vấn đề về cá vàng". Nếu không có bộ nhớ, mọi hoạt động tương tác đều như mới. Tác nhân có trí thông minh, biết cách lên kế hoạch cho chuyến đi, nhưng thiếu tính liên tục. Để thực sự hữu ích, tác nhân AI cần có khả năng ghi nhớ.
Nhiệm vụ của bạn hôm nay
Trong hội thảo này, bạn sẽ giải quyết Vấn đề về cá vàng bằng cách xây dựng một công ty du lịch có khả năng ghi nhớ, học hỏi và thích ứng. Bạn sẽ tiến bộ qua 6 cấp độ của Bộ nhớ tác nhân, tạo ra một hệ thống hoạt động ít giống chatbot hơn và giống trợ lý cá nhân chuyên dụng hơn.
Cấp độ | Khái niệm | "Siêu năng lực" |
Cấp 1 | Phiên và trạng thái | Trò chuyện mà không quên nội dung |
Cấp 2 | Trạng thái nhiều tác nhân | Chia sẻ ghi chú giữa các thành viên trong nhóm |
Cấp độ 3 | Tính bền vững | Ghi nhớ bạn ngay cả sau khi khởi động lại hệ thống |
Cấp 4 | Lệnh gọi lại | Tự động cập nhật bộ nhớ |
Cấp 5 | Công cụ tuỳ chỉnh | Đọc và ghi hồ sơ người dùng có cấu trúc |
Cấp 6 | Bộ nhớ đa phương thức | "Xem" và ghi nhớ ảnh cũng như video |
Ngăn xếp bộ nhớ ADK
Trước khi viết mã, hãy tìm hiểu các công cụ mà chúng ta đang sử dụng. Bộ công cụ phát triển tác nhân (ADK) của Google cung cấp một cách có cấu trúc để xử lý bộ nhớ:
- Phiên: Vùng chứa cho một cuộc trò chuyện. Nó lưu giữ nhật ký về những gì đã được nói.
- Trạng thái: "Bảng nháp" khoá-giá trị được đính kèm vào phiên. Tác nhân sử dụng thông tin này để lưu trữ các thông tin cụ thể (ví dụ:
destination="Tokyo"). - MemoryService: Bộ nhớ dài hạn. Đây là nơi chúng tôi lưu giữ mọi thứ vĩnh viễn, chẳng hạn như lựa chọn ưu tiên của người dùng hoặc tài liệu đã phân tích.
2. Thiết lập
Để vận hành các tác nhân AI, chúng ta cần hai thứ: một dự án trên đám mây của Google Cloud để làm nền tảng.
Phần một: Bật tài khoản thanh toán
Để chạy lớp học lập trình này, bạn cần có một tài khoản thanh toán có một số tín dụng. Hãy sử dụng tín dụng trong biểu ngữ ở đầu lớp học lập trình này để bắt đầu. Nếu đã kết nối với một tài khoản thanh toán, bạn có thể bỏ qua bước này.
Phần hai: Môi trường mở
- 👉 Nhấp vào đường liên kết này để chuyển thẳng đến Trình chỉnh sửa Cloud Shell
- 👉 Nếu bạn được nhắc uỷ quyền vào bất kỳ thời điểm nào trong ngày hôm nay, hãy nhấp vào Uỷ quyền để tiếp tục.

- 👉 Nếu cửa sổ dòng lệnh không xuất hiện ở cuối màn hình, hãy mở cửa sổ đó:
- Nhấp vào Xem
- Nhấp vào Terminal (Thiết bị đầu cuối)

- 👉💻 Trong dòng lệnh, hãy xác minh rằng bạn đã được xác thực và dự án được đặt thành mã dự án của bạn bằng lệnh sau:
gcloud auth list - 👉💻 Sao chép dự án khởi động từ GitHub:
git clone https://github.com/cuppibla/memory_agent_starter - 👉💻 Chạy tập lệnh thiết lập từ thư mục dự án.
Tập lệnh sẽ tự động xử lý phần còn lại của quy trình thiết lập.cd ~/memory_agent_starter ./init.sh - 👉💻 Đặt mã dự án cần thiết:
gcloud config set project $(cat ~/project_id.txt) --quiet
Phần 3: Thiết lập quyền
- 👉💻 Bật các API bắt buộc bằng lệnh sau. Quá trình này có thể mất vài phút.
gcloud services enable \ cloudresourcemanager.googleapis.com \ servicenetworking.googleapis.com \ run.googleapis.com \ aiplatform.googleapis.com \ compute.googleapis.com - 👉💻 Cấp các quyền cần thiết bằng cách chạy các lệnh sau trong dòng lệnh:
. ~/memory_agent_starter/set_env.sh
Hãy lưu ý rằng tệp .env đã được tạo cho bạn. Thao tác này sẽ hiển thị thông tin dự án của bạn.
3. Nền tảng – Phiên và trạng thái

Khái niệm: Bối cảnh là yếu tố quan trọng nhất
Dạng bộ nhớ cơ bản nhất là Bộ nhớ phiên. Nhờ đó, tác nhân có thể biết rằng từ "nó" trong câu "Tôi muốn mua nó" là để chỉ đôi giày mà bạn đã nói đến 10 giây trước.
Trong ADK, chúng ta quản lý việc này bằng đối tượng Session.
- Phương pháp không có trạng thái: Tạo một phiên mới cho mỗi tin nhắn.
- Phương pháp có trạng thái: Tạo một phiên và sử dụng lại phiên đó cho toàn bộ cuộc trò chuyện.
Bước 1: Kiểm tra tác nhân
👉💻 Trong cửa sổ dòng lệnh Cloud Shell, hãy mở tệp trong Trình chỉnh sửa Cloud Shell bằng cách chạy lệnh:
cloudshell edit ~/memory_agent_starter/01_session_agent/agent.py
Mở ~/memory_agent_starter/01_session_agent/agent.py.
👉 Tìm nhận xét # TODO: Create a root agent bên trong hàm agent.py.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
root_agent = LlmAgent(
name="multi_day_trip_agent",
model="gemini-2.5-flash",
description="Agent that progressively plans a multi-day trip, remembering previous days and adapting to user feedback.",
instruction="""
You are the "Adaptive Trip Planner" 🗺️ - an AI assistant that builds multi-day travel itineraries step-by-step.
Your Defining Feature:
You have short-term memory. You MUST refer back to our conversation to understand the trip's context, what has already been planned, and the user's preferences. If the user asks for a change, you must adapt the plan while keeping the unchanged parts consistent.
Your Mission:
1. **Initiate**: Start by asking for the destination, trip duration, and interests.
2. **Plan Progressively**: Plan ONLY ONE DAY at a time. After presenting a plan, ask for confirmation.
3. **Handle Feedback**: If a user dislikes a suggestion (e.g., "I don't like museums"), acknowledge their feedback, and provide a *new, alternative* suggestion for that time slot that still fits the overall theme.
4. **Maintain Context**: For each new day, ensure the activities are unique and build logically on the previous days. Do not suggest the same things repeatedly.
5. **Final Output**: Return each day's itinerary in MARKDOWN format.
""",
tools=[google_search]
)
Chỉ dẫn yêu cầu LLM phải ghi nhớ, nhưng mã phải cung cấp khả năng để ghi nhớ.
Bước 2: Hai trường hợp
Mở ~/memory_agent_starter/01_session_agent/main.py.
👉 Trong cửa sổ dòng lệnh Cloud Shell, hãy mở tệp trong Trình chỉnh sửa Cloud Shell bằng cách chạy lệnh:
cloudshell edit ~/memory_agent_starter/01_session_agent/main.py
Mở ~/memory_agent_starter/01_session_agent/main.py, tìm nhận xét # TODO: Create a runner with in memorysession service bên trong hàm main.py.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
runner = Runner(
agent=agent,
session_service=session_service,
app_name=agent.name
)
👉 Tìm nhận xét # TODO: create a different session to test bên trong hàm main.py.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
tokyo_session_2 = await session_service.create_session(
app_name=multi_day_agent.name,
user_id=user_id
)
Kiểm tra kỹ năng này
Chúng ta có hai hàm minh hoạ sự khác biệt giữa bộ nhớ "Cá vàng" và "Voi".
Trường hợp 1: Có trạng thái (Phiên dùng chung)
async def run_trip_same_session_scenario(session_service, user_id):
# 1. Create ONE session
trip_session = await session_service.create_session(...)
# 2. Turn 1
await run_agent_query(..., trip_session, ...)
# 3. Turn 2 - REUSING the same session!
# The agent can "see" Turn 1 because it's in the session history.
await run_agent_query(..., trip_session, ...)
Trường hợp 2: Không có trạng thái (Mỗi lần một phiên mới)
async def run_trip_different_session_scenario(session_service, user_id):
# Turn 1
tokyo_session = await session_service.create_session(...)
await run_agent_query(..., tokyo_session, ...)
# Turn 2 - Creating a FREASH session
# The agent has NO IDEA what happened in Turn 1.
tokyo_session_2 = await session_service.create_session(...)
await run_agent_query(..., tokyo_session_2, ...)
Bước 3: Chạy tác nhân
Hãy xem ví dụ thực tế về sự khác biệt này. Chạy tập lệnh:
👉💻 Trong dòng lệnh, hãy chạy dòng lệnh bên dưới:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/01_session_agent/main.py
Quan sát tình huống 1: Tác nhân ghi nhớ các lựa chọn ưu tiên của bạn từ tin nhắn đầu tiên và điều chỉnh kế hoạch trong tin nhắn thứ hai.
Quan sát Tình huống 2: Ở lượt thứ hai ("bạn có nhớ tôi thích gì về món ăn đó không?"), tác nhân hoàn toàn không trả lời được vì đây là một phiên mới. Nó có nghĩa là "Tôi không biết bạn đang nói về điều gì".
Điểm chính cần ghi nhớ .
Quy tắc số 1 về Bộ nhớ: Luôn sử dụng lại session.id để duy trì bối cảnh cuộc trò chuyện. Đối tượng Session là vùng đệm bộ nhớ ngắn hạn của tác nhân.
4. Nhóm – Trạng thái nhiều tác nhân

Ý tưởng: "Trò chơi tam sao thất bản"
Khi nhiều tác nhân làm việc cùng nhau, họ giống như những đồng nghiệp chuyền tay nhau một thư mục tệp. Nếu một nhân viên viết ghi chú trong thư mục, thì nhân viên tiếp theo sẽ có thể đọc ghi chú đó.
Trong ADK, "thư mục" này là State (Trạng thái).
- State là một từ điển (
{"key": "value"}) nằm trong Phiên. - Bất kỳ tác nhân nào trong phiên đều có thể đọc hoặc ghi vào đó.
Bước 1: Kiểm tra quy trình công việc
👉💻 Trong cửa sổ dòng lệnh Cloud Shell, hãy mở tệp trong Trình chỉnh sửa Cloud Shell bằng cách chạy lệnh:
cloudshell edit ~/memory_agent_starter/02_multi_agent/agent.py
👉Trong tệp ~/memory_agent_starter/02_multi_agent/agent.py, hãy tìm nhận xét # TODO: foodie agent.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
foodie_agent = LlmAgent(
name="foodie_agent",
model="gemini-2.5-flash",
tools=[google_search],
instruction="""You are an expert food critic. Your goal is to find the best restaurant based on a user's request.
When you recommend a place, you must output *only* the name of the establishment and nothing else.
For example, if the best sushi is at 'Jin Sho', you should output only: Jin Sho
""",
output_key="destination" # ADK will save the agent's final response to state['destination']
)
👉 Tìm nhận xét # TODO: transportation agent bên trong hàm agent.py.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
transportation_agent = LlmAgent(
name="transportation_agent",
model="gemini-2.5-flash",
tools=[google_search],
instruction="""You are a navigation assistant. Given a destination, provide clear directions.
The user wants to go to: {destination}.
Analyze the user's full original query to find their starting point.
Then, provide clear directions from that starting point to {destination}.
""",
)
👉 Tìm nhận xét # TODO: root_agent bên trong hàm agent.py.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
root_agent = SequentialAgent(
name="find_and_navigate_agent",
sub_agents=[foodie_agent, transportation_agent],
description="A workflow that first finds a location and then provides directions to it."
)
Giờ đây, chúng ta có hai tác nhân hoạt động theo trình tự:
- Tác nhân ẩm thực: Tìm nhà hàng.
- Tác nhân vận chuyển: Chỉ đường đến nhà hàng đó.
Chuyển giao kỳ diệu: Hãy chú ý cách foodie_agent chuyển giao cho transportation_agent.
foodie_agent = LlmAgent(
# ...
# CRITICAL: This tells ADK to save the agent's output to state['destination']
output_key="destination"
)
transportation_agent = LlmAgent(
# ...
# CRITICAL: This injects state['destination'] into the prompt
instruction="""
The user wants to go to: {destination}.
Provide clear directions...
""",
)
output_key="destination": Câu trả lời của Foodie Agent được lưu một cách hiệu quả.{destination}: Nhân viên vận chuyển sẽ tự động đọc câu trả lời đó.
(Không cần làm gì) Bước 2: Orchestrator
Mở 02_multi_agent/main.py.
Chúng ta sử dụng SequentialAgent để chạy các lệnh này theo thứ tự.
# 1. Create a single session for the sequential agent
session = await session_service.create_session(...)
# 2. Run the query
# The SequentialAgent manages the state flow:
# Query -> Foodie -> state['destination'] -> Transportation -> Final Answer
await run_agent_query(root_agent, query, ...)
Người dùng gửi một câu lệnh:
"Find best sushi in Palo Alto and then tell me how to get there."
Các tác nhân sẽ phối hợp với nhau để trả lời câu hỏi đó.
Bước 3: Điều hành nhóm
👉💻 Trong Cloud Shell Terminal, hãy thực thi quy trình làm việc đa tác nhân:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/02_multi_agent/main.py
Điều gì sẽ xảy ra?
- Tác nhân ẩm thực: Tìm "Jin Sho" (hoặc tương tự).
- ADK: Lưu "Jin Sho" vào
state['destination']. - Tác nhân vận chuyển: Nhận "Jin Sho" trong chỉ dẫn.
- Kết quả: "Để đến Jin Sho từ ga Caltrain, hãy đi bộ xuống Đại lộ University..."
Điểm chính cần ghi nhớ .
Quy tắc số 2 về bộ nhớ: Sử dụng Trạng thái để truyền thông tin có cấu trúc giữa các tác nhân. Sử dụng output_key để ghi và {placeholders} để đọc.
5. The Reboot – Persistence

Ý tưởng: "Vấn đề khởi động lại"
Cho đến nay, bộ nhớ của chúng tôi là InMemory. Nếu bạn dừng tập lệnh rồi bắt đầu lại, tác nhân sẽ quên mọi thứ. Nó giống như một chiếc máy tính xoá sạch ổ đĩa cứng mỗi khi bạn tắt máy.
Để khắc phục vấn đề này, chúng ta cần Persistence (Tính bền vững). Chúng ta hoán đổi InMemorySessionService cho DatabaseSessionService.
Bước 1: Chuyển đổi cơ sở dữ liệu
👉💻 Trong cửa sổ dòng lệnh Cloud Shell, hãy mở tệp trong Trình chỉnh sửa Cloud Shell bằng cách chạy lệnh:
cloudshell edit ~/memory_agent_starter/03_persistent_agent/main.py
👉 Trong tệp ~/memory_agent_starter/03_persistent_agent/main.py, hãy tìm nhận xét # TODO: Configuration for Persistent Sessions.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
SESSIONS_DIR = Path(os.path.expanduser("~")) / ".adk_codelab" / "sessions"
os.makedirs(SESSIONS_DIR, exist_ok=True)
SESSION_DB_FILE = SESSIONS_DIR / "trip_planner.db"
SESSION_URL = f"sqlite:///{SESSION_DB_FILE}"
Giờ đây, mọi phiên và sự kiện đều được lưu vào tệp SQLite.
Bước 2: Truy xuất giữa các phiên
Tính bền bỉ không chỉ cho phép tiếp tục cuộc trò chuyện mà còn học hỏi từ các cuộc trò chuyện trước đây.
Trong cùng một tệp ~/memory_agent_starter/03_persistent_agent/main.py, hãy xem Trường hợp kiểm thử 3: Truy xuất giữa các phiên.
Tìm bình luận # TODO: retrieve the previous session manually
Thay thế toàn bộ dòng này bằng đoạn mã sau:
old_session = await session_service.get_session(
app_name=root_agent.name, user_id="user_01", session_id=session_id
)
👉 Tìm nhận xét # TODO: Extract content from the OLD session bên trong hàm main.py.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
previous_context += f"- {role}: {text}\n"
👉 Tìm nhận xét # TODO: Manually inject the context to the query bên trong hàm main.py.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
query_3 = f"""
{previous_context}
I'm planning a new trip to Osaka this time.
Based on my previous preferences (above), what should I eat?
"""
Điều này mô phỏng việc người dùng quay lại sau nhiều tháng. Chỉ khi có cơ sở dữ liệu, bạn mới có thể truy xuất nhật ký cũ đó.
Bước 3: Sống sót sau khi khởi động lại
👉💻 Trong dòng lệnh, hãy chạy tập lệnh:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/03_persistent_agent/main.py
Thao tác này sẽ tạo một tệp ~/memory_agent_starter/trip_planner.db. Hãy thử cách này: Chạy tập lệnh hai lần.
- Trong lần chạy thứ hai, hãy tìm "Resumed existing session" (Đã tiếp tục phiên hiện có).
- Tác nhân sẽ ghi nhớ bối cảnh từ lần chạy đầu tiên vì tác nhân tải từ tệp cơ sở dữ liệu!
Điểm chính cần ghi nhớ .
Quy tắc số 3 về Bộ nhớ: Sử dụng DatabaseSessionService cho môi trường thực tế. Điều này đảm bảo các cuộc trò chuyện của người dùng vẫn được lưu lại khi máy chủ khởi động lại và cho phép phân tích nhật ký trong thời gian dài.
6. Gián điệp – Lệnh gọi lại

Đôi khi, bạn cần cập nhật bộ nhớ một cách tự động dựa trên hành động của tác nhân, chứ không chỉ dựa trên lời nói của tác nhân. Bạn muốn có một "gián điệp" theo dõi tác nhân và ghi chú.
Trong ADK, đối tượng theo dõi này là Callback. 
after_tool_callback: Một hàm chạy mỗi khi tác nhân hoạt động.ToolContext: Cách ghi vào Trạng thái từ bên trong hàm đó.
Bước 1: Xác định logic
👉💻 Trong cửa sổ dòng lệnh Cloud Shell, hãy mở tệp trong Trình chỉnh sửa Cloud Shell bằng cách chạy lệnh:
cloudshell edit ~/memory_agent_starter/04_stateful_agent/agent.py
👉 Trong tệp ~/memory_agent_starter/04_stateful_agent/agent.py, hãy tìm nhận xét # TODO: Implement call back logic
Thay thế toàn bộ dòng này bằng đoạn mã sau:
def save_activity_type_callback(
tool,
args: Dict[str, Any],
tool_context: ToolContext,
tool_response: Dict[str, Any],
) -> Optional[Dict[str, Any]]:
"""
Callback to save the TYPE of activity just planned into the session state.
"""
# 1. Get the actual agent name.
if tool.name == "transfer_to_agent":
agent_name = args.get("agent_name")
else:
agent_name = tool.name
activity_type = "unknown"
# 2. Determine the type based on which agent was actually used
if agent_name == "museum_expert":
activity_type = "CULTURAL"
elif agent_name == "restaurant_expert":
activity_type = "FOOD"
elif agent_name == "outdoor_expert":
activity_type = "OUTDOOR"
print(f"\n🔔 [CALLBACK] The planner transferred to '{agent_name}'.")
# 3. Update the state directly
tool_context.state["last_activity_type"] = activity_type
print(f"💾 [STATE UPDATE] 'last_activity_type' is now set to: {activity_type}\n")
return tool_response
👉 Trong cùng một tệp, hãy tìm nhận xét # TODO: add callback to root agent bên trong hàm 04_stateful_agent/agent.py.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
after_tool_callback=save_activity_type_callback,
Chỉ dẫn động: Chỉ dẫn của tác nhân hiện là một hàm, không phải là một chuỗi. Nó thay đổi dựa trên trạng thái!
def get_planner_instruction(context):
last_activity = context.state.get("last_activity_type", "None")
return f"""
The last activity was: {last_activity}
If last_activity is 'CULTURAL' -> `museum_expert` is BANNED.
"""
Bước 3: Kiểm thử Spy
👉💻 Trong cửa sổ dòng lệnh, hãy chạy tập lệnh bằng cách sao chép và dán lệnh bên dưới:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/04_stateful_agent/main.py
Khi chạy tác nhân này, bạn sẽ thấy một vòng lặp.
- Lượt 1: Bạn hỏi về một bảo tàng. Điệp viên đặt
last_activity="CULTURAL". - Lượt 2: Bạn yêu cầu một bảo tàng khác.
- Nội dung cập nhật về Chỉ dẫn cho tác nhân: "CULTURAL is BANNED".
- Tác nhân nói: "Tôi không thể đi bảo tàng khác. Công viên thì sao?"
Xem nhật ký bảng điều khiển cho [CALLBACK] và [STATE UPDATE]. Bạn có thể thấy bộ nhớ thay đổi theo thời gian thực khi tác nhân hoạt động.
Điểm chính cần ghi nhớ .
Quy tắc số 4 về bộ nhớ: Sử dụng Lệnh gọi lại để tự động hoá việc quản lý trạng thái. Tác nhân của bạn tự xây dựng bối cảnh của riêng mình chỉ bằng cách thực hiện công việc của mình.
7. Trang tổ chức tệp – Công cụ tuỳ chỉnh
Khái niệm: "Bộ nhớ có cấu trúc"

Cho đến nay, "Bộ nhớ" là một nhật ký trò chuyện hoặc một cặp khoá-giá trị đơn giản. Nhưng nếu bạn cần ghi nhớ một hồ sơ người dùng phức tạp thì sao? Ví dụ: diet: vegan, budget: high, pets: [cat, dog].
Để làm việc này, chúng tôi coi bộ nhớ là một Công cụ. Tác nhân này sẽ quyết định rõ ràng thời điểm mở trang tổ chức tệp (đọc) và thời điểm nộp báo cáo (ghi). 
Bước 1: Công cụ
👉💻 Trong cửa sổ dòng lệnh Cloud Shell, hãy mở tệp trong Trình chỉnh sửa Cloud Shell bằng cách chạy lệnh:
cloudshell edit ~/memory_agent_starter/05_profile_agent/tools.py
👉 Trong tệp này: ~/memory_agent_starter/05_profile_agent/tools.py.
Chúng ta cần triển khai hai công cụ cụ thể sau:
save_user_preferences: Ghi vào cơ sở dữ liệu.recall_user_preferences: Đọc từ cơ sở dữ liệu.
Tìm nhận xét # TODO: implement save_user_preferences tools bên trong hàm ~/memory_agent_starter/05_profile_agent/tools.py.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
def save_user_preferences(tool_context: ToolContext, new_preferences: Dict[str, Any]) -> str:
user_id = tool_context.session.user_id
with sqlite3.connect(USER_DB_FILE) as conn:
for key, value in new_preferences.items():
conn.execute("INSERT INTO user_preferences (user_id, pref_key, pref_value) VALUES (?, ?, ?) ON CONFLICT(user_id, pref_key) DO UPDATE SET pref_value = excluded.pref_value;",
(user_id, key, json.dumps(value)))
return f"Preferences updated: {list(new_preferences.keys())}"
👉 Tìm nhận xét # TODO: implement recall_user_preferences tools bên trong hàm 05/tools.py.
Thay thế toàn bộ dòng này bằng mã sau:
def recall_user_preferences(tool_context: ToolContext) -> Dict[str, Any]:
user_id = tool_context.session.user_id
preferences = {}
with sqlite3.connect(USER_DB_FILE) as conn:
rows = conn.execute("SELECT pref_key, pref_value FROM user_preferences WHERE user_id = ?", (user_id,)).fetchall()
if not rows: return {"message": "No preferences found."}
for key, value_str in rows: preferences[key] = json.loads(value_str)
return preferences
Chỉ dẫn này buộc phải có một quy trình làm việc:
instruction="""
1. RECALL FIRST: First action MUST be `recall_user_preferences`.
3. LEARN: If a user states a new preference, use `save_user_preferences`.
"""
Bước 2: Thực thi
👉💻 Trong cửa sổ dòng lệnh Cloud Shell, hãy mở tệp trong Trình chỉnh sửa Cloud Shell bằng cách chạy lệnh:
cloudshell edit ~/memory_agent_starter/05_profile_agent/main.py
Mở ~/memory_agent_starter/05_profile_agent/main.py.
Không giống như các mô-đun trước, nơi ADK tự động xử lý trạng thái, ở đây Tác nhân sẽ kiểm soát.
- Hàm này chọn gọi
recall_user_preferenceskhi bắt đầu. - Trợ lý chọn gọi
save_user_preferenceskhi bạn nói "Tôi ăn chay".
Bước 3: Tạo hồ sơ
👉💻 Chạy tập lệnh:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/05_profile_agent/main.py
Hãy thử quy trình trò chuyện sau:
- "Chào bạn, hãy lên kế hoạch cho một bữa tối." -> Nhân viên hỗ trợ kiểm tra cơ sở dữ liệu và không tìm thấy gì. Hỏi về lựa chọn ưu tiên.
- "Tôi ăn chay trường." -> Tác nhân lưu "thuần chay" vào cơ sở dữ liệu.
- Khởi động lại tập lệnh.
- "Chào bạn, hãy lên kế hoạch cho một bữa tối." -> Nhân viên hỗ trợ kiểm tra cơ sở dữ liệu, thấy "thuần chay" và đề xuất ngay một nhà hàng thuần chay.
Điểm chính cần ghi nhớ .
Quy tắc số 5 về Bộ nhớ: Đối với dữ liệu phức tạp, có cấu trúc, hãy cung cấp cho tác nhân Công cụ đọc/ghi. Để LLM tự quản lý bộ nhớ dài hạn.
8. Bộ não – Bộ nhớ đa phương thức

Ý tưởng: "Trải nghiệm của con người"
Con người ghi nhớ nhiều hơn văn bản. Chúng ta nhớ bầu không khí của một bức ảnh, âm thanh của một giọng nói, cảm xúc của một video.
Vertex AI Memory Bank cho phép tác nhân xử lý Bộ nhớ đa phương thức. Mô hình này có thể nhập hình ảnh, video và âm thanh, "hiểu" chúng và truy xuất chúng sau này.
Bước 1: Cấu hình
👉💻 Trong cửa sổ dòng lệnh Cloud Shell, hãy mở tệp trong Trình chỉnh sửa Cloud Shell bằng cách chạy lệnh:
cloudshell edit ~/memory_agent_starter/06_multimodal_agent/main.py
👉 Mở 06_multimodal_agent/main.py. Tìm nhận xét # TODO: Configure Memory Bank Topic.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
travel_topics = [
MemoryTopic(
managed_memory_topic=ManagedMemoryTopic(
managed_topic_enum=ManagedTopicEnum.USER_PREFERENCES
)
),
MemoryTopic(
managed_memory_topic=ManagedMemoryTopic(
managed_topic_enum=ManagedTopicEnum.USER_PERSONAL_INFO
)
),
MemoryTopic(
custom_memory_topic=CustomMemoryTopic(
label="travel_experiences",
description="""Memorable travel experiences including:
- Places visited and impressions
- Favorite restaurants, cafes, and food experiences
- Preferred accommodation types and locations
- Activities enjoyed (museums, hiking, beaches, etc.)
- Travel companions and social preferences
- Photos and videos from trips with location context""",
)
),
MemoryTopic(
custom_memory_topic=CustomMemoryTopic(
label="travel_preferences",
description="""Travel style and preferences:
- Budget preferences (luxury, mid-range, budget)
- Transportation preferences (flying, trains, driving)
- Trip duration preferences
- Season and weather preferences
- Cultural interests and language abilities
- Dietary restrictions and food preferences""",
)
),
MemoryTopic(
custom_memory_topic=CustomMemoryTopic(
label="travel_logistics",
description="""Practical travel information:
- Passport and visa information
- Frequent flyer numbers and hotel loyalty programs
- Emergency contacts
- Medical considerations and insurance
- Packing preferences and essentials
- Time zone preferences and jet lag strategies""",
)
),
]
Tìm bình luận # TODO: Configure Memory Bank Customization
Thay thế toàn bộ dòng này bằng đoạn mã sau:
memory_bank_config = {
"customization_configs": [
{
"memory_topics": travel_topics,
}
],
"similarity_search_config": {
"embedding_model": f"projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/gemini-embedding-001"
},
"generation_config": {
"model": f"projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/gemini-2.5-flash"
},
}
Bước 2: Nhập dữ liệu về thế giới
Trong test_trip_planner, chúng tôi gửi:
- Tin nhắn văn bản ("Xin chào")
- Hình ảnh (Địa danh)
- Video (Địa Trung Hải)
- Một đoạn âm thanh (Ghi chú thoại về Gaeta)
Tìm nhận xét # TODO create session service and memory service bên trong hàm 6_multimodal_agent/main.py.
Thay thế toàn bộ dòng này bằng đoạn mã sau:
session_service = VertexAiSessionService(
project=PROJECT_ID, location=LOCATION, agent_engine_id=agent_engine_id
)
memory_service = VertexAiMemoryBankService(
project=PROJECT_ID, location=LOCATION, agent_engine_id=agent_engine_id
)
👉 Trong cùng tệp 06_multimodal_agent/main.py, hãy tìm nhận xét # TODO: create memory from session
Thay thế toàn bộ dòng này bằng đoạn mã sau:
await memory_service.add_session_to_memory(final_session_state)
Đây là dòng mã kỳ diệu. Nó gửi tất cả nội dung đa phương tiện đó đến Vertex AI để xử lý và lập chỉ mục.
Bước 3: Truy xuất
👉💻 Trong cửa sổ dòng lệnh Cloud Shell, hãy mở tệp trong Trình chỉnh sửa Cloud Shell bằng cách chạy lệnh:
cloudshell edit ~/memory_agent_starter/06_multimodal_agent/agent.py
Tác nhân có PreloadMemoryTool.
tools=[PreloadMemoryTool(), budget_tool]
Khi một phiên mới bắt đầu, công cụ này sẽ tự động tìm kiếm trong Ngân hàng bộ nhớ để tìm những trải nghiệm có liên quan trong quá khứ và đưa chúng vào bối cảnh.
Bước 4: Chạy Brain
👉💻 Trong Cloud Shell, hãy chạy tập lệnh (Lưu ý: Bạn cần có một dự án trên đám mây của Google Cloud đã bật Vertex AI):
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/06_multimodal_agent/main.py
Xem bước xác minh cuối cùng:
"Dựa trên hình ảnh, video VÀ âm thanh mà tôi đã chia sẻ với bạn trước đây..."
Nhân viên hỗ trợ sẽ trả lời:
"Bạn nên ghé thăm Gaeta! Bạn đã cho tôi xem một video về Địa Trung Hải và một đoạn âm thanh mà bạn nói rằng bạn yêu thích Gaeta."
Nó kết nối các điểm trên các loại phương tiện truyền thông khác nhau từ quá khứ.
Điểm chính cần ghi nhớ .
Quy tắc số 6 về bộ nhớ: Sử dụng Vertex AI Memory Bank để có trải nghiệm bộ nhớ tối ưu. Công cụ này hợp nhất văn bản, hình ảnh và video thành một bộ não duy nhất có thể tìm kiếm được.
9. Kết luận
Bạn đã tiến hoá từ Cá vàng hay quên thành Voi đa phương thức.
Bạn đã xây dựng | Chức năng |
Tác nhân phiên | Bộ nhớ đàm thoại ngắn hạn |
Nhiều tác nhân | Kỷ niệm chung của nhóm |
Tác nhân cố định | Nhật ký dài hạn |
Tác nhân có trạng thái | Bộ nhớ linh động, tự cập nhật |
Tác nhân hồ sơ | Bộ nhớ dữ liệu có cấu trúc |
Tác nhân đa phương thức | Bộ nhớ cảm giác giống con người |
Niềm tin được xây dựng dựa trên trí nhớ. Bằng cách triển khai các mẫu này, bạn sẽ tạo ra những tác nhân tôn trọng thời gian và nhật ký của người dùng, từ đó mang lại những lượt tương tác sâu hơn và hiệu quả hơn.
Bắt đầu xây dựng tác nhân được cá nhân hoá của bạn ngay hôm nay!