Codelab - یک برنامه پیشنهادی یوگا پوزهای متنی با Firestore، Vector Search، Langchain و Gemini (نسخه پایتون) بسازید.

۱. مقدمه

در این آزمایشگاه کد، شما یک برنامه کاربردی خواهید ساخت که از جستجوی برداری برای پیشنهاد حرکات یوگا استفاده می‌کند.

از طریق codelab، شما یک رویکرد گام به گام به شرح زیر را به کار خواهید گرفت:

  1. از یک مجموعه داده موجود در مورد حالت‌های یوگا با موضوع چهره در حال بغل کردن (با فرمت JSON) استفاده کنید.
  2. مجموعه داده‌ها را با یک توصیف فیلد اضافی که از Gemini برای تولید توصیفات برای هر یک از حالت‌ها استفاده می‌کند، بهبود بخشید.
  3. از Langchain برای ایجاد یک سند استفاده کنید، از ادغام Firestore Langchain برای ایجاد مجموعه و جاسازی‌ها در Firestore استفاده کنید.
  4. یک فهرست ترکیبی در Firestore ایجاد کنید تا امکان جستجوی برداری فراهم شود.
  5. از جستجوی برداری در یک برنامه Flask استفاده کنید که همه چیز را مطابق شکل زیر گرد هم می‌آورد:

84e1cbf29cbaeedc.png

کاری که انجام خواهید داد

  • طراحی، ساخت و استقرار یک برنامه وب که از جستجوی برداری برای پیشنهاد حرکات یوگا استفاده می‌کند.

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

  • نحوه استفاده از Gemini برای تولید محتوای متنی و در چارچوب این codelab، تولید توضیحات برای حرکات یوگا
  • نحوه استفاده از Langchain Document Loader برای Firestore جهت بارگذاری رکوردها از یک مجموعه داده پیشرفته از Hugging Face به Firestore به همراه Vector Embeddings
  • نحوه استفاده از Langchain Vector Store برای Firestore جهت جستجوی داده‌ها بر اساس یک پرس‌وجوی زبان طبیعی
  • نحوه استفاده از API تبدیل متن به گفتار گوگل کلود برای تولید محتوای صوتی

آنچه نیاز دارید

  • مرورگر وب کروم
  • یک حساب جیمیل
  • یک پروژه ابری با قابلیت پرداخت صورتحساب

این آزمایشگاه کد که برای توسعه‌دهندگان در تمام سطوح (از جمله مبتدیان) طراحی شده است، در برنامه نمونه خود از پایتون استفاده می‌کند. با این حال، برای درک مفاهیم ارائه شده، دانش پایتون لازم نیست.

۲. قبل از شروع

ایجاد یک پروژه

  1. در کنسول گوگل کلود ، در صفحه انتخاب پروژه، یک پروژه گوگل کلود را انتخاب یا ایجاد کنید.
  2. مطمئن شوید که صورتحساب برای پروژه ابری شما فعال است. یاد بگیرید که چگونه بررسی کنید که آیا صورتحساب در یک پروژه فعال است یا خیر .
  3. شما از Cloud Shell ، یک محیط خط فرمان که در Google Cloud اجرا می‌شود و bq از قبل روی آن بارگذاری شده است، استفاده خواهید کرد. روی Activate Cloud Shell در بالای کنسول Google Cloud کلیک کنید.

تصویر دکمه فعال کردن Cloud Shell

  1. پس از اتصال به Cloud Shell، با استفاده از دستور زیر بررسی می‌کنید که آیا از قبل احراز هویت شده‌اید و پروژه روی شناسه پروژه شما تنظیم شده است یا خیر:
gcloud auth list
  1. دستور زیر را در Cloud Shell اجرا کنید تا تأیید شود که دستور gcloud از پروژه شما اطلاع دارد.
gcloud config list project
  1. اگر پروژه شما تنظیم نشده است، از دستور زیر برای تنظیم آن استفاده کنید:
gcloud config set project <YOUR_PROJECT_ID>
  1. API های مورد نیاز را از طریق دستور زیر فعال کنید. این کار ممکن است چند دقیقه طول بکشد، پس لطفاً صبور باشید.
gcloud services enable firestore.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       run.googleapis.com \
                       cloudbuild.googleapis.com \
                       cloudfunctions.googleapis.com \
                       aiplatform.googleapis.com \
                       texttospeech.googleapis.com

