Spanner AI ve Graph ile Gerçek Zamanlı Perakende Önerileri

1. Giriş

Bu codelab'de, mevcut bir perakende veritabanını geliştirmek için Spanner'ın yapay zeka ve grafik özelliklerini kullanma konusunda size yol gösterilecektir. Müşterilerinize daha iyi hizmet vermek için Spanner'da makine öğreniminden yararlanmaya yönelik pratik teknikler öğreneceksiniz. Özellikle, her müşterinin ihtiyaçlarına uygun yeni ürünler keşfetmek için k-En Yakın Komşular (kNN) ve Yaklaşık En Yakın Komşular (ANN) algoritmalarını uygulayacağız. Ayrıca, belirli bir ürün önerisinin neden yapıldığına dair net ve doğal dilde açıklamalar sunmak için bir LLM de entegre edeceksiniz.

Önerinin ötesinde, Spanner'ın grafik işlevselliğini inceleyeceğiz. Müşterilerin satın alma geçmişine ve ürün açıklamalarına göre ürünler arasındaki ilişkileri modellemek için grafik sorgularını kullanırsınız. Bu yaklaşım, yakından ilişkili öğelerin keşfedilmesini sağlayarak "Müşteriler ayrıca satın aldı" veya "İlgili öğeler" özelliklerinizin alaka düzeyini ve etkinliğini önemli ölçüde artırır. Bu codelab'in sonunda, tamamen Google Cloud Spanner tarafından desteklenen akıllı, ölçeklenebilir ve duyarlı bir perakende uygulaması oluşturma becerisine sahip olacaksınız.

Senaryo

Elektronik ekipman perakendecisinde çalıştığınızı varsayalım. E-ticaret sitenizde Products, Orders ve OrderItems içeren standart bir Spanner veritabanı var.

Bir müşteri, belirli bir ihtiyacı karşılamak için sitenize geliyor: "Yüksek performanslı bir klavye satın almak istiyorum. Bazen plajda kod yazıyorum, bu nedenle ıslanabilir."

Amacınız, bu isteği akıllıca yanıtlamak için Spanner'ın gelişmiş özelliklerini kullanmaktır:

  1. Bulma: Vektör aramayı kullanarak, kullanıcının isteğiyle semantik olarak eşleşen açıklamalara sahip ürünleri bulmak için basit anahtar kelime aramasının ötesine geçin.
  2. Açıklama: En iyi eşleşmeleri analiz etmek ve önerinin neden uygun olduğunu açıklayarak müşteri güvenini artırmak için bir LLM kullanın.
  3. İlişkilendirme: Müşterilerin bu öneriyle birlikte sıklıkla satın aldığı diğer ürünleri bulmak için grafik sorgularını kullanın.

2. Başlamadan önce

  1. Proje oluşturma Google Cloud Console'daki proje seçici sayfasında bir Google Cloud projesi seçin veya oluşturun.
  2. Faturalandırmayı etkinleştirin: Cloud projeniz için faturalandırmanın etkinleştirildiğinden emin olun. Faturalandırmanın bir projede etkin olup olmadığını kontrol etmeyi öğrenin.
  3. Cloud Shell'i etkinleştirme Konsolda "Cloud Shell'i etkinleştir" düğmesini tıklayarak Cloud Shell'i etkinleştirin. Cloud Shell Terminali ile Düzenleyici arasında geçiş yapabilirsiniz.

c3c8bfefc88138cc.png

  1. Yetkilendirme ve Projeyi Ayarlama Cloud Shell'e bağlandıktan sonra kimliğinizin doğrulandığını ve projenin proje kimliğinize ayarlandığını kontrol edin.
gcloud auth list
gcloud config list project
  1. Projeniz ayarlanmamışsa <PROJECT_ID> kısmını gerçek proje kimliğinizle değiştirerek projeyi ayarlamak için aşağıdaki komutu kullanın:
export PROJECT_ID=<PROJECT_ID>
gcloud config set project $PROJECT_ID
  1. Gerekli API'leri Etkinleştirme Spanner, Vertex AI ve Compute Engine API'lerini etkinleştirin. Bu işlem birkaç dakika sürebilir.
