1. 소개
이 Codelab에서는 지속적이고 전문적인 지식을 추가하여 ADK 에이전트를 한 단계 업그레이드합니다. Agent Platform 세션으로 대화 상태를 관리하고, 메모리 뱅크로 장기 학습을 사용 설정하고, Spark 및 AlloyDB를 사용하여 RAG (검색 증강 생성)를 위한 복잡한 도시 규칙 데이터를 통합하는 방법을 알아봅니다.
실습할 내용
- 대화 지속성을 위해 Agent Platform 세션 을 구성합니다.
- 에이전트가 이전 상호작용에서 학습할 수 있도록 메모리 뱅크 를 구현합니다.
- Spark Lightning Engine 을 사용하여 도시 규칙 문서를 수집하고 처리합니다.
- AlloyDB 및 벡터 검색을 사용하여 RAG 시스템을 빌드합니다.
- 향상된 에이전트를 Agent Platform에 배포합니다.
필요한 항목
- 웹브라우저(예: Chrome)
- 결제가 사용 설정된 Google Cloud 프로젝트
- Python 및 SQL에 관한 기본 지식
예상 소요 시간: 60분
이 Codelab에서 만든 리소스의 비용은 $5 미만이어야 합니다.
2. 시작하기 전에
Google Cloud 프로젝트 만들기
- Google Cloud 콘솔의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.
- Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다. 프로젝트에 결제가 사용 설정되어 있는지 확인하는 방법을 알아보세요.
Cloud Shell 시작
Cloud Shell 은 Google Cloud에서 실행되는 명령줄 환경으로, 필요한 도구가 사전 로드되어 있습니다.
- Google Cloud 콘솔 상단에서 Cloud Shell 활성화 를 클릭합니다.
- Cloud Shell에 연결되면 인증을 확인합니다.
gcloud auth list - 프로젝트가 구성되었는지 확인합니다.
gcloud config get project - 프로젝트가 예상대로 설정되지 않은 경우 설정합니다.
export PROJECT_ID=<YOUR_PROJECT_ID> gcloud config set project $PROJECT_ID
인증 확인:
gcloud auth list
프로젝트 확인:
gcloud config get project
필요한 경우 설정:
export PROJECT_ID=<YOUR_PROJECT_ID> gcloud config set project $PROJECT_ID
API 사용 설정
이 명령어를 실행하여 세션 관리, Spark 처리, AlloyDB에 필요한 모든 API를 사용 설정합니다.
gcloud services enable \ aiplatform.googleapis.com \ run.googleapis.com \ alloydb.googleapis.com \ dataproc.googleapis.com \ documentai.googleapis.com \ storage.googleapis.com \ secretmanager.googleapis.com
3. 환경 설정
이 Codelab에서는 키노트 저장소의 사전 구성된 환경을 사용합니다.
- 저장소를 클론하고 프로젝트 폴더로 이동합니다.
git clone https://github.com/GoogleCloudPlatform/next-26-keynotes cd next-26-keynotes/devkey/enhancing-agents-with-memory
- Python 가상 환경을 설정하고 필요한 ADK 패키지를 설치합니다.
uv venv source .venv/bin/activate uv sync
환경 변수 구성
에이전트가 Agent Platform 및 AlloyDB에 연결하려면 특정 구성이 필요합니다.
- 샘플 환경 파일을 복사합니다.
cp .env.example .env
.env를 열고 다음 필드를 업데이트합니다.GOOGLE_CLOUD_PROJECT: 프로젝트 ID입니다.GOOGLE_CLOUD_LOCATION:us-central1입니다.ALLOYDB_CLUSTER_ID:rules-db입니다.
GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID> GOOGLE_CLOUD_LOCATION=global GOOGLE_GENAI_USE_VERTEXAI=TRUE GOOGLE_CLOUD_REGION=us-central1 ALLOYDB_CLUSTER_ID=rules-db
- 다음 도우미 스크립트를 실행하여 대화 세션 및 장기 메모리에 사용할 Agent Engine 인스턴스 를 만듭니다. 이렇게 하면
.env파일의AGENT_ENGINE_ID가 자동으로 채워집니다.
uv run utils/setup_agent_engine.py
성공하면 다음이 표시됩니다.
Creating Agent Engine instance...
Successfully created Agent Engine. ID: 1234567890
Updated .env with AGENT_ENGINE_ID=1234567890
4. 세션 관리로 에이전트 만들기
이 단계에서는 여러 차례에 걸쳐 대화 기록을 유지할 수 있는 마라톤 플래너 에이전트 를 초기화합니다. 이는 ADK App 클래스와 Agent Platform 세션 을 사용하여 이루어집니다.
에이전트 및 세션 서비스 초기화
planner_agent/agent.py를 엽니다. Agent Platform 세션 을 통합하기 위해 ADK 클래스를 추가하는 방법을 확인할 수 있습니다. 이를 통해 시간이 지남에 따라 에이전트를 상태 저장으로 만들고 필요에 따라 컨텍스트를 수정할 수 있습니다.
from google.adk.agents import LlmAgent
from google.adk.sessions import VertexAiSessionService
from vertexai.agent_engines import AdkApp
PROJECT_ID = os.environ.get("GOOGLE_CLOUD_PROJECT")
REGION = os.environ.get("GOOGLE_CLOUD_REGION", "us-central1")
# Initialize Vertex AI for regional services
if PROJECT_ID:
vertexai.init(project=PROJECT_ID, location=REGION)
# Define the agent logic
root_agent = LlmAgent(
name="planner_agent",
model="gemini-3-flash-preview",
instruction="You are a helpful marathon planning assistant...",
tools=[] # We will add tools in the next steps
)
def session_service_builder():
"""Builder for Agent Platform Sessions."""
return VertexAiSessionService(project=PROJECT_ID, location=REGION)
# Wrap the agent in an AdkApp to manage stateful context
app = AdkApp(
agent=root_agent,
session_service_builder=session_service_builder
)
5. 메모리 뱅크로 장기 학습 사용 설정
세션 관리는 개별 대화를 추적하지만 장기 메모리에서도 동일한 작업을 할 수 있습니다. 이 단계에서는 에이전트를 엔터프라이즈 지원 및 완전 관리형 메모리 서비스인 Agent Platform의 메모리 뱅크에 연결합니다.
메모리 뱅크 서비스 초기화
메모리 뱅크를 사용하면 에이전트가 여러 세션에서 컨텍스트를 다시 호출할 수 있습니다. 메모리 서비스를 포함하도록 planner_agent/agent.py를 업데이트합니다.
from google.adk.memory import VertexAiMemoryBankService
def memory_service_builder():
"""Builder for Agent Platform Memory Bank."""
return VertexAiMemoryBankService(
project=PROJECT_ID,
location=REGION,
agent_engine_id=AGENT_ENGINE_ID
)
자동 메모리 수집 구현
에이전트가 모든 턴에서 학습하도록 하려면 after_agent_callback을 추가합니다. 이 함수는 에이전트가 응답을 완료한 후에 트리거되므로 세션을 '소화'하고 관련 메모리를 뱅크에 저장할 수 있습니다.
- 콜백 함수를 정의합니다.
async def auto_save_memories(callback_context):
"""Callback to ingest the session into the memory bank after the turn."""
# In AdkApp, the memory service is available via the invocation context
if hasattr(callback_context._invocation_context, 'memory_service') and callback_context._invocation_context.memory_service:
await callback_context._invocation_context.memory_service.add_session_to_memory(
callback_context._invocation_context.session
)
- 콜백을
LlmAgent에 연결합니다.
root_agent = LlmAgent(
# ... other params
after_agent_callback=[auto_save_memories],
)
6. RAG용 AlloyDB 설정
도시 규칙 데이터를 수집하려면 먼저 이를 저장할 고성능 데이터베이스가 필요합니다. 이 단계에서는 AlloyDB 클러스터를 만들고 벡터 검색을 위한 데이터베이스 스키마를 초기화합니다.
1. AlloyDB 클러스터 및 기본 인스턴스 만들기
Cloud Shell에서 다음 명령어를 실행하여 클러스터와 기본 인스턴스를 만듭니다.
# Create the cluster gcloud alloydb clusters create rules-db \ --password=postgres \ --region=us-central1 # Create the primary instance with IAM authentication enabled gcloud alloydb instances create rules-db-primary \ --instance-type=PRIMARY \ --cpu-count=2 \ --region=us-central1 \ --cluster=rules-db \ --database-flags=alloydb.iam_authentication=on
2. 필수 IAM 역할 부여
관리형 AlloyDB MCP 서버를 사용하려면 ID에 특정 권한이 필요합니다. 다음 명령어를 실행하여 필요한 역할을 부여합니다.
export USER_EMAIL=$(gcloud config get-value account) # Role to use MCP tools gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="user:$USER_EMAIL" \ --role="roles/mcp.toolUser" # Role to execute SQL in AlloyDB gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="user:$USER_EMAIL" \ --role="roles/alloydb.admin" # Role for IAM database authentication gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="user:$USER_EMAIL" \ --role="roles/alloydb.databaseUser" # Create the IAM-based database user gcloud alloydb users create "$USER_EMAIL" \ --cluster=rules-db \ --region=us-central1 \ --type=IAM_BASED
3. AlloyDB Studio를 통해 데이터베이스 및 테이블 만들기
AlloyDB 데이터베이스와 테이블은 SQL을 통해 관리되므로 Google Cloud 콘솔에서 AlloyDB Studio 를 사용하여 스키마를 완료합니다.
- AlloyDB > 클러스터 로 이동하여
rules-db를 클릭합니다. - 왼쪽 탐색 메뉴에서 AlloyDB Studio 를 클릭합니다.
- postgres 사용자 및 설정한 비밀번호 (
postgres)를 사용하여 로그인합니다. - 다음 SQL을 실행하여 데이터베이스를 만듭니다.
CREATE DATABASE city_rules; - AlloyDB Studio에서 데이터베이스 연결을
city_rules로 전환하고 다음 SQL을 실행하여 확장 프로그램을 설치하고rules테이블을 만듭니다.-- Install extensions for vector search and ML CREATE EXTENSION IF NOT EXISTS vector; CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE; -- Create the rules table CREATE TABLE IF NOT EXISTS rules ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), text TEXT NOT NULL, city TEXT NOT NULL, embedding vector(3072) DEFAULT NULL ); -- Grant your IAM user access to the table (replace with your email) GRANT ALL PRIVILEGES ON TABLE rules TO "YOUR_EMAIL_ADDRESS";
7. Spark Lightning Engine으로 도시 규칙 데이터 수집
정말 정확한 계획을 제공하려면 에이전트에게 잘 만들어진 프롬프트뿐만 아니라 데이터 및 조직 컨텍스트에 대한 그라운딩 이 필요합니다. 이 단계에서는 Dataproc Serverless에서 Spark Lightning Engine 을 사용하여 대규모 도시 규칙 PDF를 처리하고 AlloyDB로 수집합니다.
Spark Lightning Engine을 사용해야 하는 이유
대규모로 에이전트를 그라운딩하려면 대량의 비정형 데이터를 처리해야 합니다. Spark Lightning Engine 은 Spark의 고성능 실행 엔진으로, 이러한 워크로드를 크게 가속화합니다. 여기서는 Google의 Document AI 를 사용하여 문서에 시맨틱 청킹 을 실행하는 데 사용합니다.
Spark 파이프라인 살펴보기
수집 로직은 spark-setup/spark_alloydb_processor.py에 정의되어 있습니다. 파이프라인은 다음 단계를 따릅니다.
- PDF 나열: Google Cloud Storage 버킷에서 문서 URI를 가져옵니다.
- 시맨틱 추출: UDF (사용자 정의 함수)를 사용하여 Document AI API를 호출합니다.
- AlloyDB에 쓰기: 추출된 텍스트 청크를
rules라는 AlloyDB 테이블에 저장합니다.
# Extract from spark_alloydb_processor.py
def process_document(gcs_uri: str):
# ... calls Document AI to parse PDF ...
return chunks
# Parallel processing with Spark Lightning Engine
process_udf = udf(process_document, chunk_schema)
chunked_df = uri_df.withColumn("chunks", process_udf(col("gcs_uri"))) \
.select(explode(col("chunks")).alias("chunk")) \
.select("chunk.*")
# Save to AlloyDB for Vector Search
chunked_df.write.format("jdbc") \
.option("url", jdbc_url) \
.option("dbtable", "rules") \
.mode("append") \
.save()
수집 작업 실행
제공된 스크립트를 사용하여 수집 프로세스를 트리거합니다.
./spark-setup/run_dataproc.sh
8. AlloyDB를 사용한 RAG
이제 도시 규칙 데이터가 AlloyDB에 있으므로 에이전트가 이를 사용하여 검색 증강 생성 (RAG) 을 실행할 수 있습니다. 이렇게 하면 마라톤 계획이 특정 도시 코드를 준수합니다.
RAG용 AlloyDB의 강력한 기능
AlloyDB는 벡터 검색에 탁월하므로 구조화된 데이터와 벡터 임베딩을 모두 같은 위치에 저장할 수 있습니다. 에이전트는 AlloyDB의 기본 제공 embedding 함수를 사용하여 가장 관련성이 높은 규칙 정보를 찾을 수 있습니다.
벡터 검색을 사용한 하이브리드 재현율
에이전트가 이 데이터에 액세스할 수 있도록 벡터 유사성을 사용하여 AlloyDB를 쿼리하는 도구를 제공합니다. 쿼리와 저장된 규칙 간의 거리를 계산하는 방법을 보여주는 hybrid_recall.sql에서 이 로직을 확인할 수 있습니다.
SELECT
text,
(embedding <=>
embedding('gemini-embedding-001',
'Restrictions for running a race on the Las Vegas strip')::vector)
as distance
FROM
rules
WHERE city = 'Las Vegas'
ORDER BY
distance ASC
LIMIT 5;
RAG 도구로 현지 규칙에 에이전트 기반
에이전트가 도구를 사용할 수 있도록 하려면 planner_agent/tools.py에서 도구를 정의한 다음 planner_agent/agent.py에 등록해야 합니다. Google Cloud의 관리형 원격 AlloyDB MCP 서버 를 사용하여 데이터베이스에 연결합니다.
- '하이브리드 재호출' 패턴을 사용하여
planner_agent/tools.py에서 도구를 정의합니다.streamable_http프로토콜을 사용하여 관리형 AlloyDB MCP 서버에 연결합니다.
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def get_local_and_traffic_rules(query: str) -> str:
"""Uses vector search in AlloyDB via managed MCP server."""
# Vector search query using built-in AlloyDB embedding functions
sql = f"SELECT text FROM rules WHERE city = 'Las Vegas' ORDER BY embedding <=> google_ml.embedding('gemini-embedding-001', '{query}')::vector ASC LIMIT 5;"
# Establish a streamable HTTP connection to the MCP server
async with streamablehttp_client(url, headers=get_auth_headers()) as (read_stream, write_stream, _):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()
result = await session.call_tool(
"execute_sql",
arguments={
"instance": full_instance_name,
"database": "city_rules",
"sqlStatement": sql
}
)
return "\n".join([c.text for c in result.content if hasattr(c, 'text')])
- 도구를 등록하고
planner_agent/agent.py를 완료합니다.
# ... imports ...
# Assemble the Agent
root_agent = LlmAgent(
name="planner_agent",
model="gemini-3-flash-preview",
instruction="You are a helpful marathon planning assistant...",
tools=[
get_local_and_traffic_rules,
],
after_agent_callback=[auto_save_memories],
)
# 2. Wrap the agent in an AdkApp to manage the stateful lifecycle
app = AdkApp(
agent=root_agent,
session_service_builder=session_service_builder,
memory_service_builder=memory_service_builder
)
9. 에이전트 기술을 사용한 전문가 가이던스
에이전트 기술 은 에이전트가 작업을 더 효과적으로 수행할 수 있도록 특정 안내, 가이던스, 리소스를 제공하는 자체 포함 모듈입니다. 모든 도구에 대한 복잡한 안내로 시스템 프롬프트를 어수선하게 만드는 대신 필요할 때만 로드되는 기능으로 전문 지식을 캡슐화할 수 있습니다.
Google은 에이전트가 데이터 쿼리 및 리소스 관리에 관한 업계 권장사항을 따르도록 Google 제품용 사전 빌드된 기술 (예: AlloyDB 및 BigQuery)을 제공합니다. Google Skills Depot에서 이러한 기술과 기타 전문 패턴을 살펴볼 수 있습니다. 여기에서 AlloyDB 기본 기술을 확인할 수 있습니다.
1. 기술 파일 살펴보기
planner_agent/skills/get-local-and-traffic-rules/SKILL.md에서 사전 구성된 기술 파일을 엽니다. 다음과 같이 표시됩니다.
---
name: get-local-and-traffic-rules
description: Retrieve local rules and traffic information for a specific jurisdiction.
---
# get_local_and_traffic_rules Skill
This skill provides guidelines on how to effectively use the `get_local_and_traffic_rules` tool.
## Overview
The `get_local_and_traffic_rules` tool interfaces with an AlloyDB database to perform vector similarity searches on a corpus of rules and traffic information using a provided natural language query.
## Usage Guidelines
1. **Query Specificity**: When calling the tool, provide specific details in the `query` argument. For example, instead of querying "food rules", use "rules regarding food vendors during public events".
2. **Contextual Use**: Use the tool when planning events or activities that require adherence to local municipal or state rules (e.g., street closures, noise ordinances, environmental rules).
3. **Handling Results**: The tool returns a string containing the text of the top 5 most relevant rules. If no error occurs, parse the returned string to inform your planning tasks.
4. **Error Handling**: If an error string is returned (e.g., "Error querying rules: ..."), you must report this failure or attempt an alternative approach if applicable.
## Underlying Mechanism
- The tool uses `google_ml.embedding` to convert the query into a vector representation.
- It calculates distance (`<=>`) against the `embedding` column in the `rules` table on an AlloyDB instance.
- Results are fetched in descending order of similarity, limited to 5 results.
2. 기술 등록 방법
planner_agent/agent.py에서 기술은 디렉터리에서 로드되어 에이전트의 도구에 추가됩니다. 코드는 다음과 같습니다.
import pathlib
from google.adk.skills import load_skill_from_dir
from google.adk.tools import skill_toolset
# Load the AlloyDB skill from its directory
alloydb_skill = load_skill_from_dir(pathlib.Path(__file__).parent / "skills" / "get-local-and-traffic-rules")
# Assemble the Agent with the Skill Toolset
root_agent = LlmAgent(
name="planner_agent",
model="gemini-3-flash-preview",
instruction="You are a helpful marathon planning assistant...",
tools=[
get_local_and_traffic_rules,
skill_toolset.SkillToolset(skills=[alloydb_skill])
],
after_agent_callback=[auto_save_memories],
)
10. 에이전트 테스트
- 에이전트를 로컬에서 시작합니다.
uv run adk run planner_agent
- 도시 규칙에 관한 질문을 합니다.
[user]: What are the rules for running a race on the Las Vegas strip?
에이전트는 get_local_and_traffic_rules 도구를 호출하고 AlloyDB에서 벡터 검색을 실행하며 Spark에서 처리한 공식 규칙 청크를 기반으로 답변을 반환합니다.
11. 에이전트 배포
Agent Platform에 배포
uv run adk deploy agent_engine \ --env_file .env \ planner_agent
12. 정리
지속적인 요금이 발생하지 않도록 하려면 이 Codelab 중에 만든 리소스를 삭제합니다.
AlloyDB 클러스터 삭제
# Delete the AlloyDB Cluster gcloud alloydb clusters delete rules-db --region=us-central1 --force
에이전트 런타임 앱 삭제
콘솔을 통해 또는 gcloud 명령어 (리소스 이름이 있는 경우)를 사용하여 추론 엔진 인스턴스를 삭제할 수 있습니다. 간단히 콘솔을 사용합니다.
- 에이전트 런타임 페이지로 이동합니다.
planner_agent를 선택하고 오른쪽의 점 3개 버튼을 클릭합니다.- 삭제 를 클릭합니다.
13. 축하합니다
축하합니다. 고급 메모리 및 데이터 그라운딩 기능을 사용하여 ADK 에이전트를 성공적으로 개선했습니다.
학습한 내용
- 상태 저장 에이전트: 대화 컨텍스트를 유지하기 위해 Agent Platform 세션을 통합합니다.
- 장기 학습: 에이전트가 사용자 상호작용에서 학습할 수 있도록 Agent Platform 메모리 뱅크를 연결합니다.
- 데이터 수집: Spark Lightning Engine 및 Document AI 를 사용하여 구조화되지 않은 문서를 처리합니다.
- RAG: AlloyDB 에서 벡터 검색 시스템을 빌드하여 에이전트를 실제 규칙에 기반합니다.
다음 단계
- Agent Platform 문서를 살펴보고 관리형 배포에 관해 자세히 알아보세요.
- 고급 RAG 패턴을 위해 AlloyDB 벡터 검색을 심층 분석합니다.
- Dataproc Serverless로 수집 파이프라인을 확장합니다.