วิธีทดสอบ Agent ประเภท ADK ที่เขียนไปยัง Google ชีตในเครื่องก่อนที่จะติดตั้งใช้งานใน Cloud Run

1. บทนำ

ภาพรวม

ในโพสต์นี้ คุณจะได้สร้างเอเจนต์ Gemini โดยใช้ Google Agent Development Kit (ADK) และ FastAPI ก่อนการทำให้ใช้งานได้ คุณจะกำหนดค่าข้อมูลเข้าสู่ระบบเริ่มต้นของแอปพลิเคชัน (ADC) เพื่อทดสอบในเครื่องโดยใช้บัญชีบริการเดียวกันกับข้อมูลประจำตัวของบริการ Cloud Run

หากต้องการสื่อสารกับ Google ชีต แอปพลิเคชันของคุณต้องมีโทเค็นเพื่อการเข้าถึง OAuth ที่มีขอบเขตที่เหมาะสมเพื่อเข้าถึงสเปรดชีต คุณจะได้เรียนรู้วิธีขอโทเค็นเพื่อการเข้าถึงนี้เมื่อเรียกใช้ในเครื่องและใน Cloud Run ด้วย ADC

หมายเหตุเกี่ยวกับคำศัพท์

คุณอาจคุ้นเคยกับคำว่า "การแอบอ้างเป็นบุคคลอื่น" หรือ "การใช้สิทธิ์เดียวกัน" มากกว่า ใน Google Cloud การแอบอ้างเป็นบัญชีบริการจะช่วยให้ผู้ใช้หลักที่ได้รับการตรวจสอบสิทธิ์เข้าถึงทุกอย่างที่บัญชีบริการเข้าถึงได้ มีเพียงหลักการที่ได้รับการตรวจสอบสิทธิ์ซึ่งมีสิทธิ์ที่เหมาะสมเท่านั้นที่สามารถแอบอ้างเป็นบัญชีบริการได้ อ่านเพิ่มเติมได้ที่ https://docs.cloud.google.com/iam/docs/service-account-overview#impersonation

สิ่งที่คุณจะได้เรียนรู้

  • วิธีกำหนดค่าข้อมูลรับรองเริ่มต้นของแอปพลิเคชัน (ADC) สำหรับสภาพแวดล้อมในเครื่อง
  • วิธีสร้างเอเจนต์ ADK ที่อ่านและเขียนไปยัง Google ชีตได้
  • วิธีติดตั้งใช้งานเอเจนต์ใน Cloud Run

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

ข้อกำหนดเบื้องต้น

  • คุณเข้าสู่ระบบ Cloud Console แล้ว
  • คุณเคยทำให้บริการ Cloud Run ใช้งานได้แล้ว เช่น คุณสามารถทำตามขั้นตอนการทำให้บริการ Cloud Run ใช้งานได้เพื่อเริ่มต้นใช้งาน

ตั้งค่าตัวแปรสภาพแวดล้อม

คุณตั้งค่าตัวแปรสภาพแวดล้อมที่จะใช้ตลอดทั้งโค้ดแล็บนี้ได้

คุณดูรหัสชีตได้ใน URL ของ Google ชีตเมื่อคัดลอกลิงก์แชร์ เช่น https://docs.google.com/spreadsheets/d/YOUR_SPREADSHEET_ID/edit?usp=sharing

PROJECT_ID=<YOUR-PROJECT-ID>
REGION=<YOUR_REGION>
SPREADSHEET_ID=<YOUR_SPREADSHEET_ID>
SA_NAME=sheet-agent-sa
SERVICE_ACCOUNT_EMAIL=$SA_NAME@$PROJECT_ID.iam.gserviceaccount.com

เปิดใช้ Google Cloud APIs ที่จำเป็น

gcloud services enable \
  sheets.googleapis.com \
  aiplatform.googleapis.com \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  run.googleapis.com \
  logging.googleapis.com \
  --project=$PROJECT_ID

สร้างบัญชีบริการ

ก่อนอื่น ให้สร้างบัญชีบริการด้วยคำสั่งต่อไปนี้

gcloud iam service-accounts create $SA_NAME \
    --description="Service account for spreadsheet agent codelab" \
    --display-name="Spreadsheet Agent Service Account" \
    --project=$PROJECT_ID

