ADK, AlloyDB ve Vertex AI Memory Bank ile tedarik zinciri düzenleyici oluşturma

1. Genel Bakış

Bu codelab'de bir tedarik zinciri düzenleyici aracısı oluşturacaksınız. Bu uygulama, kullanıcıların doğal dili kullanarak envanteri analiz etmesine, lojistiği takip etmesine ve tedarik zinciri risklerini yönetmesine olanak tanır.

Bağlamı koruyan, Vertex AI Memory Bank aracılığıyla kullanıcı tercihlerini hatırlayan ve MCP Toolbox aracılığıyla AlloyDB'de depolanan büyük bir veri kümesiyle etkileşime giren çoklu aracı mimarisi oluşturmak için Google'ın Agent Development Kit'ini (ADK) kullanacağız.

Ne oluşturacaksınız?

91e8e53556ac1966.jpeg

Aşağıdakilerden oluşan bir Python Flask uygulaması:

Global Düzenleyici Ajan: Sohbet akışını ve yetki devrini yöneten kök ajandır.

Uzman Temsilciler: Alana özgü görevler için "InventorySpecialist" (Envanter Uzmanı) ve "LogisticsManager" (Lojistik Yöneticisi).

Bellek entegrasyonu: Vertex AI Memory Bank kullanılarak kısa süreli oturum belleği ve uzun süreli bellek.

Açıklayıcı kullanıcı arayüzü: Aracının muhakeme sürecini (İzleme Bağlamı) görselleştiren bir web arayüzü.

Neler öğreneceksiniz?

  • Özel temsilciler ve alt temsilciler oluşturmak için Google ADK'yı kullanma
  • Uzun süreli aracı belleği için Vertex AI Memory Bank'ı entegre etme
  • Ajanları AlloyDB veri araçlarına bağlamak için MCP Toolbox'ı kullanma
  • Ajan muhakemesini izlemek ve görselleştirmek için ADK geri çağırmalarını uygulama
  • Çözümü Cloud Run kullanarak dağıtma veya yerel olarak çalıştırma

Mimari

Teknoloji Yığını

  1. AlloyDB for PostgreSQL: 50.000'den fazla tedarik zinciri kaydını tutan yüksek performanslı operasyonel veritabanı olarak hizmet verir. Vektör arama ve alma işlemlerini destekler.
  2. Veritabanları için MCP Araç Kutusu: "Orkestrasyon Ustası" olarak işlev görür ve AlloyDB verilerini, aracıların çağırabileceği yürütülebilir araçlar olarak kullanıma sunar.
  3. Agent Development Kit (ADK): Aracıları, talimatları ve araçları tanımlamak için kullanılan çerçeve.
  4. Vertex AI Memory Bank: Uzun süreli bellek sağlayarak aracının oturumlar genelinde kullanıcı tercihlerini ve geçmiş etkileşimleri hatırlamasına olanak tanır.
  5. Vertex AI Session Service: Kısa süreli sohbet bağlamını yönetir.

The Flow

  1. Kullanıcı Sorgusu: Kullanıcı soru sorar (ör. "Premium dondurma stokta var mı?").
  2. Bellek Kontrolü: Düzenleyici, Bellek Bankası'nda ilgili geçmiş bilgileri (ör. "Kullanıcı, EMEA bölgesinin bölge yöneticisidir") kontrol eder.
  3. Yetki verme: Düzenleyici, görevi InventorySpecialist'e (Envanter Uzmanı) devreder.
  4. Araç Yürütme: Uzman, AlloyDB'ye sorgu göndermek için MCP Araç Kutusu tarafından sağlanan araçları kullanır.
  5. Yanıt: Aracı, verileri işler ve Markdown biçimli bir tablo döndürür.
  6. Bellek Depolama: Önemli etkileşimler, Bellek Bankası'na geri kaydedilir.

Şartlar

  • Chrome veya Firefox gibi bir tarayıcı
  • Faturalandırmanın etkin olduğu bir Google Cloud projesi.
  • SQL ve Python hakkında temel düzeyde bilgi sahibi olmak.

2. Başlamadan önce

Proje oluşturma

  1. Google Cloud Console'daki proje seçici sayfasında bir Google Cloud projesi seçin veya oluşturun.
  2. Cloud projeniz için faturalandırmanın etkinleştirildiğinden emin olun. Bir projede faturalandırmanın etkin olup olmadığını kontrol etmeyi öğrenin.
  1. Google Cloud'da çalışan bir komut satırı ortamı olan Cloud Shell'i kullanacaksınız. Google Cloud Console'un üst kısmından Cloud Shell'i etkinleştir'i tıklayın.

Cloud Shell'i etkinleştir düğmesinin resmi

  1. Cloud Shell'e bağlandıktan sonra aşağıdaki komutu kullanarak kimliğinizin doğrulandığını ve projenin proje kimliğinize ayarlandığını kontrol edin:
gcloud auth list
  1. gcloud komutunun projeniz hakkında bilgi sahibi olduğunu onaylamak için Cloud Shell'de aşağıdaki komutu çalıştırın.
gcloud config list project
  1. Projeniz ayarlanmamışsa ayarlamak için aşağıdaki komutu kullanın:
gcloud config set project <YOUR_PROJECT_ID>
  1. Gerekli API'leri etkinleştirin: Bağlantıyı takip ederek API'leri etkinleştirin.

Alternatif olarak, bu işlem için gcloud komutunu kullanabilirsiniz. gcloud komutları ve kullanımı için belgelere bakın.