gcloud services enable \
    spanner.googleapis.com \
    aiplatform.googleapis.com \
    compute.googleapis.com
  1. Yeniden kullanacağınız birkaç ortam değişkeni ayarlayın.
export INSTANCE_ID=my-first-spanner
export INSTANCE_CONFIG=regional-us-central1
  1. Henüz bir Spanner örneğiniz yoksa ücretsiz deneme Spanner örneği oluşturun . Veritabanınızı barındırmak için bir Spanner örneğine ihtiyacınız vardır. Yapılandırma olarak regional-us-central1 kullanılacak. İsterseniz bu bilgiyi güncelleyebilirsiniz.
gcloud spanner instances create $INSTANCE_ID \
   --instance-type=free-instance --config=$INSTANCE_CONFIG \
   --description="Trial Instance" 

3. Mimari Genel Bakış

Spanner, Vertex AI'da barındırılan modeller hariç tüm gerekli işlevleri kapsar.

4. 1. adım: Veritabanını ayarlayın ve ilk sorgunuzu gönderin.

Öncelikle veritabanımızı oluşturmamız, örnek perakende verilerimizi yüklememiz ve Spanner'a Vertex AI ile nasıl iletişim kuracağını söylememiz gerekiyor.

Bu bölümde aşağıdaki SQL komut dosyalarını kullanacaksınız.

  1. Spanner'ın ürün sayfasına gidin.
  2. Doğru örneği seçin.

a8792346efb017d5.png

  1. Ekranda Veri Kümelerini Keşfet'i seçin. Ardından, pop-up'ta "Perakende" seçeneğini belirleyin.

49800ad520771ecb.png

c2a7cd37d5c1c493.png

  1. Spanner Studio'ya gidin. Spanner Studio'da, sorgu düzenleyici ve SQL sorgu sonuçları tablosuyla entegre olan bir Gezgin bölmesi bulunur. Bu tek arayüzden DDL, DML ve SQL ifadelerini çalıştırabilirsiniz. Yandaki menüyü genişletmeniz ve büyüteci bulmanız gerekir.

b6a188814a821aba.png

  1. Ürünler tablosunu okuyun. Yeni bir sekme oluşturun veya önceden oluşturulmuş "Adsız sorgu" sekmesini kullanın.

cb65b9aa4e7138b1.png

SELECT *
FROM Products;

5. 2. adım: Yapay zeka modellerini oluşturun.

Şimdi Spanner nesneleriyle uzak modelleri oluşturalım. Bu SQL ifadeleri, Vertex AI uç noktalarına bağlanan Spanner nesneleri oluşturur.

  1. Spanner Studio'da yeni bir sekme açın ve iki modelinizi oluşturun. Bunlardan ilki, yerleştirmeler oluşturmanıza olanak tanıyan EmbeddingsModel'dir. İkincisi ise LLMModel. Bu model, bir LLM ile (örneğimizde gemini-2.5-flash) etkileşim kurmanıza olanak tanır. <PROJECT_ID> kısmını proje kimliğinizle güncellediğinizden emin olun.
### Create the Embedding Model object in Spanner
CREATE MODEL EmbeddingsModel INPUT(
content STRING(MAX),
) OUTPUT(
embeddings STRUCT<statistics STRUCT<truncated BOOL, token_count FLOAT32>, values ARRAY<FLOAT32>>,
) REMOTE OPTIONS (
endpoint = '//aiplatform.googleapis.com/projects/<PROJECT_ID>/locations/us-central1/publishers/google/models/text-embedding-005'
);

### Create the LLM Model object in Spanner
CREATE MODEL LLMModel INPUT(
prompt STRING(MAX),
) OUTPUT(
content STRING(MAX),
) REMOTE OPTIONS (
endpoint = '//aiplatform.googleapis.com/projects/<PROJECT_ID>/locations/us-central1/publishers/google/models/gemini-2.5-flash',
default_batch_size = 1
);
  1. Not: PROJECT_ID yerine gerçek $PROJECT_ID değerinizi girmeyi unutmayın.

