สร้างและติดตั้งใช้งานเอเจนต์หนังสือเดินทางสัตว์เลี้ยงใน Cloud Run

1. ภาพรวม

ใน Codelab นี้ คุณจะได้เรียนรู้วิธีติดตั้งใช้งานแอป Pet Passport ซึ่งเป็น AI Agent ที่ใช้ Model Context Protocol (MCP) เพื่อรวมการวิเคราะห์ข้อมูลและบริการตำแหน่ง

แอปนี้ช่วยให้ผู้ใช้วางแผนวันหยุดที่สมบูรณ์แบบกับสุนัขได้โดยอิงตามความนิยมของสายพันธุ์ในนิวยอร์กซิตี้ เอเจนต์ใช้เชนการให้เหตุผลแบบ "จากภาพรวมไปสู่รายละเอียด" ดังนี้

  1. การค้นพบเชิงกลยุทธ์ (BigQuery): ระบุรหัสไปรษณีย์ในนิวยอร์กซิตี้ที่มีประชากรสายพันธุ์หนึ่งๆ สูงที่สุด
  2. การดำเนินการในพื้นที่ (Maps): ใช้รหัสไปรษณีย์ดังกล่าวเป็นค่าความเอนเอียงของตำแหน่งเพื่อค้นหา "คาเฟ่ที่อนุญาตให้นำสัตว์เลี้ยงเข้า" และ "สวนสาธารณะสำหรับสุนัข"
  3. การสร้างแผนการเดินทาง: รวมข้อมูลเพื่อสร้างแผนการเดินทาง "หนังสือเดินทางสัตว์เลี้ยง" พร้อมลิงก์และรูปภาพที่คลิกได้

Agent สร้างขึ้นโดยใช้google-adk Framework และขับเคลื่อนโดย Gemini

หมายเหตุ: โค้ดโปรเจ็กต์ทั้งหมด รวมถึง UI ของส่วนหน้า พร้อมให้บริการบน GitHub ใน Codelab นี้ เราจะมุ่งเน้นไปที่ตรรกะหลักของเอเจนต์และการตั้งค่าโครงสร้างพื้นฐาน

2. การตั้งค่าและข้อกำหนด

ก่อนอื่น ให้ตรวจสอบว่าได้ตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์อย่างถูกต้อง

1. ตรวจสอบสิทธิ์ด้วย Google Cloud

ตั้งค่าโปรเจ็กต์ Google Cloud ที่ใช้งานอยู่และตรวจสอบสิทธิ์ ซึ่งจำเป็นต่อการให้ Agent เข้าถึง BigQuery และบริการอื่นๆ

gcloud config set project [YOUR-PROJECT-ID]
gcloud auth application-default login --project [YOUR-PROJECT-ID]

หมายเหตุ: หากพบข้อผิดพลาดเกี่ยวกับโปรเจ็กต์อื่นในระหว่างการตรวจสอบสิทธิ์ คุณสามารถข้ามข้อผิดพลาดดังกล่าวได้โดยการปิดใช้โปรเจ็กต์โควต้าและตั้งค่าด้วยตนเอง ดังนี้

gcloud auth application-default login --disable-quota-project
gcloud auth application-default set-quota-project [YOUR-PROJECT-ID]

2. ข้อกำหนดของซอฟต์แวร์

คุณต้องติดตั้งซอฟต์แวร์ต่อไปนี้ในเครื่องของคุณ

  • Python (ต้องใช้เวอร์ชัน 3.13 ขึ้นไป)
  • Git (เพื่อดาวน์โหลดที่เก็บ)

ดาวน์โหลดที่เก็บ

โค้ดสำหรับโปรเจ็กต์นี้อยู่ในที่เก็บ MCP ของ Google โคลนที่เก็บและไปที่โฟลเดอร์โปรเจ็กต์

git clone https://github.com/google/mcp.git
cd examples/petpassport

3. การติดตั้ง

