สร้างและติดตั้งใช้งานโปรแกรมวางแผนอาหารที่ทำงานด้วยระบบ AI ด้วย Streamlit, Gemini Pro, Vertex AI และ BigQuery

1. บทนำ

9370c0f92c692ebb.png

ในโค้ดแล็บนี้ คุณจะได้เรียนรู้วิธีสร้างและติดตั้งใช้งานเครื่องมือวางแผนการรับประทานอาหารที่ทำงานด้วยระบบ AI สำหรับ UI ที่ใช้ Streamlit, โมเดล LLM ที่ใช้ Gemini Pro 2.5, ตัวจัดสรรเครื่องมือ Agentic AI ที่ใช้ Vertex AI สำหรับการพัฒนา Agentic AI, BigQuery สำหรับจัดเก็บข้อมูล และ Cloud Run สำหรับการติดตั้งใช้งาน

ใน Codelab นี้ คุณจะได้ใช้แนวทางแบบทีละขั้นตอนดังนี้

  1. เตรียมโปรเจ็กต์ Google Cloud และเปิดใช้ API ที่จำเป็นทั้งหมดในโปรเจ็กต์
  2. สร้างโปรแกรมวางแผนอาหารที่ใช้ AI แบบเอเจนต์โดยใช้ Streamlit, Vertex AI และ BigQuery
  3. ทำให้แอปพลิเคชันใช้งานได้ใน Cloud Run

ภาพรวมสถาปัตยกรรม

84e3f3620dc4ed68.png

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

  • โปรเจ็กต์ Google Cloud Platform (GCP) ที่เปิดใช้การเรียกเก็บเงิน
  • ความรู้พื้นฐานเกี่ยวกับ Python

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

  • วิธีสร้างโปรแกรมวางแผนการรับประทานอาหารที่ใช้ AI แบบเอเจนต์โดยใช้ Streamlit, Vertex AI และจัดเก็บข้อมูลไว้ใน BigQuery
  • วิธีนำแอปพลิเคชันไปใช้งานใน Cloud Run

สิ่งที่ต้องมี

  • เว็บเบราว์เซอร์ Chrome
  • บัญชี Gmail
  • โปรเจ็กต์ Cloud ที่เปิดใช้การเรียกเก็บเงิน

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

การตั้งค่าสภาพแวดล้อมแบบเรียนรู้ด้วยตนเอง

  1. ลงชื่อเข้าใช้ Google Cloud Console แล้วสร้างโปรเจ็กต์ใหม่หรือใช้โปรเจ็กต์ที่มีอยู่ซ้ำ หากยังไม่มีบัญชี Gmail หรือ Google Workspace คุณต้องสร้างบัญชี

fbef9caa1602edd0.png

37d264871000675d.png

5e3ff691252acf41.png

  • ชื่อโปรเจ็กต์คือชื่อที่แสดงสำหรับผู้เข้าร่วมของโปรเจ็กต์นี้ ซึ่งเป็นสตริงอักขระที่ Google APIs ไม่ได้ใช้ คุณอัปเดตได้ทุกเมื่อ
  • รหัสโปรเจ็กต์จะไม่ซ้ำกันในโปรเจ็กต์ Google Cloud ทั้งหมดและเปลี่ยนแปลงไม่ได้ (เปลี่ยนไม่ได้หลังจากตั้งค่าแล้ว) Cloud Console จะสร้างสตริงที่ไม่ซ้ำกันโดยอัตโนมัติ ซึ่งโดยปกติแล้วคุณไม่จำเป็นต้องสนใจว่าสตริงนั้นคืออะไร ใน Codelab ส่วนใหญ่ คุณจะต้องอ้างอิงรหัสโปรเจ็กต์ (โดยปกติจะระบุเป็น PROJECT_ID) หากไม่ชอบรหัสที่สร้างขึ้น คุณอาจสร้างรหัสแบบสุ่มอีกรหัสหนึ่งได้ หรือคุณอาจลองใช้ชื่อของคุณเองและดูว่ามีชื่อนั้นหรือไม่ คุณจะเปลี่ยนแปลงรหัสนี้หลังจากขั้นตอนนี้ไม่ได้ และรหัสจะคงอยู่ตลอดระยะเวลาของโปรเจ็กต์
  • โปรดทราบว่ามีค่าที่ 3 คือหมายเลขโปรเจ็กต์ ซึ่ง API บางตัวใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับค่าทั้ง 3 นี้ได้ในเอกสารประกอบ
  1. จากนั้นคุณจะต้องเปิดใช้การเรียกเก็บเงินใน Cloud Console เพื่อใช้ทรัพยากร/API ของ Cloud การทำตาม Codelab นี้จะไม่เสียค่าใช้จ่ายมากนัก หรืออาจไม่เสียเลย หากต้องการปิดทรัพยากรเพื่อหลีกเลี่ยงการเรียกเก็บเงินนอกเหนือจากบทแนะนำนี้ คุณสามารถลบทรัพยากรที่สร้างขึ้นหรือลบโปรเจ็กต์ได้ ผู้ใช้ Google Cloud รายใหม่มีสิทธิ์เข้าร่วมโปรแกรมช่วงทดลองใช้ฟรีมูลค่า$300 USD

