Xây dựng ứng dụng đề xuất 360 độ về khách hàng bằng BigQuery Graph

1. Giới thiệu

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách sử dụng BigQuery Graph để xây dựng chân dung khách hàng 360 độ và một công cụ đề xuất cho Cymbal Pets, một công ty bán lẻ giả định. Bạn sẽ khai thác sức mạnh của SQL để tạo, truy vấn và phân tích dữ liệu đồ thị ngay trong BigQuery, kết hợp dữ liệu đó với tính năng tìm kiếm vectơ để đưa ra các đề xuất sản phẩm nâng cao.

BigQuery Graph cho phép bạn mô hình hoá mối quan hệ giữa các thực thể dữ liệu (chẳng hạn như khách hàng, sản phẩm và đơn đặt hàng) dưới dạng đồ thị, giúp bạn dễ dàng trả lời các câu hỏi phức tạp về hành vi của khách hàng và mối quan hệ thân thiết với sản phẩm.

Biểu đồ trường hợp sử dụng

Bạn sẽ thực hiện

  • Tạo tập dữ liệu và giản đồ BigQuery cho biểu đồ Cymbal Pets
  • Tải dữ liệu mẫu (Khách hàng, Sản phẩm, Đơn đặt hàng, Cửa hàng) từ Cloud Storage
  • Tạo Biểu đồ tài sản trong BigQuery để kết nối các thực thể này
  • Trực quan hoá nhật ký mua hàng của khách hàng bằng cách sử dụng truy vấn đồ thị
  • Xây dựng hệ thống đề xuất sản phẩm bằng tính năng tìm kiếm vectơ
  • Nâng cao đề xuất bằng cách sử dụng mối quan hệ trong biểu đồ "Mua cùng nhau" và độ tương đồng Jaccard

Bạn cần có

  • Một trình duyệt web như Chrome
  • Một dự án trên Google Cloud đã bật tính năng thanh toán

Lớp học lập trình này dành cho nhà phát triển ở mọi cấp độ, kể cả người mới bắt đầu.

2. Trước khi bắt đầu

Tạo một dự án trên Google Cloud

  1. Trong Google Cloud Console, hãy chọn hoặc tạo một dự án trên Google Cloud.
  2. Đảm bảo rằng bạn đã bật tính năng thanh toán cho dự án trên Cloud.

Khởi động Cloud Shell

  1. Nhấp vào Kích hoạt Cloud Shell ở đầu bảng điều khiển Google Cloud.
  2. Xác minh hoạt động xác thực:
gcloud auth list
  1. Xác nhận dự án của bạn:
gcloud config get project
  1. Đặt nếu cần:
export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID

Bật API

Chạy lệnh này để bật BigQuery API bắt buộc:

gcloud services enable bigquery.googleapis.com

3. Xác định giản đồ

Trước tiên, bạn cần tạo một tập dữ liệu để lưu trữ các bảng liên quan đến biểu đồ và xác định giản đồ cho các nút và cạnh.

  1. Trong lớp học lập trình này, chúng ta sẽ thực thi các lệnh SQL. Bạn có thể chạy các lệnh này trong BigQuery Studio > Trình chỉnh sửa SQL hoặc sử dụng lệnh bq query trong Cloud Shell. Truy vấn SQL mớiChúng tôi giả định rằng bạn đang sử dụng Trình chỉnh sửa SQL của BigQuery để có trải nghiệm tốt hơn với các câu lệnh tạo nhiều dòng.
  2. Tạo tập dữ liệu cymbal_pets_demo:
CREATE SCHEMA IF NOT EXISTS cymbal_pets_demo;
  1. Tạo các bảng cho order_items, products, orders, stores, customersco_related_products_for_angelica. Các bảng này sẽ đóng vai trò là dữ liệu nguồn cho biểu đồ của chúng ta.
CREATE TABLE IF NOT EXISTS cymbal_pets_demo.order_items
(
  order_id INT64,
  product_id INT64,
  order_item_id INT64,
  quantity INT64,
  price FLOAT64,
  PRIMARY KEY (order_id, product_id, order_item_id) NOT ENFORCED
)
CLUSTER BY order_item_id;

