Cymbal Transit: یک سیستم چندعامله با استفاده از LangChain4J و MCP Toolbox Java SDK

۱. مرور کلی

مسافران امروزی انتظار تجربیات محاوره‌ای دارند. آن‌ها به جای پیمایش فیلترهای پیچیده رابط کاربری، می‌خواهند بپرسند: «آیا می‌توانم سگم را با اتوبوس ساعت ۹ صبح به بوستون بیاورم؟» این امر مستلزم عاملی است که بتواند داده‌های بدون ساختار (سیاست‌های PDF) و داده‌های ساختار یافته (برنامه‌های SQL) را تجزیه و تحلیل کند.

در این آزمایش، ما عامل ترانزیت سیمبال را با استفاده از موارد زیر می‌سازیم:

  • LangChain4j: چارچوب برتر جاوا برای هماهنگ‌سازی هوش مصنوعی.
  • AlloyDB: یک پایگاه داده با کارایی بالا و سازگار با PostgreSQL.
  • MCP Toolbox Java SDK: روشی استاندارد برای اتصال عامل‌های جاوا به ابزارها و منابع داده خارجی.

آنچه خواهید ساخت

e68388d533c9997e.png

Cymbal Bus Agent، یک برنامه‌ی Java Spring Boot متشکل از:

  1. پایگاه داده AlloyDB و MCP Toolbox Java SDK برای هماهنگ‌سازی ابزارها با عامل‌ها.
  2. اجرای ابری برای استقرار جعبه ابزار و برنامه (استقرار عامل).
  3. کتابخانه LangChain4J برای عامل و چارچوب LLM در یک برنامه Spring Boot با جاوا ۱۷.

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

  • نحوه استفاده از LangChain4J برای ایجاد عامل‌ها و زیرعامل‌های تخصصی هماهنگ‌شده با استفاده از MCP Toolbox for Databases Java SDK
  • نحوه راه‌اندازی و استفاده از AlloyDB برای داده‌ها و هوش مصنوعی.
  • نحوه استفاده از جعبه ابزار MCP برای اتصال عامل‌ها به ابزارهای داده AlloyDB.
  • نحوه استقرار راهکار با استفاده از Cloud Run یا اجرای آن به صورت محلی.

معماری

  1. AlloyDB برای PostgreSQL: به عنوان پایگاه داده عملیاتی با کارایی بالا که سوابق مسیر، سیاست‌ها و رزروهای ما را در خود جای داده است، عمل می‌کند. این پایگاه داده، جستجو و بازیابی برداری را امکان‌پذیر می‌سازد.
  2. جعبه ابزار MCP برای پایگاه‌های داده جاوا SDK: به عنوان "Orchestration Maestro" عمل می‌کند و داده‌های AlloyDB را به عنوان ابزارهای اجرایی که عامل‌ها می‌توانند فراخوانی کنند، در معرض نمایش قرار می‌دهد.

کیت توسعه نرم‌افزار جاوای MCP Toolbox امکان هماهنگ‌سازی آسان عامل‌ها با ابزارهای پایگاه داده شما را برای برنامه‌های کاربردی در سطح سازمانی فراهم می‌کند.

  1. LangChain4J: یک کتابخانه جاوای متن‌باز که ادغام مدل‌های زبان بزرگ (LLM) را در برنامه‌های جاوا ساده می‌کند. این کتابخانه ابزارها و انتزاع‌هایی را برای ساخت برنامه‌های مبتنی بر هوش مصنوعی، از جمله چت‌بات‌ها، عامل‌ها و سیستم‌های تولید افزوده بازیابی (RAG) فراهم می‌کند.
  2. Cloud Run: یک پلتفرم کاملاً مدیریت‌شده‌ی SERVERLESS که به شما امکان می‌دهد برنامه‌ها یا وب‌سایت‌ها را به سرعت و بدون دردسر به هر زبانی، هر کتابخانه‌ای، هر باینری بسازید و مستقر کنید. می‌توانید با استفاده از زبان، چارچوب و کتابخانه‌های مورد علاقه خود کد بنویسید، آن را به عنوان یک کانتینر بسته‌بندی کنید، "gcloud run deploy" را اجرا کنید و برنامه شما به صورت زنده اجرا خواهد شد - هر آنچه را که برای اجرا در محیط عملیاتی نیاز دارد، در اختیار شما قرار می‌دهد. ساخت کانتینر کاملاً اختیاری است. اگر از Go، Node.js، Python، Java، .NET Core یا Ruby استفاده می‌کنید، می‌توانید از گزینه استقرار مبتنی بر منبع استفاده کنید که کانتینر را برای شما می‌سازد و از بهترین شیوه‌ها برای زبانی که استفاده می‌کنید استفاده می‌کند.

الزامات

  • یک مرورگر، مانند کروم یا فایرفاکس .
  • یک پروژه گوگل کلود با قابلیت پرداخت.
  • آشنایی اولیه با SQL و جاوا.

۲. قبل از شروع

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

  1. در کنسول گوگل کلود ، در صفحه انتخاب پروژه، یک پروژه گوگل کلود را انتخاب یا ایجاد کنید.
  2. مطمئن شوید که صورتحساب برای پروژه ابری شما فعال است. یاد بگیرید که چگونه بررسی کنید که آیا صورتحساب در یک پروژه فعال است یا خیر .
  1. شما از Cloud Shell ، یک محیط خط فرمان که در Google Cloud اجرا می‌شود، استفاده خواهید کرد. روی 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 های مورد نیاز: روی لینک کلیک کنید و API ها را فعال کنید.

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