ตอนนี้คุณมีไฟล์แล้ว มาตั้งค่าสภาพแวดล้อม Python กัน

  1. สร้างสภาพแวดล้อมเสมือน: วิธีนี้จะช่วยให้การพึ่งพากันแยกกัน
    python3 -m venv .venv
    
  2. เปิดใช้งานสภาพแวดล้อมเสมือน
    • ใน Linux/macOS ให้ทำดังนี้
      source .venv/bin/activate
      
    • บน Windows:
      .venv\Scripts\activate
      
  3. ติดตั้งการอ้างอิง
    pip install google-adk==1.28.0 python-dotenv google-genai pillow uvicorn
    

เปิดใช้ Cloud API

เปิดใช้ API ต่อไปนี้ในโปรเจ็กต์

gcloud services enable \
  bigquery.googleapis.com \
  aiplatform.googleapis.com \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  run.googleapis.com \
  storage.googleapis.com

เลือกภูมิภาค

ตั้งค่าภูมิภาคเป็นตัวแปรสภาพแวดล้อมในเชลล์

export REGION=us-central1

4. รับคีย์ API

หากต้องการใช้บริการ Maps และ Gemini คุณต้องขอรับคีย์ API และจัดเก็บไว้ในไฟล์ .env ในรูทของโปรเจ็กต์

1. คีย์ API ของ Google Maps

  1. ไปที่ คอนโซล Google Cloud
  2. ไปที่ API และบริการ > ข้อมูลเข้าสู่ระบบ
  3. คลิกสร้างข้อมูลเข้าสู่ระบบ > คีย์ API
  4. คัดลอกคีย์ที่สร้างขึ้นแล้วเพิ่มลงในไฟล์ .env เป็น MAPS_API_KEY=[YOUR_KEY]
  5. (แนะนํา) จํากัดคีย์เพื่อให้อนุญาตเฉพาะ Maps API ที่เซิร์ฟเวอร์ MCP ใช้

2. คีย์ Gemini API (AI Studio)

  1. ไปที่ Google AI Studio
  2. คลิกรับคีย์ API หรือไปที่ส่วนคีย์ API
  3. คลิก Create API key
  4. คัดลอกคีย์แล้วเพิ่มลงในไฟล์ .env เป็น GEMINI_API_KEY=[YOUR_KEY]

5. ติดตั้งการอ้างอิง

สร้างไฟล์ requirements.txt ในโฟลเดอร์ petpassport/ โดยทำดังนี้

google-adk==1.28.0
python-dotenv
google-genai
pillow

6. ตรวจสอบสิทธิ์เซิร์ฟเวอร์ MCP

แอปพลิเคชันนี้ใช้เซิร์ฟเวอร์ Model Context Protocol (MCP) เพื่อโต้ตอบกับ Google Maps และ BigQuery หากต้องการตรวจสอบสิทธิ์เซิร์ฟเวอร์เหล่านี้ คุณต้องกำหนดค่าตัวแปรสภาพแวดล้อมและส่วนหัวที่เหมาะสม

  1. MCP ของ Google Maps: ต้องมีคีย์ Maps API ที่ถูกต้องซึ่งส่งในส่วนหัว X-Goog-Api-Key
  2. BigQuery MCP: ต้องใช้ข้อมูลเข้าสู่ระบบ OAuth ที่มีสิทธิ์เข้าถึงบริการ BigQuery เอเจนต์จะใช้บัญชีบริการ Compute เริ่มต้นเมื่อเรียกใช้ใน Cloud Run หรือใช้ข้อมูลเข้าสู่ระบบในเครื่องเมื่อเรียกใช้ในเครื่อง

เรามีสคริปต์การตั้งค่า setup/setup_env.sh ในที่เก็บที่จะช่วยกำหนดค่าตัวแปรเหล่านี้ในไฟล์ .env

7. สร้างตาราง BigQuery

ก่อนที่ตัวแทนจะค้นหาข้อมูลใบอนุญาตสุนัขได้ เราต้องสร้างชุดข้อมูลและตารางใน BigQuery แล้วโหลดข้อมูล