در صورت اجرای موفقیت‌آمیز دستور، باید پیامی مشابه آنچه در زیر نشان داده شده است را مشاهده کنید:

Operation "operations/..." finished successfully.

جایگزین دستور gcloud از طریق کنسول با جستجوی هر محصول یا استفاده از این لینک است.

اگر هر API از قلم افتاده باشد، می‌توانید همیشه آن را در طول پیاده‌سازی فعال کنید.

برای دستورات و نحوه‌ی استفاده از gcloud به مستندات مراجعه کنید.

مخزن کلون و تنظیمات محیط راه‌اندازی

مرحله بعدی، کپی کردن مخزن نمونه‌ای است که در ادامه‌ی کد به آن ارجاع خواهیم داد. با فرض اینکه در Cloud Shell هستید، دستور زیر را از دایرکتوری خانگی خود اجرا کنید:

git clone https://github.com/rominirani/yoga-poses-recommender-python

برای اجرای ویرایشگر، روی گزینه Open Editor در نوار ابزار پنجره Cloud Shell کلیک کنید. روی نوار منو در گوشه بالا سمت چپ کلیک کنید و مطابق شکل زیر، File → Open Folder را انتخاب کنید:

۶۶۲۲۱fd0d0e5202f.png

پوشه yoga-poses-recommender-python را انتخاب کنید. باید پوشه‌ای را مشاهده کنید که حاوی فایل‌های زیر است، همانطور که در زیر نشان داده شده است:

۴۴۶۹۹efc7fb1b911.png

اکنون باید متغیرهای محیطی مورد استفاده خود را تنظیم کنیم. روی فایل config.template.yaml کلیک کنید. باید محتویات آن را مانند تصویر زیر مشاهده کنید:

project_id: your-project-id
location: us-central1
gemini_model_name: gemini-1.5-flash-002
embedding_model_name: text-embedding-004
image_generation_model_name: imagen-3.0-fast-generate-002
database: (default)
collection: poses
test_collection: test-poses
top_k: "3"

لطفاً مقادیر project_id و location را مطابق با آنچه هنگام ایجاد منطقه Google Cloud Project و Firestore Database انتخاب کرده‌اید، به‌روزرسانی کنید. در حالت ایده‌آل، ما می‌خواهیم مقادیر location برای Google Cloud Project و Firestore Database یکسان باشد، مثلاً us-central1 .

برای اهداف این آزمایشگاه کد، ما از مقادیر از پیش تنظیم‌شده استفاده خواهیم کرد (البته به جز project_id و location که باید طبق پیکربندی خود تنظیم کنید).

لطفاً این فایل را با نام config.yaml و در همان پوشه‌ای که فایل config.template.yaml قرار دارد، ذخیره کنید.

مرحله آخر اکنون ایجاد یک محیط پایتون است که به صورت محلی با تمام وابستگی‌های پایتون تنظیم شده برای ما استفاده خواهد شد. به فایل pyproject.toml که حاوی جزئیات مربوط به آن است نگاهی بیندازید، محتوای آن در زیر نشان داده شده است:

dependencies = [
    "datasets>=3.2.0",
    "flask>=3.1.0",
    "google-cloud-aiplatform>=1.78.0",
    "google-cloud-texttospeech>=2.24.0",
    "langchain-community>=0.3.15",
    "langchain-core>=0.3.31",
    "langchain-google-community>=2.0.4",
    "langchain-google-firestore>=0.5.0",
    "langchain-google-vertexai>=2.0.7",
    "pydantic-settings>=2.7.1",
    "pyyaml>=6.0.2",
    "tenacity>=9.0.0",
]

این وابستگی‌ها از قبل در requirements.txt قفل نسخه شده‌اند . به طور خلاصه، ما باید یک محیط مجازی پایتون با وابستگی‌های بسته پایتون در requirements.txt ایجاد کنیم تا در محیط مجازی نصب شوند. برای انجام این کار، به Command Palette (Ctrl+Shift+P) در Cloud Shell IDE بروید و عبارت Python: Create Environment تایپ کنید. چند مرحله بعدی را برای انتخاب یک Virtual Environment(venv) ، Python 3.x interpreter و فایل requirements.txt دنبال کنید.