Dikkat Edilmesi Gerekenler ve Sorun Giderme

"Hayalet Proje" Sendromu

gcloud config set project komutunu çalıştırdınız ancak Console kullanıcı arayüzünde aslında farklı bir projeye bakıyorsunuz. Sol üstteki açılır listede proje kimliğini kontrol edin.

Faturalandırma Barikatı

Projeyi etkinleştirdiniz ancak faturalandırma hesabını unuttunuz. AlloyDB yüksek performanslı bir motordur. "Yakıt deposu" (faturalandırma) boşsa çalışmaz.

API Yayılımı Gecikmesi

"API'leri etkinleştir"i tıkladınız ancak komut satırında hâlâ Service Not Enabled yazıyor. 60 saniye bekleyin. Bulutun nöronlarını uyandırması biraz zaman alır.

Kota Quags

Yeni bir deneme hesabı kullanıyorsanız AlloyDB örnekleri için bölgesel kotaya ulaşabilirsiniz. us-central1 başarısız olursa us-east1'ı deneyin.

"Gizli" Hizmet Aracısı

Bazen AlloyDB hizmet aracısına aiplatform.user rolü otomatik olarak verilmez. SQL sorgularınız daha sonra Gemini ile iletişim kuramıyorsa genellikle sorun bundan kaynaklanır.

3. Veritabanı kurulumu

Uygulamamızın temelinde PostgreSQL için AlloyDB yer alıyor. 50.000'den fazla SCM kaydı için yerleştirmeler oluşturmak üzere güçlü vektör özelliklerinden ve entegre sütun motorundan yararlandık. Bu sayede, anlık vektör analizi yapılabiliyor ve temsilcilerimiz, saniyeler içinde büyük veri kümelerindeki envanter anormalliklerini veya lojistik risklerini belirleyebiliyor.

Bu laboratuvarda, test verileri için veritabanı olarak AlloyDB'yi kullanacağız. Veritabanları ve günlükler gibi tüm kaynakları tutmak için kümeler kullanılır. Her kümede, verilere erişim noktası sağlayan bir birincil örnek bulunur. Tablolar gerçek verileri içerir.

Test veri kümesinin yükleneceği bir AlloyDB kümesi, örneği ve tablosu oluşturalım.

  1. Google Cloud Console kullanıcısının oturumunun açık olduğu tarayıcınızda aşağıdaki bağlantıyı kopyalayın veya düğmeyi tıklayın.

Alternatif olarak, faturalandırma hesabını kullandığınız projenizden Cloud Shell Terminal'e gidebilir, GitHub deposunu klonlayabilir ve aşağıdaki komutları kullanarak projeye gidebilirsiniz:

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

cd easy-alloydb-setup
  1. Bu adım tamamlandıktan sonra depo, yerel Cloud Shell düzenleyicinize klonlanır ve aşağıdaki komutu proje klasöründen çalıştırabilirsiniz (proje dizininde olduğunuzdan emin olmanız önemlidir):
sh run.sh
  1. Şimdi kullanıcı arayüzünü kullanın (terminaldeki bağlantıyı veya terminaldeki "web'de önizleme" bağlantısını tıklayarak).
  2. Başlamak için proje kimliği, küme ve örnek adlarıyla ilgili ayrıntılarınızı girin.
  3. Günlükler kayarken kahve almaya gidebilirsiniz. Bu işlemin perde arkasında nasıl yapıldığı hakkında bilgi edinmek için burayı ziyaret edebilirsiniz.

Dikkat Edilmesi Gerekenler ve Sorun Giderme

"Sabır" Sorunu

Veritabanı kümeleri ağır altyapılardır. Sayfayı yenilerseniz veya "takılmış gibi göründüğü" için Cloud Shell oturumunu sonlandırırsanız kısmen sağlanan ve manuel müdahale olmadan silinmesi mümkün olmayan bir "hayalet" örneğiyle karşılaşabilirsiniz.

Bölge Uyuşmazlığı

API'lerinizi us-central1 içinde etkinleştirdiyseniz ancak kümeyi asia-south1 içinde sağlamaya çalışıyorsanız kota sorunları veya hizmet hesabı izniyle ilgili gecikmelerle karşılaşabilirsiniz. Tüm laboratuvar boyunca tek bir bölgeye bağlı kalın.

Zombi Kümeleri

Daha önce bir küme için aynı adı kullandıysanız ve bu adı silmediyseniz komut dosyası, küme adının zaten mevcut olduğunu söyleyebilir. Küme adları, proje içinde benzersiz olmalıdır.

Cloud Shell Zaman Aşımı

Kahve molanız 30 dakika sürerse Cloud Shell uyku moduna geçebilir ve sh run.sh işleminin bağlantısını kesebilir. Sekmeyi etkin tutun.

4. Şema Sağlama

AlloyDB kümeniz ve örneğiniz çalıştıktan sonra, yapay zeka uzantılarını etkinleştirmek ve şemayı sağlamak için AlloyDB Studio SQL düzenleyicisine gidin.

1e3ac974b18a8113.png

Örneğinizin oluşturulmasının tamamlanmasını beklemeniz gerekebilir. Bu işlem tamamlandıktan sonra, kümeyi oluştururken oluşturduğunuz kimlik bilgilerini kullanarak AlloyDB'de oturum açın. PostgreSQL'de kimlik doğrulaması yapmak için aşağıdaki verileri kullanın:

  • Kullanıcı adı : "postgres"
  • Veritabanı : "postgres"
  • Şifre : "alloydb" (veya oluşturma sırasında ayarladığınız şifre)