CREATE TABLE IF NOT EXISTS cymbal_pets_demo.products
(
  product_id INT64,
  product_name STRING,
  brand STRING,
  category STRING,
  subcategory INT64,
  animal_type INT64,
  search_keywords INT64,
  price FLOAT64,
  description STRING,
  inventory_level INT64,
  supplier_id INT64,
  average_rating FLOAT64,
  uri STRING,
  embedding ARRAY<FLOAT64>,
  PRIMARY KEY (product_id) NOT ENFORCED
)
CLUSTER BY product_id;

CREATE TABLE IF NOT EXISTS cymbal_pets_demo.orders
(
  customer_id INT64,
  order_id INT64,
  shipping_address_city STRING,
  store_id INT64,
  order_date DATE,
  order_type STRING,
  payment_method STRING,
  PRIMARY KEY (order_id) NOT ENFORCED
)
PARTITION BY order_date
CLUSTER BY order_id;

CREATE TABLE IF NOT EXISTS cymbal_pets_demo.stores
(
  store_id INT64,
  store_name STRING,
  address_state STRING,
  address_city STRING,
  latitude FLOAT64,
  longitude FLOAT64,
  opening_hours STRUCT<Monday STRING, Tuesday STRING, Wednesday STRING, Thursday STRING, Friday STRING, Saturday STRING, Sunday STRING>,
  manager_id INT64,
  PRIMARY KEY (store_id) NOT ENFORCED
)
CLUSTER BY store_id;

CREATE TABLE IF NOT EXISTS cymbal_pets_demo.customers
(
  customer_id INT64,
  first_name STRING,
  last_name STRING,
  email STRING,
  gender STRING,
  address_city STRING,
  address_state STRING,
  loyalty_member BOOL,
  PRIMARY KEY (customer_id) NOT ENFORCED
)
CLUSTER BY customer_id;

CREATE TABLE IF NOT EXISTS cymbal_pets_demo.co_related_products_for_angelica
(
  angelica_product_id INT64,
  other_product_id INT64,
  co_purchase_count INT64,
  jaccard_similarity FLOAT64
);

Giờ đây, bạn đã xác định cấu trúc cho dữ liệu biểu đồ của mình.

4. Tải dữ liệu

Bây giờ, hãy điền dữ liệu mẫu vào các bảng từ Cloud Storage.

Chạy các câu lệnh LOAD DATA sau trong trình chỉnh sửa SQL của BigQuery:

LOAD DATA INTO `cymbal_pets_demo.customers`
FROM FILES (
    format = 'AVRO',
    uris = ['gs://sample-data-and-media/cymbal-pets/tables/customers/*.avro'],
    enable_logical_types = true
);

LOAD DATA INTO `cymbal_pets_demo.order_items`
FROM FILES (
    format = 'AVRO',
    uris = ['gs://sample-data-and-media/cymbal-pets/tables/order_items/*.avro'],
    enable_logical_types = true
);

LOAD DATA INTO `cymbal_pets_demo.orders`
FROM FILES (
    format = 'AVRO',
    uris = ['gs://sample-data-and-media/cymbal-pets/tables/orders/*.avro'],
    enable_logical_types = true
);

LOAD DATA INTO `cymbal_pets_demo.products`
FROM FILES (
    format = 'AVRO',
    uris = ['gs://sample-data-and-media/cymbal-pets/tables/products/*.avro'],
    enable_logical_types = true
);

LOAD DATA INTO `cymbal_pets_demo.stores`
FROM FILES (
    format = 'AVRO',
    uris = ['gs://sample-data-and-media/cymbal-pets/tables/stores/*.avro'],
    enable_logical_types = true
);

Bạn sẽ thấy thông báo xác nhận rằng các hàng đã được tải vào từng bảng.

5. Tạo biểu đồ thuộc tính

Sau khi tải dữ liệu, giờ đây, bạn có thể xác định biểu đồ thuộc tính. Thông tin này cho BigQuery biết bảng nào đại diện cho nút (các thực thể như Khách hàng, Sản phẩm) và bảng nào đại diện cho cạnh (các mối quan hệ như "Đã truy cập", "Đã đặt", "Có").