پس از ایجاد محیط، باید محیط ایجاد شده را با دستور زیر فعال کنیم.

source .venv/bin/activate

شما باید (.venv) را در کنسول خود ببینید. مثال -> (.venv) yourusername@cloudshell:

عالی! حالا همه چیز برای شروع راه‌اندازی پایگاه داده Firestore آماده است.

۳. نصب فایراستور

کلود فایراستور یک پایگاه داده سند بدون سرور و کاملاً مدیریت‌شده است که ما به عنوان بک‌اند برای داده‌های برنامه خود از آن استفاده خواهیم کرد. داده‌ها در کلود فایراستور در مجموعه‌ای از اسناد ساختار یافته‌اند.

مقداردهی اولیه پایگاه داده Firestore

از صفحه Firestore در کنسول Cloud دیدن کنید.

اگر قبلاً در پروژه، پایگاه داده Firestore را مقداردهی اولیه نکرده‌اید، با کلیک روی Create Database ، پایگاه داده default ایجاد کنید. در حین ایجاد پایگاه داده، مقادیر زیر را وارد کنید:

  • حالت فایراستور: Native.
  • نوع مکان را روی Region انتخاب کنید و مکان us-central1 را برای منطقه انتخاب کنید.
  • برای قوانین امنیتی، از Test rules استفاده کنید.
  • پایگاه داده را ایجاد کنید.

61d0277510803c8d.png

در بخش بعدی، مقدمات ایجاد مجموعه‌ای به نام poses در پایگاه داده پیش‌فرض Firestore خود فراهم خواهیم کرد. این مجموعه داده‌های نمونه (اسناد) یا اطلاعات پوزهای Yoga را در خود نگه می‌دارد که سپس در برنامه خود از آنها استفاده خواهیم کرد.

این بخش مربوط به راه‌اندازی پایگاه داده Firestore را تکمیل می‌کند.

۴. مجموعه داده‌های حرکات یوگا را آماده کنید

اولین وظیفه ما آماده‌سازی مجموعه داده‌های حالت‌های یوگا است که برای برنامه از آنها استفاده خواهیم کرد. ما با یک مجموعه داده موجود از چهره‌های در حال آغوش گرفتن شروع می‌کنیم و سپس آن را با اطلاعات اضافی بهبود می‌دهیم.

مجموعه داده‌های چهره در آغوش گرفته برای حالت‌های یوگا را بررسی کنید. توجه داشته باشید که اگرچه این آزمایشگاه کد از یکی از این مجموعه داده‌ها استفاده می‌کند، در واقع می‌توانید از هر مجموعه داده دیگری استفاده کنید و همان تکنیک‌های نشان داده شده را برای بهبود مجموعه داده دنبال کنید.

298cfae7f23e4bef.png

اگر به بخش Files and versions برویم، می‌توانیم فایل داده JSON را برای همه پوزها دریافت کنیم.

3fe6e55abdc032ec.png

ما فایل yoga_poses.json را دانلود کرده و آن را در اختیار شما قرار داده‌ایم. نام این فایل yoga_poses_alldata.json است و در پوشه /data قرار دارد.

به فایل data/yoga_poses.json در ویرایشگر Cloud Shell بروید و نگاهی به لیست اشیاء JSON بیندازید، که در آن هر شیء JSON نشان دهنده یک حرکت یوگا است. ما در مجموع ۳ رکورد داریم و یک رکورد نمونه در زیر نشان داده شده است:

{
   "name": "Big Toe Pose",
   "sanskrit_name": "Padangusthasana",
   "photo_url": "https://pocketyoga.com/assets/images/full/ForwardBendBigToe.png",
   "expertise_level": "Beginner",
   "pose_type": ["Standing", "Forward Bend"]
 }

اکنون فرصت بسیار خوبی برای معرفی Gemini و نحوه استفاده از خود مدل پیش‌فرض برای ایجاد فیلد description برای آن است.

در ویرایشگر Cloud Shell، به فایل generate-descriptions.py بروید. محتوای این فایل در زیر نشان داده شده است:

import json
import time
import logging
import vertexai
from langchain_google_vertexai import VertexAI
from tenacity import retry, stop_after_attempt, wait_exponential
from settings import get_settings

