چگونه قبل از استقرار در Cloud Run، یک عامل ADK را که در Google Sheet می‌نویسد، به صورت محلی آزمایش کنیم؟

۱. مقدمه

نمای کلی

در این پست، شما یک عامل Gemini را با استفاده از کیت توسعه عامل گوگل (ADK) و FastAPI خواهید ساخت. قبل از استقرار، اعتبارنامه‌های پیش‌فرض برنامه (ADC) را پیکربندی خواهید کرد تا به صورت محلی با استفاده از همان حساب سرویس به عنوان هویت سرویس Cloud Run آزمایش شود.

برای ارتباط با Google Sheets، برنامه شما به یک توکن دسترسی OAuth با دامنه مناسب برای دسترسی به صفحه گسترده نیاز دارد. شما یاد خواهید گرفت که چگونه این توکن دسترسی را هنگام اجرای محلی و در Cloud Run با ADC به دست آورید:

  • محلی: ADC اعتبارنامه‌ها را همانطور که توسط دستور gcloud auth application-default تولید شده است، پیدا می‌کند. می‌توانید اطلاعات بیشتر را اینجا بیابید.
  • در Cloud Run: ADC از سرور Metadata برای دریافت اعتبارنامه‌ها استفاده می‌کند. می‌توانید اطلاعات بیشتر را اینجا بیابید.

یادداشت اصطلاحات:

ممکن است با اصطلاحات «فرض کردن یک هویت» یا «فرض کردن همان مجوزها» بیشتر آشنا باشید. در Google Cloud، جعل هویت یک حساب کاربری سرویس به یک حساب کاربری اصلی تأیید شده اجازه می‌دهد به هر چیزی که حساب کاربری سرویس می‌تواند دسترسی داشته باشد، دسترسی داشته باشد. فقط حساب‌های کاربری اصلی تأیید شده با مجوزهای مناسب می‌توانند حساب‌های کاربری سرویس را جعل هویت کنند. می‌توانید اطلاعات بیشتر را در اینجا بخوانید https://docs.cloud.google.com/iam/docs/service-account-overview#impersonation

آنچه یاد خواهید گرفت

  • نحوه پیکربندی اعتبارنامه‌های پیش‌فرض برنامه (ADC) برای محیط محلی شما
  • چگونه یک عامل ADK ایجاد کنیم که بتواند یک صفحه Google را بخواند و بنویسد
  • نحوه استقرار عامل در Cloud Run

۲. تنظیمات و الزامات

پیش‌نیازها

  • شما وارد کنسول ابری شده‌اید.
  • شما قبلاً یک سرویس Cloud Run را مستقر کرده‌اید. برای مثال، می‌توانید برای شروع، مراحل استقرار سرویس Cloud Run را دنبال کنید.

تنظیم متغیرهای محیطی

شما می‌توانید متغیرهای محیطی که در سراسر این آزمایشگاه کد استفاده خواهند شد را تنظیم کنید.

می‌توانید شناسه برگه خود را در آدرس اینترنتی برگه گوگل خود هنگام کپی کردن لینک اشتراک‌گذاری پیدا کنید، مثلاً 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

فعال کردن API های مورد نیاز Google Cloud

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 User را به حساب کاربری سرویس (Service Account) اعطا کنید (برای مدل‌های 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. گوگل شیت را در مرورگر باز کنید.
  2. روی دکمه اشتراک‌گذاری کلیک کنید.
  3. ایمیل حساب سرویس $SERVICE_ACCOUNT_EMAIL را جایگذاری کنید و به آن دسترسی ویرایشگر بدهید.

۳. اپلیکیشن را ایجاد کنید

ابتدا، یک دایرکتوری برای کد منبع ایجاد کنید و با دستور 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

۴. سرویس را به صورت محلی آزمایش کنید

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\"."}

۵. استقرار در 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\"."} دریافت کنید.

حالا گوگل شیت خود را باز کنید. مقدار "hello world" را در سلول اول خواهید دید.

۶. تبریک می‌گویم!

تبریک می‌گویم که آزمایشگاه کد را تمام کردید!

بعدش چی؟

توصیه می‌کنیم برای گسترش قابلیت‌های نماینده خود، مستندات زیر را بررسی کنید:

آنچه ما پوشش داده‌ایم

  • نحوه پیکربندی اعتبارنامه‌های پیش‌فرض برنامه (ADC) برای محیط محلی شما
  • چگونه یک عامل ADK ایجاد کنیم که بتواند یک صفحه Google را بخواند و بنویسد
  • نحوه استقرار عامل در Cloud Run

۷. تمیز کردن

برای جلوگیری از هزینه‌های ناخواسته، (برای مثال، اگر این تابع Cloud Run سهواً بیشتر از تخصیص فراخوانی ماهانه Cloud Run شما در سطح رایگان فراخوانی شود)، می‌توانید سرویس Cloud Run یا پروژه را حذف کنید.

برای حذف یک سرویس Cloud Run، به Cloud Run در کنسول ابری به آدرس https://console.cloud.google.com/run/ بروید و سرویس local-adk-sheets-codelab که در این codelab ایجاد کرده‌اید را حذف کنید.

اگر تصمیم به حذف کل پروژه دارید، می‌توانید به آدرس https://console.cloud.google.com/cloud-resource-manager بروید، پروژه‌ای را که در مرحله ۲ ایجاد کرده‌اید انتخاب کنید و گزینه Delete را انتخاب کنید. اگر پروژه را حذف کنید، باید پروژه‌ها را در Cloud SDK خود تغییر دهید. می‌توانید با اجرای gcloud projects list لیست تمام پروژه‌های موجود را مشاهده کنید.