3. ก่อนเริ่มต้น

ตั้งค่าโปรเจ็กต์ Cloud ใน Cloud Shell Editor

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

  1. ในคอนโซล Google Cloud ให้เลือกหรือสร้างโปรเจ็กต์ Google Cloud ในหน้าตัวเลือกโปรเจ็กต์
  2. ตรวจสอบว่าได้เปิดใช้การเรียกเก็บเงินสำหรับโปรเจ็กต์ Cloud แล้ว ดูวิธีตรวจสอบว่าได้เปิดใช้การเรียกเก็บเงินในโปรเจ็กต์แล้วหรือไม่
  3. คุณจะใช้ Cloud Shell ซึ่งเป็นสภาพแวดล้อมบรรทัดคำสั่งที่ทำงานใน Google Cloud และโหลด bq ไว้ล่วงหน้า คลิกเปิดใช้งาน Cloud Shell ที่ด้านบนของคอนโซล Google Cloud

26f20e837ff06119.png

  1. เมื่อเชื่อมต่อกับ Cloud Shell แล้ว ให้ตรวจสอบว่าคุณได้รับการตรวจสอบสิทธิ์แล้วและตั้งค่าโปรเจ็กต์เป็นรหัสโปรเจ็กต์ของคุณโดยใช้คำสั่งต่อไปนี้
gcloud auth list
  1. เรียกใช้คำสั่งต่อไปนี้ใน Cloud Shell เพื่อยืนยันว่าคำสั่ง gcloud รู้จักโปรเจ็กต์ของคุณ
gcloud config list project
  1. หากไม่ได้ตั้งค่าโปรเจ็กต์ ให้ใช้คำสั่งต่อไปนี้เพื่อตั้งค่า
gcloud config set project <YOUR_PROJECT_ID>

หรือคุณจะดู PROJECT_ID id ในคอนโซลก็ได้

bb98435b79995b15.jpeg

คลิก แล้วคุณจะเห็นโปรเจ็กต์ทั้งหมดและรหัสโปรเจ็กต์ทางด้านขวา

ffa73dee57de5307.jpeg

  1. เปิดใช้ API ที่จำเป็นผ่านคำสั่งที่แสดงด้านล่าง การดำเนินการนี้อาจใช้เวลาสักครู่ โปรดอดทนรอ
gcloud services enable aiplatform.googleapis.com \
                           run.googleapis.com \
                           cloudbuild.googleapis.com \
                           cloudresourcemanager.googleapis.com \
                    bigquery.googleapis.com

เมื่อเรียกใช้คำสั่งสำเร็จ คุณควรเห็นข้อความที่คล้ายกับข้อความที่แสดงด้านล่าง

Operation "operations/..." finished successfully.

คุณสามารถใช้คอนโซลแทนคำสั่ง gcloud ได้โดยค้นหาแต่ละผลิตภัณฑ์หรือใช้ลิงก์นี้

หากพลาด API ใดไป คุณก็เปิดใช้ได้เสมอในระหว่างการติดตั้งใช้งาน

โปรดดูคำสั่งและการใช้งาน gcloud ในเอกสารประกอบ