AlloyDB Studio'da kimliğinizi başarıyla doğruladıktan sonra SQL komutları Düzenleyici'ye girilir. Son pencerenin sağındaki artı işaretini kullanarak birden fazla Düzenleyici penceresi ekleyebilirsiniz.

28cb9a8b6aa0789f.png

AlloyDB için komutları düzenleyici pencerelerine girerken gerektiğinde Çalıştır, Biçimlendir ve Temizle seçeneklerini kullanacaksınız.

Uzantıları etkinleştirme

Bu uygulamayı oluşturmak için pgvector ve google_ml_integration uzantılarını kullanacağız. pgvector uzantısı, vektör yerleştirmelerini depolamanıza ve aramanıza olanak tanır. google_ml_integration uzantısı, SQL'de tahmin almak için Vertex AI tahmin uç noktalarına erişmek üzere kullandığınız işlevleri sağlar. Aşağıdaki DDL'leri çalıştırarak bu uzantıları etkinleştirin:

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

Tablo oluşturma

AlloyDB Studio'da aşağıdaki DDL ifadesini kullanarak bir tablo oluşturabilirsiniz:

DROP TABLE IF EXISTS shipments;
DROP TABLE IF EXISTS products;

-- 1. Product Inventory Table

CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
category VARCHAR(100),
stock_level INTEGER,
distribution_center VARCHAR(100),
region VARCHAR(50),
embedding vector(768),
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 2. Logistics & Shipments
CREATE TABLE shipments (
shipment_id SERIAL PRIMARY KEY,
product_id INTEGER REFERENCES products(id),
status VARCHAR(50), -- 'In Transit', 'Delayed', 'Delivered', 'Pending'
estimated_arrival TIMESTAMP,
route_efficiency_score DECIMAL(3, 2)
);

embedding sütunu, bazı metin alanlarının vektör değerlerinin depolanmasına olanak tanır.

Veri Kullanımı

Ürünler tablosuna 50.000 kaydı toplu olarak eklemek için aşağıdaki SQL ifadeleri grubunu çalıştırın:

-- We use a CROSS JOIN pattern with realistic naming segments to create meaningful variety
DO $$
DECLARE
brand_names TEXT[] := ARRAY['Artisan', 'Nature', 'Elite', 'Pure', 'Global', 'Eco', 'Velocity', 'Heritage', 'Aura', 'Summit'];
product_types TEXT[] := ARRAY['Ice Cream', 'Body Wash', 'Laundry Detergent', 'Shampoo', 'Mayonnaise', 'Deodorant', 'Tea', 'Soup', 'Face Cream', 'Soap'];
variants TEXT[] := ARRAY['Classic', 'Gold', 'Premium', 'Eco-Friendly', 'Organic', 'Night-Repair', 'Extra-Fresh', 'Zero-Sugar', 'Sensitive', 'Maximum-Strength'];
regions TEXT[] := ARRAY['EMEA', 'APAC', 'LATAM', 'NAMER'];
dcs TEXT[] := ARRAY['London-Hub', 'Mumbai-Central', 'Sao-Paulo-Logistics', 'Singapore-Port', 'Rotterdam-Gate', 'New-York-DC'];
BEGIN
INSERT INTO products (name, category, stock_level, distribution_center, region)
SELECT
b || ' ' || v || ' ' || t as name,
CASE
WHEN t IN ('Ice Cream', 'Mayonnaise', 'Tea', 'Soup') THEN 'Food & Refreshment'
WHEN t IN ('Body Wash', 'Shampoo', 'Deodorant', 'Face Cream', 'Soap') THEN 'Personal Care'
ELSE 'Home Care'
END as category,
floor(random() * 20000 + 100)::int as stock_level,
dcs[floor(random() * 6 + 1)] as distribution_center,
regions[floor(random() * 4 + 1)] as region
FROM
unnest(brand_names) b,
unnest(variants) v,
unnest(product_types) t,
generate_series(1, 50); -- 10 * 10 * 10 * 50 = 50,000 records
END $$;

Yönetici tarzı sorulara tahmin edilebilir yanıtlar verilmesini sağlamak için demoya özel kayıtlar ekleyelim

-- These ensure you have predictable answers for specific "Executive" questions
INSERT INTO products (name, category, stock_level, distribution_center, region) VALUES
('Magnum Ultra Gold Limited Edition', 'Food & Refreshment', 45, 'Rotterdam-Gate', 'EMEA'),
('Dove Pro-Health Deep Moisture', 'Personal Care', 12000, 'Mumbai-Central', 'APAC'),
('Hellmanns Real Organic Mayonnaise', 'Food & Refreshment', 8000, 'London-Hub', 'EMEA');

Kargolar verilerini ekleme

-- Shipments Generation (More shipments than products)
INSERT INTO shipments (product_id, status, estimated_arrival, route_efficiency_score)
SELECT
id,
CASE
WHEN random() > 0.8 THEN 'Delayed'
WHEN random() > 0.4 THEN 'In Transit'
ELSE 'Delivered'
END,
NOW() + (random() * 10 || ' days')::interval,
(random() * 0.5 + 0.5)::decimal(3,2)
FROM products
WHERE random() > 0.3; -- Create shipments for ~70% of products