67f60ff3a90e926c.png

Bu adımı test edin: Modellerin oluşturulduğunu doğrulamak için SQL düzenleyicide aşağıdakileri çalıştırabilirsiniz.

SELECT *
FROM information_schema.models;

9d2c9cab3733a964.png

6. 3. adım: Vektör yerleştirmeleri oluşturun ve saklayın

Ürün tablomuzda metin açıklamaları var ancak yapay zeka modeli vektörleri (sayı dizileri) anlıyor. Bu vektörleri depolamak için yeni bir sütun eklememiz ve ardından tüm ürün açıklamalarımızı EmbeddingsModel üzerinden geçirerek bu sütunu doldurmamız gerekiyor.

  1. Yerleştirmeleri desteklemek için yeni bir tablo oluşturun. Öncelikle yerleştirmeleri destekleyebilecek bir tablo oluşturun. Ürün tablosu örnek yerleştirmelerinden farklı bir yerleştirme modeli kullanıyoruz. Vektör aramasının düzgün çalışması için yerleştirmelerin aynı modelden oluşturulduğundan emin olmanız gerekir.
CREATE TABLE products_with_embeddings (
   ProductID INT64,
   embedding_vector ARRAY<FLOAT32>(vector_length=>768),
   embedding_text STRING(MAX)
)
PRIMARY KEY (ProductID);
  1. Yeni tabloyu, modelden oluşturulan yerleştirmelerle doldurun. Burada basitlik için insert into ifadesini kullanıyoruz. Bu işlem, sorgu sonuçlarını yeni oluşturduğunuz tabloya aktarır.

SQL ifadesi, ilk olarak yerleştirme oluşturmak istediğimiz tüm alakalı metin sütunlarını alır ve birleştirir. Ardından, kullandığımız metin de dahil olmak üzere ilgili bilgileri döndürürüz. Bu genellikle gerekli değildir ancak sonuçları görselleştirebilmeniz için eklenmiştir.

INSERT INTO products_with_embeddings (productId, embedding_text, embedding_vector)
SELECT
ProductID,
content as embedding_text,
embeddings.values as embedding_vector
FROM ML.PREDICT(
 MODEL EmbeddingsModel,
 (
   SELECT
   ProductID,
   embedding_text AS content
   FROM (
     SELECT
       ProductID,
       CONCAT(
         Category,
         " ",
         Description,
         " ",
         Name
       ) AS embedding_text
       FROM products)));
  1. Yeni yerleştirmelerinizi kontrol edin. Oluşturulan yerleştirmeleri göreceksiniz.
SELECT *
FROM products_with_embeddings
LIMIT 1;

d40975087736e604.png

7. 4. adım: ANN araması için vektör dizini oluşturun

Milyonlarca vektörde anında arama yapmak için bir dizine ihtiyacımız var. Bu dizin, Yaklaşık En Yakın Komşu (ANN) aramayı mümkün kılar. Bu arama son derece hızlıdır ve yatay olarak ölçeklenebilir.

  1. Dizini oluşturmak için aşağıdaki DDL sorgusunu çalıştırın. Uzaklık metriğimiz olarak COSINE değerini belirtiyoruz. Bu değer, semantik metin araması için mükemmeldir. Spanner, sorgu için WHERE ifadesini zorunlu kılacağından bu ifadenin gerekli olduğunu unutmayın.
CREATE VECTOR INDEX DescriptionEmbeddingIndex
   ON products_with_embeddings(embedding_vector)
   WHERE embedding_vector IS NOT NULL
OPTIONS (
 distance_type = 'COSINE'
);
  1. İşlemler sekmesinde dizin oluşturma işleminizin durumunu kontrol edin.

2ad9c88bc86b77f0.png

8. 5. adım: K-En Yakın Komşu (KNN) aramasıyla önerileri bulma