ตั้งค่าไดเรกทอรีการทำงานของแอปพลิเคชัน

  1. คลิกปุ่ม "เปิดเครื่องมือแก้ไข" ซึ่งจะเปิด Cloud Shell Editor และเราจะเขียนโค้ดที่นี่ได้ 6f8e18e89d3198c0.png
  2. ตรวจสอบว่าได้ตั้งค่าโปรเจ็กต์ Cloud Code ไว้ที่มุมล่างซ้าย (แถบสถานะ) ของโปรแกรมแก้ไข Cloud Shell ตามที่ไฮไลต์ไว้ในรูปภาพด้านล่าง และตั้งค่าเป็นโปรเจ็กต์ Google Cloud ที่ใช้งานอยู่ซึ่งคุณเปิดใช้การเรียกเก็บเงินไว้ ให้สิทธิ์หากได้รับข้อความแจ้ง หลังจากเริ่มต้นเครื่องมือแก้ไข Cloud Shell แล้ว อาจต้องรอสักครู่เพื่อให้ปุ่ม Cloud Code - ลงชื่อเข้าใช้ปรากฏขึ้น โปรดอดทนรอ

4e372d87c51afa30.png

จากนั้นเราจะเตรียมสภาพแวดล้อม Python

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

เตรียมสภาพแวดล้อมเสมือนของ Python

ขั้นตอนถัดไปคือการเตรียมสภาพแวดล้อมในการพัฒนา เราจะใช้ Python 3.12 ในโค้ดแล็บนี้ และจะใช้ python virtualenv เพื่อลดความซับซ้อนในการสร้างและจัดการเวอร์ชัน Python และสภาพแวดล้อมเสมือน

  1. หากยังไม่ได้เปิดเทอร์มินัล ให้เปิดโดยคลิกเทอร์มินัล -> เทอร์มินัลใหม่ หรือใช้ Ctrl + Shift + C

8635b60ae2f45bbc.jpeg

  1. สร้างโฟลเดอร์ใหม่และเปลี่ยนตำแหน่งไปยังโฟลเดอร์นี้โดยเรียกใช้คำสั่งต่อไปนี้
mkdir agent_diet_planner
cd agent_diet_planner
  1. สร้าง virtualenv ใหม่ด้วยการเรียกใช้คำสั่งต่อไปนี้
python -m venv .env
  1. เปิดใช้งาน virtualenv ด้วยคำสั่งต่อไปนี้
source .env/bin/activate
  1. สร้าง requirements.txt คลิกไฟล์ → ไฟล์ข้อความใหม่ แล้วกรอกเนื้อหาด้านล่าง จากนั้นบันทึกเป็น requirements.txt
streamlit==1.33.0
google-cloud-aiplatform
google-cloud-bigquery
pandas==2.2.2
db-dtypes==1.2.0
pyarrow==16.1.0
  1. จากนั้นติดตั้งการขึ้นต่อกันทั้งหมดจาก requirements.txt ด้วยการเรียกใช้คำสั่งต่อไปนี้
pip install -r requirements.txt
  1. พิมพ์คำสั่งต่อไปนี้ด้านล่างเพื่อตรวจสอบว่าได้ติดตั้งทรัพยากร Dependency ของไลบรารี Python ทั้งหมดแล้ว
pip list

ตั้งค่าไฟล์การกำหนดค่า

ตอนนี้เราจะต้องตั้งค่าไฟล์การกำหนดค่าสำหรับโปรเจ็กต์นี้ ไฟล์การกำหนดค่าใช้เพื่อจัดเก็บตัวแปรและข้อมูลเข้าสู่ระบบบัญชีบริการ

  1. ขั้นตอนแรกคือการสร้างบัญชีบริการ พิมพ์บัญชีบริการในการค้นหา แล้วคลิกบัญชีบริการ 18c210d5d1e2a666.png
  2. คลิก + สร้างบัญชีบริการ ป้อนชื่อบัญชีบริการ แล้วคลิกสร้างและดำเนินการต่อ 67cad62d367e236a.png
  3. ในสิทธิ์ ให้เลือกบทบาทผู้ใช้บัญชีบริการ คลิก + เพิ่มบทบาทอื่น แล้วเลือกบทบาท IAM : ผู้ดูแลระบบ BigQuery, ผู้ดูแลระบบ Cloud Run, ผู้เรียกใช้ Cloud Run, ตัวแทนบริการ Vertex AI และผู้ใช้ Vertex AI จากนั้นคลิกเสร็จสิ้น be84afdc13678f6c.png
  4. คลิกอีเมลบัญชีบริการ คลิกปุ่ม Tab คลิกเพิ่มคีย์ → สร้างคีย์ใหม่ 50989af3bb9e1538.png
  5. เลือก JSON แล้วคลิกสร้าง บันทึกไฟล์บัญชีบริการนี้ไว้ในเครื่องสำหรับขั้นตอนถัดไป a4a119672da532da.png
  6. สร้างโฟลเดอร์ชื่อ .streamlit ที่มีการกำหนดค่าต่อไปนี้ คลิกขวาที่เมาส์ คลิกโฟลเดอร์ใหม่ แล้วพิมพ์ชื่อโฟลเดอร์ .streamlit
  7. คลิกขวาในโฟลเดอร์ .streamlit จากนั้นคลิกไฟล์ใหม่และกรอกค่าด้านล่าง จากนั้นบันทึกเป็น secrets.toml