Giản đồ biểu đồ

Chạy câu lệnh DDL sau:

CREATE OR REPLACE PROPERTY GRAPH cymbal_pets_demo.PetsOrderGraph
NODE TABLES (
  cymbal_pets_demo.customers KEY(customer_id) LABEL Customer,
  cymbal_pets_demo.products KEY(product_id) LABEL Products,
  cymbal_pets_demo.stores KEY(store_id) LABEL Stores,
  cymbal_pets_demo.orders KEY(order_id) LABEL Orders
)
EDGE TABLES (
  cymbal_pets_demo.orders as customer_to_store_edge
    KEY (order_id)
    SOURCE KEY (customer_id) references customers(customer_id)
    DESTINATION KEY (store_id) references stores(store_id)
    LABEL Visited
    PROPERTIES ALL COLUMNS,

  cymbal_pets_demo.order_items
    KEY (order_item_id)
    SOURCE KEY (order_id) references orders(order_id)
    DESTINATION KEY (product_id) references products(product_id)
    LABEL Has
    PROPERTIES ALL COLUMNS,

  cymbal_pets_demo.orders as customer_to_orders_edge
    KEY (order_id)
    SOURCE KEY (customer_id) references customers(customer_id)
    DESTINATION KEY (order_id) references orders(order_id)
    LABEL Placed
    PROPERTIES ALL COLUMNS,

  cymbal_pets_demo.co_related_products_for_angelica
    KEY (angelica_product_id)
    SOURCE KEY (angelica_product_id) references products(product_id)
    DESTINATION KEY (other_product_id) references products(product_id)
    LABEL BoughtTogether
    PROPERTIES ALL COLUMNS
);

Thao tác này sẽ tạo ra biểu đồ PetsOrderGraph, cho phép chúng ta thực hiện các thao tác duyệt qua biểu đồ bằng cách sử dụng toán tử GRAPH_TABLE.

6. Trực quan hoá Nhật ký mua hàng của tất cả khách hàng

Mở Sổ tay mới trong BigQuery Studio.

Tạo sổ tay mới

Đối với các phần trực quan hoá và đề xuất của lớp học lập trình này, chúng ta sẽ sử dụng một sổ tay Google Colab trong BigQuery Studio. Nhờ đó, chúng ta có thể dễ dàng hình dung kết quả của biểu đồ.

Dán nội dung sau vào một ô chứa mã:

!pip install bigquery-magics==0.12.1

BigQuery Graph Notebook được triển khai dưới dạng IPython Magics. Bằng cách thêm lệnh %%bigquery (lệnh đặc biệt) bằng hàm TO_JSON, bạn có thể trực quan hoá kết quả như minh hoạ trong các phần sau.

Giả sử Cymbal Pets muốn có hình ảnh trực quan 360 độ về tất cả khách hàng và giao dịch mua mà họ đã thực hiện trong một khoảng thời gian cụ thể.

Chạy lệnh sau trong một ô mới:

%%bigquery --graph

GRAPH cymbal_pets_demo.PetsOrderGraph
  # finds the customer node and then finds all
  # the Orders nodes that are connected to that customer through the
  # Placed relationship
  MATCH (customer:Customer)-[placed:Placed]->(ordr:Orders)-[has:Has]->(product:Products)
  # filters the Orders nodes to only include those where the
  # order_date is within the last 3 months.
  WHERE ordr.order_date >= date('2024-11-27')
  # # This line finds all the Products nodes that are connected to the
  # # filtered Orders nodes through the Has relationship.
  MATCH p=(customer:Customer)-[placed:Placed]->(ordr:Orders)-[has:Has]->(product:Products)
  LIMIT 40
  RETURN 
    TO_JSON(p) as paths

Bạn sẽ thấy một bản trình bày trực quan về kết quả biểu đồ.

Nhật ký mua hàng của tất cả khách hàng

7. Hình dung nhật ký mua hàng của Angelica

Giả sử Cymbal Pets muốn tìm hiểu sâu về một khách hàng tên là Angelica Russell. Họ muốn phân tích những sản phẩm mà Angelica đã mua trong vòng 3 tháng qua và những cửa hàng mà khách hàng này đã ghé thăm.