จากนั้นให้บทบาทผู้ใช้ Vertex AI แก่บัญชีบริการ (จำเป็นสำหรับโมเดล Gemini ใน Vertex AI)

gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
    --role="roles/aiplatform.user"

ให้สิทธิ์แก่ข้อมูลประจำตัว gcloud ในการแอบอ้างเป็นบัญชีบริการ (จำเป็นสำหรับการพัฒนาในเครื่อง) คุณดูข้อมูลประจำตัว gcloud ได้โดยเรียกใช้ gcloud auth list

USER_EMAIL=$(gcloud config get-value account)

gcloud iam service-accounts add-iam-policy-binding $SERVICE_ACCOUNT_EMAIL \
    --member="user:$USER_EMAIL" \
    --role="roles/iam.serviceAccountTokenCreator" \
    --project=$PROJECT_ID
  1. เปิด Google ชีตในเบราว์เซอร์
  2. คลิกปุ่มแชร์
  3. วางอีเมลของบัญชีบริการ $SERVICE_ACCOUNT_EMAIL และให้สิทธิ์ผู้แก้ไข

3. สร้างแอป

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

mkdir local-adk-sheets-codelab && cd $_

จากนั้นสร้างไฟล์ main.py ที่มีเนื้อหาต่อไปนี้

import os
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from google.auth import default
from googleapiclient.discovery import build
from google.adk.agents.llm_agent import Agent
from google.adk.runners import InMemoryRunner

# 1. Environment and Global Google Sheets Client Setup (ADC)
SPREADSHEET_ID = os.environ.get("SPREADSHEET_ID")
if not SPREADSHEET_ID:
    raise ValueError("SPREADSHEET_ID environment variable is missing. Please set it before running.")

credentials, _ = default(scopes=['https://www.googleapis.com/auth/spreadsheets'])
sheets_api = build('sheets', 'v4', credentials=credentials).spreadsheets()

# 2. Tools
def read_spreadsheet(range_name: str) -> dict:
    """Reads values from the Google Spreadsheet for a given range.
   
    Args:
        range_name: The A1 notation or R1C1 notation of the range to retrieve, e.g., 'Sheet1!A1:D10'.
    """
    return sheets_api.values().get(spreadsheetId=SPREADSHEET_ID, range=range_name).execute()

def update_spreadsheet(range_name: str, values: list[list[str]]) -> dict:
    """Updates the Google Spreadsheet range with the specified grid of values.
   
    Args:
        range_name: The A1 notation or R1C1 notation of the range to update, e.g., 'Sheet1!C2'.
        values: A list of lists of strings representing the grid of values to write.
    """
    return sheets_api.values().update(
        spreadsheetId=SPREADSHEET_ID,
        range=range_name,
        valueInputOption="USER_ENTERED",
        body={"values": values}
    ).execute()

# 3. Agent Definition
MODEL_NAME = os.environ.get("GEMINI_MODEL", "gemini-3.1-flash-lite")
root_agent = Agent(
    name="spreadsheet_agent",
    model=MODEL_NAME,
    instruction="""You are a helpful spreadsheet assistant.
    You can read and write to the user's Google Spreadsheet using the tools provided.
    Always use the appropriate tools when the user asks you to read or update a spreadsheet.
    When updating a range, make sure the values parameter is a list of lists (e.g. [[value]]).
    Be concise and helpful in your responses.""",
    description="An agent that can read and write to a specific Google Spreadsheet.",
    tools=[read_spreadsheet, update_spreadsheet]
)

# 4. FastAPI Application Setup
app = FastAPI()

class ChatRequest(BaseModel):
    prompt: str

@app.post("/chat")
async def chat_endpoint(request: ChatRequest):
    try:
        async with InMemoryRunner(app_name="sheets_agent_app", agent=root_agent) as runner:
            events = await runner.run_debug(request.prompt, quiet=True)
           
            # Extract the final response text
            texts = [
                "".join(p.text for p in e.content.parts if p.text)
                for e in reversed(events) if e.content and e.content.parts
            ]
            return {"response": next((t for t in texts if t), "No response from agent.")}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

จากนั้นสร้างไฟล์ requirements.txt ที่มีเนื้อหาต่อไปนี้

fastapi>=0.100.0
uvicorn>=0.22.0
google-adk>=1.27.1
google-auth
google-api-python-client