# secrets.toml (for Streamlit sharing)
# Store in .streamlit/secrets.toml

[gcp]
project_id = "your_gcp_project"
location = "us-central1"

[gcp_service_account]
type = "service_account"
project_id = "your-project-id"
private_key_id = "your-private-key-id"
private_key = '''-----BEGIN PRIVATE KEY-----
YOUR_PRIVATE_KEY_HERE
-----END PRIVATE KEY-----'''
client_email = "your-sa@project-id.iam.gserviceaccount.com"
client_id = "your-client-id"
auth_uri = "https://accounts.google.com/o/oauth2/auth"
token_uri = "https://oauth2.googleapis.com/token"
auth_provider_x509_cert_url = "https://www.googleapis.com/oauth2/v1/certs"
client_x509_cert_url = "https://www.googleapis.com/robot/v1/metadata/x509/your-sa%40project-id.iam.gserviceaccount.com"
  1. อัปเดตค่าสำหรับ project_id, private_key_id, private_key, client_email , client_id , and auth_provider_x509_cert_url ตามบัญชีบริการที่สร้างในขั้นตอนก่อนหน้า

เตรียมชุดข้อมูล BigQuery

ขั้นตอนถัดไปคือการสร้างชุดข้อมูล BigQuery เพื่อบันทึกผลลัพธ์การสร้างไปยัง BigQuery

  1. พิมพ์ BigQuery ในการค้นหา แล้วคลิก BigQuery
  2. คลิก 2f2e87396859bc74.pngแล้วคลิกสร้างชุดข้อมูล
  3. ป้อนรหัสชุดข้อมูล diet_planner_data แล้วคลิกสร้างชุดข้อมูล 2055cda1ee0360bd.png

4. สร้างแอป Agent Diet Planner

เราจะสร้างอินเทอร์เฟซเว็บแบบง่ายๆ ที่มีอินพุต 4 รายการซึ่งมีลักษณะดังนี้

43b20db2d5f94f38.png

เปลี่ยนน้ำหนัก ส่วนสูง อายุ และเพศตามโปรไฟล์ แล้วคลิกสร้าง โดยจะเรียกโมเดล LLM ว่า Gemini Pro 2.5 ในไลบรารี Vertex AI และจัดเก็บผลลัพธ์ที่สร้างขึ้นไว้ใน BigQuery

รหัสจะแบ่งออกเป็น 6 ส่วนเพื่อไม่ให้ยาวเกินไป

สร้างฟังก์ชันคำนวณสถานะ BMI

  1. คลิกขวาที่โฟลเดอร์ agent_diet_planner → ไฟล์ใหม่ .. → ป้อนชื่อไฟล์ bmi_calc.py แล้วกด Enter
  2. กรอกโค้ดด้วยข้อมูลต่อไปนี้
# Add this function to calculate BMI and health status
def calculate_bmi_status(weight, height):
   """
   Calculate BMI and return status message
   """
   height_m = height / 100  # Convert cm to meters
   bmi = weight / (height_m ** 2)
  
   if bmi < 18.5:
       status = "underweight"
       message = "⚠️ Your BMI suggests you're underweight. Consider increasing calorie intake with nutrient-dense foods."
   elif 18.5 <= bmi < 25:
       status = "normal"
       message = "✅ Your BMI is in the healthy range. Let's maintain this balance!"
   elif 25 <= bmi < 30:
       status = "overweight"
       message = "⚠️ Your BMI suggests you're overweight. Focus on gradual weight loss through balanced nutrition."
   else:
       status = "obese"
       message = "❗ Your BMI indicates obesity. Please consult a healthcare provider for personalized guidance."
  
   return {
       "value": round(bmi, 1),
       "status": status,
       "message": message
   }

