🤖 Graph RAG, ADK ve Memory Bank ile Çok Formatlı Yapay Zeka Temsilcisi Oluşturma

1. Giriş

cover

1. Hedef

Afet müdahale senaryolarında, birden fazla konumdaki farklı becerilere, kaynaklara ve ihtiyaçlara sahip hayatta kalanları koordine etmek için akıllı veri yönetimi ve arama özellikleri gerekir. Bu atölye çalışmasında, aşağıdakileri birleştiren bir üretim yapay zeka sistemi oluşturmayı öğreneceksiniz:

  1. 🗄️ Grafik Veritabanı (Spanner): Hayatta kalanlar, beceriler ve kaynaklar arasındaki karmaşık ilişkileri depolama
  2. 🔍 Yapay Zeka Destekli Arama: Yerleştirmeleri kullanarak semantik ve anahtar kelime karma arama
  3. 📸 Çok Formatlı İşleme: Görüntülerden, metinlerden ve videolardan yapılandırılmış veriler ayıklama
  4. 🤖 Çoklu aracı düzenleme: Karmaşık iş akışları için uzmanlaşmış aracıları koordine edin
  5. 🧠 Uzun Süreli Bellek: Vertex AI Memory Bank ile Kişiselleştirme

görüşme

2. Ne Oluşturacaksınız?

Aşağıdakileri içeren bir Survivor Network Graph Database:

  • 🗺️ Hayatta kalanlar arasındaki ilişkilerin 3D etkileşimli grafik görselleştirmesi
  • 🔍 Akıllı Arama (anahtar kelime, semantik ve karma)
  • 📸 Çok formatlı yükleme ardışık düzeni (resimlerden/videolardan öğe çıkarma)
  • 🤖 Karmaşık görev düzenleme için çoklu aracı sistemi
  • 🧠 Kişiselleştirilmiş etkileşimler için Bellek Bankası Entegrasyonu

3. Temel Teknolojiler

Bileşen

Teknoloji

Amaç

Veritabanı

Cloud Spanner Graph

Düğümleri (hayatta kalanlar, beceriler) ve kenarları (ilişkiler) depolama

Yapay Zeka Arama

Gemini + Embeddings

Semantik anlayış + benzerlik araması

Agent Framework

ADK (Agent Development Kit)

Yapay zeka iş akışlarını düzenleme

Bellek

Vertex AI Memory Bank

Uzun süreli kullanıcı tercihi depolama alanı

Frontend

React + Three.js

Etkileşimli 3D grafik görselleştirme

2. Ortam Hazırlığı (Atölyedeyseniz atlayın)

Birinci Bölüm: Fatura Hesabını Etkinleştirme

  • Faturalandırma hesabınızı 5 ABD doları krediyle talep edin. Bu krediyi dağıtımınız için kullanmanız gerekir. Gmail hesabınızda oturum açtığınızdan emin olun.

İkinci Bölüm: Açık Ortam

  1. 👉 Doğrudan Cloud Shell Düzenleyici'ye gitmek için bu bağlantıyı tıklayın.
  2. 👉 Bugün herhangi bir noktada yetkilendirme yapmanız istenirse devam etmek için Yetkilendir'i tıklayın. Cloud Shell'e yetki vermek için tıklayın.
  3. 👉 Terminal ekranın alt kısmında görünmüyorsa açın:
    • Görünüm'ü tıklayın.
    • Terminal'i tıklayın.Cloud Shell Düzenleyici'de yeni terminal açma
  4. 👉💻 Terminalde, aşağıdaki komutu kullanarak kimliğinizin doğrulandığını ve projenin proje kimliğinize ayarlandığını doğrulayın:
    gcloud auth list
    
  5. 👉💻 Bootstrap projesini GitHub'dan kopyalayın:
    git clone https://github.com/google-americas/way-back-home.git
    

3. Ortam Kurulumu

1. Başlat

Cloud Shell Düzenleyici terminalinde, terminal ekranın alt kısmında görünmüyorsa terminali açın:

  • Görünüm'ü tıklayın.
  • Terminal'i tıklayın.

Cloud Shell Düzenleyici'de yeni terminal açma

👉💻 Terminalde, init komut dosyasını yürütülebilir hale getirin ve çalıştırın:

cd ~/way-back-home/level_2
./init.sh

2. Projeyi yapılandırma

👉💻 Proje kimliğinizi ayarlayın:

gcloud config set project $(cat ~/project_id.txt) --quiet

👉💻 Gerekli API'leri etkinleştirin (bu işlem yaklaşık 2-3 dakika sürer):

gcloud services enable compute.googleapis.com \
                       aiplatform.googleapis.com \
                       run.googleapis.com \
                       cloudbuild.googleapis.com \
                       artifactregistry.googleapis.com \
                       spanner.googleapis.com \
                       storage.googleapis.com

3. Kurulum komut dosyasını çalıştırma

👉💻 Kurulum komut dosyasını çalıştırın:

cd ~/way-back-home/level_2
./setup.sh

Bu işlem sizin için .env oluşturur. Cloud Shell'inizde way_back_homeproject dosyasını açın. level_2 klasöründe, sizin için .env dosyasının oluşturulduğunu görebilirsiniz. Bu seçeneği bulamıyorsanız View -> Toggle Hidden File simgesini tıklayarak görebilirsiniz. open_project

4. Örnek Verileri Yükle

👉💻 Arka uca gidin ve bağımlılıkları yükleyin:

cd ~/way-back-home/level_2/backend
uv sync

👉💻 İlk hayatta kalan verilerini yükleme:

uv run python ~/way-back-home/level_2/backend/setup_data.py

Bu durumda:

  • Spanner örneği (survivor-network)
  • Veritabanı (graph-db)
  • Tüm düğüm ve kenar tabloları
  • Sorgulama için özellik grafikleri Beklenen çıktı:
============================================================
SUCCESS! Database setup complete.
============================================================

Instance:  survivor-network
Database:  graph-db
Graph:     SurvivorGraph

Access your database at:
https://console.cloud.google.com/spanner/instances/survivor-network/databases/graph-db?project=waybackhome

Çıktıda Access your database at işaretinden sonraki bağlantıyı tıklarsanız Google Cloud Console Spanner'ı açabilirsiniz.

open_spanner

Google Cloud Console'da Spanner'ı görürsünüz.

spanner

4. Spanner Studio'da Grafik Verilerini Görselleştirme

Bu kılavuz, Spanner Studio'yu kullanarak Survivor Network grafik verilerini doğrudan Google Cloud Console'da görselleştirmenize ve bu verilerle etkileşimde bulunmanıza yardımcı olur. Bu, yapay zeka temsilcinizi oluşturmadan önce verilerinizi doğrulamanın ve grafik yapısını anlamanın harika bir yoludur.

1. Spanner Studio'ya erişme

  1. Son adımda bağlantıyı tıkladığınızdan ve Spanner Studio'yu açtığınızdan emin olun.

spanner_studio

2. Grafik Yapısını Anlama ("Büyük Resim")

Survivor Network veri kümesini bir mantık bulmacası veya Oyun Durumu olarak düşünün:

Varlık

Sistemdeki Rol

Analoji

Survivors

Temsilciler/oyuncular

Oyuncular

Biomes

Bulundukları yer

Harita Bölgeleri

Beceriler

Yapabilecekleri işlemler

Yetkileri

İhtiyaçlar (Needs)

Eksiklikleri (Krizler)

Görevler

Kaynaklar

Dünyada bulunan öğeler

Ganimet

Amaç: Yapay zeka aracının görevi, Biyomları (Konum kısıtlamaları) göz önünde bulundurarak İhtiyaçları (Sorunlar) Becerilerle (Çözümler) eşleştirmektir.

🔗 Kenarlar (İlişkiler):

  • SurvivorInBiome: Konum izleme
  • SurvivorHasSkill: Yetenek envanteri
  • SurvivorHasNeed: Etkin sorunların listesi
  • SurvivorFoundResource: Öğelerin envanteri
  • SurvivorCanHelp: Çıkarılan ilişki (Yapay zeka bunu hesaplar.)