-- Add duplicate shipments for some products to show complex logistics
INSERT INTO shipments (product_id, status, estimated_arrival, route_efficiency_score)
SELECT id, 'In Transit', NOW() + INTERVAL '12 days', 0.88
FROM products
LIMIT 5000;

İzin Ver

"embedding" işlevinde yürütme izni vermek için aşağıdaki ifadeyi çalıştırın:

GRANT EXECUTE ON FUNCTION embedding TO postgres;

AlloyDB hizmet hesabına Vertex AI Kullanıcısı ROLÜ'nü verme

Google Cloud IAM Console'dan AlloyDB hizmet hesabına (service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com şeklinde görünür) "Vertex AI Kullanıcısı" rolüne erişim izni verin. PROJECT_NUMBER, proje numaranızı içerir.

Alternatif olarak, aşağıdaki komutu Cloud Shell Terminali'nden çalıştırabilirsiniz:

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"

Yerleştirilmiş Öğeler Oluşturma

Ardından, belirli anlamlı metin alanları için vektör yerleştirmeleri oluşturalım:

WITH
 rows_to_update AS (
 SELECT
   id
 FROM
   products
 WHERE
   embedding IS NULL
 LIMIT
   5000 )
UPDATE
 products
SET
 embedding = ai.embedding('text-embedding-005', name || ' ' || category || ' ' || distribution_center || ' ' || region)::vector
FROM
 rows_to_update
WHERE
 products.id = rows_to_update.id
 AND embedding IS null;

Yukarıdaki ifadede sınırı 5.000 olarak belirledik. Bu nedenle, tabloda sütun yerleştirme NULL olan satır kalmayana kadar bu ifadeyi tekrar tekrar uyguladığınızdan emin olun.

Dikkat Edilmesi Gerekenler ve Sorun Giderme

"Parola Unutma" Döngüsü

"Tek Tıkla" kurulumunu kullandıysanız ve şifrenizi hatırlamıyorsanız konsoldaki örnek temel bilgileri sayfasına gidip postgres şifresini sıfırlamak için "Düzenle"yi tıklayın.

"Uzantı Bulunamadı" Hatası

CREATE EXTENSION başarısız olursa bunun nedeni genellikle ilk sağlama işleminden sonra örneğin hâlâ "Bakım" veya "Güncelleme" durumunda olmasıdır. Örnek oluşturma adımının tamamlanıp tamamlanmadığını kontrol edin ve gerekirse birkaç saniye bekleyin.

IAM Yayılma Boşluğu

gcloud IAM komutunu çalıştırdınız ancak SQL CALL, izin hatasıyla başarısız olmaya devam ediyor. IAM değişikliklerinin Google omurgasında yayılması biraz zaman alabilir. Derin bir nefes alın.

Vektör Boyutu Uyuşmazlığı

items tablosu VECTOR(768) olarak ayarlandı. Daha sonra farklı bir model (ör. 1536 boyutlu bir model) kullanmayı denerseniz eklemeleriniz patlar. text-embedding-005'ya bağlı kalın.

Proje Kimliği Yazım Hatası

create_model çağrısında köşeli parantezleri « » bırakırsanız veya proje kimliğinizi yanlış yazarsanız model kaydı başarılı görünür ancak ilk gerçek sorgu sırasında başarısız olur. Dizenizi tekrar kontrol edin.

5. Araçlar ve Araç Kutusu Kurulumu

Veritabanları için MCP Toolbox, veritabanları için açık kaynaklı bir MCP sunucusudur. Bağlantı havuzu oluşturma, kimlik doğrulama gibi karmaşık işlemleri yöneterek araçları daha kolay, hızlı ve güvenli bir şekilde geliştirmenizi sağlar. Daha fazla bilgi Toolbox, temsilcilerinizin veritabanınızdaki verilere erişmesine olanak tanıyan üretken yapay zeka araçları oluşturmanıza yardımcı olur.

"Orkestra şefi" olarak Model Context Protocol (MCP) Toolbox for Databases'i kullanırız. Temsilcilerimiz ve AlloyDB arasında standartlaştırılmış bir ara yazılım görevi görür. Araç kutusu, tools.yaml yapılandırması tanımlayarak karmaşık veritabanı işlemlerini otomatik olarak search_products_by_context veya check_inventory_levels gibi temiz ve yürütülebilir araçlar olarak kullanıma sunar. Bu sayede, aracı mantığında manuel bağlantı havuzu oluşturmaya veya standart SQL'e gerek kalmaz.

Araç kutusu sunucusunu yükleme

Cloud Shell terminalinizden, yeni araçlar yaml dosyanızı ve araç kutusu ikili dosyasını kaydetmek için bir klasör oluşturun:

mkdir scm-agent-toolbox

cd scm-agent-toolbox

Bu yeni klasörün içinden aşağıdaki komut grubunu çalıştırın:

# 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

Ardından, Cloud Shell Düzenleyici'ye giderek yeni klasörün içinde tools.yaml dosyasını oluşturun ve bu depo dosyasının içeriğini tools.yaml dosyasına kopyalayın.

sources:
    supply_chain_db:
        kind: "alloydb-postgres"
        project: "YOUR_PROJECT_ID"
        region: "us-central1"
        cluster: "YOUR_CLUSTER"
        instance: "YOUR_INSTANCE"
        database: "postgres"
        user: "postgres"
        password: "YOUR_PASSWORD"