สร้างแอปหลักของโปรแกรมวางแผนการรับประทานอาหารของเอเจนต์

  1. คลิกขวาที่โฟลเดอร์ agent_diet_planner → ไฟล์ใหม่ .. → ป้อนชื่อไฟล์ app.py แล้วกด Enter
  2. กรอกโค้ดด้วยข้อมูลต่อไปนี้
import os
from google.oauth2 import service_account
import streamlit as st
from google.cloud import bigquery
from vertexai.preview.generative_models import GenerativeModel
import vertexai
import datetime
import time
import pandas as pd
from bmi_calc import calculate_bmi_status

# Get configuration from environment
PROJECT_ID = os.environ.get("GCP_PROJECT_ID", "your_gcp_project_id")
LOCATION = os.environ.get("GCP_LOCATION", "us-central1")

#CONSTANTS Dataset and table in BigQuery
DATASET = "diet_planner_data"
TABLE = "user_plans"

# Initialize Vertex AI
vertexai.init(project=PROJECT_ID, location=LOCATION)

# Initialize BigQuery client
try:
   # For Cloud Run, use default credentials
   bq_client = bigquery.Client()
except:
   # For local development, use service account from secrets
   if "gcp_service_account" in st.secrets:
       service_account_info = dict(st.secrets["gcp_service_account"])
       credentials = service_account.Credentials.from_service_account_info(service_account_info)
       bq_client = bigquery.Client(credentials=credentials, project=PROJECT_ID)
   else:
       st.error("BigQuery client initialization failed")
       st.stop()

เปลี่ยนค่า your_gcp_project_id ด้วยรหัสโปรเจ็กต์ของคุณ

สร้างแอปหลักของโปรแกรมวางแผนอาหารของเอเจนต์ - setup_bq_tables

ในส่วนนี้ เราจะสร้างฟังก์ชันชื่อ setup_bq_table โดยมีพารามิเตอร์อินพุต 1 รายการคือ bq_client ฟังก์ชันนี้จะกำหนดสคีมาในตาราง BigQuery และสร้างตารางหากยังไม่มี

ป้อนรหัสโดยใช้รหัสก่อนหน้าใน app.py

# Create BigQuery table if not exists
def setup_bq_table(bq_client):
   dataset_id = f"{st.secrets['gcp']['project_id']}.{DATASET}"
   table_id = f"{dataset_id}.{TABLE}"
  
   schema = [
       bigquery.SchemaField("user_id", "STRING", mode="REQUIRED"),
       bigquery.SchemaField("timestamp", "TIMESTAMP", mode="REQUIRED"),
       bigquery.SchemaField("weight", "FLOAT", mode="REQUIRED"),
       bigquery.SchemaField("height", "INTEGER", mode="REQUIRED"),
       bigquery.SchemaField("age", "INTEGER", mode="REQUIRED"),
       bigquery.SchemaField("gender", "STRING", mode="REQUIRED"),
       bigquery.SchemaField("diet_plan", "STRING", mode="REQUIRED")
   ]
  
   try:
       bq_client.get_table(table_id)
   except:
       table = bigquery.Table(table_id, schema=schema)
       bq_client.create_table(table)
       st.toast("BigQuery table created successfully")

สร้างแอปหลักของโปรแกรมวางแผนอาหารของเอเจนต์ - generate_diet_plan

ในส่วนนี้ เราจะสร้างฟังก์ชันชื่อ generate_diet_plan โดยมีพารามิเตอร์อินพุต 1 รายการ ฟังก์ชันนี้จะเรียกใช้โมเดล LLM Gemini Pro 2.5 ด้วยพรอมต์คำจำกัดความและสร้างผลลัพธ์

ป้อนรหัสโดยใช้รหัสก่อนหน้าใน app.py

# Generate diet plan using Gemini Pro
def generate_diet_plan(params):
   try:
       model = GenerativeModel("gemini-2.5-pro")
       prompt = f"""
       Create a personalized 7-day diet plan for:
       - {params['gender']}, {params['age']} years old
       - Weight: {params['weight']} kg
       - Height: {params['height']} cm
      
       Include:
       1. Daily calorie target
       2. Macronutrient breakdown (carbs, protein, fat)
       3. Meal timing and frequency
       4. Food recommendations
       5. Hydration guidance
      
       Make the plan:
       - Nutritionally balanced
       - Practical for daily use
       - Culturally adaptable
       - With portion size guidance
       """
      
       response = model.generate_content(prompt)
       return response.text
   except Exception as e:
       st.error(f"AI generation error: {str(e)}")
       return None