اشکالات و عیب‌یابی

سندرم «پروژه ارواح»

شما gcloud config set project اجرا کردید، اما در واقع در رابط کاربری کنسول به پروژه‌ی دیگری نگاه می‌کنید. شناسه‌ی پروژه را در منوی کشویی بالا سمت چپ بررسی کنید!

سنگر بیلینگ

شما پروژه را فعال کردید، اما حساب صورتحساب را فراموش کردید. AlloyDB یک موتور با کارایی بالا است؛ اگر "مخزن بنزین" (صورتحساب) خالی باشد، روشن نمی‌شود.

تأخیر انتشار API

شما روی «فعال کردن APIها» کلیک کرده‌اید، اما خط فرمان هنوز می‌گوید Service Not Enabled . ۶۰ ثانیه به آن فرصت دهید. ابر به یک لحظه نیاز دارد تا نورون‌های خود را بیدار کند.

کواگ‌های سهمیه‌ای

اگر از یک حساب آزمایشی کاملاً جدید استفاده می‌کنید، ممکن است به سهمیه منطقه‌ای برای نمونه‌های AlloyDB برسید. اگر us-central1 با شکست مواجه شد، us-east1 امتحان کنید.

نماینده خدمات "پنهان"

گاهی اوقات به طور خودکار نقش aiplatform.user به عامل سرویس AlloyDB اعطا نمی‌شود . اگر کوئری‌های SQL شما بعداً نتوانند با Gemini ارتباط برقرار کنند، معمولاً مشکل از همین است.

۳. راه‌اندازی پایگاه داده

در قلب برنامه ما ، AlloyDB برای PostgreSQL قرار دارد. ما از قابلیت‌های برداری قدرتمند و موتور ستونی یکپارچه آن برای ایجاد جاسازی‌ها برای بیش از ۵۰،۰۰۰ رکورد SCM استفاده کردیم. این امر امکان تجزیه و تحلیل برداری تقریباً بلادرنگ را فراهم می‌کند و به نمایندگان ما اجازه می‌دهد تا ناهنجاری‌های موجودی یا خطرات لجستیکی را در مجموعه داده‌های عظیم در عرض چند میلی‌ثانیه شناسایی کنند.

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

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

  1. روی دکمه کلیک کنید یا لینک زیر را در مرورگر خود که کاربر Google Cloud Console در آن وارد شده است، کپی کنید.

روش دیگر این است که می‌توانید از پروژه خود که در آن حساب صورتحساب را فعال کرده‌اید، به Cloud Shell Terminal بروید و مخزن github را کلون کنید و با استفاده از دستورات زیر به پروژه بروید:

git clone https://github.com/AbiramiSukumaran/easy-alloydb-setup

cd easy-alloydb-setup
  1. پس از اتمام این مرحله، مخزن در ویرایشگر پوسته ابری محلی شما کلون می‌شود و می‌توانید دستور زیر را از پوشه پروژه اجرا کنید (مهم است که مطمئن شوید در دایرکتوری پروژه هستید):
sh run.sh
  1. حالا از رابط کاربری استفاده کنید (با کلیک روی لینک در ترمینال یا کلیک روی لینک «پیش‌نمایش در وب» در ترمینال).
  2. برای شروع، اطلاعات مربوط به شناسه پروژه، نام کلاستر و نمونه را وارد کنید.
  3. در حالی که کنده‌ها در حال حرکت هستند، یک قهوه بنوشید و می‌توانید در اینجا در مورد چگونگی انجام این کار در پشت صحنه بخوانید.

اشکالات و عیب‌یابی

مشکل «صبر»

خوشه‌های پایگاه داده زیرساخت‌های سنگینی هستند. اگر صفحه را رفرش کنید یا جلسه Cloud Shell را به دلیل «گیر کردن» از بین ببرید، ممکن است در نهایت با یک نمونه «شبح» مواجه شوید که تا حدی آماده شده و حذف آن بدون مداخله دستی غیرممکن است.

عدم تطابق منطقه

اگر APIهای خود را در us-central1 فعال کرده‌اید اما سعی می‌کنید کلاستر را در asia-south1 آماده‌سازی کنید، ممکن است با مشکلات سهمیه‌بندی یا تأخیر در مجوز حساب سرویس مواجه شوید. در کل آزمایش به یک منطقه پایبند باشید!

خوشه‌های زامبی

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

مهلت زمانی پوسته ابری

اگر زمان استراحت قهوه شما 30 دقیقه طول بکشد، ممکن است Cloud Shell به حالت خواب برود و فرآیند sh run.sh قطع کند. تب را فعال نگه دارید!

۴. تأمین طرحواره

پس از اجرای کلاستر و نمونه AlloyDB، به ویرایشگر SQL در AlloyDB Studio بروید تا افزونه‌های هوش مصنوعی را فعال کرده و طرحواره را آماده کنید.

1e3ac974b18a8113.png

ممکن است لازم باشد منتظر بمانید تا نمونه شما به طور کامل ایجاد شود. پس از اتمام این کار، با استفاده از اعتبارنامه‌هایی که هنگام ایجاد خوشه ایجاد کرده‌اید، وارد AlloyDB شوید. از داده‌های زیر برای تأیید اعتبار در PostgreSQL استفاده کنید:

  • نام کاربری: " postgres "
  • پایگاه داده: " postgres "
  • رمز عبور: " alloydb " (یا هر چیزی که در زمان ایجاد تعیین کرده‌اید)