Şimdi de işin eğlenceli kısmına geçelim. Müşterimizin sorgusuyla eşleşen ürünleri bulalım: "Yüksek performanslı bir klavye satın almak istiyorum. Bazen plajda kod yazıyorum, bu nedenle ıslanabilir.".

K-Nearest Neighbor (KNN) aramasıyla başlayalım. Bu, sorgu vektörümüzü her bir ürün vektörüyle karşılaştıran tam bir aramadır. Hassas olsa da çok büyük veri kümelerinde yavaş olabilir (bu nedenle 5. adım için bir ANN dizini oluşturduk).

Bu sorgu iki işlem yapar:

  1. Bir alt sorgu, müşterimizin sorgusu için yerleştirme vektörünü almak üzere ML.PREDICT işlevini kullanır.
  2. Dış sorgu, sorgu vektörü ile her ürünün embedding_vector'ü arasındaki"uzaklığı" hesaplamak için COSINE_DISTANCE işlevini kullanır. Daha kısa mesafe, daha iyi eşleşme anlamına gelir.
SELECT
    productid,
    embedding_text,
    COSINE_DISTANCE(
      embedding_vector,
      (
        SELECT embeddings.values
        FROM ML.PREDICT(
          MODEL EmbeddingsModel,
          (SELECT "I'd like to buy a high performance keyboard. I sometimes code while I'm at the beach so it may get wet." AS content)
        )
      )
    ) AS distance
FROM products_with_embeddings
WHERE embedding_vector IS NOT NULL
ORDER BY distance
LIMIT 5;

En üstte suya dayanıklı klavyelerin yer aldığı bir ürün listesi görürsünüz.

9. 6. adım: Yaklaşık (ANN) Arama ile önerileri bulma

KNN harika bir yöntem olsa da milyonlarca ürün ve saniyede binlerce sorgu içeren bir üretim sistemi için ANN dizinimizin hızına ihtiyacımız var.

Dizini kullanmak için APPROX_COSINE_DISTANCE işlevini belirtmeniz gerekir.

  1. Metninizin vektör yerleştirmesini yukarıda yaptığınız gibi alın. Bu sonuçları, APPROX_COSINE_DISTANCE işlevinizde kullanabilmeniz için products_with_embeddings tablosundaki kayıtlarla çapraz olarak birleştiririz.
WITH vector_query as
(
 SELECT embeddings.values as vector
 FROM ML.PREDICT(
 MODEL EmbeddingsModel,
  (SELECT "I'd like to buy a high performance keyboard. I sometimes code while I'm at the beach so it may get wet." as content)
 )
)
SELECT
ProductID,
embedding_text,
APPROX_COSINE_DISTANCE(embedding_vector, vector, options => JSON '{\"num_leaves_to_search\": 10}') distance
FROM products_with_embeddings @{force_index=DescriptionEmbeddingIndex},
vector_query
WHERE embedding_vector IS NOT NULL
ORDER BY distance
LIMIT 5;

Beklenen Çıkış: Sonuçlar, KNN sorgusuyla aynı veya çok benzer olmalıdır ancak dizin kullanılarak çok daha verimli bir şekilde yürütülür. Bu durumu örnekte fark etmeyebilirsiniz.

10. 7. adım: Önerileri açıklamak için LLM kullanın

Yalnızca ürün listesi göstermek iyi olsa da neden iyi veya kötü bir seçim olduğunu açıklamak daha da iyidir. Bunu yapmak için LLMModel'imizi (Gemini) kullanabiliriz.

Bu sorgu, 4. adımda oluşturduğumuz KNN sorgusunu bir ML.PREDICT çağrısının içine yerleştirir. Büyük dil modeline istem oluşturmak için CONCAT işlevini kullanırız. Bu işlev, büyük dil modeline şunları sağlar:

  1. Net bir talimat ("Evet" veya "Hayır" şeklinde yanıtlayın ve nedenini açıklayın).
  2. Müşterinin orijinal sorgusu.
  3. En iyi eşleşen her ürünün adı ve açıklaması.

Ardından LLM, her ürünü sorguya göre değerlendirir ve doğal dilde bir yanıt verir.