สร้างแอปหลักของโปรแกรมวางแผนอาหารของเอเจนต์ - save_to_bq

ในส่วนนี้ เราจะสร้างฟังก์ชันชื่อ save_to_bq ที่มีพารามิเตอร์อินพุต 3 รายการ ได้แก่ bq_client, user_id และ plan ฟังก์ชันนี้จะบันทึกผลลัพธ์ที่สร้างขึ้นไปยังตาราง BigQuery

ป้อนรหัสโดยใช้รหัสก่อนหน้าใน app.py

# Save user data to BigQuery
def save_to_bq(bq_client, user_id, plan):
   try:
       dataset_id = f"{st.secrets['gcp']['project_id']}.{DATASET}"
       table_id = f"{dataset_id}.{TABLE}"
      
       row = {
           "user_id": user_id,
           "timestamp": datetime.datetime.utcnow().isoformat(),
           "weight": st.session_state.user_data["weight"],
           "height": st.session_state.user_data["height"],
           "age": st.session_state.user_data["age"],
           "gender": st.session_state.user_data["gender"],
           "diet_plan": plan
       }
      
       errors = bq_client.insert_rows_json(table_id, [row])
       if errors:
           st.error(f"BigQuery error: {errors}")
       else:
           return True
   except Exception as e:
       st.error(f"Data saving error: {str(e)}")
       return False

สร้างแอปหลักของโปรแกรมวางแผนการรับประทานอาหารของตัวแทน - main

ในส่วนนี้ เราจะสร้างฟังก์ชันชื่อ main โดยไม่มีพารามิเตอร์อินพุต ฟังก์ชันนี้ส่วนใหญ่จะจัดการสคริปต์ UI ของ Streamlit, แสดงผลลัพธ์ที่สร้างขึ้น, แสดงผลลัพธ์ที่สร้างขึ้นในอดีตจากตาราง BigQuery และสำหรับการดาวน์โหลดข้อมูลไปยังไฟล์ Markdown

ป้อนรหัสโดยใช้รหัสก่อนหน้าใน app.py