پس از اینکه با موفقیت در AlloyDB Studio احراز هویت شدید، دستورات SQL در ویرایشگر وارد می‌شوند. می‌توانید با استفاده از علامت + در سمت راست آخرین پنجره، چندین پنجره ویرایشگر اضافه کنید.

۲۸cb9a8b6aa0789f.png

شما می‌توانید دستورات AlloyDB را در پنجره‌های ویرایشگر وارد کنید و در صورت لزوم از گزینه‌های Run، Format و Clear استفاده کنید.

فعال کردن افزونه‌ها

برای ساخت این برنامه، از افزونه‌های pgvector و google_ml_integration استفاده خواهیم کرد. افزونه pgvector به شما امکان ذخیره و جستجوی جاسازی‌های برداری را می‌دهد. افزونه google_ml_integration توابعی را ارائه می‌دهد که برای دسترسی به نقاط پایانی پیش‌بینی هوش مصنوعی Vertex برای دریافت پیش‌بینی‌ها در SQL استفاده می‌کنید. این افزونه‌ها را با اجرای DDL های زیر فعال کنید :

CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;

اعطای مجوز

برای اعطای مجوز اجرا به تابع "embedding"، دستور زیر را اجرا کنید:

GRANT EXECUTE ON FUNCTION embedding TO postgres;

اعطای نقش کاربری Vertex AI به حساب سرویس AlloyDB

از کنسول Google Cloud IAM ، به حساب سرویس AlloyDB (که به این شکل است: service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com) دسترسی به نقش "Vertex AI User" را بدهید. PROJECT_NUMBER شماره پروژه شما را خواهد داشت.

همچنین می‌توانید دستور زیر را از ترمینال Cloud Shell اجرا کنید:

PROJECT_ID=$(gcloud config get-value project)


gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"

ایجاد یک جدول

شما می‌توانید با استفاده از دستور DDL زیر در AlloyDB Studio یک جدول ایجاد کنید:

DROP TABLE IF EXISTS transit_policies;
DROP TABLE IF EXISTS bus_schedules;
DROP TABLE IF EXISTS bookings;

-- Table 1: Transit Policies (Unstructured Data for RAG)
CREATE TABLE transit_policies (
    policy_id SERIAL PRIMARY KEY,
    category VARCHAR(50),
    policy_text TEXT,
    policy_embedding vector(768) 
);

-- Table 2: Intercity Bus Schedules (Structured Data)
CREATE TABLE bus_schedules (
    trip_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    origin_city VARCHAR(100),
    destination_city VARCHAR(100),
    departure_time TIMESTAMP,
    arrival_time TIMESTAMP,
    available_seats INT DEFAULT 50,
    ticket_price DECIMAL(6,2)
);