SELECT
   ProductID,
   embedding_text,
   content AS LLMResponse
FROM ML.PREDICT(
   MODEL LLMModel,
   (
     SELECT
       ProductID,
       embedding_text,
       CONCAT(
         "Answer with ‘Yes' or ‘No' and explain why: Is this a good fit for me?",
         "I'd like to buy a high performance keyboard. I sometimes code while I'm at the beach so it may get wet. \n",
         "Product Description:", embedding_text
       ) AS prompt,
     FROM products_with_embeddings
     WHERE embedding_vector IS NOT NULL
     ORDER BY COSINE_DISTANCE(
       embedding_vector,
       (
         SELECT embeddings.values
         FROM ML.PREDICT(
           MODEL EmbeddingsModel,
           (SELECT "I'd like to buy a high performance keyboard. I sometimes code while I'm at the beach so it may get wet." AS content)
         )
       )
     )
     LIMIT 5
   ),
   STRUCT(1056 AS maxOutputTokens)
);

Beklenen Çıkış: Yeni bir LLMResponse sütunu içeren bir tablo elde edersiniz. Yanıt şu şekilde olmalıdır: "Hayır. Bunun nedeni: * "Suya dayanıklı" ile "su geçirmez" aynı şey değildir. "Suya dayanıklı" bir klavye, sıçramalara, hafif yağmura veya dökülen sıvılara karşı dayanıklıdır.

11. 8. adım: Mülk grafiği oluşturun

Şimdi de farklı bir öneri türüne bakalım: "Bu ürünü satın alan müşteriler şunları da satın aldı..."

Bu, ilişkiye dayalı bir sorgudur. Bu amaç için ideal araç özellik grafiğidir. Spanner, verileri kopyalamadan mevcut tablolarınızın üzerinde grafik oluşturmanıza olanak tanır.

Bu DDL ifadesi grafiğimizi tanımlar:

  • Düğümler: Product ve User tabloları. Düğümler, ilişki oluşturmak istediğiniz öğelerdir. Örneğin, ürününüzü satın alan müşterilerin "XYZ" ürünlerini de satın alıp almadığını öğrenmek isteyebilirsiniz.
  • Kenarlar: Bir User (Kaynak) öğesini "Satın alındı" etiketiyle bir Product (Hedef) öğesine bağlayan Orders tablosu. Kenarlar, kullanıcı ile satın aldığı ürün arasındaki ilişkiyi gösterir.
CREATE PROPERTY GRAPH RetailGraph
 NODE TABLES (
   products_with_embeddings,
   Orders
 )
 EDGE TABLES (
   OrderItems
     SOURCE KEY (OrderID) REFERENCES Orders
     DESTINATION KEY (ProductID) REFERENCES products_with_embeddings
     LABEL Purchased
 );

12. 9. adım: Vector Search ve grafik sorgularını birleştirin

Bu en etkili adımdır. İlgili ürünleri bulmak için yapay zeka Vector Search ve grafik sorgularını tek bir ifadede birleştiririz.

Bu sorgu, NEXT statement ile ayrılmış üç bölüm halinde okunur. Şimdi bunu bölümlere ayıralım.

  1. Öncelikle vektör arama kullanarak en iyi eşleşmeyi buluruz.
  2. ML.PREDICT, EmbeddingsModel'i kullanarak kullanıcının metin sorgusundan vektör yerleştirme oluşturur.
  3. Sorgu, bu yeni yerleştirme ile tüm ürünler için depolanan p.embedding_vector arasındaki COSINE_DISTANCE değerini hesaplar.
  4. En kısa mesafeye (en yüksek semantik benzerlik) sahip tek bir bestMatch ürününü seçip döndürür.
  5. Ardından, ilişkileri bulmak için grafikte ilerleriz.