# Streamlit UI
def main():
   st.set_page_config(page_title="AI Diet Planner", page_icon="🍏", layout="wide")
  
   # Initialize session state
   if "user_data" not in st.session_state:
       st.session_state.user_data = None
   if "diet_plan" not in st.session_state:
       st.session_state.diet_plan = None
  
   # Initialize clients
   #bq_client = init_clients()
   setup_bq_table(bq_client)
  
   st.title("🍏 AI-Powered Diet Planner")
   st.markdown("""
   <style>
   .stProgress > div > div > div > div {
       background-color: #4CAF50;
   }
   [data-testid="stForm"] {
       background: #f0f5ff;
       padding: 20px;
       border-radius: 10px;
       border: 1px solid #e6e9ef;
   }
   </style>
   """, unsafe_allow_html=True)
  
   # User input form
   with st.form("user_profile", clear_on_submit=False):
       st.subheader("Your Profile")
       col1, col2 = st.columns(2)
      
       with col1:
           weight = st.number_input("Weight (kg)", min_value=30.0, max_value=200.0, value=70.0)
           height = st.number_input("Height (cm)", min_value=100, max_value=250, value=170)
          
       with col2:
           age = st.number_input("Age", min_value=18, max_value=100, value=30)
           gender = st.selectbox("Gender", ["Man", "Woman"])
      
       submitted = st.form_submit_button("Generate Diet Plan")
      
       if submitted:
           user_data = {
               "weight": weight,
               "height": height,
               "age": age,
               "gender": gender
           }

           st.session_state.user_data = user_data
           # Calculate BMI
           bmi_result = calculate_bmi_status(weight, height)

           # Display BMI results in a visually distinct box
           with st.container():
               st.subheader("📊 Your Health Assessment")
               col1, col2 = st.columns([1, 3])
      
               with col1:
                   st.metric("BMI", bmi_result["value"])
          
               with col2:
                   if bmi_result["status"] != "normal":
                       st.warning(bmi_result["message"])
                   else:
                       st.success(bmi_result["message"])
      
           # Add BMI scale visualization
           st.markdown(f"""
           <div style="background:#f0f2f6;padding:10px;border-radius:10px;margin-top:10px">
           <small>BMI Scale:</small><br>
           <div style="display:flex;height:20px;background:linear-gradient(90deg,
           #4e79a7 0%,
           #4e79a7 18.5%,
           #60bd68 18.5%,
           #60bd68 25%,
           #f28e2b 25%,
           #f28e2b 30%,
           #e15759 30%,
           #e15759 100%);position:relative">
           <div style="position:absolute;left:{min(100, max(0, (bmi_result["value"]/40)*100))}%;top:-5px">

           </div>
           </div>
           <div style="display:flex;justify-content:space-between">
           <span>Underweight (<18.5)</span>
           <span>Healthy (18.5-25)</span>
           <span>Overweight (25-30)</span>
           <span>Obese (30+)</span>
           </div>
           </div>
           """, unsafe_allow_html=True)

           # Store BMI in session state
           st.session_state.bmi = bmi_result         
  
   # Plan generation and display
   if submitted and st.session_state.user_data:
       with st.spinner("🧠 Generating your personalized diet plan using Gemini AI..."):
           #diet_plan = generate_diet_plan(st.session_state.user_data)
           diet_plan = generate_diet_plan({**st.session_state.user_data,"bmi": bmi_result["value"],
                                           "bmi_status": bmi_result["status"]
           })

           if diet_plan:
               st.session_state.diet_plan = diet_plan
              
               # Generate unique user ID
               user_id = f"user_{int(time.time())}"
              
               # Save to BigQuery
               if save_to_bq(bq_client, user_id, diet_plan):
                   st.toast("✅ Plan saved to database!")
  
   # Display generated plan
   if st.session_state.diet_plan:
       st.subheader("Your Personalized Diet Plan")
       st.markdown("---")
       st.markdown(st.session_state.diet_plan)
      
       # Download button
       st.download_button(
           label="Download Plan",
           data=st.session_state.diet_plan,
           file_name="my_diet_plan.md",
           mime="text/markdown"
       )
      
       # Show history
       st.subheader("Your Plan History")
       try:
           query = f"""
               SELECT timestamp, weight, height, age, gender
               FROM `{st.secrets['gcp']['project_id']}.{DATASET}.{TABLE}`
               WHERE user_id LIKE 'user_%'
               ORDER BY timestamp DESC
               LIMIT 5
           """
           history = bq_client.query(query).to_dataframe()
           if not history.empty:
               history["timestamp"] = pd.to_datetime(history["timestamp"])
               st.dataframe(history.style.format({
                   "weight": "{:.1f} kg",
                   "height": "{:.0f} cm"
               }))
           else:
               st.info("No previous plans found")
       except Exception as e:
           st.error(f"History load error: {str(e)}")

if __name__ == "__main__":
   main()

บันทึกโค้ดโดยใช้ชื่อ app.py

5. ทำให้แอปที่ใช้ Cloud Build ใช้งานได้กับ Cloud Run

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

84e3f3620dc4ed68.png

ก่อนอื่นเราต้องมี Dockerfile ให้คลิกไฟล์->ไฟล์ข้อความใหม่ แล้วคัดลอกโค้ดต่อไปนี้มาวาง จากนั้นบันทึกเป็น Dockerfile

# Use official Python image
FROM python:3.12-slim

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV PORT 8080