%%bigquery --graph

GRAPH cymbal_pets_demo.PetsOrderGraph
  # finds the customer node with the name "Angelica Russell" and then finds all
  # the Orders nodes that are connected to that customer through the
  # Placed relationship and all the Products nodes that are connected to the
  # filtered Orders nodes through the Has relationship.
   MATCH p=(customer:Customer {first_name: 'Angelica', last_name: 'Russell'})-[placed:Placed]->(ordr:Orders)-[has:Has]->(product:Products)
  # filters the Orders nodes to only include those where the
  # order_date is within the last 3 months.
  WHERE ordr.order_date >= date('2024-11-27')
  # finds the Stores nodes where Angelica placed order from
  MATCH p2=(customer)-[visited:Visited]->(store:Stores)
  RETURN
    TO_JSON(p) as path, TO_JSON(p2) as path2

Nhật ký mua hàng của Angelica

8. Đề xuất về sản phẩm bằng tính năng tìm kiếm vectơ

Cymbal Pets muốn đề xuất sản phẩm cho Angelica dựa trên những gì cô ấy đã mua gần đây. Chúng ta có thể sử dụng tính năng tìm kiếm vectơ để tìm những sản phẩm có thông tin nhúng tương tự với các sản phẩm mà cô ấy đã mua trước đây.

Chạy tập lệnh SQL sau đây trong một ô Colab mới. Tập lệnh này:

  1. Xác định những sản phẩm mà Angelica đã mua gần đây.
  2. Sử dụng VECTOR_SEARCH để tìm 4 sản phẩm tương tự hàng đầu trong bảng products.

Lưu ý: Bước này giả định rằng bạn đã chạy AI.GENERATE_EMBEDDINGS để tạo một cột embeddings trong bảng sản phẩm.

%%bigquery
DECLARE products_bought_by_angelica ARRAY<INT64>;

-- 1. Get IDs of products bought by Angelica
SET products_bought_by_angelica = (
  SELECT ARRAY_AGG(product_id) FROM
   GRAPH_TABLE(
    cymbal_pets_demo.PetsOrderGraph
      MATCH (c:Customer {first_name: 'Angelica', last_name: 'Russell'})-[placed:Placed]->(o:Orders)
      WHERE o.order_date >= date('2024-11-27')
      MATCH (o)-[has_edge:Has]->(p:Products)
      RETURN DISTINCT p.product_id as product_id
  ));

-- 2. Find similar products using vector search
SELECT 
  query.product_name as AngelicaBought, 
  base.product_name as RecommendedProducts, 
  base.category
FROM
  VECTOR_SEARCH(
    TABLE cymbal_pets_demo.products,
    'embedding',
    (SELECT * FROM cymbal_pets_demo.products
     WHERE product_id IN UNNEST(products_bought_by_angelica)),
    'embedding',
    top_k => 4)
WHERE query.product_name <> base.product_name;

Bạn sẽ thấy một danh sách các sản phẩm được đề xuất có ý nghĩa tương tự như sản phẩm mà Angelica đã mua.

Kết quả tìm kiếm vectơ

9. Đề xuất sử dụng "Mua cùng nhau" và Độ tương đồng Jaccard

Một kỹ thuật đề xuất hiệu quả khác là "Lọc cộng tác" – đề xuất những sản phẩm mà những người dùng khác thường mua cùng nhau.

Chúng ta có thể tìm thấy những sản phẩm này bằng cách duyệt qua biểu đồ từ một khách hàng đến các sản phẩm mà họ đã mua, sau đó đến những khách hàng khác đã mua những sản phẩm đó và cuối cùng là đến những sản phẩm khác mà những khách hàng đó đã mua.

Khắc phục thiên kiến về mức độ phổ biến bằng độ tương đồng Jaccard

Mặc dù số lượng giao dịch mua chung thô rất hữu ích, nhưng số liệu này có thể thiên về các sản phẩm phổ biến. Một sản phẩm rất phổ biến có thể được mua kèm với nhiều thứ chỉ là ngẫu nhiên.