เรามีสคริปต์การตั้งค่า setup/setup_bigquery.sh ที่จะดำเนินการตามขั้นตอนต่อไปนี้

  1. สร้าง Bucket ของ Cloud Storage ชื่อ pet-passport-data-[PROJECT_ID] เพื่อจัดเก็บข้อมูลดิบ
  2. ดาวน์โหลดชุดข้อมูลการออกใบอนุญาตสุนัขในนิวยอร์ก (CSV) ที่เป็นแบบสาธารณะ
  3. อัปโหลด CSV ไปยังที่เก็บข้อมูล
  4. สร้างชุดข้อมูล BigQuery ชื่อ nyc_dogs
  5. โหลดข้อมูลจาก Bucket ลงในตารางชื่อ licenses ในชุดข้อมูล

หากต้องการเรียกใช้สคริปต์การตั้งค่า ให้เรียกใช้คำสั่งต่อไปนี้ในเทอร์มินัล

bash setup/setup_bigquery.sh

8. เชื่อมต่อกับเซิร์ฟเวอร์ MCP

ส่วนสำคัญของแอปนี้คือการใช้ MCP เพื่อเชื่อมต่อกับข้อมูลและบริการ ในส่วนนี้ คุณจะได้กำหนดค่าชุดเครื่องมือ MCP สำหรับ BigQuery และ Google Maps ในไฟล์ที่ชื่อ petpassport/tools.py

โค้ด tools.py ที่สมบูรณ์

ต่อไปนี้คือการติดตั้งใช้งานทั้งหมดสำหรับ tools.py ซึ่งรวมถึงชุดเครื่องมือ MCP และเครื่องมือที่กำหนดเองสำหรับการคงอยู่ของรูปภาพและข้อมูล เราได้เพิ่มประสิทธิภาพโค้ดนี้เพื่อลดความซ้ำซ้อนโดยย้ายความละเอียดของกลุ่มไปที่ระดับโมดูล

import os
import dotenv
import google.auth
import time
import datetime
from google.cloud import storage
from PIL import Image
from google import genai
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams 

MAPS_MCP_URL = "https://mapstools.googleapis.com/mcp" 
BIGQUERY_MCP_URL = "https://bigquery.googleapis.com/mcp" 

PROJECT_ID = os.getenv('GOOGLE_CLOUD_PROJECT', 'project_not_set')
BUCKET_NAME = f"pet-passport-data-{PROJECT_ID}" 

def get_maps_mcp_toolset():
    dotenv.load_dotenv()
    maps_api_key = os.getenv('MAPS_API_KEY', 'no_api_found')
    
    tools = MCPToolset(
        connection_params=StreamableHTTPConnectionParams(
            url=MAPS_MCP_URL,
            headers={    
                "X-Goog-Api-Key": maps_api_key
            },
            timeout=30.0,          
            sse_read_timeout=300.0
        )
    )
    print("Maps MCP Toolset configured.")
    return tools


def get_bigquery_mcp_toolset():   
    credentials, project_id = google.auth.default(
            scopes=["https://www.googleapis.com/auth/bigquery"]
    )

    credentials.refresh(google.auth.transport.requests.Request())
    oauth_token = credentials.token
        
    HEADERS_WITH_OAUTH = {
        "Authorization": f"Bearer {oauth_token}",
        "x-goog-user-project": project_id
    }

    tools = MCPToolset(
        connection_params=StreamableHTTPConnectionParams(
            url=BIGQUERY_MCP_URL,
            headers=HEADERS_WITH_OAUTH,
            timeout=30.0,          
            sse_read_timeout=300.0
        )
    )
    print("BigQuery MCP Toolset configured.")
    return tools