# Install system dependencies
RUN apt-get update && \
   apt-get install -y --no-install-recommends \
   build-essential \
   libpq-dev \
   && rm -rf /var/lib/apt/lists/*

# Set working directory
WORKDIR /app

# Copy requirements
COPY requirements.txt .

# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Copy application files
COPY . .

# Expose port
EXPOSE $PORT

# Run the application
CMD ["streamlit", "run", "app.py", "--server.port", "8080", "--server.address", "0.0.0.0"]

ต่อไปเราจะสร้าง cloudbuild.yaml เพื่อสร้างแอปให้กลายเป็นอิมเมจ Docker พุชไปยัง Artifact Registry และทําให้ใช้งานได้ใน Cloud Run

คลิกไฟล์->ไฟล์ข้อความใหม่ แล้วคัดลอกโค้ดต่อไปนี้และวาง จากนั้นบันทึกเป็น cloudbuild.yaml

steps:
 # Build Docker image
 - name: 'gcr.io/cloud-builders/docker'
   args: ['build', '-t', 'gcr.io/$PROJECT_ID/diet-planner:$BUILD_ID', '--no-cache',
        '--progress=plain',
        '.']
   id: 'Build'
   timeout: 1200s
   waitFor: ['-']
   dir: '.'
  # Push to Container Registry
 - name: 'gcr.io/cloud-builders/docker'
   args: ['push', 'gcr.io/$PROJECT_ID/diet-planner:$BUILD_ID']
   id: 'Push'
   waitFor: ['Build']
  # Deploy to Cloud Run
 - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
   entrypoint: gcloud
   args:
     - 'run'
     - 'deploy'
     - 'diet-planner-service'
     - '--image=gcr.io/$PROJECT_ID/diet-planner:$BUILD_ID'
     - '--port=8080'
     - '--region=us-central1'
     - '--platform=managed'
     - '--allow-unauthenticated'
     - '--set-env-vars=GCP_PROJECT_ID=$PROJECT_ID,GCP_LOCATION=us-central1'
     - '--cpu=1'
     - '--memory=1Gi'
     - '--timeout=300'
   waitFor: ['Push']

options:
 logging: CLOUD_LOGGING_ONLY
 machineType: 'E2_HIGHCPU_8'
 diskSizeGb: 100

images:
 - 'gcr.io/$PROJECT_ID/diet-planner:$BUILD_ID'

ตอนนี้เรามีไฟล์ทั้งหมดที่จำเป็นในการสร้างแอปให้กลายเป็นอิมเมจ Docker พุชไปยัง Artifact Registry และทำให้ใช้งานได้ใน Cloud Run แล้ว มาทำให้ใช้งานได้กันเลย ไปที่เทอร์มินัล Cloud Shell และตรวจสอบว่าได้กำหนดค่าโปรเจ็กต์ปัจจุบันเป็นโปรเจ็กต์ที่ใช้งานอยู่แล้ว หากยังไม่ได้กำหนดค่า ให้ใช้คำสั่ง gcloud configure เพื่อตั้งค่ารหัสโปรเจ็กต์

gcloud config set project [PROJECT_ID]

จากนั้นเรียกใช้คำสั่งต่อไปนี้เพื่อสร้างแอปให้เป็นอิมเมจ Docker พุชไปยัง Artifact Registry และทำให้ใช้งานได้กับ Cloud Run

gcloud builds submit --config cloudbuild.yaml

โดยจะสร้างคอนเทนเนอร์ Docker ตาม Dockerfile ที่เราให้ไว้ก่อนหน้านี้ แล้วพุชไปยัง Artifact Registry หลังจากนั้น เราจะทําให้อิมเมจที่สร้างขึ้นใช้งานได้ใน Cloud Run กระบวนการทั้งหมดนี้กำหนดไว้ในcloudbuild.yamlขั้นตอน

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

เมื่อการติดตั้งใช้งานเสร็จสมบูรณ์ เราจะตรวจสอบได้ในหน้า Cloud Run โดยค้นหา Cloud Run ในแถบค้นหาของ Cloud Console ที่ด้านบน แล้วคลิกผลิตภัณฑ์ Cloud Run

3c460765656fc072.png

หลังจากนั้น คุณจะตรวจสอบบริการที่ทำให้ใช้งานได้ซึ่งแสดงอยู่ในหน้าบริการ Cloud Run ได้โดยคลิกที่บริการเพื่อให้เราได้รับ URL ของบริการ

93dc975d3caeab0e.png

URL ของบริการจะอยู่ที่แถบด้านบน

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

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

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

  1. ในคอนโซล Google Cloud ให้ไปที่หน้าจัดการทรัพยากร
  2. ในรายการโปรเจ็กต์ ให้เลือกโปรเจ็กต์ที่ต้องการลบ แล้วคลิกลบ
  3. ในกล่องโต้ตอบ ให้พิมพ์รหัสโปรเจ็กต์ แล้วคลิกปิดเพื่อลบโปรเจ็กต์
  4. หรือจะไปที่ Cloud Run ในคอนโซล เลือกบริการที่คุณเพิ่งทําให้ใช้งานได้ แล้วลบก็ได้