3. Grafiği sorgulama

Verilerdeki "Hikaye"yi görmek için birkaç sorgu çalıştıralım.

Spanner Graph, GQL (Graph Query Language) kullanır. Sorgu çalıştırmak için GRAPH SurvivorNetwork simgesini ve ardından eşleşme kalıbınızı kullanın.

👉 1. Sorgu: Küresel Liste (Kim nerede?) Bu, temelinizdir. Konumu anlamak kurtarma operasyonları için çok önemlidir.

GRAPH SurvivorNetwork
MATCH result = (s:Survivors)-[:SurvivorInBiome]->(b:Biomes)
RETURN TO_JSON(result) AS json_result

Sonucun aşağıdaki gibi olması beklenir: query1

👉 2. Sorgu: Beceri Matrisi (Yetenekler) Herkesin nerede olduğunu öğrendiğinize göre neler yapabileceklerini öğrenin.

GRAPH SurvivorNetwork
MATCH result = (s:Survivors)-[h:SurvivorHasSkill]->(k:Skills)
RETURN TO_JSON(result) AS json_result

Sonucun aşağıdaki gibi olması beklenir: query2

👉 3. Sorgu: Kim krizde? (Görev Panosu) Yardıma ihtiyacı olan kurtulanları ve ihtiyaçlarını görün.

GRAPH SurvivorNetwork
MATCH result = (s:Survivors)-[h:SurvivorHasNeed]->(n:Needs)
RETURN TO_JSON(result) AS json_result

Sonucun aşağıdaki gibi olması beklenir: query3

🔎 İleri düzey: Eşleştirme - Kim Kime Yardımcı Olabilir?

Grafiğin gücü burada ortaya çıkar. Bu sorgu, diğer savaşçıların ihtiyaçlarını karşılayabilecek becerilere sahip savaşçıları bulur.

GRAPH SurvivorNetwork
MATCH result = (helper:Survivors)-[:SurvivorHasSkill]->(skill:Skills)-[:SkillTreatsNeed]->(need:Needs)<-[:SurvivorHasNeed]-(helpee:Survivors)
RETURN TO_JSON(result) AS json_result

Sonucun aşağıdaki gibi olması beklenir: query4

aside positive Bu Sorgu Ne Yapar?

Bu sorgu, yalnızca "İlk yardımda yanıklar tedavi edilir" (şemadan açıkça anlaşılmaktadır) ifadesini göstermek yerine şunları bulur:

  • Dr. Elena Frost (Tıp eğitimi almış) → tedavi edebilir → Kaptan Tanaka (yanıkları var)
  • David Chen (ilk yardım bilgisi var) → Park Teğmeni'ni (ayak bileği burkulmuş) tedavi edebilir.

Neden Etkili?

Yapay Zeka Temsilcinizin Yapacakları:

Bir kullanıcı "Yanıkları kim tedavi edebilir?" diye sorduğunda aracı:

  1. Benzer bir grafik sorgusu çalıştırma
  2. Yanıt: "Dr. Frost, tıbbi eğitim almış ve Kaptan Tanaka'ya yardımcı olabilir"
  3. Kullanıcının ara tablolar veya ilişkiler hakkında bilgi sahibi olması gerekmez.

5. Spanner'da Yapay Zeka Destekli Yerleştirmeler

1. Neden yerleştirmeler? (İşlem yok, yalnızca okunabilir)

Hayatta kalma senaryosunda zaman çok önemlidir. Hayatta kalanlar I need someone who can treat burns veya Looking for a medic gibi bir acil durumu bildirdiğinde veritabanındaki beceri adlarını tahmin ederek zaman kaybetmemelidir.

Gerçek Senaryo: Survivor: Captain Tanaka has burns—we need medical help NOW!

"Sağlık görevlisi" için geleneksel anahtar kelime araması → 0 sonuç ❌

Yerleştirmelerle semantik arama → "Tıbbi Eğitim" ve "İlk Yardım" sonuçlarını bulur. ✅

Bu, temsilcilerin tam olarak ihtiyaç duyduğu şeydir: Akıllı, insana benzer bir arama. Bu arama, yalnızca anahtar kelimeleri değil, amacı da anlar.

2. Yerleştirme modeli oluşturma

spanner_embedding

Şimdi de Google'ın text-embedding-004 kullanarak metni yerleştirmelere dönüştüren bir model oluşturalım.

👉 Spanner Studio'da şu SQL'i çalıştırın ($YOUR_PROJECT_ID yerine gerçek proje kimliğinizi girin):

‼️ Cloud Shell düzenleyicisinde, projenin tamamını görmek için File -> Open Folder -> way-back-home/level_2'i açın.

project_id

👉 Aşağıdaki sorguyu kopyalayıp yapıştırarak Spanner Studio'da çalıştırın ve ardından Çalıştır düğmesini tıklayın:

CREATE MODEL TextEmbeddings
INPUT(content STRING(MAX))
OUTPUT(embeddings STRUCT<values ARRAY<FLOAT32>>)
REMOTE OPTIONS (
    endpoint = '//aiplatform.googleapis.com/projects/$YOUR_PROJECT_ID/locations/us-central1/publishers/google/models/text-embedding-004'
);

Bu İşlemin Etkisi:

  • Spanner'da sanal model oluşturur (model ağırlıkları yerel olarak depolanmaz).
  • Vertex AI'da Google'ın text-embedding-004 hizmetine yönlendirir.
  • Sözleşmeyi tanımlar: Giriş metin, çıkış 768 boyutlu bir kayan nokta dizisidir.

Neden "UZAKTAN SEÇENEKLER"?

  • Spanner, modeli kendisi çalıştırmaz
  • ML.PREDICT kullandığınızda Vertex AI'ı API aracılığıyla çağırır.
  • Zero-ETL: Verileri Python'a aktarmaya, işlemeye ve yeniden içe aktarmaya gerek yoktur.

Run düğmesini tıklayın. İşlem başarılı olduğunda sonucu aşağıdaki gibi görebilirsiniz:

spanner_result

3. Yerleştirme sütunu ekleme

👉 Yerleştirmeleri depolamak için bir sütun ekleyin:

ALTER TABLE Skills ADD COLUMN skill_embedding ARRAY<FLOAT32>;

Run düğmesini tıklayın. İşlem başarılı olduğunda sonucu aşağıdaki gibi görebilirsiniz:

embedding_result

4. Yerleştirilmiş Öğeler Oluşturma

👉 Her beceri için vektör yerleştirmeler oluşturmak üzere yapay zekayı kullanın:

UPDATE Skills
SET skill_embedding = (
    SELECT embeddings.values
    FROM ML.PREDICT(
        MODEL TextEmbeddings,
        (SELECT name AS content)
    )
)
WHERE skill_embedding IS NULL;

Run düğmesini tıklayın. İşlem başarılı olduğunda sonucu aşağıdaki gibi görebilirsiniz:

skills_result

Ne olur? Her beceri adı (ör. "first aid") anlamsal anlamını temsil eden 768 boyutlu bir vektöre dönüştürülür.

5. Yerleştirilmiş öğeleri doğrulama

👉 Yerleştirmelerin oluşturulduğunu kontrol edin:

SELECT 
    skill_id,
    name,
    ARRAY_LENGTH(skill_embedding) AS embedding_dimensions
FROM Skills
LIMIT 5;

Beklenen çıkış:

spanner_result

Şimdi senaryomuzdaki tam kullanım alanını test ediyoruz: "sağlık görevlisi" terimini kullanarak tıbbi becerileri bulma.

👉 "Sağlık görevlisi"ne benzer becerileri bulma:

WITH query_embedding AS (
    SELECT embeddings.values AS val
    FROM ML.PREDICT(MODEL TextEmbeddings, (SELECT "medic" AS content))
)
SELECT
    s.name AS skill_name,
    s.category,
    COSINE_DISTANCE(s.skill_embedding, (SELECT val FROM query_embedding)) AS distance