def generate_pet_passport_photo(prompt: str, image_path: str = None) -> str:
    """Generates an image using gemini-3.1-flash-image-preview based on a prompt and a reference image."""
    client = genai.Client()
    output_path = f"/tmp/pet_passport_{int(time.time())}.png"
    
    try:
        image = Image.open(image_path)
        response = client.models.generate_content(
            model="gemini-3.1-flash-image-preview",
            contents=[prompt, image],
        )
        
        for part in response.parts:
            if part.inline_data is not None:
                generated_image = part.as_image()
                generated_image.save(output_path)
                
                # Upload to GCS and generate signed URL
                try:
                    storage_client = storage.Client()
                    bucket = storage_client.bucket(BUCKET_NAME)
                    blob_name = os.path.basename(output_path)
                    blob = bucket.blob(blob_name)
                    
                    blob.upload_from_filename(output_path)
                    
                    url = blob.generate_signed_url(
                        version="v4",
                        expiration=datetime.timedelta(hours=24),
                        method="GET",
                    )
                    return url
                except Exception as e:
                    print(f"Error uploading image to GCS: {e}")
                    return output_path
                
        raise ValueError("No image was returned by the model.")
    except Exception as e:
        print(f"Error generating image: {e}")
        raise

def save_pet_passport(user_id: str, breed: str, postal_code: str, route_details: str, image_paths: list[str] = None) -> str:
    """Appends the generated itinerary to the user's history in GCS."""
    try:
        storage_client = storage.Client()
        bucket = storage_client.bucket(BUCKET_NAME)
        blob = bucket.blob(f"user-{user_id}.json")
        
        # Download existing or start fresh
        # ... (Implementation details hidden for brevity) ...
        return "Success"
    except Exception as e:
        print(f"Error saving path: {e}")
        raise

คำอธิบายรหัส: tools.py

  • get_maps_mcp_toolset และ get_bigquery_mcp_toolset กำหนดค่าไคลเอ็นต์ MCP ด้วยปลายทางและส่วนหัวการตรวจสอบสิทธิ์ที่ถูกต้อง
  • generate_pet_passport_photo ใช้ Gemini เพื่อสร้างฉากและอัปโหลดผลลัพธ์ไปยัง Google Cloud Storage โดยจะแสดงผล URL ที่ลงนามแล้วไปยังส่วนหน้าเพื่อให้อยู่รอดได้เมื่อเซิร์ฟเวอร์รีสตาร์ท

9. การสร้าง Agent

เมื่อกำหนดค่าเครื่องมือแล้ว ก็ได้เวลาสร้าง "สมอง" ของเอเจนต์ คุณจะใช้ Agent Development Kit (ADK) เพื่อสร้าง Agent ในไฟล์ชื่อ petpassport/agent.py

โค้ด agent.py ที่สมบูรณ์

ต่อไปนี้คือการติดตั้งใช้งานทั้งหมดสำหรับ agent.py ซึ่งเราจะกำหนด Agent และคำสั่งของ Agent

import os
import dotenv
import tools
from google.adk.agents import LlmAgent

dotenv.load_dotenv()

PROJECT_ID = os.getenv('GOOGLE_CLOUD_PROJECT', 'project_not_set')

maps_toolset = tools.get_maps_mcp_toolset()
bigquery_toolset = tools.get_bigquery_mcp_toolset()

root_agent = LlmAgent(
    model='gemini-2.5-pro',
    name='root_agent',
    instruction=f"""
        You are the Pet Passport Agent. Your goal is to help users find a fun walking route for their dog in NYC.
        
        When given a breed and a postal code, follow this flow:
        1. **Strategic Discovery:** Use BigQuery to find the most popular neighborhood for that breed in NYC.
        2. **Local Execution:** Use Maps to build a walking route with specific places (parks, cafes) in that area.
        
        **NO DIRECTIONS LINKS:** You must NOT include a Google Maps directions link (e.g., `https://www.google.com/maps/dir/...`) in your final response. Only provide links to individual places.
        
        After generating the itinerary, you MUST call the `save_pet_passport` tool to save this path to the user's profile. Pass a clean summary of the itinerary as `route_details`. The summary should include details (like rating, description from maps).
    """,
    tools=[maps_toolset, bigquery_toolset, tools.generate_pet_passport_photo, tools.save_pet_passport]
)