NEXT MATCH (bestMatch)<-[:Purchased]-(user:Orders)-[:Purchased]->(purchasedWith:products_with_embeddings)

  1. Sorgu, bestMatch'ten ortak Orders düğümlerine (kullanıcı) geri, ardından da purchasedWith ile satın alınan diğer ürünlere doğru izlenir.
  2. Orijinal ürünü filtreler ve öğelerin birlikte satın alınma sıklığını toplamak için GROUP BY ve COUNT(1) işlevlerini kullanır.
  3. Birlikte satın alınma sıklığına göre sıralanmış, birlikte satın alınan en popüler 3 ürünü (purchasedWith) döndürür.

Ayrıca, Kullanıcı Sipariş İlişkisi'ni de buluruz.

NEXT MATCH (bestMatch)<-[:Purchased]-(user:Orders)-[purchased:Purchased]->(purchasedWith)

  1. Bu ara adım, anahtar öğeleri (bestMatch, bağlanan kullanıcı:Siparişler düğümü ve purchasedWith öğesi) bağlamak için geçiş modelini yürütür.
  2. Bu işlev, özellikle bir sonraki adımda veri ayıklama için ilişkinin kendisini satın alınmış olarak bağlar.
  3. Bu kalıp, siparişe ve ürüne özel ayrıntıların getirilmesi için bağlamın oluşturulmasını sağlar.
  4. Son olarak, döndürülecek sonuçları çıkış olarak veriyoruz. Grafik düğümleri olarak döndürülecek sonuçlar, SQL sonuçları olarak döndürülmeden önce biçimlendirilmelidir.
GRAPH RetailGraph
MATCH (p:products_with_embeddings)
WHERE p.embedding_vector IS NOT NULL
RETURN p AS bestMatch
ORDER BY COSINE_DISTANCE(
 p.embedding_vector,
 (
   SELECT embeddings.values
   FROM ML.PREDICT(
     MODEL EmbeddingsModel,
     (SELECT "I'd like to buy a high performance keyboard. I sometimes code while I'm at the beach so it may get wet." AS content)
   )
 )
)
LIMIT 1

NEXT
MATCH (bestMatch)<-[:Purchased]-(user:Orders)-[:Purchased]->(purchasedWith:products_with_embeddings)
FILTER bestMatch.productId <> purchasedWith.productId
RETURN bestMatch, purchasedWith
GROUP BY bestMatch, purchasedWith
ORDER BY COUNT(1) DESC
LIMIT 3

NEXT
MATCH (bestMatch)<-[:Purchased]-(user:Orders)-[purchased:Purchased]->(purchasedWith)
RETURN
 TO_JSON(Purchased) AS purchased,
 TO_JSON(user.OrderID) AS user,
 TO_JSON(purchasedWith.productId) AS purchasedWith;

Beklenen Çıkış: Çapraz satış önerileri sunan, birlikte satın alınan ilk 3 öğeyi temsil eden JSON nesnelerini görürsünüz.

13. Temizleme

Ücretlendirilmemek için oluşturduğunuz kaynakları silebilirsiniz.

  1. Spanner örneğini silin: Örneği sildiğinizde veritabanı da silinir.
gcloud spanner instances delete my-first-spanner --quiet
  1. Google Cloud projesini silme: Bu projeyi yalnızca codelab için oluşturduysanız temizlik yapmanın en kolay yolu projeyi silmektir.
  • Google Cloud Console'da Kaynakları yönetin sayfasına gidin.
  • Projenizi seçin ve Sil'i tıklayın.

🎉 Tebrikler!

Spanner AI ve Graph'ı kullanarak gelişmiş ve gerçek zamanlı bir öneri sistemi oluşturmayı başarıyla tamamladınız.

Yerleştirilmiş öğeler ve LLM oluşturma için Spanner'ı Vertex AI ile entegre etmeyi, semantik olarak alakalı ürünleri bulmak için yüksek hızlı vektör araması (KNN ve ANN) yapmayı ve ürün ilişkilerini keşfetmek için grafik sorgularını kullanmayı öğrendiniz. Tek bir ölçeklenebilir veritabanından ürünleri bulmanın yanı sıra önerileri açıklayabilen ve ilgili öğeleri önerebilen bir sistem oluşturdunuz.