FROM Skills AS s
WHERE s.skill_embedding IS NOT NULL
ORDER BY distance ASC
LIMIT 10;
  • Kullanıcının "doktor" arama terimini yerleştirmeye dönüştürür.
  • query_embedding geçici tablosunda saklar.

Beklenen sonuçlar (daha düşük mesafe = daha benzer):

spanner_result

7. Analiz için Gemini modeli oluşturma

spanner_gemini

👉 Üretken yapay zeka modeli referansı oluşturun ($YOUR_PROJECT_ID yerine gerçek proje kimliğinizi girin):

CREATE MODEL GeminiPro
INPUT(prompt STRING(MAX))
OUTPUT(content STRING(MAX))
REMOTE OPTIONS (
    endpoint = '//aiplatform.googleapis.com/projects/$YOUR_PROJECT_ID/locations/us-central1/publishers/google/models/gemini-2.5-pro',
    default_batch_size = 1
);

Yerleştirme modelinden fark:

  • Yerleştirmeler: Metin → Vektör (benzerlik araması için)
  • Gemini: Metin → Oluşturulan Metin (akıl yürütme/analiz için)

spanner_result

8. Uyumluluk analizi için Gemini'ı kullanma

👉 Görev uyumluluğu için hayatta kalan çiftleri analiz edin:

WITH PairData AS (
    SELECT
        s1.name AS Name_A,
        s2.name AS Name_B,
        CONCAT(
            "Assess compatibility of these two survivors for a resource-gathering mission. ",
            "Survivor 1: ", s1.name, ". ",
            "Survivor 2: ", s2.name, ". ",
            "Give a score from 1-10 and a 1-sentence reason."
        ) AS prompt
    FROM Survivors s1
    JOIN Survivors s2 ON s1.survivor_id < s2.survivor_id
    LIMIT 1
)
SELECT
    Name_A,
    Name_B,
    content AS ai_assessment
FROM ML.PREDICT(
    MODEL GeminiPro,
    (SELECT Name_A, Name_B, prompt FROM PairData)
);

Beklenen çıkış:

Name_A          | Name_B            | ai_assessment
----------------|-------------------|----------------
"David Chen"    | "Dr. Elena Frost" | "**Score: 9/10** Their compatibility is extremely high as David's practical, hands-on scavenging skills are perfectly complemented by Dr. Frost's specialized knowledge to identify critical medical supplies and avoid biological hazards."

6. Karma Arama ile Grafik RAG Temsilcinizi Oluşturma

1. Sistem Mimarisine Genel Bakış

Bu bölümde, aracınıza farklı sorgu türlerini işleme esnekliği sağlayan bir çok yöntemli arama sistemi oluşturulur. Sistem üç katmandan oluşur: Aracı Katmanı, Araç Katmanı, Hizmet Katmanı.

architecture_hybrid_search

Neden Üç Katman?

  • İlgi alanlarının ayrılması: Aracı, amaca; araçlar, arayüze; hizmet ise uygulamaya odaklanır.
  • Esneklik: Temsilci, belirli yöntemleri zorlayabilir veya yapay zekanın otomatik yönlendirme yapmasına izin verebilir.
  • Optimizasyon: Yöntem bilindiğinde pahalı yapay zeka analizi atlanabilir.

Bu bölümde, öncelikle semantik aramayı (RAG) uygulayacaksınız. Bu, sonuçları yalnızca anahtar kelimelere göre değil, anlamlarına göre bulma işlemidir. Daha sonra, karma arama özelliğinin birden fazla yöntemi nasıl birleştirdiğini açıklayacağız.

2. RAG Hizmeti Uygulaması

👉💻 Terminalde, aşağıdaki komutu çalıştırarak dosyayı Cloud Shell Düzenleyici'de açın:

cloudshell edit ~/way-back-home/level_2/backend/services/hybrid_search_service.py

Yorumu bulun # TODO: REPLACE_SQL

Bu satırın tamamını aşağıdaki kodla değiştirin:

        # This is your working query from the successful run!
        sql = """
            WITH query_embedding AS (
                SELECT embeddings.values AS val
                FROM ML.PREDICT(
                    MODEL TextEmbeddings,
                    (SELECT @query AS content)
                )
            )
            SELECT
                s.survivor_id,
                s.name AS survivor_name,
                s.biome,
                sk.skill_id,
                sk.name AS skill_name,
                sk.category,
                COSINE_DISTANCE(
                    sk.skill_embedding, 
                    (SELECT val FROM query_embedding)
                ) AS distance
            FROM Survivors s
            JOIN SurvivorHasSkill shs ON s.survivor_id = shs.survivor_id
            JOIN Skills sk ON shs.skill_id = sk.skill_id
            WHERE sk.skill_embedding IS NOT NULL
            ORDER BY distance ASC
            LIMIT @limit
        """

3. Semantik Arama Aracı Tanımı

👉💻 Terminalde, aşağıdaki komutu çalıştırarak dosyayı Cloud Shell Düzenleyici'de açın:

cloudshell edit ~/way-back-home/level_2/backend/agent/tools/hybrid_search_tools.py

hybrid_search_tools.py bölümünde, yorumu bulun. # TODO: REPLACE_SEMANTIC_SEARCH_TOOL

👉Bu satırın tamamını aşağıdaki kodla değiştirin:

async def semantic_search(query: str, limit: int = 10) -> str:
    """
    Force semantic (RAG) search using embeddings.
    
    Use this when you specifically want to find things by MEANING,
    not just matching keywords. Great for:
    - Finding conceptually similar items
    - Handling vague or abstract queries
    - When exact terms are unknown
    
    Example: "healing abilities" will find "first aid", "surgery", 
    "herbalism" even though no keywords match exactly.
    
    Args:
        query: What you're looking for (describe the concept)
        limit: Maximum results
        
    Returns:
        Semantically similar results ranked by relevance
    """
    try:
        service = _get_service()
        result = service.smart_search(
            query, 
            force_method=SearchMethod.RAG,
            limit=limit
        )
        
        return _format_results(
            result["results"],
            result["analysis"],
            show_analysis=True
        )
        
    except Exception as e:
        return f"Error in semantic search: {str(e)}"

Temsilci Kullanımı:

  • Benzerlik isteyen sorgular ("X'e benzer bir şey bul")
  • Kavramsal sorgular ("iyileştirme yetenekleri")
  • Anlamın anlaşılmasının önemli olduğu durumlar

4. Aracı Karar Kılavuzu (Talimatlar)

Temsilci tanımında, semantik arama ile ilgili kısmı talimata kopyalayıp yapıştırın.

👉💻 Terminalde, aşağıdaki komutu çalıştırarak dosyayı Cloud Shell Düzenleyici'de açın:

cloudshell edit ~/way-back-home/level_2/backend/agent/agent.py

Aracı, doğru aracı seçmek için bu talimatı kullanır:

👉agent.py dosyasında # TODO: REPLACE_SEARCH_LOGIC yorumunu bulun, Replace this whole line ifadesini aşağıdaki kodla değiştirin:

- `semantic_search`: Force RAG/embedding search
  Use for: "Find similar to X", conceptual queries, unknown terminology
  Example: "Find skills related to healing"

👉Yorumu bulun. # TODO: ADD_SEARCH_TOOLReplace this whole line satırını aşağıdaki kodla değiştirin:

    semantic_search,         # Force RAG

5. Karma Arama'nın İşleyiş Şeklini Anlama (Yalnızca Okuma, İşlem Gerekmez)

2-4. adımlarda, sonuçları anlamlarına göre bulan temel arama yöntemi olan semantik aramayı (RAG) uyguladınız. Ancak sistemin adının "Karma Arama" olduğunu fark etmiş olabilirsiniz. Bu özelliklerin nasıl birlikte çalıştığını aşağıda görebilirsiniz:

Karma Birleştirme Nasıl Çalışır?:

way-back-home/level_2/backend/services/hybrid_search_service.py dosyasında, hybrid_search() çağrıldığında hizmet HEM aramaları çalıştırır HEM de sonuçları birleştirir:

# Location: backend/services/hybrid_search_service.py

    rank_kw = keyword_ranks.get(surv_id, float('inf'))
    rank_rag = rag_ranks.get(surv_id, float('inf'))

    rrf_score = 0.0
    if rank_kw != float('inf'):
        rrf_score += 1.0 / (K + rank_kw)
    if rank_rag != float('inf'):
        rrf_score += 1.0 / (K + rank_rag)

    combined_score = rrf_score

Bu codelab'de, temel olan semantik arama bileşenini (RAG) uyguladınız. Anahtar kelime ve karma yöntemler hizmette zaten uygulanıyor. Aracınız üç yöntemi de kullanabilir.

Tebrikler! Hibrit arama ile Graph RAG Temsilcinizi başarıyla tamamladınız.

7. ADK Web ile Temsilcinizi Test Etme

Temsilcinizi test etmenin en kolay yolu, adk web komutunu kullanmaktır. Bu komut, temsilcinizi yerleşik bir sohbet arayüzüyle başlatır.

1. Aracıyı çalıştırma

👉💻 Arka uç dizinine (temsilcinizin tanımlandığı yer) gidin ve web arayüzünü başlatın:

cd ~/way-back-home/level_2/backend
uv run adk web

Bu komut,

agent/agent.py

ve test için bir web arayüzü açar.

👉 URL'yi açın:

Komut, yerel bir URL (genellikle http://127.0.0.1:8000 veya benzeri) oluşturur. Bunu tarayıcınızda açın.

adk web

URL'yi tıkladığınızda ADK Web kullanıcı arayüzünü görürsünüz. Sol üst köşeden "aracı"yı seçtiğinizden emin olun.

adk_ui

2. Arama Özelliklerini Test Etme

Temsilci, sorgularınızı akıllıca yönlendirmek için tasarlanmıştır. Farklı arama yöntemlerini görmek için sohbet penceresinde aşağıdaki girişleri deneyin.

Anahtar kelimeler eşleşmese bile anlam ve konsepte göre öğeler bulur.

Test Sorguları: (Aşağıdakilerden herhangi birini seçin)

Who can help with injuries?
What abilities are related to survival?

Dikkat edilecek noktalar:

  • Gerekçede Semantik veya RAG aramadan bahsedilmelidir.
  • Kavramsal olarak ilişkili sonuçlar (ör. "İlk yardım" isterken "Ameliyat" yanıtını alabilirsiniz.
  • Sonuçlarda 🧬 simgesi bulunur.

Karmaşık sorgular için anahtar kelime filtrelerini semantik anlama ile birleştirir.

Test Sorguları:(Aşağıdakilerden herhangi birini seçin)

Find someone who can ply a plane in the volcanic area
Who has healing abilities in the FOSSILIZED?
Who has healing abilities in the mountains?

Dikkat edilecek noktalar:

  • Gerekçede karma aramadan bahsedilmelidir.
  • Sonuçlar HER İKİ ölçütle (kavram + konum/kategori) eşleşmelidir.
  • Her iki yöntemle de bulunan sonuçlar 🔀 simgesine sahip olur ve en üstte yer alır.

👉💻 Testi tamamladığınızda komut satırınızda Ctrl+C tuşuna basarak işlemi sonlandırın.

8. Tam Uygulamayı Çalıştırma

Full Stack Architecture Overview (Tam Yığın Mimari Genel Bakışı)

architecture_fullstack

SessionService ve Runner ekleme

👉💻 Terminalde, chat.py dosyasını Cloud Shell Düzenleyici'de aşağıdaki komutu çalıştırarak açın (devam etmeden önce önceki işlemi "ctrl+C" ile sonlandırdığınızdan emin olun):

cloudshell edit ~/way-back-home/level_2/backend/api/routes/chat.py

👉chat.py dosyasında # TODO: REPLACE_INMEMORY_SERVICES yorumunu bulun, Replace this whole line ifadesini aşağıdaki kodla değiştirin:

    session_service = InMemorySessionService()
    memory_service = InMemoryMemoryService()

👉chat.py dosyasında # TODO: REPLACE_RUNNER yorumunu bulun, Replace this whole line ifadesini aşağıdaki kodla değiştirin:

runner = Runner(
    agent=root_agent, 
    session_service=session_service,
    memory_service=memory_service,
    app_name="survivor-network"
)

1. Başvuruyu başlatma

Önceki terminal hâlâ çalışıyorsa Ctrl+C tuşuna basarak sonlandırın.

👉💻 Uygulamayı başlatma:

cd ~/way-back-home/level_2/
./start_app.sh

Arka uç başarıyla başlatıldığında aşağıdaki gibi Local: http://localhost:5173/" simgesini görürsünüz: fronted

👉 Terminalde Local: http://localhost:5173/ seçeneğini tıklayın.

görüşme

Sorgu:

Find skills similar to healing

sohbet

Ne olur?

  • Temsilci, benzerlik isteğini tanıyor
  • "İyileşme" için yerleştirilmiş öğe oluşturur.
  • Anlamsal olarak benzer becerileri bulmak için kosinüs uzaklığını kullanır.
  • Dönüşler: İlk yardım (adlar "iyileşme" ile eşleşmese bile)

Sorgu:

Find medical skills in the mountains

Ne olur?

  1. Anahtar kelime bileşeni: category='medical' için filtreleme
  2. Anlamsal bileşen: "Tıbbi" kelimesini yerleştirin ve benzerliğe göre sıralayın
  3. Birleştir: Sonuçları birleştirin ve her iki yöntemle de bulunanlara öncelik verin 🔀.

Sorgu(isteğe bağlı):

Who is good at survival and in the forest?

Ne olur?

  • Anahtar kelime bulguları: biome='forest'
  • Anlamsal bulgular: "Hayatta kalma" ile benzer beceriler
  • Karma, en iyi sonuçları elde etmek için her ikisini de birleştirir.

👉💻 Testi tamamladığınızda terminalde Ctrl+C tuşuna basarak testi sonlandırın.

9. Çok formatlı ardışık düzen - Araç katmanı

Neden Çok Modlu Bir Ardışık Düzene İhtiyacımız Var?

Hayatta kalma ağı yalnızca metinden ibaret değildir. Sahadaki kurtulanlar, yapılandırılmamış verileri doğrudan sohbet üzerinden gönderir:

  • 📸 Görseller: Kaynakların, tehlikelerin veya ekipmanların fotoğrafları
  • 🎥 Videolar: Durum raporları veya SOS yayınları
  • 📄 Metin: Saha notları veya günlükler

Hangi Dosyaları İşliyoruz?

Mevcut verileri aradığımız önceki adımın aksine, burada kullanıcı tarafından yüklenen dosyaları işleriz. chat.py arayüzü, dosya eklerini dinamik olarak işler:

Kaynak

İçerik

Hedef

Kullanıcı eki

Resim/Video/Metin

Grafiğe eklenecek bilgiler

Chat Context

"Here is a photo of the supplies" (Malzemelerin fotoğrafı)

Amaç ve ek ayrıntılar

Planlanan Yaklaşım: Sıralı Temsilci İşlem Hattı

Özel aracıları birbirine bağlayan bir Sıralı Aracı (multimedia_agent.py) kullanırız:

architecture_uploading

Bu, backend/agent/multimedia_agent.py içinde SequentialAgent olarak tanımlanır.

Araç katmanı, aracıların çağırabileceği özellikleri sağlar. Araçlar, "nasıl" sorusunun cevabını verir: dosyaları yükleme, varlıkları ayıklama ve veritabanına kaydetme.

1. Araçlar dosyasını açın

👉💻 Yeni bir terminal açın. Terminalde dosyayı Cloud Shell Düzenleyici'de açın:

cloudshell edit ~/way-back-home/level_2/backend/agent/tools/extraction_tools.py

2. upload_media aracını uygulama

Bu araç, yerel bir dosyayı Google Cloud Storage'a yükler.

👉 extraction_tools.py bölümünde yorumu pass # TODO: REPLACE_UPLOAD_MEDIA_FUNCTION bulun.

Bu satırın tamamını aşağıdaki kodla değiştirin:

    """
    Upload media file to GCS and detect its type.
    
    Args:
        file_path: Path to the local file
        survivor_id: Optional survivor ID to associate with upload
        
    Returns:
        Dict with gcs_uri, media_type, and status
    """
    try:
        if not file_path:
            return {"status": "error", "error": "No file path provided"}
        
        # Strip quotes if present
        file_path = file_path.strip().strip("'").strip('"')
        
        if not os.path.exists(file_path):
            return {"status": "error", "error": f"File not found: {file_path}"}
        
        gcs_uri, media_type, signed_url = gcs_service.upload_file(file_path, survivor_id)
        
        return {
            "status": "success",
            "gcs_uri": gcs_uri,
            "signed_url": signed_url,
            "media_type": media_type.value,
            "file_name": os.path.basename(file_path),
            "survivor_id": survivor_id
        }
    except Exception as e:
        logger.error(f"Upload failed: {e}")
        return {"status": "error", "error": str(e)}

3. extract_from_media aracını uygulama

Bu araç bir yönlendiricidir. media_type öğesini kontrol eder ve doğru ayıklayıcıya (metin, resim veya video) gönderir.

👉extraction_tools.py bölümünde yorumu pass # TODO: REPLACE_EXTRACT_FROM_MEDIA bulun.

Bu satırın tamamını aşağıdaki kodla değiştirin:

    """
    Extract entities and relationships from uploaded media.
    
    Args:
        gcs_uri: GCS URI of the uploaded file
        media_type: Type of media (text/image/video)
        signed_url: Optional signed URL for public/temporary access
        
    Returns:
        Dict with extraction results
    """
    try:
        if not gcs_uri:
             return {"status": "error", "error": "No GCS URI provided"}

        # Select appropriate extractor
        if media_type == MediaType.TEXT.value or media_type == "text":
            result = await text_extractor.extract(gcs_uri)
        elif media_type == MediaType.IMAGE.value or media_type == "image":
            result = await image_extractor.extract(gcs_uri)
        elif media_type == MediaType.VIDEO.value or media_type == "video":
            result = await video_extractor.extract(gcs_uri)
        else:
            return {"status": "error", "error": f"Unsupported media type: {media_type}"}
            
        # Inject signed URL into broadcast info if present
        if signed_url:
            if not result.broadcast_info:
                result.broadcast_info = {}
            result.broadcast_info['thumbnail_url'] = signed_url
        
        return {
            "status": "success",
            "extraction_result": result.to_dict(), # Return valid JSON dict instead of object
            "summary": result.summary,
            "entities_count": len(result.entities),
            "relationships_count": len(result.relationships),
            "entities": [e.to_dict() for e in result.entities],
            "relationships": [r.to_dict() for r in result.relationships]
        }
    except Exception as e:
        logger.error(f"Extraction failed: {e}")
        return {"status": "error", "error": str(e)}

Önemli Uygulama Ayrıntıları:

  • Çok formatlı giriş: generate_content'a hem metin istemini (_get_extraction_prompt()) hem de görüntü nesnesini iletiyoruz.
  • Yapılandırılmış Çıkış: response_mime_type="application/json", LLM'nin geçerli JSON döndürmesini sağlar. Bu, işlem hattı için kritik öneme sahiptir.
  • Görsel Varlık Bağlantısı: İstemde bilinen varlıklar yer aldığından Gemini, belirli karakterleri tanıyabilir.

4. save_to_spanner aracını uygulama

Bu araç, çıkarılan öğeleri ve ilişkileri Spanner Graph DB'de kalıcı hale getirir.

👉extraction_tools.py bölümünde yorumu pass # TODO: REPLACE_SPANNER_AGENT bulun.

Bu satırın tamamını aşağıdaki kodla değiştirin:

    """
    Save extracted entities and relationships to Spanner Graph DB.
    
    Args:
        extraction_result: ExtractionResult object (or dict from previous step if passed as dict)
        survivor_id: Optional survivor ID to associate with the broadcast
        
    Returns:
        Dict with save statistics
    """
    try:
        # Handle if extraction_result is passed as the wrapper dict from extract_from_media
        result_obj = extraction_result
        if isinstance(extraction_result, dict) and 'extraction_result' in extraction_result:
             result_obj = extraction_result['extraction_result']
        
        # If result_obj is a dict (from to_dict()), reconstruct it
        if isinstance(result_obj, dict):
            from extractors.base_extractor import ExtractionResult
            result_obj = ExtractionResult.from_dict(result_obj)
        
        if not result_obj:
            return {"status": "error", "error": "No extraction result provided"}
            
        stats = spanner_service.save_extraction_result(result_obj, survivor_id)
        
        return {
            "status": "success",
            "entities_created": stats['entities_created'],
            "entities_existing": stats['entities_found_existing'],
            "relationships_created": stats['relationships_created'],
            "broadcast_id": stats['broadcast_id'],
            "errors": stats['errors'] if stats['errors'] else None
        }
    except Exception as e:
        logger.error(f"Spanner save failed: {e}")
        return {"status": "error", "error": str(e)}

Temsilcilere üst düzey araçlar sunarak, temsilcinin muhakeme yeteneklerinden yararlanırken veri bütünlüğünü sağlıyoruz.

5. GCS Hizmetini Güncelleme

GCSService, dosyanın Google Cloud Storage'a yüklenmesini sağlar.

👉💻 Terminalde dosyayı Cloud Shell Düzenleyici'de açın:

cloudshell edit ~/way-back-home/level_2/backend/services/gcs_service.py

👉 gcs_service.py dosyasında, upload_file işlevinin içindeki # TODO: REPLACE_SAVE_TO_GCS yorumunu bulun.

Bu satırın tamamını aşağıdaki kodla değiştirin:

        blob = self.bucket.blob(blob_name)
        blob.upload_from_filename(file_path)

Bu işlem bir hizmete dönüştürüldüğünde, aracı GCS paketleri, blob adları veya imzalı URL oluşturma hakkında bilgi sahibi olmak zorunda kalmaz. Sadece "yükleme" isteğinde bulunuyor.

6. (Salt Okunur)Neden Agentic Workflow > Geleneksel Yaklaşımlar?

Temsilci Tabanlı Özelliklerin Avantajı:

Özellik

Batch Pipeline

Etkinliğe Dayalı

Temsilci tabanlı iş akışı

Karmaşıklık

Düşük (1 komut dosyası)

Yüksek (5'ten fazla hizmet)

Düşük (1 Python dosyası: multimedia_agent.py)

Durum Yönetimi

Genel değişkenler

Zor (ayrılmış)

Birleştirilmiş (Temsilci durumu)

Hata İşleme

Kaza

Sessiz günlükler

Etkileşimli ("Bu dosyayı okuyamadım")

Kullanıcı Geri Bildirimi

Konsol baskıları

Yoklama yapılması gerekiyor

Anında (Sohbetin bir parçası)

Uyarlanabilirlik

Sabit mantık

Sert işlevler

Akıllı (LLM, sonraki adıma karar verir)

Bağlama Duyarlılığı (Context Awareness)

Yok

Yok

Tam (Kullanıcı niyetini bilir)

Öneminin Nedeni: multimedia_agent.py (4 alt aracısı olan bir SequentialAgent: Yükle → Çıkar → Kaydet → Özet) kullanarak karmaşık altyapıyı VE kırılgan komut dosyalarını akıllı, etkileşimli uygulama mantığıyla değiştiriyoruz.

10. Çok formatlı işlem hattı: aracı katmanı

Aracı katmanı, görevleri tamamlamak için araçları kullanan yapay zeka temsilcilerini tanımlar. Her aracının belirli bir rolü vardır ve bağlamı bir sonraki aracıya iletir. Aşağıda, çoklu aracı sisteminin mimari şeması yer almaktadır.

agent_diagram

1. Temsilci Dosyasını Açma

👉💻 Terminalde dosyayı Cloud Shell Düzenleyici'de açın:

cloudshell edit ~/way-back-home/level_2/backend/agent/multimedia_agent.py

2. Yükleme aracısını tanımlama

Bu temsilci, kullanıcının mesajından bir dosya yolu çıkarır ve bunu GCS'ye yükler.

👉multimedia_agent.py dosyasında # TODO: REPLACE_UPLOAD_AGENT yorumunu bulun.

Bu satırın tamamını aşağıdaki kodla değiştirin:

upload_agent = LlmAgent(
    name="UploadAgent",
    model="gemini-2.5-flash",
    instruction="""Extract the file path from the user's message and upload it.

Use `upload_media(file_path, survivor_id)` to upload the file.
The survivor_id is optional - include it if the user mentions a specific survivor (e.g., "survivor Sarah" -> "Sarah").
If the user provides a path like "/path/to/file", use that.

Return the upload result with gcs_uri and media_type.""",
    tools=[upload_media],
    output_key="upload_result"
)

3. Ayıklama aracısını tanımlama

Bu aracı, yüklenen medyayı "görür" ve Gemini Vision'ı kullanarak yapılandırılmış verileri ayıklar.

👉multimedia_agent.py dosyasında # TODO: REPLACE_EXTRACT_AGENT yorumunu bulun.

Bu satırın tamamını aşağıdaki kodla değiştirin:

extraction_agent = LlmAgent(
    name="ExtractionAgent", 
    model="gemini-2.5-flash",
    instruction="""Extract information from the uploaded media.

Previous step result: {upload_result}

Use `extract_from_media(gcs_uri, media_type, signed_url)` with the values from the upload result.
The gcs_uri is in upload_result['gcs_uri'], media_type in upload_result['media_type'], and signed_url in upload_result['signed_url'].

Return the extraction results including entities and relationships found.""",
    tools=[extract_from_media],
    output_key="extraction_result"
)

instructionReferansların{upload_result} nasıl kullanıldığına dikkat edin. ADK'daki aracılar arasında durum bu şekilde aktarılır.

4. Spanner aracısını tanımlama

Bu aracı, çıkarılan öğeleri ve ilişkileri grafik veritabanına kaydeder.

👉multimedia_agent.py dosyasında # TODO: REPLACE_SPANNER_AGENT yorumunu bulun.

Bu satırın tamamını aşağıdaki kodla değiştirin:

spanner_agent = LlmAgent(
    name="SpannerAgent",
    model="gemini-2.5-flash", 
    instruction="""Save the extracted information to the database.

Upload result: {upload_result}
Extraction result: {extraction_result}

Use `save_to_spanner(extraction_result, survivor_id)` to save to Spanner.
Pass the WHOLE `extraction_result` object/dict from the previous step.
Include survivor_id if it was provided in the upload step.

Return the save statistics.""",
    tools=[save_to_spanner],
    output_key="spanner_result"
)

Bu temsilci, önceki her iki adımdan (upload_result ve extraction_result) bağlam bilgisi alır.

5. Özetleme aracısını tanımlama

Bu temsilci, önceki tüm adımlardaki sonuçları kullanıcı dostu bir yanıt hâlinde birleştirir.

👉multimedia_agent.py dosyasında summary_instruction="" # TODO: REPLACE_SUMMARY_AGENT_PROMPT yorumunu bulun.

Bu satırın tamamını aşağıdaki kodla değiştirin:

USE_MEMORY_BANK = os.getenv("USE_MEMORY_BANK", "false").lower() == "true"
save_msg = "6. Mention that the data is also being synced to the memory bank." if USE_MEMORY_BANK else ""

summary_instruction = f"""Provide a user-friendly summary of the media processing.

Upload: {{upload_result}}
Extraction: {{extraction_result}}
Database: {{spanner_result}}

Summarize:
1. What file was processed (name and type)
2. Key information extracted (survivors, skills, needs, resources found) - list names and counts
3. Relationships identified
4. What was saved to the database (broadcast ID, number of entities)
5. Any issues encountered
{save_msg}

Be concise but informative."""

Bu aracının araçlara ihtiyacı yoktur. Paylaşılan bağlamı okur ve kullanıcı için net bir özet oluşturur.

🧠 Mimari Özeti

Katman

Dosya

Sorumluluk

Araçlar

extraction_tools.py + gcs_service.py

Nasıl: Yükleme, ayıklama, kaydetme

Ajan

multimedia_agent.py

Ne? Ardışık düzeni düzenleyin.

11. Çok formatlı veri ardışık düzeni: Düzenleme

Yeni sistemimizin temelini, backend/agent/multimedia_agent.py adresinde tanımlanan MultimediaExtractionPipeline oluşturur. ADK'daki (Agent Development Kit) Sequential Agent (Sıralı Aracı) düzenini kullanır.

1. Neden Sıralı?

Yükleme işleme, doğrusal bir bağımlılık zinciridir:

  1. Dosyanız (yükleme) olmadan verileri ayıklayamazsınız.
  2. Verileri ayıklamadığınız (çıkarma) sürece kaydedemezsiniz.
  3. Sonuçları alana (Kaydet) kadar özetleme yapamazsınız.

Bu işlem için SequentialAgent idealdir. Bir aracının çıkışını bir sonraki aracının bağlamı/girişi olarak iletir.

2. Temsilci Tanımı

İşlem hattının nasıl bir araya getirildiğine multimedia_agent.py bölümünün en alt kısmında bakalım: 👉💻 Terminalde, aşağıdaki komutu çalıştırarak dosyayı Cloud Shell Düzenleyici'de açın:

cloudshell edit ~/way-back-home/level_2/backend/agent/multimedia_agent.py

Her iki önceki adımdan giriş alır. Yorumu bulun # TODO: REPLACE_ORCHESTRATION. Bu satırın tamamını aşağıdaki kodla değiştirin:

    sub_agents=[upload_agent, extraction_agent, spanner_agent, summary_agent]

3. Kök temsilciyle bağlantı kurma

👉💻 Terminalde, aşağıdaki komutu çalıştırarak dosyayı Cloud Shell Düzenleyici'de açın:

cloudshell edit ~/way-back-home/level_2/backend/agent/agent.py

Yorumu bulun # TODO: REPLACE_ADD_SUBAGENT. Bu satırın tamamını aşağıdaki kodla değiştirin:

    sub_agents=[multimedia_agent],

Bu tek nesne, dört "uzmanı" tek bir çağrılabilir varlıkta etkili bir şekilde birleştirir.

4. Temsilciler Arasındaki Veri Akışı

Her aracı, çıktısını sonraki aracıların erişebileceği paylaşılan bir bağlamda depolar:

architecture_uploading

5. Uygulamayı açın (Uygulama hâlâ çalışıyorsa bu adımı atlayın)

👉💻 Uygulamayı başlatma:

cd ~/way-back-home/level_2/
./start_app.sh

👉 Terminalde Local: http://localhost:5173/ seçeneğini tıklayın.

6. Test resmi yükleme

👉 Sohbet arayüzünde, buradaki fotoğraflardan herhangi birini seçip kullanıcı arayüzüne yükleyin:

Sohbet arayüzünde, temsilciye bağlamınızla ilgili ayrıntıları verin:

Here is the survivor note

Ardından, görüntüyü buraya ekleyin.

upload_input

upload_result

👉💻 Terminalde, testi tamamladığınızda işlemi sonlandırmak için "Ctrl+C" tuşlarına basın.

6. GCS paketinde çok formatlı yüklemeyi doğrulama

gcs

  • Paketinizi seçin ve media simgesini tıklayın.

medya

  • Yüklediğiniz resmi buradan görüntüleyebilirsiniz. uploaded_img

7. Spanner'da çok formatlı yüklemeyi doğrulama (isteğe bağlı)

Aşağıda, test_photo1 için kullanıcı arayüzündeki örnek çıktı verilmiştir.

  • Google Cloud Console Spanner'ı açın.
  • Örneğinizi seçin: Survivor Network
  • Veritabanınızı seçin: graph-db
  • Sol kenar çubuğunda Spanner Studio'yu tıklayın.

👉 Spanner Studio'da yeni verileri sorgulayın:

SELECT 
  s.name AS Survivor,
  s.role AS Role,
  b.name AS Biome,
  r.name AS FoundResource,
  s.created_at
FROM Survivors s
LEFT JOIN SurvivorInBiome sib ON s.survivor_id = sib.survivor_id
LEFT JOIN Biomes b ON sib.biome_id = b.biome_id
LEFT JOIN SurvivorFoundResource sfr ON s.survivor_id = sfr.survivor_id
LEFT JOIN Resources r ON sfr.resource_id = r.resource_id
ORDER BY s.created_at DESC;

Aşağıdaki sonuçtan bunu doğrulayabiliriz:

spanner_verify

12. Agent Engine ile Memory Bank

1. Belleğin işleyiş şekli

Sistem, hem anlık bağlamı hem de uzun vadeli öğrenmeyi işlemek için çift bellekli bir yaklaşım kullanır.

memory_bank

2. Anı konuları nedir?

Hafıza Konuları, temsilcinin görüşmelerde hatırlaması gereken bilgi kategorilerini tanımlar. Bunları, farklı kullanıcı tercihlerinin bulunduğu dosya dolapları olarak düşünebilirsiniz.

2 Konumuz:

  1. search_preferences: Kullanıcının arama yapma şekli
    • Anahtar kelime aramayı mı yoksa semantik aramayı mı tercih ediyorlar?
    • Hangi becerileri/biyomları sık sık arıyorlar?
    • Örnek bellek: "Kullanıcı, tıbbi beceriler için semantik aramayı tercih ediyor"
  2. urgent_needs_context: Hangi krizleri takip ediyorlar?
    • Hangi kaynakları izliyorlar?
    • Hangi hayatta kalanlarla ilgili endişeleri var?
    • Örnek bellek: "Kullanıcı, Kuzey Kampı'nda ilaç kıtlığını takip ediyor"

3. Anı Konuları Oluşturma

Özel bellek konuları, aracının neyi hatırlaması gerektiğini tanımlar. Bunlar, Agent Engine dağıtılırken yapılandırılır.

👉💻 Terminalde, aşağıdaki komutu çalıştırarak dosyayı Cloud Shell Düzenleyici'de açın:

cloudshell edit ~/way-back-home/level_2/backend/deploy_agent.py

Bu işlemle düzenleyicinizde ~/way-back-home/level_2/backend/deploy_agent.py açılır.

Hangi bilgilerin ayıklanıp kaydedileceği konusunda LLM'ye yol göstermek için yapı MemoryTopic nesnelerini tanımlarız.

👉 deploy_agent.py dosyasında # TODO: SET_UP_TOPIC yerine aşağıdakileri girin:

# backend/deploy_agent.py

    custom_topics = [
        # Topic 1: Survivor Search Preferences
        MemoryTopic(
            custom_memory_topic=CustomMemoryTopic(
                label="search_preferences",
                description="""Extract the user's preferences for how they search for survivors. Include:
                - Preferred search methods (keyword, semantic, direct lookup)
                - Common filters used (biome, role, status)
                - Specific skills they value or frequently look for
                - Geographic areas of interest (e.g., "forest biome", "mountain outpost")
                
                Example: "User prefers semantic search for finding similar skills."
                Example: "User frequently checks for survivors in the Swamp Biome."
                """,
            )
        ),
        # Topic 2: Urgent Needs Context
        MemoryTopic(
            custom_memory_topic=CustomMemoryTopic(
                label="urgent_needs_context",
                description="""Track the user's focus on urgent needs and resource shortages. Include:
                - Specific resources they are monitoring (food, medicine, ammo)
                - Critical situations they are tracking
                - Survivors they are particularly concerned about
                
                Example: "User is monitoring the medicine shortage in the Northern Camp."
                Example: "User is looking for a doctor for the injured survivors."
                """,
            )
        )
    ]

4. Aracı Entegrasyonu

Aracı kodu, bilgileri kaydetmek ve almak için Memory Bank'ı bilmelidir.

👉💻 Terminalde, aşağıdaki komutu çalıştırarak dosyayı Cloud Shell Düzenleyici'de açın:

cloudshell edit ~/way-back-home/level_2/backend/agent/agent.py

Bu işlemle düzenleyicinizde ~/way-back-home/level_2/backend/agent/agent.py açılır.

Aracı Oluşturma

Aracı oluştururken, oturumların etkileşimlerden sonra belleğe kaydedilmesini sağlamak için after_agent_callback değerini iletiyoruz. add_session_to_memory işlevi, sohbet yanıtını yavaşlatmamak için eşzamansız olarak çalışır.

👉 agent.py dosyasında # TODO: REPLACE_ADD_SESSION_MEMORY yorumunu bulun, Replace this whole line ifadesini aşağıdaki kodla değiştirin:

async def add_session_to_memory(
        callback_context: CallbackContext
) -> Optional[types.Content]:
    """Automatically save completed sessions to memory bank in the background"""
    if hasattr(callback_context, "_invocation_context"):
        invocation_context = callback_context._invocation_context
        if invocation_context.memory_service:
            # Use create_task to run this in the background without blocking the response
            asyncio.create_task(
                invocation_context.memory_service.add_session_to_memory(
                    invocation_context.session
                )
            )
            logger.info("Scheduled session save to memory bank in background")

Arka planda kaydetme

👉 agent.py dosyasında # TODO: REPLACE_ADD_MEMORY_BANK_TOOL yorumunu bulun, Replace this whole line ifadesini aşağıdaki kodla değiştirin:

if USE_MEMORY_BANK:
    agent_tools.append(PreloadMemoryTool())

👉 agent.py dosyasında # TODO: REPLACE_ADD_CALLBACK yorumunu bulun, Replace this whole line ifadesini aşağıdaki kodla değiştirin:

    after_agent_callback=add_session_to_memory if USE_MEMORY_BANK else None

Vertex AI Session Service'i ayarlama

👉💻 Terminalde, aşağıdaki komutu çalıştırarak chat.py dosyasını Cloud Shell Düzenleyici'de açın:

cloudshell edit ~/way-back-home/level_2/backend/api/routes/chat.py

👉chat.py dosyasında # TODO: REPLACE_VERTEXAI_SERVICES yorumunu bulun, Replace this whole line ifadesini aşağıdaki kodla değiştirin:

    session_service = VertexAiSessionService(
        project=project_id,
        location=location,
        agent_engine_id=agent_engine_id
    )
    memory_service = VertexAiMemoryBankService(
        project=project_id,
        location=location,
        agent_engine_id=agent_engine_id
    )

4. Kurulum ve Dağıtım

Bellek özelliklerini test etmeden önce aracıyı yeni bellek konularıyla dağıtmanız ve ortamınızın doğru şekilde yapılandırıldığından emin olmanız gerekir.

Bu işlemi kolayca yapabilmeniz için bir komut dosyası sağladık.

Dağıtım Komut Dosyasını Çalıştırma

👉💻 Terminalde dağıtım komut dosyasını çalıştırın:

cd ~/way-back-home/level_2
./deploy_and_update_env.sh

Bu komut dosyası aşağıdaki işlemleri gerçekleştirir:

  • Temsilciyi ve bellek konularını Vertex AI'ye kaydetmek için backend/deploy_agent.py komutunu çalıştırır.
  • Yeni Agent Engine kimliğini yakalar.
  • .env dosyanızı AGENT_ENGINE_ID ile otomatik olarak günceller.
  • USE_MEMORY_BANK=TRUE öğesinin .env dosyanızda ayarlandığından emin olun.

[!IMPORTANT] custom_topics içinde deploy_agent.py ile ilgili değişiklik yaparsanız Agent Engine'i güncellemek için bu komut dosyasını yeniden çalıştırmanız gerekir.

13. Çok Formatlı Verilerle Memory Bank'ı Doğrulama

Temsilciye bir tercih öğreterek ve bu tercihin oturumlar arasında kalıcı olup olmadığını kontrol ederek bellek bankasının çalıştığını doğrulayabilirsiniz.

1. Uygulamayı açın (Uygulamanız zaten çalışıyorsa bu adımı atlayın)

Aşağıdaki talimatları uygulayarak uygulamayı tekrar açın: Önceki terminal hâlâ çalışıyorsa Ctrls+C tuşuna basarak sonlandırın.

👉💻 Uygulamayı başlatma:

cd ~/way-back-home/level_2/
./start_app.sh

👉 Terminalde Local: http://localhost:5173/ seçeneğini tıklayın.

2. Metinle Bellek Bankası'nı Test Etme

Sohbet arayüzünde, temsilciye bağlamınızla ilgili ayrıntıları verin:

"I'm planning a medical rescue mission in the mountains. I need survivors with first aid and climbing skills."

👉 Belleğin arka planda işlenmesi için yaklaşık 30 saniye bekleyin.

2. Yeni oturum başlatma

Mevcut görüşme geçmişini (kısa süreli bellek) temizlemek için sayfayı yenileyin.

Daha önce sağladığınız bağlama dayalı bir soru sorun:

"What kind of missions am I interested in?"

Beklenen Yanıt:

"Önceki görüşmelerinize göre, ilgilendiğiniz konular:

  • Tıbbi kurtarma görevleri
  • Dağ/yüksek rakım operasyonları
  • Gerekli beceriler: ilk yardım, tırmanma

Bu ölçütlere uyan hayatta kalanları bulmamı ister misiniz?"

3. Resim yükleme ile test etme

Bir resim yükleyip şu soruyu sorun:

remember this

Buradaki fotoğraflardan veya kendi fotoğraflarınızdan birini seçip kullanıcı arayüzüne yükleyebilirsiniz:

4. Vertex AI Agent Engine'de doğrulama

Google Cloud Console Agent Engine'e gidin.

  1. Sol üstteki proje seçiciden projeyi seçtiğinizden emin olun:proje seçici
  2. Önceki komuttan yeni dağıttığınız aracı motorunu doğrulayın use_memory_bank.sh:aracı motoruYeni oluşturduğunuz aracı motorunu tıklayın.
  3. Bu dağıtılmış aracının Memories sekmesini tıkladığınızda tüm anıları burada görüntüleyebilirsiniz.anıları görüntüleme

👉💻 Testi tamamladığınızda işlemi sonlandırmak için terminalinizde "Ctrl + C"yi tıklayın.

🎉 Tebrikler! Hafıza bankasını aracınıza bağladınız.

14. Cloud Run'a dağıt

1. Dağıtım komut dosyasını çalıştırın

👉💻 Dağıtım komut dosyasını çalıştırın:

cd ~/way-back-home/level_2
./deploy_cloud_run.sh

Başarıyla dağıtıldıktan sonra URL'yi alırsınız. Bu, sizin için dağıtılan URL'dir. Dağıtıldı

👉💻 URL'yi almadan önce şu komutu çalıştırarak izni verin:

source .env && gcloud run services add-iam-policy-binding survivor-frontend --region $REGION --member=allUsers --role=roles/run.invoker && gcloud run services add-iam-policy-binding survivor-backend --region $REGION --member=allUsers --role=roles/run.invoker

Dağıtılan URL'ye gidin. Uygulamanızın yayında olduğunu göreceksiniz.

2. Derleme ardışık düzenini anlama

cloudbuild.yaml dosyası aşağıdaki sıralı adımları tanımlar:

  1. Arka uç derlemesi: backend/Dockerfile konumundan Docker görüntüsünü oluşturur.
  2. Arka Uç Dağıtımı: Arka uç container'ını Cloud Run'a dağıtır.
  3. URL'yi yakala: Yeni arka uç URL'sini alır.
  4. Frontend Build:
    • Bağımlılıkları yükler.
    • VITE_API_URL= öğesini yerleştirerek React uygulamasını oluşturur.
  5. Frontend Image: frontend/Dockerfile dosyasından Docker görüntüsü oluşturur (statik öğeleri paketler).
  6. Frontend Deploy: Ön uç kapsayıcısını dağıtır.

3. Dağıtımı doğrulama

Derleme tamamlandıktan sonra (komut dosyası tarafından sağlanan günlükler bağlantısını kontrol edin) şunları doğrulayabilirsiniz:

  1. Cloud Run Console'a gidin.
  2. survivor-frontend hizmetini bulun.
  3. Uygulamayı açmak için URL'yi tıklayın.
  4. Ön ucun arka uçla iletişim kurabildiğinden emin olmak için bir arama sorgusu yapın.

4. (YALNIZCA WORKSHOP KATILIMCILARI İÇİN) Konumunuzu güncelleme

👉💻 Tamamlama komut dosyasını çalıştırın:

cd ~/way-back-home/level_2
./set_level_2.sh

Şimdi waybackhome.dev uygulamasını açtığınızda konumunuzun güncellendiğini görürsünüz. 2. seviyeyi tamamladığınız için tebrikler.

nihai sonuç

(İSTEĞE BAĞLI) 5. Manuel Dağıtım

Komutları manuel olarak çalıştırmayı veya süreci daha iyi anlamayı tercih ederseniz cloudbuild.yaml doğrudan nasıl kullanacağınızı burada bulabilirsiniz.

Yazma cloudbuild.yaml

cloudbuild.yaml dosyası, Google Cloud Build'a hangi adımların yürütüleceğini bildirir.

  • adımlar: Sıralı işlemlerin listesi. Her adım bir kapsayıcıda çalışır (ör. docker, gcloud, node, bash).
  • substitutions: Derleme sırasında iletilebilen değişkenler (ör. $_REGION).
  • workspace: Adımların dosya paylaşabileceği ortak bir dizin (ör. backend_url.txt paylaşımı).

Dağıtımı çalıştırma

Komut dosyası olmadan manuel olarak dağıtmak için gcloud builds submit komutunu kullanın. Gerekli değiştirme değişkenlerini İLETMEK ZORUNLUDUR.

# Load your env vars first or replace these values manually
export PROJECT_ID=your-project-id
export REGION=us-central1

gcloud builds submit --config cloudbuild.yaml \
    --project "$PROJECT_ID" \
    --substitutions _REGION="us-central1",_GOOGLE_API_KEY="",_AGENT_ENGINE_ID="your-agent-id",_USE_MEMORY_BANK="TRUE",_GOOGLE_GENAI_USE_VERTEXAI="TRUE"

15. Sonuç

1. Oluşturduklarınız

Grafik Veritabanı: Düğümler (hayatta kalanlar, beceriler) ve kenarlar (ilişkiler) içeren Spanner
Yapay Zeka Arama: Yerleştirmelerle anahtar kelime, anlamsal ve karma arama
Çok Formatlı İşlem Hattı: Gemini ile resimlerden/videolardan öğe çıkarma
Çok Aracılı Sistem: ADK ile koordineli iş akışı
Bellek Bankası: Vertex AI ile uzun vadeli kişiselleştirme
Üretim Dağıtımı: Cloud Run + Agent Engine

2. Mimari Özeti

architecture_fullstack

3. En önemli noktalar

  1. Graph RAG: Akıllı arama için grafik veritabanı yapısını semantik yerleştirmelerle birleştirir.
  2. Çok Aracılı Desenler: Karmaşık ve çok adımlı iş akışları için sıralı ardışık düzenler
  3. Çok formatlı yapay zeka: Yapılandırılmamış medyadan (resimler/video) yapılandırılmış verileri ayıklama
  4. Durumlu Aracılar: Memory Bank, oturumlar arasında kişiselleştirmeye olanak tanır.

4. Atölye İçeriği

5. Kaynaklar