คำอธิบายรหัส: agent.py

  • เราจะนำเข้า tools โดยตรง (โครงสร้างแบบแบน) เพื่อรองรับสภาพแวดล้อมของคอนเทนเนอร์
  • ระบบจะเริ่มต้น Agent ด้วย gemini-2.5-pro
  • คำสั่งจะกำหนดห่วงโซ่ความคิดแบบหลายขั้นตอนที่เข้มงวด (BigQuery ก่อน แล้วจึงเป็น Maps) และห้ามอย่างเคร่งครัดไม่ให้สร้างเส้นทางเดินที่ทำให้เกิดความรกรุงรัง

10. การเรียกใช้แอปพลิเคชันในเครื่อง

ก่อนที่จะทําให้ใช้งานได้ใน Cloud Run คุณควรทดสอบแอปพลิเคชันในเครื่อง

  1. ตรวจสอบว่าคุณอยู่ในไดเรกทอรีโปรเจ็กต์
    cd examples/petpassport
    
  2. เริ่มเซิร์ฟเวอร์ FastAPI: เราใช้ uvicorn เพื่อเรียกใช้แอป จุดแรกเข้าคือ main.py ภายในโฟลเดอร์ petpassport
    uvicorn petpassport.main:app --reload
    
  3. เปิด UI: ไปที่ http://127.0.0.1:8000/ui/ ในเบราว์เซอร์เพื่อโต้ตอบกับอินเทอร์เฟซหนังสือเดินทางสัตว์เลี้ยง

11. การติดตั้งใช้งานกับ Cloud Run

เมื่อ Agent พร้อมแล้ว ก็ถึงเวลาทำให้ Agent ใช้งานได้ใน Cloud Run เราใช้คำสั่ง gcloud มาตรฐานโดยตรงเพื่อควบคุมสภาพแวดล้อมของคอนเทนเนอร์อย่างเข้มงวด

เรียกใช้คำสั่งต่อไปนี้จากไดเรกทอรีโปรเจ็กต์

gcloud run deploy petpassport \
  --source petpassport \
  --region $REGION \
  --allow-unauthenticated \
  --labels dev-tutorial=google-mcp

กำหนดค่าตัวแปรสภาพแวดล้อม

หลังจากติดตั้งใช้งานแล้ว ให้ไปที่บริการ Cloud Run ในคอนโซล Google Cloud และตั้งค่าตัวแปรสภาพแวดล้อมต่อไปนี้ในแท็บตัวแปรและความลับ

  • MAPS_API_KEY: คีย์ Google Maps API
  • GOOGLE_CLOUD_PROJECT: รหัสโปรเจ็กต์
  • PROJECT_ID: รหัสโปรเจ็กต์ (รองรับการซ้ำซ้อนสำหรับโมดูลเดิม)

12. ตัวอย่างพรอมต์

ลองโต้ตอบกับเอเจนต์ที่ใช้งานจริงโดยใช้พรอมต์ต่อไปนี้

  1. มาตรฐาน: "ฉันอยากไปเดินเล่นกับโกลเด้นรีทรีฟเวอร์ในนิวยอร์กซิตี้แถว 10021 หาเส้นทางที่มีคาเฟ่ให้หน่อย"
  2. สายพันธุ์อื่น: "ฉันมีสุนัขเฟรนช์บูลด็อกและอาศัยอยู่ในอัปเปอร์เวสต์ไซด์ (ใกล้ 10024) แนะนำเส้นทางเดินสั้นๆ ที่แวะจอดที่สวนสาธารณะสำหรับสุนัขยอดนิยม"
  3. พร้อมรูปภาพ: (อัปโหลดรูปภาพสุนัข) "นี่คือรูปภาพคอร์กีของฉัน เราอยู่ใกล้ 10013 ช่วยวางแผนวันหยุดที่สมบูรณ์แบบให้หน่อย"

13. ล้างข้อมูล

โปรดดำเนินการดังนี้เพื่อเลี่ยงไม่ให้เกิดการเรียกเก็บเงินสำหรับทรัพยากรที่ใช้ในบทแนะนำนี้

  • ลบบริการ Cloud Run: gcloud run services delete petpassport --region=$REGION
  • ลบ Bucket ของ GCS: gcloud storage rm -r gs://pet-passport-data-$PROJECT_ID