settings = get_settings()
logging.basicConfig(
    level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
# Initialize Vertex AI SDK
vertexai.init(project=settings.project_id, location=settings.location)
logging.info("Done Initializing Vertex AI SDK")


@retry(
    stop=stop_after_attempt(5),
    wait=wait_exponential(multiplier=1, min=4, max=10),
)
def generate_description(pose_name, sanskrit_name, expertise_level, pose_types):
    """Generates a description for a yoga pose using the Gemini API."""

    prompt = f"""
    Generate a concise description (max 50 words) for the yoga pose: {pose_name}
    Also known as: {sanskrit_name}
    Expertise Level: {expertise_level}
    Pose Type: {", ".join(pose_types)}

    Include key benefits and any important alignment cues.
    """
    try:
        model = VertexAI(model_name=settings.gemini_model_name, verbose=True)
        response = model.invoke(prompt)
        return response
    except Exception as e:
        logging.info(f"Error generating description for {pose_name}: {e}")
        return ""


def add_descriptions_to_json(input_file, output_file):
    """Loads JSON data, adds descriptions, and saves the updated data."""

    with open(input_file, "r") as f:
        yoga_poses = json.load(f)

    total_poses = len(yoga_poses)
    processed_count = 0

    for pose in yoga_poses:
        if pose["name"] != " Pose":
            start_time = time.time()  # Record start time
            pose["description"] = generate_description(
                pose["name"],
                pose["sanskrit_name"],
                pose["expertise_level"],
                pose["pose_type"],
            )
            end_time = time.time()  # Record end time

            processed_count += 1
            end_time = time.time()  # Record end time
            time_taken = end_time - start_time
            logging.info(
                f"Processed: {processed_count}/{total_poses} - {pose['name']} ({time_taken:.2f} seconds)"
            )

        else:
            pose["description"] = ""
            processed_count += 1
            logging.info(
                f"Processed: {processed_count}/{total_poses} - {pose['name']} ({time_taken:.2f} seconds)"
            )
        # Adding a delay to avoid rate limit
        time.sleep(30)

    with open(output_file, "w") as f:
        json.dump(yoga_poses, f, indent=2)


def main():
    # File paths
    input_file = "./data/yoga_poses.json"
    output_file = "./data/yoga_poses_with_descriptions.json"

    # Add descriptions and save the updated JSON
    add_descriptions_to_json(input_file, output_file)


if __name__ == "__main__":
    main()

این برنامه یک فیلد description جدید به هر رکورد JSON مربوط به حرکات یوگا اضافه می‌کند. این توضیحات را از طریق فراخوانی مدل Gemini دریافت می‌کند، جایی که ما اعلان لازم را برای آن فراهم می‌کنیم. این فیلد به فایل JSON اضافه می‌شود و فایل جدید در فایل data/yoga_poses_with_descriptions.json نوشته می‌شود.

بیایید مراحل اصلی را طی کنیم:

  1. در تابع main() ، متوجه خواهید شد که تابع add_descriptions_to_json را فراخوانی می‌کند و فایل ورودی و فایل خروجی مورد انتظار را ارائه می‌دهد.
  2. تابع add_descriptions_to_json برای هر رکورد JSON، یعنی اطلاعات پست Yoga، کارهای زیر را انجام می‌دهد:
  3. این تابع، pose_name ، sanskrit_name ، expertise_level و pose_types را استخراج می‌کند.
  4. این تابع generate_description را فراخوانی می‌کند که یک اعلان ایجاد می‌کند و سپس کلاس مدل Langchain VertexAI را برای دریافت متن پاسخ فراخوانی می‌کند.
  5. این متن پاسخ سپس به شیء JSON اضافه می‌شود.
  6. سپس لیست به‌روز شده‌ی JSON از اشیاء در فایل مقصد نوشته می‌شود.

بیایید این برنامه را اجرا کنیم. یک پنجره ترمینال جدید (Ctrl+Shift+C) باز کنید و دستور زیر را وارد کنید:

python generate-descriptions.py

اگر از شما هرگونه مجوزی خواسته شد، لطفاً آن را ارائه دهید.

متوجه خواهید شد که برنامه شروع به اجرا می‌کند. ما یک تأخیر ۳۰ ثانیه‌ای بین رکوردها اضافه کرده‌ایم تا از هرگونه سهمیه محدودیت نرخ که ممکن است در حساب‌های جدید Google Cloud وجود داشته باشد، جلوگیری شود، بنابراین لطفاً صبور باشید.

نمونه‌ای از اجرای در حال انجام در زیر نشان داده شده است:

8e830d9ea9b6c60.png

زمانی که هر سه رکورد با فراخوانی Gemini بهبود داده شدند، فایلی data/yoga_poses_with_description.json ایجاد خواهد شد. می‌توانید نگاهی به آن بیندازید.

اکنون فایل داده ما آماده است و گام بعدی این است که نحوه پر کردن یک پایگاه داده Firestore با آن، همراه با تولید جاسازی‌ها را درک کنیم.

۵. داده‌ها را به Firestore وارد کنید و Vector Embeddings ایجاد کنید

ما فایل data/yoga_poses_with_description.json را داریم و اکنون باید پایگاه داده Firestore را با آن پر کنیم و مهم‌تر از آن، Vector Embeddings را برای هر یک از رکوردها تولید کنیم. Vector Embeddings بعداً زمانی که باید جستجوی مشابهی روی آنها با پرس‌وجوی کاربر که به زبان طبیعی ارائه شده است، انجام دهیم، مفید خواهد بود.

ما از کامپوننت‌های Langchain Firestore برای پیاده‌سازی فرآیند فوق استفاده خواهیم کرد.

مراحل انجام آن به شرح زیر خواهد بود:

  1. ما لیست اشیاء JSON را به لیستی از اشیاء سند Langchain تبدیل خواهیم کرد. هر سند دارای دو ویژگی خواهد بود: page_content و metadata . شیء metadata شامل کل شیء JSON خواهد بود که دارای ویژگی‌هایی مانند name ، description ، sanskrit_name و غیره است. page_content یک متن رشته‌ای خواهد بود که از الحاق چند فیلد تشکیل شده است.
  2. زمانی که لیستی از اشیاء Document را داشته باشیم، از کلاس FirestoreVectorStore Langchain و به طور خاص متد from_documents با این لیست از اسناد، یک نام مجموعه (ما از متغیر TEST_COLLECTION که به test-poses اشاره می‌کند استفاده می‌کنیم)، یک کلاس Vertex AI Embedding و جزئیات اتصال Firestore ( PROJECT_ID و نام DATABASE ) استفاده خواهیم کرد. این کار مجموعه را ایجاد می‌کند و همچنین یک فیلد embedding برای هر یک از ویژگی‌ها ایجاد می‌کند.

کد مربوط به import-data.py در زیر آمده است (بخش‌هایی از کد برای اختصار کوتاه شده‌اند):

... 

def create_langchain_documents(poses):
   """Creates a list of Langchain Documents from a list of poses."""
   documents = []
   for pose in poses:
       # Convert the pose to a string representation for page_content
       page_content = (
           f"name: {pose.get('name', '')}\n"
           f"description: {pose.get('description', '')}\n"
           f"sanskrit_name: {pose.get('sanskrit_name', '')}\n"
           f"expertise_level: {pose.get('expertise_level', 'N/A')}\n"
           f"pose_type: {pose.get('pose_type', 'N/A')}\n"
       ).strip()
       # The metadata will be the whole pose
       metadata = pose

       document = Document(page_content=page_content, metadata=metadata)
       documents.append(document)
   logging.info(f"Created {len(documents)} Langchain documents.")
   return documents

def main():
    all_poses = load_yoga_poses_data_from_local_file(
        "./data/yoga_poses_with_descriptions.json"
    )
    documents = create_langchain_documents(all_poses)
    logging.info(
        f"Successfully created langchain documents. Total documents: {len(documents)}"
    )

    embedding = VertexAIEmbeddings(
        model_name=settings.embedding_model_name,
        project=settings.project_id,
        location=settings.location,
    )

    client = firestore.Client(project=settings.project_id, database=settings.database)

    vector_store = FirestoreVectorStore.from_documents(
        client=client,
        collection=settings.test_collection,
        documents=documents,
        embedding=embedding,
    )
    logging.info("Added documents to the vector store.")


if __name__ == "__main__":
    main()

بیایید این برنامه را اجرا کنیم. یک پنجره ترمینال جدید (Ctrl+Shift+C) باز کنید و دستور زیر را وارد کنید:

python import-data.py

اگر همه چیز درست پیش برود، باید پیامی مشابه پیام زیر را ببینید:

2025-01-21 14:50:06,479 - INFO - Added documents to the vector store.

برای بررسی اینکه آیا رکوردها با موفقیت درج شده‌اند و جاسازی‌ها ایجاد شده‌اند، به صفحه Firestore در کنسول Cloud مراجعه کنید.

504cabdb99a222a5.png

روی پایگاه داده (پیش‌فرض) کلیک کنید، این باید مجموعه test-poses و چندین سند زیر آن مجموعه را نشان دهد. هر سند مربوط به یک حالت یوگا است.

d0708499e403aebc.png

برای بررسی فیلدها، روی هر یک از اسناد کلیک کنید. علاوه بر فیلدهایی که وارد کرده‌ایم، فیلد embedding را نیز خواهید یافت که یک فیلد برداری است که به طور خودکار از طریق کلاس Langchain VertexAIEmbeddings که ما استفاده کردیم، برای شما ایجاد شده است و در آن مدل text-embedding-004 Vertex AI Embedding را ارائه کرده‌ایم.

d67113e2dc63cd6b.png

اکنون که رکوردها را به همراه جاسازی‌ها در پایگاه داده Firestore بارگذاری کرده‌ایم، می‌توانیم به مرحله بعدی برویم و نحوه انجام جستجوی تشابه برداری در Firestore را بررسی کنیم.

۶. وارد کردن تمام حرکات یوگا به مجموعه پایگاه داده Firestore

اکنون مجموعه poses را ایجاد خواهیم کرد که فهرستی کامل از ۱۶۰ حرکت یوگا است و برای آن یک فایل ورودی پایگاه داده ایجاد کرده‌ایم که می‌توانید مستقیماً آن را وارد کنید. این کار برای صرفه‌جویی در زمان در آزمایشگاه انجام می‌شود. فرآیند تولید پایگاه داده‌ای که شامل توضیحات و جاسازی‌ها است، همان فرآیندی است که در بخش قبلی دیدیم.

با دنبال کردن مراحل زیر، پایگاه داده را وارد کنید:

  1. با استفاده از دستور gsutil که در زیر آمده است، یک باکت در پروژه خود ایجاد کنید. متغیر <PROJECT_ID> را در دستور زیر با شناسه پروژه گوگل کلود خود جایگزین کنید.
gsutil mb -l us-central1 gs://<PROJECT_ID>-my-bucket
  1. حالا که باکت ایجاد شده است، قبل از اینکه بتوانیم خروجی پایگاه داده را به پایگاه داده Firebase وارد کنیم، باید آن را در این باکت کپی کنیم. از دستور زیر استفاده کنید:
gsutil cp -r gs://yoga-database-firestore-export-bucket/2025-01-27T05:11:02_62615  gs://<PROJECT_ID>-my-bucket

حالا که داده‌ها را برای وارد کردن داریم، می‌توانیم به مرحله نهایی وارد کردن داده‌ها به پایگاه داده Firebase ( default ) که ایجاد کرده‌ایم، برویم.

  1. از دستور gcloud که در زیر آمده است استفاده کنید:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2025-01-27T05:11:02_62615

وارد کردن چند ثانیه طول می‌کشد و پس از آماده شدن، می‌توانید پایگاه داده Firestore و مجموعه آن را با مراجعه به https://console.cloud.google.com/firestore/databases اعتبارسنجی کنید، پایگاه داده default و مجموعه poses را مطابق شکل زیر انتخاب کنید:

a8f5a6ba69bec69b.png

این کار ایجاد مجموعه Firestore را که در برنامه خود استفاده خواهیم کرد، تکمیل می‌کند.

۷. جستجوی تشابه برداری را در Firestore انجام دهید

برای انجام جستجوی شباهت برداری ، عبارت مورد نظر را از کاربر دریافت می‌کنیم. نمونه‌ای از این عبارت می‌تواند "Suggest me some exercises to relieve back pain" باشد.

به فایل search-data.py نگاهی بیندازید. تابع کلیدی که باید به آن توجه کنید، تابع جستجو است که در زیر نشان داده شده است. در سطح بالا، این فایل یک کلاس جاسازی ایجاد می‌کند که برای تولید جاسازی برای کوئری کاربر استفاده خواهد شد. سپس از کلاس FirestoreVectorStore برای فراخوانی تابع similarity_search خود استفاده می‌کند.

def search(query: str):
    """Executes Firestore Vector Similarity Search"""
    embedding = VertexAIEmbeddings(
        model_name=settings.embedding_model_name,
        project=settings.project_id,
        location=settings.location,
    )

    client = firestore.Client(project=settings.project_id, database=settings.database)

    vector_store = FirestoreVectorStore(
        client=client, collection=settings.collection, embedding_service=embedding
    )

    logging.info(f"Now executing query: {query}")
    results: list[Document] = vector_store.similarity_search(
        query=query, k=int(settings.top_k), include_metadata=True
    )
    for result in results:
        print(result.page_content)

قبل از اینکه این را با چند مثال پرس‌وجو اجرا کنید، ابتدا باید یک شاخص ترکیبی Firestore ایجاد کنید که برای موفقیت پرس‌وجوهای جستجوی شما لازم است. اگر برنامه را بدون ایجاد شاخص اجرا کنید، خطایی مبنی بر اینکه ابتدا باید شاخص را ایجاد کنید با دستور ایجاد شاخص اول نمایش داده می‌شود.

دستور gcloud برای ایجاد شاخص ترکیبی در زیر نشان داده شده است:

gcloud firestore indexes composite create --project=<YOUR_PROJECT_ID> --collection-group=poses --query-scope=COLLECTION --field-config=vector-config='{"dimension":"768","flat": "{}"}',field-path=embedding

تکمیل ایندکس چند دقیقه طول خواهد کشید زیرا بیش از ۱۵۰ رکورد در پایگاه داده وجود دارد. پس از تکمیل، می‌توانید ایندکس را از طریق دستور زیر مشاهده کنید:

gcloud firestore indexes composite list

شما باید اندیسی که ایجاد کرده‌اید را در لیست ببینید.

حالا دستور زیر را امتحان کنید:

python search-data.py --prompt "Recommend me some exercises for back pain relief"

شما باید چند توصیه دریافت کنید. یک نمونه اجرا در زیر نشان داده شده است:

2025-01-21 15:48:51,282 - INFO - Now executing query: Recommend me some exercises for back pain relief
name: Supine Spinal Twist Pose
description: A gentle supine twist (Supta Matsyendrasana), great for beginners.  Releases spinal tension, improves digestion, and calms the nervous system.  Keep shoulders flat on the floor and lengthen the spine.

sanskrit_name: Supta Matsyendrasana
expertise_level: Beginner
pose_type: ['Supine', 'Twist']
name: Cow Pose
description: Cow Pose (Bitilasana) is a gentle backbend, stretching the chest, shoulders, and abdomen.  Maintain a neutral spine, lengthen the tailbone, and avoid hyperextension.  Benefits include improved posture and stress relief.

sanskrit_name: Bitilasana
expertise_level: Beginner
pose_type: ['Arm Leg Support', 'Back Bend']
name: Locust I Pose
description: Locust Pose I (Shalabhasana A) strengthens the back, glutes, and shoulders.  Lie prone, lift chest and legs simultaneously, engaging back muscles.  Keep hips grounded and gaze slightly forward.

sanskrit_name: Shalabhasana A
expertise_level: Intermediate
pose_type: ['Prone', 'Back Bend']

وقتی این کار را انجام دادید، اکنون فهمیده‌ایم که چگونه با پایگاه داده برداری Firestore کار کنیم تا رکوردها را آپلود کنیم، جاسازی‌ها را ایجاد کنیم و جستجوی شباهت برداری را انجام دهیم. اکنون می‌توانیم یک برنامه وب ایجاد کنیم که جستجوی برداری را در یک رابط کاربری وب ادغام کند.

۸. برنامه وب

برنامه وب پایتون فلسک در فایل main.py و فایل HTML رابط کاربری در templates/index.html.

توصیه می‌شود که هر دو فایل را بررسی کنید. ابتدا با فایل main.py که شامل کنترل‌کننده /search است شروع کنید، که اعلانی را که از فایل index.html HTML در سمت کاربر ارسال شده است، دریافت می‌کند. سپس این فایل، متد search را فراخوانی می‌کند که جستجوی تشابه برداری را که در بخش قبل بررسی کردیم، انجام می‌دهد.

سپس پاسخ به همراه لیست توصیه‌ها به index.html ارسال می‌شود. سپس index.html توصیه‌ها را به صورت کارت‌های مختلف نمایش می‌دهد.

اجرای برنامه به صورت محلی

یک پنجره ترمینال جدید (Ctrl+Shift+C) یا هر پنجره ترمینال موجود را باز کنید و دستور زیر را وارد کنید:

python main.py

نمونه‌ای از اجرا در زیر نشان داده شده است:

 * Serving Flask app 'main'
 * Debug mode: on
2025-01-21 16:02:37,473 - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:8080
 * Running on http://10.88.0.4:8080
2025-01-21 16:02:37,473 - INFO - Press CTRL+C to quit
2025-01-21 16:02:37,474 - INFO -  * Restarting with stat
2025-01-21 16:02:41,462 - WARNING -  * Debugger is active!
2025-01-21 16:02:41,484 - INFO -  * Debugger PIN: 440-653-555

پس از راه‌اندازی و اجرا، با کلیک بر روی دکمه پیش‌نمایش وب که در زیر نشان داده شده است، به آدرس اینترنتی اصلی برنامه مراجعه کنید:

de297d4cee10e0bf.png

باید فایل index.html را به صورت زیر نمایش دهد:

20240a0e885ac17b.png

یک نمونه سوال (مثال: Provide me some exercises for back pain relief ) ارائه دهید و روی دکمه Search کلیک کنید. این باید برخی از توصیه‌ها را از پایگاه داده بازیابی کند. همچنین دکمه Play Audio را مشاهده خواهید کرد که بر اساس توضیحات، یک جریان صوتی ایجاد می‌کند که می‌توانید مستقیماً آن را بشنوید.

789b4277dc40e2be.png

۹. (اختیاری) استقرار در Google Cloud Run

مرحله آخر ما، استقرار این برنامه در Google Cloud Run خواهد بود. دستور استقرار در زیر نشان داده شده است، قبل از استقرار آن، مطمئن شوید که مقادیر متغیر (<<YOUR_PROJECT_ID>>) را با مقادیری که مختص پروژه شما هستند جایگزین می‌کنید. اینها مقادیری هستند که می‌توانید از فایل config.yaml بازیابی کنید.

gcloud run deploy yogaposes --source . \
  --port=8080 \
  --allow-unauthenticated \
  --region=us-central1 \
  --platform=managed  \
  --project=<<YOUR_PROJECT_ID>> \
  --env-vars-file=config.yaml

دستور بالا را از پوشه ریشه برنامه اجرا کنید. همچنین ممکن است از شما خواسته شود که API های Google Cloud را فعال کنید، برای مجوزهای مختلف تأیید خود را ارائه دهید، لطفاً این کار را انجام دهید.

مراحل نصب حدود ۵ تا ۷ دقیقه طول می‌کشد، پس صبور باشید.

3a6d86fd32e4a5e.png

پس از استقرار موفقیت‌آمیز، خروجی استقرار، URL سرویس Cloud Run را ارائه می‌دهد که به شکل زیر خواهد بود:

Service URL: https://yogaposes-<<UNIQUEID>.us-central1.run.app

به آن URL عمومی مراجعه کنید و باید همان برنامه وب را که با موفقیت مستقر و اجرا شده است، ببینید.

84e1cbf29cbaeedc.png

همچنین می‌توانید از کنسول گوگل کلود به Cloud Run مراجعه کنید و لیست سرویس‌ها را در Cloud Run مشاهده خواهید کرد. سرویس yogaposes باید یکی از سرویس‌هایی باشد که در آنجا فهرست شده است (اگر نگوییم تنها سرویس).

f2b34a8c9011be4c.png

شما می‌توانید جزئیات سرویس مانند URL، پیکربندی‌ها، گزارش‌ها و موارد دیگر را با کلیک روی نام سرویس خاص (در مورد ما yogaposes ) مشاهده کنید.

faaa5e0c02fe0423.png

بدین ترتیب، توسعه و استقرار برنامه وب توصیه‌گر یوگای ما بر روی Cloud Run تکمیل می‌شود.

۱۰. تبریک

تبریک می‌گویم، شما با موفقیت برنامه‌ای ساختید که یک مجموعه داده را در Firestore آپلود می‌کند، جاسازی‌ها را تولید می‌کند و بر اساس جستجوی کاربران، جستجوی تشابه برداری را انجام می‌دهد.

اسناد مرجع