-- Table 3: Booking Ledger (Transactional Action Data)
CREATE TABLE bookings (
    booking_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    trip_id UUID REFERENCES bus_schedules(trip_id),
    passenger_id VARCHAR(100),
    status VARCHAR(20) DEFAULT 'CONFIRMED',
    booking_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

ستون policy_embedding امکان ذخیره‌سازی مقادیر برداری برخی از فیلدهای متنی را فراهم می‌کند.

دریافت داده

برای درج گروهی رکوردها در جداول مربوطه، مجموعه دستورات SQL زیر را اجرا کنید:

  1. درج سیاست‌های بدون ساختار و ایجاد جاسازی‌های واقعی به صورت بومی در AlloyDB
-- 1. Insert Unstructured Policies and GENERATE REAL EMBEDDINGS natively in AlloyDB

INSERT INTO transit_policies (category, policy_text, policy_embedding) 
VALUES 
('Pets', 'Service animals are always welcome. Small pets (under 25 lbs) are allowed in secure carriers for a $25 fee. Large dogs are not permitted on standard coaches.', embedding('text-embedding-005', 'Service animals are always welcome. Small pets (under 25 lbs) are allowed in secure carriers for a $25 fee. Large dogs are not permitted on standard coaches.')),
('Luggage', 'Each passenger is allowed one carry-on (up to 15 lbs) and two stowed bags (up to 50 lbs each) free of charge. Additional bags cost $15 each.', embedding('text-embedding-005', 'Each passenger is allowed one carry-on (up to 15 lbs) and two stowed bags (up to 50 lbs each) free of charge. Additional bags cost $15 each.')),
('Refunds', 'Tickets are fully refundable up to 24 hours before departure. Within 24 hours, tickets can be exchanged for travel credit only.', embedding('text-embedding-005', 'Tickets are fully refundable up to 24 hours before departure. Within 24 hours, tickets can be exchanged for travel credit only.'));
  1. با استفاده از generate_series، بیش از ۲۰۰ برنامه واقع‌بینانه برای ۷ روز ایجاد کنید
-- 2. Generate 200+ Realistic Schedules for the Next 7 Days using generate_series

INSERT INTO bus_schedules (origin_city, destination_city, departure_time, arrival_time, ticket_price, available_seats)
SELECT 
    origin,
    destination,
    -- Generate departures every 4 hours starting from tomorrow
    (CURRENT_DATE + 1) + (interval '4 hours' * seq) AS dep_time,
    (CURRENT_DATE + 1) + (interval '4 hours' * seq) + interval '4.5 hours' AS arr_time,
    ROUND((RANDOM() * 30 + 25)::numeric, 2) AS price, -- Random price between $25 and $55
    FLOOR(RANDOM() * 50 + 1) AS seats -- Random seats between 1 and 50
FROM 
    (VALUES 
        ('New York', 'Boston'), ('Boston', 'New York'),
        ('Philadelphia', 'Washington DC'), ('Washington DC', 'Philadelphia'),
        ('Seattle', 'Portland'), ('Portland', 'Seattle')
    ) AS routes(origin, destination)
CROSS JOIN generate_series(1, 40) AS seq; -- 6 routes * 40 time slots = 240 distinct trips ingested!

ایجاد جاسازی‌ها

جاسازی‌ها (Embeddings) به طور خودکار در دستور insert در جدول transit_policies با استفاده از تابع " embedding('text-embedding-005', '<<policytext>>') " پوشش داده می‌شوند.

اشکالات و عیب‌یابی

حلقه‌ی «فراموشی رمز عبور»

اگر از تنظیمات «یک کلیک» استفاده کرده‌اید و رمز عبور خود را به خاطر نمی‌آورید، به صفحه اطلاعات اولیه Instance در کنسول بروید و برای تنظیم مجدد رمز عبور postgres روی «ویرایش» کلیک کنید.

خطای "افزونه یافت نشد"

اگر CREATE EXTENSION با شکست مواجه شود، اغلب به این دلیل است که نمونه هنوز از زمان آماده‌سازی اولیه در حالت "Maintenance" یا "Updating" است. بررسی کنید که آیا مرحله ایجاد نمونه کامل شده است یا خیر و در صورت نیاز چند ثانیه صبر کنید.

مشکلات انتشار IAM

شما دستور gcloud IAM را اجرا کردید، اما CALL SQL همچنان با خطای مجوز مواجه می‌شود. تغییرات IAM ممکن است کمی طول بکشد تا در ستون فقرات گوگل منتشر شوند . نفس عمیقی بکشید. *** نکته مهم:

  1. گاهی اوقات، ممکن است حساب سرویس AlloyDB شما با قالب موجودی که در مرحله مجوزها استفاده کرده‌ایم، متفاوت به نظر برسد. بنابراین برای اطمینان ۱۰۰٪ از اینکه حساب سرویس AlloyDB دارای نقش کاربری Vertex AI است : به صفحه AlloyDB Clusters در کنسول Google Cloud بروید. روی خوشه خود کلیک کنید و در تب Overview ، به دنبال فیلدی با عنوان Service Account بگردید.
    مقدار را کپی کنید و سپس به IAM بروید و نقش کاربر Vertex AI را اضافه کنید.
  2. همچنین، اگر مرحله «فعال کردن API» را در بخش «قبل از شروع» نادیده گرفته باشید، در دسترسی به جاسازی‌ها از AlloyDB با مشکل مواجه خواهید شد.

عدم تطابق ابعاد برداری

ستون policy_embedding جدول transit_policies روی VECTOR(768) تنظیم شده است. اگر بعداً سعی کنید از مدل متفاوتی (مانند مدل 1536-dim) استفاده کنید، درج‌های شما از بین می‌روند. به text-embedding-005 پایبند باشید.

شناسه پروژه، غلط املایی

در فراخوانی create_model ، اگر براکت‌ها را « » بگذارید یا شناسه پروژه خود را اشتباه تایپ کنید، ثبت مدل موفقیت‌آمیز به نظر می‌رسد اما در اولین پرس‌وجوی واقعی با شکست مواجه می‌شود. رشته خود را دوباره بررسی کنید!

۵. ابزارها و تنظیمات جعبه ابزار

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

ما از جعبه ابزار Model Context Protocol (MCP) برای پایگاه‌های داده به عنوان "رسانا" استفاده می‌کنیم. این جعبه ابزار به عنوان یک میان‌افزار استاندارد بین عامل‌های ما و AlloyDB عمل می‌کند. با تعریف پیکربندی tools.yaml ، این جعبه ابزار به طور خودکار عملیات پیچیده پایگاه داده را به عنوان ابزارهای تمیز و قابل اجرا مانند find-bus-schedules and routes یا query-schedules for specific routes و اقدامات مستقلی مانند book-ticket را اجرا می‌کند. این امر نیاز به ادغام دستی اتصالات یا کدهای SQL تکراری را در منطق عامل از بین می‌برد.

نصب سرور جعبه ابزار

از ترمینال Cloud Shell خود، پوشه‌ای برای ذخیره فایل yaml ابزارهای جدید و فایل باینری جعبه ابزار ایجاد کنید:

mkdir cymbal-bus-toolbox

cd cymbal-bus-toolbox

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

# see releases page for other versions
export VERSION=0.27.0
curl -L -o toolbox https://storage.googleapis.com/genai-toolbox/v$VERSION/linux/amd64/toolbox
chmod +x toolbox

سپس با رفتن به ویرایشگر Cloud Shell، فایل tools.yaml را درون آن پوشه جدید ایجاد کنید و محتویات این فایل repo را در فایل tools.yaml کپی کنید.

... (Refer to entire file in the repo)

tools:

   find-bus-schedules:
    kind: postgres-sql
    source: alloydb
    description: Find all available bus schedules.
    statement: |
      SELECT CAST(trip_id AS TEXT) trip_id, departure_time, arrival_time, ticket_price, available_seats , origin_city, destination_city 
      FROM bus_schedules;

   query-schedules:
    kind: postgres-sql
    source: alloydb
    description: Find available bus schedules between an origin and destination city.
    parameters:
      - name: origin
        type: string
        description: The departure city name.
      - name: destination
        type: string
        description: The arrival city name.
    statement: |
      SELECT CAST(trip_id AS TEXT) trip_id, departure_time, arrival_time, ticket_price, available_seats 
      FROM bus_schedules 
      WHERE lower(origin_city) = lower($1) 
        AND lower(destination_city) = lower($2) 
        AND available_seats > 0 
      ORDER BY departure_time ASC 
      LIMIT 5;

   book-ticket:
    kind: postgres-sql
    source: alloydb
    description: Books a ticket for a specific trip, decrementing available seats and generating a confirmed booking record.
    parameters:
      - name: trip_id
        type: string
        description: The UUID of the trip schedule to book.
      - name: passenger_name
        type: string
        description: Name or ID of the passenger (Bound securely via backend or AuthToken).
        authServices:
          - name: google_auth
            field: sub
    statement: |
      WITH updated_schedule AS (
          UPDATE bus_schedules 
          SET available_seats = available_seats - 1 
          WHERE trip_id = CAST($1 AS UUID) AND available_seats > 0
          RETURNING trip_id
      )
      INSERT INTO bookings (trip_id, passenger_id)
      SELECT trip_id, $2 
      FROM updated_schedule
      RETURNING CAST(booking_id as TEXT) as booking_id, trip_id, passenger_id, status, booking_time;

   search-policies:
    kind: postgres-sql
    source: alloydb
    description: Semantic search for transit policies regarding luggage, pets, refunds, and general rules.
    parameters:
      - name: search_query
        type: string
        description: The user's question about transit policies to be embedded and searched.
    statement: |
      SELECT category, policy_text 
      FROM transit_policies 
      ORDER BY policy_embedding <=> CAST(embedding('text-embedding-005', $1) AS vector(768))
      LIMIT 2;

توجه:

  1. در تنظیمات tools.yaml، فراموش نکنید که ipType: "private" را در پیکربندی منبع alloydb وارد کنید.
  2. همچنین به یاد داشته باشید که آدرس اینترنتی سرویس MCP Toolbox را در پارامتر clientId برای پیکربندی authServices وارد کنید. ممکن است این لینک را فقط پس از استقرار اولیه دریافت کنید - بنابراین بله، باید مراحل استقرار را دو بار اجرا کنید تا مطمئن شوید که موارد استفاده ابزارهای احراز هویت شده کار می‌کنند.
  3. گزینه‌های زیر برای تست جعبه ابزار به صورت محلی در صورتی که اتصال AlloyDB شما خصوصی تنظیم شده باشد، کار نخواهند کرد. برای تست محلی آن باید آن را عمومی کنید یا از یک پروکسی برای اتصال استفاده کنید. اما نگران این موضوع نباشید . در مورد ما، ما مستقیماً آن را در Cloud Run مستقر کرده و سپس تست می‌کنیم.

برای آزمایش فایل tools.yaml در سرور محلی:

./toolbox --tools-file "tools.yaml"

می‌توانید آن را در رابط کاربری نیز آزمایش کنید:

./toolbox --ui

بیایید ادامه دهیم و آن را در Cloud Run به صورت زیر مستقر کنیم.

استقرار ابری

  1. متغیر محیطی PROJECT_ID را تنظیم کنید:
export PROJECT_ID="my-project-id"
  1. مقداردهی اولیه خط فرمان gcloud:
gcloud init
gcloud config set project $PROJECT_ID
  1. شما باید API های زیر را فعال کرده باشید:
gcloud services enable run.googleapis.com \
                       cloudbuild.googleapis.com \
                       artifactregistry.googleapis.com \
                       iam.googleapis.com \
                       secretmanager.googleapis.com
  1. اگر از قبل حساب کاربری سرویس بک‌اند ندارید، یک حساب کاربری ایجاد کنید:
gcloud iam service-accounts create toolbox-identity
  1. اعطای مجوز برای استفاده از مدیر مخفی:
gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
    --role roles/secretmanager.secretAccessor
  1. مجوزهای اضافی را به حساب سرویس که مختص منبع AlloyDB ما هستند (roles/alloydb.client و roles/serviceusage.serviceUsageConsumer) اعطا کنید.
gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
    --role roles/alloydb.client


gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
    --role roles/serviceusage.serviceUsageConsumer
  1. tools.yaml را به عنوان یک فایل مخفی آپلود کنید:
gcloud secrets create tools-cymbal-transit --data-file=tools.yaml
  1. اگر از قبل یک نسخه مخفی دارید و می‌خواهید نسخه مخفی را به‌روزرسانی کنید، دستور زیر را اجرا کنید:
gcloud secrets versions add tools-cymbal-transit --data-file=tools.yaml
  1. یک متغیر محیطی را روی تصویر کانتینری که می‌خواهید برای اجرای ابری استفاده کنید، تنظیم کنید:
export IMAGE=us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest
  1. با استفاده از دستور زیر، Toolbox را روی Cloud Run مستقر کنید:

اگر دسترسی عمومی را در نمونه AlloyDB خود فعال کرده‌اید، برای استقرار در Cloud Run، دستور زیر را دنبال کنید:

gcloud run deploy toolbox-cymbal-transit \
    --image $IMAGE \
    --service-account toolbox-identity \
    --region us-central1 \
    --set-secrets "/app/tools.yaml=tools-cymbal-transit:latest" \
    --args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
    --allow-unauthenticated

اگر از شبکه VPC استفاده می‌کنید، از دستور زیر استفاده کنید:

gcloud run deploy toolbox-cymbal-transit \
    --image $IMAGE \
    --service-account toolbox-identity \
    --region us-central1 \
    --set-secrets "/app/tools.yaml=tools-cymbal-transit:latest" \
    --args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
    --network <<YOUR_NETWORK_NAME>> \
    --subnet <<YOUR_SUBNET_NAME>> \
    --allow-unauthenticated

توجه: پس از استقرار، به لیست سرویس‌های Cloud Run بروید و مطمئن شوید که در تب امنیتی آن سرویس، گزینه «Allow public access» انتخاب شده باشد.

۶. راه‌اندازی برنامه‌ی عامل

این مخزن را در پروژه خود کلون کنید و بیایید آن را بررسی کنیم.

مخزن گیت‌هاب

برای کلون کردن این، از ترمینال Cloud Shell خود (در دایرکتوری ریشه یا از هر جایی که می‌خواهید این پروژه را ایجاد کنید)، دستور زیر را اجرا کنید:

git clone https://github.com/googleapis/mcp-toolbox-sdk-java

دستور بالا در واقع کل mcp-toolbox-sdk-java را کپی می‌کند. ما فقط به پروژه نمونه از آن نیاز داریم. بنابراین به دایرکتوری ریشه پروژه در داخل مخزن بروید:

cd mcp-toolbox-sdk-java/demo-applications/cymbal-transit
  1. این باید پروژه را ایجاد کند و شما می‌توانید آن را در ویرایشگر Cloud Shell تأیید کنید.

a494664032904c77.png

  1. CymbalTransitController.java را باز کنید و متغیرهای محیطی را تنظیم کنید:
  2. شناسه پروژه GCP
  3. منطقه GCP
  4. نام مدل GEMINI
  5. نشانی وب MCP_TOOLBOX

به عنوان یک روش جایگزین (فقط برای اهداف توسعه) می‌توانید متغیرهای مقدار جایگزین مربوطه را نیز جایگزین کنید.

۷. راهنمای کد

CymbalTransitController به عنوان نقطه ورود برای سرویس Cloud Run ما عمل می‌کند. این کنترلر جریان مکالمه را مدیریت می‌کند و تضمین می‌کند که اپراتور به درخواست فعلی کاربر دسترسی داشته باشد.

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

۱. پیکربندی عامل هوش مصنوعی ( AgentConfiguration )

این کلاس از @Configuration در Spring برای بوت‌استرپ کردن کامپوننت‌های هوش مصنوعی استفاده می‌کند. این کلاس VertexAiGeminiChatModel را مقداردهی اولیه کرده و آن را به رابط Agent ما متصل می‌کند.

@Bean
ChatLanguageModel geminiChatModel() {
    return VertexAiGeminiChatModel.builder()
        .project(projectId)
        .location(region)
        .modelName(modelName)
        .build();
}

@Bean
TransitAgent transitAgent(ChatLanguageModel chatLanguageModel, TransitAgentTools tools) {
    return AiServices.builder(TransitAgent.class)
        .chatLanguageModel(chatLanguageModel)
        .chatMemoryProvider(memoryId -> MessageWindowChatMemory.withMaxMessages(20))
        .tools(tools) 
        .build();
}

اهمیت: AiServices رابط را به LLM متصل می‌کند. MessageWindowChatMemory تضمین می‌کند که عامل، تنظیمات کاربر (مانند جعبه حمل حیوانات خانگی که قبلاً ذکر شد) را تا حداکثر 20 پیام در یک جلسه به خاطر می‌سپارد.

۲. رابط عامل هوش مصنوعی ( TransitAgent )

حاشیه‌نویسی @SystemMessage «شخصیت» و محدودیت‌های عملیاتی، به‌ویژه یک «استراتژی مسیریابی» (Routing Strategy) را تعریف می‌کند.

@SystemMessage({
    "You are the Cymbal Transit Concierge.",
    "CRITICAL INSTRUCTION: On your very first interaction, you MUST use the 'findAllSchedules' tool to fetch and memorize the broad bus routes.",
    "ONLY if the user asks a specifically narrowed-down question... should you route to the specific tools like 'querySchedules', 'bookTicket', 'searchPolicies'.",
    "Don't show any asterisks while listing results. Keep it formatted and numbered or bulleted."
})
String chat(@MemoryId String sessionId, @UserMessage String userMessage);

اهمیت: این استراتژی تأخیر را به حداقل می‌رساند. با واکشی داده‌های گسترده در ابتدا، عامل می‌تواند با استفاده از زمینه داخلی خود و بدون انجام تماس‌های اضافی در backend، به سؤالات عمومی مسیریابی پاسخ دهد.

۳. پل جعبه ابزار ( TransitAgentTools )

این سرویس به عنوان "دست‌های" عامل عمل می‌کند و فراخوانی‌های ابزار LangChain4j را به منطق اجرا تبدیل می‌کند.

@Tool("Fetches the initial, broad dataset of all available bus schedules and routes.")
public String findAllSchedules() {
    return mcpService.findAllSchedules().join();
}


@Tool("Book a ticket for a passenger using a specific trip ID.")
public String bookTicket(String tripId, String passengerName) {
    return mcpService.bookTicket(tripId, passengerName).join();
}

اجرای همزمان: در حالی که فراخوانی‌های MCP ناهمزمان هستند ( CompletableFuture را برمی‌گردانند)، LLM قبل از اینکه بتواند فرآیند "فکر کردن" خود را ادامه دهد، به نتیجه نیاز دارد. ما .join() برای ارائه نتایج همزمان به عامل استفاده می‌کنیم.

۴. سرویس جعبه ابزار MCP ( McpToolboxService )

این لایه ارتباطی است که از MCP Toolbox Java SDK برای تعامل با بک‌اند AlloyDB استفاده می‌کند.

// Identity Management: Fetching OIDC ID Token for Auth
GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
this.idToken = ((IdTokenProvider) credentials)
    .idTokenWithAudience(targetUrl, Collections.emptyList())
    .getTokenValue();

// Dynamic Invocation: Executing a tool by name
public CompletableFuture<String> findAllSchedules() {
    return mcpClient.invokeTool("find-bus-schedules", Collections.emptyMap()).thenApply(result -> {
        return result.content().stream()
            .map(content -> content.text())
            .collect(Collectors.joining(", ", "[", "]"));
    });
}

اهمیت: McpToolboxClient بخش سنگین ارتباطات JSON-RPC را مدیریت می‌کند. متد bookTicket به طور خاص توانایی SDK را در اتصال پویای پارامترهای پیچیده نشان می‌دهد.

۵. کنترلر REST ( TransitAgentController )

نقطه پایانی به طور اساسی ساده شده است زیرا LangChain4j حالت و منطق را مدیریت می‌کند.

@PostMapping("/chat")
public ResponseEntity<String> handleUserChat(@RequestBody String userMessage, HttpSession session) {
    String sessionId = session.getId();
    String agentResponse = transitAgent.chat(sessionId, userMessage);
    return ResponseEntity.ok(agentResponse);
}

اهمیت: با نگاشت شناسه HttpSession به @MemoryId ، اطمینان حاصل می‌کنیم که برنامه‌های سفر کاربران مختلف با هم قاطی نمی‌شود، و در عین حال کد کنترلر تمیز و خوانا باقی می‌ماند.

۸. جعبه ابزار MCP: اهمیت و SDK جاوا

ام سی پی چیست؟

پروتکل زمینه مدل (MCP) را به عنوان یک مترجم جهانی برای هوش مصنوعی در نظر بگیرید. MCP که برای استانداردسازی نحوه اتصال مدل‌های هوش مصنوعی به ابزارها و مجموعه داده‌های خارجی ایجاد شده است، اسکریپت‌های یکپارچه‌سازی سفارشی و تکه‌تکه را با یک پروتکل امن و جهانی جایگزین می‌کند. چه نماینده شما نیاز به اجرای یک کوئری SQL تراکنشی داشته باشد، چه نیاز به جستجو در هزاران سند سیاست‌گذاری یا راه‌اندازی یک REST API، MCP یک رابط واحد و یکپارچه ارائه می‌دهد.

جعبه ابزار MCP برای پایگاه‌های داده

تیم‌های مهندسی در حال گذار از چت‌بات‌های ساده به سمت ساخت سیستم‌های عاملی هستند که مستقیماً با پایگاه‌های داده حیاتی تعامل دارند. با این حال، ساخت این عامل‌های سازمانی اغلب به معنای برخورد با دیوار یکپارچه‌سازی از کدهای چسبی سفارشی، APIهای شکننده و منطق پیچیده پایگاه داده است.

برای جایگزینی این گلوگاه‌های کدنویسی‌شده با یک صفحه کنترل امن و یکپارچه، مفتخریم که SDK جاوا را برای جعبه‌ابزار پروتکل زمینه مدل (MCP) برای پایگاه‌های داده معرفی کنیم. این نسخه، هماهنگی عامل درجه یک و ایمن از نظر نوع را به گسترده‌ترین اکوسیستم سازمانی جهان ارائه می‌دهد. معماری بالغ جاوا برای این خواسته‌های دقیق ساخته شده است و همزمانی بالا، یکپارچگی تراکنشی دقیق و مدیریت وضعیت قوی مورد نیاز برای مقیاس‌پذیری ایمن عامل‌های هوش مصنوعی حیاتی در محیط تولید را فراهم می‌کند.

چرا SDK جاوا؟

کیت توسعه نرم‌افزار جاوای MCP Toolbox به توسعه‌دهندگان جاوا اجازه می‌دهد تا:

  1. مصرف ابزارها: به یک سرور MCP (مانند جعبه ابزار MCP برای AlloyDB) متصل شوید و به طور خودکار قابلیت‌های آن را به متدهای جاوا که LangChain4j آنها را می‌فهمد تبدیل کنید.
  2. ایمنی نوع: از تایپ قوی جاوا برای پارامترهای ابزار استفاده کنید و خطاهای "توهم" زمان اجرا را در فراخوانی‌های ابزار کاهش دهید.
  3. آمادگی سازمانی: به راحتی با Spring Boot، Quarkus، Micronaut و غیره ادغام می‌شود.
  4. اتصال آسان: از نوشتن کد JSON-RPC تکراری خودداری کنید.
  5. استانداردسازی احراز هویت: پشتیبانی بومی از توکن‌های Google Cloud OIDC، اجرای امن ابزار را تضمین می‌کند.

و خیلی چیزهای دیگر .

وابستگی‌ها: پیکربندی pom.xml

وابستگی زیر را به پروژه Maven خود اضافه کنید تا آخرین MCP Toolbox Java SDK را شامل شود:

   <dependency>
        <groupId>com.google.cloud.mcp</groupId>
        <artifactId>mcp-toolbox-sdk-java</artifactId>
        <version>0.2.0</version>
    </dependency>

وابستگی زیر را به پروژه Maven خود اضافه کنید تا شامل مصنوع LangChain4j باشد:

     <!-- LangChain4j Core & Gemini -->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j</artifactId>
        <version>0.35.0</version>
    </dependency>

همین!!! ما با موفقیت پروژه را کلون کردیم و جزئیات عامل، MCP Toolbox Java SDK و زمینه را بررسی کردیم.

۹. اجرای محلی

برای آزمایش عامل روی دستگاه خود، باید آن را به سرور MCP Toolbox مستقر خود متصل کنید.

  1. تنظیم متغیرهای محیطی:
export GCP_PROJECT_ID="<<YOUR_PROJECT_ID>>"
export GCP_REGION="us-central1"
export GEMINI_MODEL_NAME="gemini-2.5-flash"
export MCP_TOOLBOX_URL="<<YOUR_TOOLBOX_ENDPOINT_URL>>/mcp"
  1. با Maven اجرا کنید:
mvn compile

mvn spring-boot:run

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

۱۰. بیایید آن را در Cloud Run مستقر کنیم

با اجرای دستور زیر از ترمینال Cloud Shell که پروژه در آن کلون شده است، آن را روی Cloud Run مستقر کنید و مطمئن شوید که در پوشه ریشه پروژه هستید .

اگر در پوشه ریشه پروژه فعلی ما نیستید، این را در ترمینال Cloud Shell خود اجرا کنید:

cd cymbal-transit

اگر از قبل در ریشه cymbal-transit هستید، دستور زیر را اجرا کنید تا برنامه مستقیماً روی Cloud Run مستقر شود:

gcloud run deploy cymbal-transit --source . --set-env-vars GCP_PROJECT_ID=<<YOUR_PROJECT_ID>>,GCP_REGION=us-central1,GEMINI_MODEL_NAME=gemini-2.5-flash,MCP_TOOLBOX_URL=<<YOUR_MCP_TOOLBOX_URL>> --allow-unauthenticated

مقادیر مربوط به متغیرهای <<YOUR_PROJECT>> and <<YOUR_MCP_TOOLBOX_URL>> را جایگزین کنید.

پس از اتمام دستور، یک URL سرویس نمایش داده می‌شود. آن را کپی کنید.

نقش AlloyDB Client را به حساب سرویس Cloud Run اعطا کنید. این به برنامه بدون سرور شما اجازه می‌دهد تا به طور ایمن به پایگاه داده تونل بزند.

این را در ترمینال Cloud Shell خود اجرا کنید:

# 1. Get your Project ID and Project Number
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")

# 2. Grant the AlloyDB Client role
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
--role="roles/alloydb.client"

توجه: پس از استقرار، به لیست سرویس‌های Cloud Run بروید و مطمئن شوید که در تب امنیتی آن سرویس، گزینه «Allow public access» انتخاب شده باشد.

حالا از آدرس اینترنتی سرویس (نقطه پایانی Cloud Run که قبلاً کپی کرده‌اید) استفاده کنید و برنامه را آزمایش کنید.

توجه: اگر با مشکل سرویس مواجه شدید و دلیل آن را حافظه اعلام کرد، برای آزمایش، محدودیت حافظه اختصاص داده شده را به ۱ گیگابایت افزایش دهید.

۱۱. نسخه آزمایشی

از نماینده بپرسید: «من باید فردا صبح از نیویورک به بوستون بروم. آیا می‌توانم سگ گلدن رتریورم را بیاورم؟» مشاهده کنید که نماینده چگونه:

  1. سیاست‌های جستجو برای سگ‌های بزرگ.
  2. برنامه‌های مشخصی پیدا می‌کند.
  3. سریع‌ترین سفر را با شناسه سفر خلاصه می‌کند.
  4. همچنین اگر آن درخواست اقدام را پیگیری کنید، یک تیکت رزرو کنید.

aa0408a81074d0fc.png

۱۲. تمیز کردن

پس از انجام این آزمایش، فراموش نکنید که کلاستر و نمونه alloyDB را حذف کنید.

باید کلاستر را به همراه نمونه(های) آن پاکسازی کند.

۱۳. تبریک

شما با موفقیت یک عامل حمل و نقل پیچیده مبتنی بر جاوا ساخته‌اید. با بهره‌گیری از LangChain4j برای هماهنگ‌سازی و MCP Toolbox Java SDK برای اتصال داده‌ها، سیستمی ایجاد کرده‌اید که می‌تواند بین عامل‌ها، ابزارها و منابع داده استدلال کند. اگر می‌خواهید هماهنگ‌سازی برنامه‌های عامل خود را با MCP Toolbox for Databases در چندین پایگاه داده، حتی در پلتفرم‌های مختلف، آغاز کنید، همین امروز با Java SDK شروع کنید! در اینجا وبلاگ اطلاعیه راه‌اندازی آمده است که اطلاعات دقیق‌تری در مورد کتابخانه ارائه می‌دهد . اگر می‌خواهید برنامه‌های کاربردی بیشتری از این دست را به صورت عملی، رایگان با سرعت خودتان و با هدایت مدرس بسازید، در Code Vipassana در https://codevipassana.dev ثبت نام کنید!!!