4. ทดสอบบริการในพื้นที่

gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_EMAIL
GOOGLE_GENAI_USE_VERTEXAI=1 GOOGLE_CLOUD_PROJECT=$PROJECT_ID SPREADSHEET_ID=$SPREADSHEET_ID uvicorn main:app --host 0.0.0.0 --port 8080

ตอนนี้ให้ทดสอบเอเจนต์จากเทอร์มินัลอื่นโดยทำดังนี้

curl -X POST http://localhost:8080/chat \
    -H "Content-Type: application/json" \
    -d '{"prompt": "Update spreadsheet '$SPREADSHEET_ID' at range Sheet1!A1 with the value hello world"}'

เซิร์ฟเวอร์ควรตอบกลับว่า {"response":"The spreadsheet at Sheet1!A1 has been updated with the value \"hello world\"."}

5. ทำให้ใช้งานได้กับ Cloud Run

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

gcloud run deploy local-adk-sheets-codelab \
    --source . \
    --region=$REGION \
    --set-env-vars GOOGLE_GENAI_USE_VERTEXAI=1,GOOGLE_CLOUD_PROJECT=$PROJECT_ID,GOOGLE_CLOUD_LOCATION=global,SPREADSHEET_ID=$SPREADSHEET_ID \
    --service-account $SERVICE_ACCOUNT_EMAIL \
    --no-allow-unauthenticated \
    --project=$PROJECT_ID

เมื่อการติดตั้งใช้งานเสร็จสิ้น ให้ส่งพรอมต์ไปยังบริการ Cloud Run

# Retrieve the Service URL
SERVICE_URL=$(gcloud run services describe local-adk-sheets-codelab --region $REGION --format 'value(status.url)')
curl -X POST $SERVICE_URL/chat \
    -H "Authorization: bearer $(gcloud auth print-identity-token)" \
    -H "Content-Type: application/json" \
    -d '{"prompt": "Update spreadsheet '$SPREADSHEET_ID' at range Sheet1!A1 with the value hello world"}'

คุณควรได้รับการตอบกลับเป็น {"response":"OK. I've updated cell A1 in Sheet1 with \"hello world\"."}

ตอนนี้ให้เปิด Google ชีต คุณจะเห็นค่า "hello world" ในเซลล์แรก

6. ยินดีด้วย

ขอแสดงความยินดีที่ทำ Codelab เสร็จสมบูรณ์

สิ่งต่อไปที่ควรทำ

เราขอแนะนำให้คุณดูเอกสารต่อไปนี้เพื่อขยายความสามารถของเอเจนต์

สิ่งที่เราได้พูดถึง

  • วิธีกำหนดค่าข้อมูลรับรองเริ่มต้นของแอปพลิเคชัน (ADC) สำหรับสภาพแวดล้อมในเครื่อง
  • วิธีสร้างเอเจนต์ ADK ที่อ่านและเขียนไปยัง Google ชีตได้
  • วิธีติดตั้งใช้งานเอเจนต์ใน Cloud Run

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

หากต้องการหลีกเลี่ยงการเรียกเก็บเงินโดยไม่ตั้งใจ (เช่น หากฟังก์ชัน Cloud Run นี้ได้รับการเรียกใช้โดยไม่ตั้งใจมากกว่าการจัดสรรการเรียกใช้ Cloud Run รายเดือนในระดับฟรี) คุณสามารถลบบริการ Cloud Run หรือลบโปรเจ็กต์ได้

หากต้องการลบบริการ Cloud Run ให้ไปที่ Cloud Run ใน Cloud Console ที่ https://console.cloud.google.com/run/ แล้วลบบริการ local-adk-sheets-codelab ที่คุณสร้างใน Codelab นี้

หากเลือกที่จะลบทั้งโปรเจ็กต์ ให้ไปที่ https://console.cloud.google.com/cloud-resource-manager เลือกโปรเจ็กต์ที่สร้างในขั้นตอนที่ 2 แล้วเลือก "ลบ" หากลบโปรเจ็กต์ คุณจะต้องเปลี่ยนโปรเจ็กต์ใน Cloud SDK คุณดูรายการโปรเจ็กต์ทั้งหมดที่พร้อมใช้งานได้โดยเรียกใช้ gcloud projects list