Độ tương đồng Jaccard giúp đề xuất hiệu quả hơn bằng cách chuẩn hoá số lượng giao dịch mua chung. Chỉ số này đo lường mức độ tương đồng giữa hai tập hợp (trong trường hợp này là tập hợp các đơn đặt hàng có chứa từng sản phẩm).

Công thức tính độ tương đồng Jaccard là:

Địa điểm:

  • A giao B là số đơn đặt hàng có cả sản phẩm A và sản phẩm B (số lượng đơn đặt hàng mua cùng).
  • A là tổng số đơn đặt hàng có chứa sản phẩm A.
  • B là tổng số đơn đặt hàng có chứa sản phẩm B.

Trong ví dụ sau, tập hợp A = {b,c,e,f,g}, tập hợp B = {a,d,b,g}, giao của chúng A⋂B = {b,g}, hợp của chúng A⋃B = {a,b,c,d,e,f,g}, do đó, độ tương đồng Jaccard giữa A và B là 2 / 7 = 0,285714

Tạo và sắp xếp lại đề xuất

Trong các hệ thống đề xuất thực tế hoạt động trên các tập dữ liệu khổng lồ, việc tính toán điểm số tương tự phức tạp (như Jaccard) cho tất cả các cặp sản phẩm có thể có thường là không thực tế. Thay vào đó, một mẫu hình phổ biến là sử dụng phương pháp gồm 2 giai đoạn:

  1. Đề xuất sản phẩm: Sử dụng một chỉ số đơn giản và nhanh chóng (chẳng hạn như số lượng giao dịch mua chung thô) để lọc không gian tìm kiếm và tìm một số lượng đề xuất có thể quản lý được (ví dụ: 10 sản phẩm hàng đầu).
  2. Xếp hạng lại: Áp dụng một chỉ số chính xác hơn nhưng đòi hỏi nhiều sức mạnh tính toán hơn (chẳng hạn như Jaccard Similarity) để xếp hạng nhóm nhỏ các đề xuất này và chọn ra các đề xuất hàng đầu cuối cùng.

Trong lớp học lập trình này, chúng ta sẽ làm theo mẫu sau:

  • Giai đoạn 1: Chạy một truy vấn để tìm 10 sản phẩm được mua cùng nhiều nhất cho từng sản phẩm, dựa trên số lượng sản phẩm được mua cùng chưa xử lý và lưu trữ các sản phẩm đó trong một bảng.
  • Giai đoạn 2: Sử dụng truy vấn biểu đồ để truy xuất các đề xuất này, xếp hạng theo mức độ tương đồng Jaccard và trả về 3 đề xuất hàng đầu.

[!WARNING] Nhược điểm: Bằng cách lọc theo số lượng thô ở Giai đoạn 1, chúng ta có thể mất "khả năng thu hồi" của các giao dịch mua chung có tần suất thấp nhưng rất cụ thể. Nếu một sản phẩm rất giống với một sản phẩm khác nhưng cả hai đều hiếm khi được mua, thì sản phẩm đó có thể không nằm trong số 10 sản phẩm đề xuất hàng đầu và sẽ bị bỏ lỡ.

Chạy truy vấn sau để tính cả số lượng đồng mua thô và độ tương đồng Jaccard, đồng thời lưu trữ 10 ứng viên hàng đầu theo số lượng thô:

%%bigquery
CREATE OR REPLACE TABLE cymbal_pets_demo.co_related_products_for_angelica AS
-- Calculate the total number of orders for each product
WITH ProductOrderCounts AS (
    SELECT product_id, COUNT(DISTINCT order_id) as total_count
    FROM cymbal_pets_demo.order_items
    GROUP BY product_id
),
-- Calculate the intersection of each product pairs
CoPurchases AS (
    SELECT
        angelicaProduct.product_id AS angelica_product_id,
        otherProduct.product_id AS other_product_id,
        count(DISTINCT otherOrder.order_id) AS co_purchase_count
    FROM
        GRAPH_TABLE (cymbal_pets_demo.PetsOrderGraph
          MATCH (angelica:Customer {first_name: 'Angelica', last_name: 'Russell'})-[:Placed]->(o:Orders)-[:Has]->(angelicaProduct:Products)
          WHERE o.order_date >= date('2024-11-27')
          WITH angelica, angelicaProduct
          MATCH (otherCustomer:Customer)-[:Placed]->(otherOrder:Orders)-[:Has]->(angelicaProduct)
          WHERE otherCustomer <> angelica
          WITH angelicaProduct, otherOrder
          MATCH (otherOrder)-[:HAS]->(otherProduct:Products)
          WHERE angelicaProduct <> otherProduct
          RETURN angelicaProduct, otherProduct, otherOrder
        )
    GROUP BY
        angelicaProduct.product_id, otherProduct.product_id
)
SELECT * FROM (
    SELECT
        cp.angelica_product_id,
        cp.other_product_id,
        cp.co_purchase_count,
        -- The Jaccard calculation, which is the intersection of A and B divided by (A + B - intersection)
        SAFE_DIVIDE(cp.co_purchase_count, (poc1.total_count + poc2.total_count - cp.co_purchase_count)) AS jaccard_similarity,
        ROW_NUMBER() OVER (PARTITION BY cp.angelica_product_id ORDER BY cp.co_purchase_count DESC) AS rn
    FROM CoPurchases cp
    JOIN ProductOrderCounts poc1 ON cp.angelica_product_id = poc1.product_id
    JOIN ProductOrderCounts poc2 ON cp.other_product_id = poc2.product_id
)
WHERE rn <= 10;

Logic đề xuất

Chạy truy vấn này để đề xuất 3 sản phẩm hàng đầu cho mỗi giao dịch mua của Angelica, được kết nối trực tiếp thông qua cạnh BoughtTogether, cho thấy cả số lượng giao dịch mua chung và mức độ tương đồng Jaccard:

%%bigquery
SELECT * FROM GRAPH_TABLE(
  cymbal_pets_demo.PetsOrderGraph
  MATCH (customer:Customer {first_name: 'Angelica', last_name: 'Russell'})-[placed:Placed]->(ordr:Orders)
  WHERE ordr.order_date >= date('2024-11-27')
  MATCH (ordr)-[has:Has]->(product:Products)
  MATCH (product)-[bought_together:BoughtTogether]->(recommended_product:Products)
  RETURN 
    product.product_name AS OriginalProduct,
    recommended_product.product_name AS Recommended,
    bought_together.co_purchase_count AS Strength,
    bought_together.jaccard_similarity AS JaccardSimilarity
)
-- Rank product recommendations by Jaccard Similarity
QUALIFY ROW_NUMBER() OVER (PARTITION BY OriginalProduct ORDER BY JaccardSimilarity DESC) <= 3
ORDER BY OriginalProduct;

Truy vấn này đi từ Khách hàng -> Đơn đặt hàng -> Sản phẩm -> (BoughtTogether) -> Sản phẩm được đề xuất, cho bạn thấy các đề xuất dựa trên hành vi mua hàng tập thể và truy xuất điểm số tương đồng của các sản phẩm đó.

Mua cùng nhau

10. Dọn dẹp

Để tránh các khoản phí phát sinh cho tài khoản Google Cloud của bạn, hãy xoá các tài nguyên đã tạo trong lớp học lập trình này.

Xoá tập dữ liệu và tất cả các bảng:

DROP SCHEMA IF EXISTS cymbal_pets_demo CASCADE;

Nếu đã tạo một dự án mới cho lớp học lập trình này, bạn cũng có thể xoá dự án đó:

gcloud projects delete $PROJECT_ID

11. Xin chúc mừng

Xin chúc mừng! Bạn đã xây dựng thành công chân dung khách hàng 360 độ và công cụ đề xuất bằng BigQuery Graph.

Kiến thức bạn học được

  • Cách tạo biểu đồ thuộc tính trong BigQuery.
  • Cách tải dữ liệu vào các nút và cạnh của biểu đồ.
  • Cách truy vấn các mẫu đồ thị bằng cách sử dụng GRAPH_TABLEMATCH.
  • Cách kết hợp các truy vấn đồ thị với tính năng tìm kiếm vectơ để đưa ra đề xuất kết hợp.

Các bước tiếp theo