tools:
  search_products_by_context:
    kind: postgres-sql
    source: supply_chain_db
    description: Find products in the inventory using natural language search and vector embeddings.
    parameters:
      - name: search_text
        type: string
        description: Description of the product or category the user is looking for.
    statement: |
     SELECT name, category, stock_level, distribution_center, region
      FROM products
      ORDER BY embedding <=> ai.embedding('text-embedding-005', $1)::vector
      LIMIT 5;

  check_inventory_levels:
    kind: postgres-sql
    source: supply_chain_db
    description: Get precise stock levels for a specific product name.
    parameters:
      - name: product_name
        type: string
        description: The exact or partial name of the product.
    statement: |
     SELECT name, stock_level, distribution_center, last_updated
      FROM products
      WHERE name ILIKE '%' || $1 || '%'
      ORDER BY stock_level DESC;

  track_shipment_status:
    kind: postgres-sql
    source: supply_chain_db
    description: Retrieve real-time logistics and shipping status for a specific region or product.
    parameters:
      - name: region
        type: string
        description: The geographical region to filter shipments (e.g., EMEA, APAC).
    statement: |
     SELECT p.name, s.status, s.estimated_arrival, s.route_efficiency_score
      FROM shipments s
      JOIN products p ON s.product_id = p.id
      WHERE p.region = $1
      ORDER BY s.estimated_arrival ASC;

  analyze_supply_chain_risk:
    kind: postgres-sql
    source: supply_chain_db
    description: Rerank and filter shipments based on risk profiles and efficiency scores using Google ML reranker.
    parameters:
      - name: risk_context
        type: string
        description: The business context for risk analysis (e.g., 'heatwave impact' or 'port strike').
    statement: |
     WITH initial_ranking AS (
      SELECT s.shipment_id, p.name, s.status, p.distribution_center,
      ROW_NUMBER() OVER () AS ref_number
      FROM shipments s
      JOIN products p ON s.product_id = p.id
      WHERE s.status != 'Delivered'
      LIMIT 10
      ),
      reranked_results AS (
      SELECT index, score FROM
      ai.rank(
      model_id => 'semantic-ranker-default-003',
      search_string => $1,
      documents => (SELECT ARRAY_AGG(name || ' at ' || distribution_center ORDER BY ref_number) FROM initial_ranking)
      )
      )
      SELECT i.name, i.status, i.distribution_center, r.score
      FROM initial_ranking i, reranked_results r
      WHERE i.ref_number = r.index
      ORDER BY r.score DESC;

toolsets:
   supply_chain_toolset:
     - search_products_by_context
     - check_inventory_levels
     - track_shipment_status
     - analyze_supply_chain_risk

Şimdi tools.yaml dosyasını yerel sunucuda test edin:

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

Alternatif olarak, kullanıcı arayüzünde de test edebilirsiniz.

./toolbox --ui

Mükemmel!! Her şeyin çalıştığından emin olduktan sonra, aşağıdaki şekilde Cloud Run'da dağıtın.

Cloud Run dağıtımı

  1. PROJECT_ID ortam değişkenini ayarlayın:
export PROJECT_ID="my-project-id"
  1. gcloud CLI'yı başlatın:
gcloud init
gcloud config set project $PROJECT_ID
  1. Aşağıdaki API'lerin etkinleştirilmiş olması gerekir:
gcloud services enable run.googleapis.com \
                       cloudbuild.googleapis.com \
                       artifactregistry.googleapis.com \
                       iam.googleapis.com \
                       secretmanager.googleapis.com
  1. Henüz bir arka uç hizmet hesabınız yoksa oluşturun:
gcloud iam service-accounts create toolbox-identity
  1. Secret Manager'ı kullanma izinleri verme:
gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member serviceAccount:toolbox-identity@$PROJECT_ID.iam.gserviceaccount.com \
    --role roles/secretmanager.secretAccessor
  1. Hizmet hesabına AlloyDB kaynağımıza özgü ek izinler verin (roles/alloydb.client ve 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 serviceusage.serviceUsageConsumer
  1. tools.yaml dosyasını gizli olarak yükleyin:
gcloud secrets create tools-scm-agent --data-file=tools.yaml
  1. Zaten bir gizli anahtarınız varsa ve gizli anahtar sürümünü güncellemek istiyorsanız aşağıdakileri yürütün:
gcloud secrets versions add tools-scm-agent --data-file=tools.yaml
  1. Cloud Run için kullanmak istediğiniz container görüntüsüne bir ortam değişkeni ayarlayın:
export IMAGE=us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest
  1. Aşağıdaki komutu kullanarak Toolbox'ı Cloud Run'a dağıtın:

AlloyDB örneğinizde herkese açık erişimi etkinleştirdiyseniz (önerilmez) Cloud Run'a dağıtım için aşağıdaki komutu uygulayın:

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

VPC ağı kullanıyorsanız aşağıdaki komutu kullanın:

gcloud run deploy toolbox-scm-agent \
    --image $IMAGE \
    --service-account toolbox-identity \
    --region us-central1 \
    --set-secrets "/app/tools.yaml=tools-scm-agent:latest" \
    --args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
    # TODO(dev): update the following to match your VPC details
    --network <<YOUR_NETWORK_NAME>> \
    --subnet <<YOUR_SUBNET_NAME>> \
    --allow-unauthenticated

6. Aracı Kurulumu

Agent Development Kit (ADK)'i kullanarak tek bir istemden oluşan yapıyı bırakıp uzmanlaşmış, çoklu aracı mimarisine geçtik:

  • InventorySpecialist: Ürün stoğu ve depo metriklerine odaklanır.
  • LogisticsManager: Küresel kargo rotaları ve risk analizi konusunda uzman.
  • GlobalOrchestrator: Görevleri delege etmek ve bulguları sentezlemek için akıl yürütmeyi kullanan "beyin".

Bu depoyu projenize klonlayın ve inceleyelim.

Bunu klonlamak için Cloud Shell terminalinizde (kök dizinde veya bu projeyi oluşturmak istediğiniz herhangi bir yerden) aşağıdaki komutu çalıştırın:

git clone https://github.com/AbiramiSukumaran/scm-memory-agent
  1. Bu işlem projeyi oluşturur ve Cloud Shell Düzenleyici'de bunu doğrulayabilirsiniz.

53a398aff6ba7d5b.png

  1. .env dosyasını projenizin ve örneğinizin değerleriyle güncellediğinizden emin olun.

Kodun adım adım açıklamalı kılavuzu

Orchestrator aracısına hızlı bir bakış

    Go to app.py and you should be able to see the following snippet:
orchestrator = adk.Agent(
    name="GlobalOrchestrator",
    model="gemini-2.5-flash",
    description="Global Supply Chain Orchestrator root agent.",
    instruction="""
    You are the Global Supply Chain Brain. You are responsible for products, inventory and logistics.
    You also have access to the memory tool, remember to include all the information that the tool can provide you with about the user before you respond.
    1. Understand intent and delegate to specialists. As the Global Orchestrator, you have access to the full conversation history with the user.
    When you transfer a query to a specialist agent, sub agent or tool, share the important facts and information from your memory to them so they can operate with the full context. 
    2. Ensure the final response is professional and uses Markdown tables for data.
    3. If a specialist provides a long list, ensure only the top 10 items are shown initially.
    4. Conclude with a brief, high-level executive summary of what the data implies.
    """,
    tools=[adk.tools.preload_memory_tool.PreloadMemoryTool()],
    sub_agents=[inventory_agent, logistics_agent],
    
    #after_agent_callback=auto_save_session_to_memory_callback,
)

Bu snippet, kullanıcının konuşmasını veya isteğini alan ve göreve göre ilgili alt aracıya ya da kullanıcıya ilgili araçları yönlendiren düzenleyici aracı olan kökün tanımıdır.

  1. Envanter aracısına göz atalım
inventory_agent = adk.Agent(
    name="InventorySpecialist",
    model="gemini-2.5-flash",
    description="Specialist in product stock and warehouse data.",
    instruction="""
    Analyze inventory levels.
    1. Use 'search_products_by_context' or 'check_inventory_levels'.
    2. ALWAYS format results as a clean Markdown table.
    3. If there are many results, display only the TOP 10 most relevant ones.
    4. At the end, state: 'There are additional records available. Would you like to see more?'
    """,
    tools=tools
)

Bu alt aracı, ürünleri bağlama göre arama ve envanter seviyelerini kontrol etme gibi envanter etkinlikleri konusunda uzmanlaşmıştır.

  1. Ardından, lojistik alt acentesi gelir:
logistics_agent = adk.Agent(
    name="LogisticsManager",
    model="gemini-2.5-flash",
    description="Expert in global shipping routes and logistics tracking.",
    instruction="""
    Check shipment statuses.
    1. Use 'track_shipment_status' or 'analyze_supply_chain_risk'.
    2. ALWAYS format results as a clean Markdown table.
    3. Limit initial output to the top 10 shipments.
    4. Ask if the user needs the full manifest if more results exist.
    """,
    tools=tools
)

Bu alt acente, gönderileri takip etme ve tedarik zincirindeki riskleri analiz etme gibi lojistik faaliyetlerinde uzmanlaşmıştır.

  1. Şimdiye kadar bahsettiğimiz 3 aracının tümü araçları kullanıyor ve araçlara, önceki bölümde dağıttığımız Araç Kutusu sunucumuz aracılığıyla referans veriliyor. Aşağıdaki snippet'e bakın:
from toolbox_core import ToolboxSyncClient

TOOLBOX_SERVER = os.environ["TOOLBOX_SERVER"]
TOOLBOX_TOOLSET = os.environ["TOOLBOX_TOOLSET"]

# --- ADK TOOLBOX CONFIGURATION ---
toolbox = ToolboxSyncClient(TOOLBOX_SERVER)
tools = toolbox.load_toolset(TOOLBOX_TOOLSET)

Bu alt acente, gönderileri takip etme ve tedarik zincirindeki riskleri analiz etme gibi lojistik faaliyetlerinde uzmanlaşmıştır.

7. Agent Engine

İlk çalıştırmada Agent Engine'i oluşturun

import vertexai

GOOGLE_CLOUD_PROJECT = os.environ["GOOGLE_CLOUD_PROJECT"]
GOOGLE_CLOUD_LOCATION = os.environ["GOOGLE_CLOUD_LOCATION"]

client = vertexai.Client(
  project=GOOGLE_CLOUD_PROJECT,
  location=GOOGLE_CLOUD_LOCATION
)

agent_engine = client.agent_engines.create()
  1. Bir sonraki çalıştırma için Agent Engine'i Memory Bank yapılandırmasıyla güncelleyin:
agent_engine = client.agent_engines.update(
    name=APP_NAME,
    config={
        "context_spec": {
            "memory_bank_config": {
                "generation_config": {
                    "model": f"projects/{PROJECT_ID}/locations/{GOOGLE_CLOUD_LOCATION}/publishers/google/models/gemini-2.5-flash"
                }
            }
        }
    })

8. Bağlam, Çalıştırma ve Bellek

Bağlam yönetimi, aracının durum bilgisiz bir bot yerine sürekli bir iş ortağı gibi davranmasını sağlamak için iki ayrı katmana ayrılmıştır:

Kısa Süreli Bellek (Oturumlar): VertexAiSessionService üzerinden yönetilen bu bellek, tek bir etkileşimdeki anlık olay geçmişini (kullanıcı mesajları, araç yanıtları) izler.

Uzun Süreli Bellek (Bellek Bankası): adk.memorybankservice aracılığıyla Vertex AI Memory Bank tarafından desteklenir. Bu katman, "anlamlı" bilgileri (ör. kullanıcının belirli kargo şirketlerine yönelik tercihi veya tekrarlanan depo gecikmeleri) ayıklar ve oturumlar arasında kalıcı hale getirir.

Oturum belleği için oturumu, görüşme kapsamında başlatma

Bu, snippet'in mevcut kullanıcı için mevcut uygulama oturumunu oluşturan kısmıdır.

from google.adk.sessions import VertexAiSessionService

...

session_service = VertexAiSessionService(
    project=PROJECT_ID,
    location=GOOGLE_CLOUD_LOCATION,
)

...

# Initialize the session *outside* of the route handler to avoid repeated creation
session = None
session_lock = threading.Lock()

async def initialize_session():
    global session
    try:
        session = await session_service.create_session(app_name=APP_NAME, user_id=USER_ID)
        print(f"Session {session.id} created successfully.")  # Add a log
    except Exception as e:
        print(f"Error creating session: {e}")
        session = None  # Ensure session is None in case of error

# Create the session on app startup
asyncio.run(initialize_session())

Uzun süreli bellek için Vertex AI Memory Bank'ı başlatma

Bu, snippet'in aracı motoru için Vertex AI Memory Bank Service nesnesini başlatan kısmıdır.

from google.adk.memory import InMemoryMemoryService
from google.adk.memory import VertexAiMemoryBankService

...

try:
    memory_bank_service = adk.memory.VertexAiMemoryBankService(
        agent_engine_id=AGENT_ENGINE_ID,
        project=PROJECT_ID,
        location=GOOGLE_CLOUD_LOCATION,
    )
    #in_memory_service = InMemoryMemoryService()
    print("Memory Bank Service initialized successfully.")
except Exception as e:
    print(f"Error initializing Memory Bank Service: {e}")
    memory_bank_service = None

runner = adk.Runner(
    agent=orchestrator,
    app_name=APP_NAME,
    session_service=session_service,
    memory_service=memory_bank_service,
)

...

Neler yapılandırılır?

Snippet'in bu bölümünde, uzun süreli bellek için Vertex AI Memory Bank Service'i yapılandırıyoruz. Bu hizmet, belirli bir kullanıcı için belirli bir uygulamanın oturumunu Vertex AI Memory Bank'te bellek olarak bağlama duyarlı bir şekilde saklar.

Aracı yürütme kapsamında neler çalıştırılır?

   async def run_and_collect():
        final_text = ""
        try:
            async for event in runner.run_async(
                new_message=content,
                user_id=user_id,
                session_id=session_id
            ):
                if hasattr(event, 'author') and event.author:
                    if not any(log['agent'] == event.author for log in execution_logs):
                        execution_logs.append({
                            "agent": event.author,
                            "action": "Analyzing data requirements...",
                            "type": "orchestration_event"
                        })
                if hasattr(event, 'text') and event.text:
                    final_text = event.text
                elif hasattr(event, 'content') and hasattr(event.content, 'parts'):
                    for part in event.content.parts:
                        if hasattr(part, 'text') and part.text:
                            final_text = part.text
        except Exception as e:
            print(f"Error during runner.run_async: {e}")
            raise  # Re-raise the exception to signal failure
        finally:
            gc.collect()
            return final_text

Kullanıcının giriş içeriğini, kapsam dahilindeki kullanıcı kimliği ve oturum kimliği ile birlikte new_message nesnesine dönüştürür. Ardından, temsilci devralır ve temsilci yanıtı işlenip döndürülür.

Uzun süreli bellekte neler saklanır?

Uygulama ve kullanıcı kapsamındaki oturum ayrıntısı, oturum değişkeninde ayıklanır.

Bu oturum daha sonra "add_session_to_memory" yöntemi kullanılarak Vertex AI Memory Bank nesnesinin mevcut uygulaması için mevcut kullanıcının belleği olarak eklenir.

session = asyncio.run(session_service.get_session(app_name=APP_NAME, user_id=USER_ID, session_id=session.id))

if memory_bank_service and session:  # Check memory service AND session
                try:
                    #asyncio.run(in_memory_service.add_session_to_memory(session))
                    asyncio.run(memory_bank_service.add_session_to_memory(session))
                    '''
                    client.agent_engines.memories.generate(
                        scope={"app_name": APP_NAME, "user_id": USER_ID},
                        name=APP_NAME,
                        direct_contents_source={
                            "events": [
                                {"content": content}
                            ]
                        },
                        config={"wait_for_completion": True},
                    )   
                    '''

                    print("Successfully added session to memory.******")
                    print(session.id)

                except Exception as e:
                    print(f"Error adding session to memory: {e}")

Bellek Geri Çağırma

Bu bilgiyi, bağlamın bir parçası olarak düzenleyiciye ve geçerli olduğu durumlarda diğer aracılara iletebilmek için, uygulama adını ve kullanıcı adını kapsam olarak kullanarak (anıları bu kapsamda sakladığımız için) saklanan uzun süreli belleği almamız gerekir.

    results = client.agent_engines.memories.retrieve(
    name=APP_NAME,
    scope={"app_name": APP_NAME, "user_id": USER_ID}
    )
    # RetrieveMemories returns a pager. You can use `list` to retrieve all pages' memories.
    list(results)
    print(list(results))

Alınan anı, bağlamın bir parçası olarak nasıl yüklenir?

Kök aracının bağlamı bellek bankasından önceden yüklemesine olanak tanıyan Orchestrator aracısının tanımında aşağıdaki özelliği kullanırız. Bu, alt temsilciler için araç kutusu sunucusundan eriştiğimiz araçlara ek olarak sunulur.

tools=[adk.tools.preload_memory_tool.PreloadMemoryTool()],

Geri Arama Bağlamı

Kurumsal tedarik zincirinde "kara kutu" olamaz. Bir Narrative Engine oluşturmak için ADK'nın CallbackContext'ini kullanırız. Aracının yürütülmesine bağlanarak her düşünce sürecini ve araç çağrısını yakalayıp bunları bir kullanıcı arayüzü kenar çubuğuna aktarıyoruz.

  • İzleme Etkinliği: "GlobalOrchestrator, veri gereksinimlerini analiz ediyor..."
  • İzleme Etkinliği: "Stok seviyeleri için InventorySpecialist'e yetki veriliyor..."
  • İzleme Etkinliği: "Geçmiş tedarikçi gecikme kalıpları Memory Bank'ten alınıyor..."

Bu denetim izi, hata ayıklama için çok değerlidir ve operatörlerin, aracının bağımsız kararlarına güvenmesini sağlar.

from google.adk.agents.callback_context import CallbackContext

...

# --- ADK CALLBACKS (Narrative Engine) ---
execution_logs = []

async def trace_callback(context: CallbackContext):
    """
    Captures agent and tool invocation flow for the UI narrative.
    """
    agent_name = context.agent.name
    event = {
        "agent": agent_name,
        "action": "Processing request steps...",
        "type": "orchestration_event"
    }
    execution_logs.append(event)
    return None

...

Hepsi bu kadar!!! Projeyi başarıyla klonladık ve aracı, bellek ve bağlam ayrıntılarını inceledik.

Klonlanan deponun proje klasörüne gidip aşağıdaki komutları çalıştırarak test edebilirsiniz:

>> pip install -r requirements.txt

>> python app.py

Bu işlem, aracınızı yerel olarak başlatır ve test edebilirsiniz.

9. Cloud Run'a dağıtalım

  1. Projeyi klonladığınız Cloud Shell terminalinden aşağıdaki komutu çalıştırarak Cloud Run'da dağıtın ve projenin kök klasöründe olduğunuzdan emin olun.

Cloud Shell terminalinizde şunu çalıştırın:

gcloud run deploy supply-chain-agent --source . --platform managed   --region us-central1 --allow-unauthenticated --set-env-vars GOOGLE_CLOUD_PROJECT=<<YOUR_PROJECT>>,GOOGLE_CLOUD_LOCATION=us-central1,GOOGLE_GENAI_USE_VERTEXAI=TRUE,REASONING_ENGINE_APP_NAME=<<YOUR_APP_ENGINE_URL>>,TOOLBOX_SERVER=<<YOUR_TOOLBOX_SERVER>>,TOOLBOX_TOOLSET=supply_chain_toolset,AGENT_ENGINE_ID=<<YOUR_AGENT_ENGINE_ID>>

<<YOUR_PROJECT>>, <<YOUR_APP_ENGINE_URL>>, <<YOUR_TOOLBOX_SERVER>> ve <<YOUR_AGENT_ENGINE_ID>> yer tutucularının değerlerini değiştirin.

Komut tamamlandığında bir hizmet URL'si oluşturulur. Kopyalayın.

  1. Cloud Run hizmet hesabına AlloyDB İstemcisi rolünü verin.Bu, sunucusuz uygulamanızın veritabanına güvenli bir şekilde tünel oluşturmasına olanak tanır.

Cloud Shell terminalinizde şunu çalıştırın:

# 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"

Şimdi hizmet URL'sini (daha önce kopyaladığınız Cloud Run uç noktası) kullanarak uygulamayı test edin.

Not: Bir hizmet sorunuyla karşılaşırsanız ve bunun nedeni olarak bellek gösteriliyorsa sorunu test etmek için ayrılan bellek sınırını 1 GiB'ye yükseltmeyi deneyin.

3e4d36ed99b39325.png

d6b337f79a1f1d82.png

5e781a193a4aa903.png

10. Temizleme

Bu laboratuvar tamamlandıktan sonra AlloyDB kümesini ve örneğini silmeyi unutmayın.

Küme, örnekleriyle birlikte temizlenmelidir.

11. Tebrikler

AlloyDB'nin hızı, MCP Toolbox'ın düzenleme verimliliği ve Vertex AI Memory Bank'in "kurumsal hafızası" ile gelişen bir tedarik zinciri sistemi oluşturduk. Sadece soruları yanıtlamakla kalmaz. Singapur'daki deponuzun musonla ilgili gecikmelerle her zaman sorun yaşadığını hatırlar ve siz sormadan önce gönderilerin yeniden yönlendirilmesini proaktif olarak önerir.