使用Weaviate和Gemini API实现个性化描述生成

本教程面向有编程基础的开发者,讲解如何用 Weaviate 向量数据库与 Gemini API 构建个性化商品描述生成系统。内容涵盖 Weaviate 集群连接、Schema 定义、数据批量导入、向量搜索与混合搜索、autocut 与筛选器、生成式反馈循环,以及通过交叉引用构建 Products、Personas、Personalized 三集合知识图谱。读者将掌握嵌入、语义检索、LLM 生成回写与用户画像定制的完整工程链路,并了解常见错误与生产优化方向。

技术背景

传统电商商品描述依赖人工撰写或模板填充,难以规模化且缺乏个性化。向量数据库让语义检索成为可能,而大语言模型能基于商品图片与文本生成自然语言描述。Weaviate 作为开源向量数据库,内置 text2vec-palm 与 generative-palm 模块,可直接对接 Gemini API,把嵌入、检索、生成、回写整合到同一数据层。该方案适用于电商推荐、广告文案生成、知识图谱构建等场景。主要限制在于需要付费层级的 Gemini API 速率限制,Embedded 模式停止终端即断开,且生成质量受提示词与模型版本影响。

核心原理

核心原理是向量化与语义相似度检索。Weaviate 在写入对象时调用 text-embedding-004 生成向量并存储,查询时用 near_text 将查询文本向量化后做近邻搜索。混合搜索结合 BM25 关键词与向量相似度,通过 alpha 参数调节权重。autocut 依据结果分数显著跳变自动截断,避免硬编码 limit。生成式反馈循环指把 Gemini 生成的描述写回 generated_description 属性,使其可被再次检索。个性化阶段通过交叉引用把 Personalized 集合同时指向 Products 与 Personas,形成有向知识图谱,再用 Gemini 结合商品描述与画像描述生成定制文案。

架构分析

系统由三层组成:数据层为 Weaviate 集群,包含 Products、Personas、Personalized 三个集合,每个集合配置向量化器与生成模块;模型层为 Gemini API,提供 text-embedding-004 嵌入与 gemini-3.8-flash 生成能力;应用层为 Python 客户端,负责批量导入、查询、生成与回写。关键设计决策包括:用 Embedded 模式降低实验门槛,用 batch.dynamic 提升导入吞吐,用 autocut 替代固定 limit 提升召回质量,用交叉引用而非冗余字段维护实体关系,用生成式反馈循环让 LLM 输出成为可检索资产。

完整实战教程

##### 版权所有 2026 Google LLC。

# @title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

使用 Weaviate 和 Gemini API 实现个性化产品描述

注意: 本笔记本需要付费层级的速率限制才能正常运行。(更多详情请参阅定价)。

Weaviate 是一个开源向量数据库,可让您使用 Gemini API 构建 AI 驱动的应用程序!本笔记本包含四个部分:

  1. 第 1 部分:连接到 Weaviate、定义 Schema 并导入数据
  1. 第 2 部分:运行向量搜索查询
  1. 第 3 部分:生成式反馈循环
  1. 第 4 部分:个性化产品描述

在本演示中,您将学习如何嵌入数据、运行语义搜索、向 Gemini API 发起生成式调用并将输出存储到向量数据库中,以及根据用户画像个性化描述。

用例

您将使用一个包含 Google 周边商品的电子商务数据集。您将把数据加载到 Weaviate 向量数据库中,并使用语义搜索功能检索数据。接下来,您将生成产品描述,并将其连同向量嵌入一起存回数据库以供检索(即生成式反馈循环)。最后,您将为买家画像 Alice 和 Bob 创建一个包含独特生成产品描述的小型知识图谱。

要求

您需要一个正在运行的 Weaviate 集群和 Gemini API 密钥。您将在完成本笔记本的过程中设置这些要求!

  1. Weaviate 向量数据库
  2. 无服务器
  3. 嵌入式
  4. 本地(Docker)
  5. Gemini API 密钥
  6. 通过 AI Studio 创建 API 密钥

视频

如需观看本演示的精彩讲解,请查看来自 Google Cloud Next 的这个演讲!

From RAG to autonomous apps with Weaviate and Gemini API on Google Kubernetes Engine

安装依赖项和库

%pip install weaviate-client==4.7.1
%pip install -U -q "google-genai>=2.9.0"
%pip install requests
%pip install 'protobuf>=5'
import weaviate
from weaviate.classes.config import Configure
from weaviate.embedded import EmbeddedOptions
import weaviate.classes as wvc
from weaviate.classes.config import Property, DataType, ReferenceProperty
from weaviate.util import generate_uuid5
from weaviate.classes.query import QueryReference

import os
import json
import requests
import PIL
import IPython

from PIL import Image
from io import BytesIO
from IPython.display import Markdown

# Convert image links to PIL object
def url_to_pil(url):
    response = requests.get(url)
    return Image.open(BytesIO(response.content))

# display images
def display_image(url, size=100):
    response = requests.get(url)
    image_data = BytesIO(response.content)
    image = Image.open(image_data)

    resized_image = image.resize((size,size))

    display(resized_image)

第 1 部分:连接到 Weaviate、定义 Schema 并导入数据

连接到 Weaviate

你需要创建一个 Weaviate 集群。有几种方法可以实现:

  1. Weaviate Embedded:在你的运行时中运行 Weaviate
  1. Weaviate Cloud:在我们的托管服务上创建一个沙盒。你需要将其部署在美国西部、美国东部或澳大利亚。
  1. 本地主机:Docker 或 Kubernetes

完整的安装选项列表,请参见此页面。

Weaviate Embedded

你将默认使用 Weaviate Embedded。它会在你的 notebook 中运行 Weaviate,非常适合快速实验。

注意:一旦你停止终端,它就会断开连接。

设置你的 API 密钥

要运行以下单元格,你的 Gemini API 密钥必须存储在 Colab Secret 中,并命名为 GEMINI_API_KEY。如果你还没有 API 密钥,或者不确定如何创建 Colab Secret,请参阅 Authentication 快速入门以获取示例。

from google import genai
from google.colab import userdata

GEMINI_API_KEY = userdata.get("GEMINI_API_KEY")
gemini_client = genai.Client(api_key=GEMINI_API_KEY)
client = weaviate.WeaviateClient(
    embedded_options=EmbeddedOptions(
        version="1.25.10",
        additional_env_vars={
            "ENABLE_MODULES": "text2vec-palm, generative-palm"
        }),
        additional_headers={
            "X-Google-Studio-Api-Key": GEMINI_API_KEY
        }
)

client.connect()

其他选项:Weaviate Cloud 和本地主机

Weaviate Cloud

你可以将 notebook 连接到无服务器 Weaviate 集群,以便将数据持久保存在云端。你可以在此处注册并创建一个免费的 14 天沙盒!

要连接到你的 WCD 集群:

WCD_URL = "https://sandbox.gcp.weaviate.cloud"
WCD_AUTH_KEY = "sk-key"
GEMINI_API_KEY = "sk-key"

client = weaviate.connect_to_wcs(
    cluster_url=WCD_URL,
    auth_credentials=weaviate.auth.AuthApiKey(WCD_AUTH_KEY),
    headers={"X-Google-Studio-Api-Key": GEMINI_API_KEY},
)

print(client.is_ready())

本地主机

如果你想自己运行 Weaviate,可以下载 Docker 文件,并在本地机器或云端运行。此文件夹中还有一个 yaml 文件可供使用。

要连接到本地的 Weaviate:

client = weaviate.connect_to_local()

print(client.is_ready())

创建 schema

schema 告诉 Weaviate 你希望如何存储数据。

你首先需要创建两个集合:Products 和 Personas。每个集合都有元数据(属性),并指定嵌入模型和语言模型。

在第 4 部分中,你将创建另一个集合 Personalized,它会根据 persona 生成产品描述。

# This is optional to empty your database
result = client.collections.delete("Products")
print(result)
result = client.collections.delete("Personas")
print(result)
PROJECT_ID = "" # leave this empty
API_ENDPOINT = "generativelanguage.googleapis.com"
embedding_model = "text-embedding-004" # embedding model
generative_model = "gemini-3.8-flash" # language model

# Products Collection
if not client.collections.exists("Products"):
  collection = client.collections.create(
    name="Products",
    vectorizer_config=Configure.Vectorizer.text2vec_palm
    (
        project_id=PROJECT_ID,
        api_endpoint=API_ENDPOINT,
        model_id = embedding_model
    ),
    generative_config=Configure.Generative.palm(
        project_id=PROJECT_ID,
        api_endpoint=API_ENDPOINT,
        model_id = generative_model
    ),
    properties=[ # properties for the Products collection
            Property(name="product_id", data_type=DataType.TEXT),
            Property(name="title", data_type=DataType.TEXT),
            Property(name="category", data_type=DataType.TEXT),
            Property(name="link", data_type=DataType.TEXT),
            Property(name="description", data_type=DataType.TEXT),
            Property(name="brand", data_type=DataType.TEXT),
            Property(name="generated_description", data_type=DataType.TEXT),
      ]
  )

# Personas Collection
if not client.collections.exists("Personas"):
  collection = client.collections.create(
    name="Personas",
    vectorizer_config=Configure.Vectorizer.text2vec_palm
    (
        project_id=PROJECT_ID,
        api_endpoint=API_ENDPOINT,
        model_id = embedding_model
    ),
    generative_config=Configure.Generative.palm(
        project_id=PROJECT_ID,
        api_endpoint=API_ENDPOINT,
        model_id = generative_model
    ),
    properties=[ # properties for the Personas collection
            Property(name="name", data_type=DataType.TEXT),
            Property(name="description", data_type=DataType.TEXT),
      ]
  )

导入对象

# URL to the raw JSON file
url = 'https://raw.githubusercontent.com/bkauf/next-store/main/first_99_objects.json'
response = requests.get(url)

# Load the entire JSON content
data = json.loads(response.text)
# Print first object
data[0]

上传到 Weaviate

为确保一切就绪,你将只上传一个对象并确认它已在数据库中。

products = client.collections.get("Products")

first_object = data[0]

products.data.insert(
    properties={
        "product_id": first_object['product_id'],
        "title": first_object['title'],
        "category": first_object['category'],
        "link": first_object['link'],
        "description": first_object['description'],
        "brand": first_object['brand']
    }
)

response = products.aggregate.over_all(total_count=True)
print(response.total_count) # This should output 1

让我们导入数据集的剩余部分。你将使用 Weaviate 的批量导入功能将这 98 个对象导入到我们的数据库中。

products = client.collections.get("Products")

remaining_data = data[1:]

with products.batch.dynamic() as batch:
  for item in remaining_data:
    batch.add_object(
      properties={
        "product_id": item['product_id'],
        "title": item['title'],
        "category": item['category'],
        "link": item['link'],
        "description": item['description'],
        "brand": item['brand']
    }
  )

response = products.aggregate.over_all(total_count=True)
print(response.total_count) # this should print 99
# print the first object uuid and properties to analyze how data is structured
first_product = next(products.iterator())
print(first_product.uuid,"\n", json.dumps(first_product.properties, indent=4))

你将通过创建的 UUID 来获取该对象。它还会打印出向量嵌入!

product = products.query.fetch_object_by_id(
    first_product.uuid,
    include_vector=True
)

print(f"Product: {product.properties['title']}")
print(f"Vector Dimensionality: {len(product.vector['default'])}")
print(f"Vector Preview: {product.vector['default'][:50]} ...")

第 2 部分:向量搜索

向量搜索

向量搜索返回与查询向量最相似的对象。你将使用 near_text 操作符来查找与输入文本向量最接近的对象。

products = client.collections.get("Products")

response = products.query.near_text(
        query="travel mug",
        return_properties=["title", "description", "link"], # only return these 3 properties
        limit=3 # limited to 3 objects
)

for product in response.objects:
    print(json.dumps(product.properties, indent=2))
    display_image(product.properties['link'])
    print('===')

Notebook output

Notebook output

Notebook output

混合搜索

混合搜索将关键词(BM25)搜索与向量搜索结合在一起,让你兼得两种算法的优势。

要在 Weaviate 中使用混合搜索,你只需定义 alpha 参数来确定权重。

alpha = 0 --> 纯 BM25

alpha = 0.5 --> 一半 BM25,一半向量搜索

alpha = 1 --> 纯向量搜索

products = client.collections.get("Products")

response = products.query.hybrid(
    query = "dishwasher safe container", # query
    alpha = 0.75, # leaning more towards vector search
    return_properties=["title", "description", "link"], # return these 3 properties
    limit = 3 # limited to only 3 objects
)

for product in response.objects:
    print(json.dumps(product.properties, indent=2))
    display_image(product.properties['link'])
    print('===')

Notebook output

Notebook output

Notebook output

Autocut

与硬编码对象数量限制(见上文)不同,可以使用 autocut 功能来截断结果集。Autocut 根据结果集指标(如向量距离或分数)的显著变化来限制返回的结果数量。

要使用 autocut,必须指定 auto_limit 参数,该参数将在达到指定数量的变化或“跳跃”后停止返回结果。

你将使用与上述相同的混合搜索查询,但使用 auto_limit 而不是 limit。注意,在这种情况下实际上检索到了 4 个对象,而之前的查询返回了 3 个对象。

# auto_limit set to 1

products = client.collections.get("Products")

response = products.query.hybrid(
    query = "dishwasher safe container", # query
    alpha = 0.75, # leaning more towards vector search
    return_properties=["title", "description", "link"], # return these 3 properties
    auto_limit = 1 # autocut after 1 jump
)

for product in response.objects:
    print(json.dumps(product.properties, indent=2))
    display_image(product.properties['link'])
    print('===')

Notebook output

筛选器

通过向查询添加筛选器来缩小结果范围。

查找 category 等于 drinkware 的对象。

products = client.collections.get("Products")

response = products.query.near_text(
    query="travel cup",
    return_properties=["title", "description", "category", "link"], # returned properties
    filters=wvc.query.Filter.by_property("category").equal("Drinkware"), # filter
    limit=3, # limit to 3 objects
)

for product in response.objects:
    print(json.dumps(product.properties, indent=2))
    display_image(product.properties['link'])
    print('===')

Notebook output

Notebook output

Notebook output

第 3 部分:生成式反馈循环

生成式反馈循环 指的是将语言模型的输出存回数据库的过程。

你将使用 Gemini API 为数据库中的每个产品生成描述,并将其保存到 Products 集合中的 generated_description 属性。

连接并配置 Gemini API 模型

请确保您已初始化 Gemini 客户端。请确认此步骤已在第 1 部分中完成。

生成描述并将其存储到 Products 集合中

以下单元格的步骤:

  1. 运行向量搜索查询以查找旅行夹克
  2. * 在此处了解有关 autocut(auto_limit)的更多信息。

  1. 获取返回的对象,将任务和图像提示给 Gemini API,并将描述存储到 generated_description 属性中
response = products.query.near_text( # first find travel jackets
    query="travel jacket",
    return_properties=["title", "description", "category", "link"],
    auto_limit=1, # limit it to 1 close group
)

for product in response.objects:
    if "link" in product.properties:
        id = product.uuid
        img_url = product.properties["link"]

        pil_image = url_to_pil(img_url) # convert image to PIL object
        generated_description = gemini_client.models.generate_content(
            model="gemini-3.8-flash",
            contents=[
                "Write a short Facebook ad about this product photo.",
                pil_image
            ]
        ) # prompt to the Gemini API
        generated_description = generated_description.text
        display_image(product.properties['link'])
        print(generated_description)
        print('===')

        # Update the Product collection with the generated description
        products.data.update(
            uuid=id,
            properties={"generated_description": generated_description}
        )

Notebook output

Notebook output

Notebook output

Notebook output

Notebook output

Notebook output

Notebook output

在 generated_description 属性上进行向量搜索

由于产品描述已保存在我们的 Products 集合中,你可以对其运行向量搜索查询。

products = client.collections.get("Products")

response = products.query.near_text(
        query="travel jacket",
        return_properties=["generated_description", "description", "title"],
        limit=1
    )

for o in response.objects:
    print(o.uuid)
    print(json.dumps(o.properties, indent=2))

第 4 部分:个性化

到目前为止,你已经使用 gemini-3.7-flash 模型通过 Gemini API 生成了产品描述。在第 4 部分中,你将生成针对用户画像量身定制的产品描述。

你将使用交叉引用来建立 Products 和 Personas 集合之间的有向关系。

result = client.collections.delete("Personalized")
print(result)
PROJECT_ID = "" # leave this empty
API_ENDPOINT = "generativelanguage.googleapis.com"
embedding_model = "text-embedding-004" # embedding model
generative_model = "gemini-3.8-flash"

# Personalized Collection

if not client.collections.exists("Personalized"):
  collection = client.collections.create(
    name="Personalized",
    vectorizer_config=Configure.Vectorizer.text2vec_palm(
        project_id=PROJECT_ID,
        api_endpoint=API_ENDPOINT,
        model_id = embedding_model
    ),
    generative_config=Configure.Generative.palm(
        project_id=PROJECT_ID,
        api_endpoint=API_ENDPOINT,
        model_id = generative_model
    ),
    properties=[
            Property(name="description", data_type=DataType.TEXT),
    ],
    # cross-references
    references=[
        ReferenceProperty(
            name="ofProduct",
            target_collection="Products" # connect personalized to the products collection
        ),
        ReferenceProperty(
            name="ofPersona",
            target_collection="Personas" # connect personalized to the personas collection
        )
    ]
)

创建两个角色(Alice 和 Bob)

personas = client.collections.get("Personas")

for persona in ['Alice', 'Bob']:
  generated_description = gemini_client.models.generate_content(
      model="gemini-3.8-flash",
      contents=[
          "Create a fictional buyer persona named "
          + persona + ", write a short description about them"
      ]
  ) # use gemini-3.7-flash to generate persona description
  uuid = personas.data.insert({
    "name": persona,
    "description": generated_description.text
  })
  print(uuid)
  print(generated_description.text)
  print("===")
# print objects in the Personas collection

personas = client.collections.get("Personas")

for persona in personas.iterator():
    print(persona.uuid, persona.properties)

为人物画像生成定制化的产品描述

从第 1 部分获取产品 uuid 并粘贴到下方

personalized = client.collections.get("Personalized")

product = products.query.fetch_object_by_id(product.uuid)
display_image(product.properties['link'])

personas = client.collections.get("Personas")

for persona in personas.iterator():
    generated_description = gemini_client.models.generate_content(
        model="gemini-3.8-flash",
        contents=[
            """
              Create a product description tailored to the following person,
              make sure to use the name (
            """,
            persona.properties["name"],") of the persona.\n\n",
            "# Product Description\n",
            product.properties["description"], "# Persona",
            persona.properties["description"]]
    ) # generate a description tailored to the persona
    print(generated_description.text)
    print('====')
    # Add the personalized description to the `description` property in the Personalized collection
    new_uuid = personalized.data.insert(
        properties={
            "description": generated_description.text },
        references={
            "ofProduct": product.uuid, # add cross-reference to the Product collection
            "ofPersona": persona.uuid # add cross-reference to the Persona collection
        },
    )

Notebook output

获取 Personalized 集合中的对象

personalized = client.collections.get("Personalized")

response = personalized.query.fetch_objects(
    limit=2,
    return_references=[QueryReference(
            link_on="ofProduct", # return the title property from the Product collection
            return_properties=["title", "link"]
        ),
        QueryReference(
            link_on="ofPersona",
            return_properties=["name"] # return the name property from the Persona collection
        )
    ]
)

for item in response.objects:
    print(item.properties)
    for ref_obj in item.references["ofProduct"].objects:
        print(ref_obj.properties)
    for ref_obj in item.references["ofPersona"].objects:
        print(ref_obj.properties)
    display_image(product.properties['link'])
    print("===")

Notebook output

Notebook output

笔记本回顾

在本笔记本中,你学习了如何:

  1. 使用 Embedded 创建 Weaviate 集群
  2. 定义 Weaviate schema 并选择嵌入模型和生成模型
  3. 连接到 Gemini API
  4. 执行带过滤和 autocut 的向量搜索和混合搜索
  5. 使用生成反馈循环(Generative Feedback Loops)将语言模型的输出存回数据库,以供将来检索
  6. 使用交叉引用(cross-references)在集合之间建立关系

你可以通过我们的文档进一步了解 Weaviate,并且可以在这里找到更多 Weaviate 和 Google 的 cookbook!

作者:Erika Cardenas 和 Bob Van Luijt

欢迎与我们联系,如有任何问题请告诉我们!

Erika 的账号:

* 在 X 上关注

* 在 LinkedIn 上联系

Bob 的账号:

* 在 X 上关注

* 在 LinkedIn 上联系

常见问题

常见错误包括:GEMINI_API_KEY 未存入 Colab Secret 导致认证失败;Weaviate Embedded 版本与模块名不匹配导致连接异常;批量导入时未等待完成就查询导致计数不符;near_text 返回空结果通常是嵌入模型未正确配置;交叉引用查询时未指定 return_references 导致引用为空。排查方法:先用 client.is_ready() 确认连接,用 aggregate.over_all(total_count=True) 校验数据量,用 fetch_object_by_id(include_vector=True) 检查向量维度。生产环境建议改用 Weaviate Cloud 或 Docker 持久化,增加重试与限流,对生成结果做缓存与人工审核,并监控 API 配额。

企业应用扩展

可扩展方向包括:引入多模态嵌入对商品图片直接向量化;用 RAG 将检索结果注入生成提示词提升事实一致性;为 Personalized 集合增加反馈评分属性,形成闭环优化;用 Kubernetes 部署 Weaviate 并配置副本与分片;将 Gemini 调用封装为异步任务队列,避免阻塞主流程;结合用户行为日志动态更新画像,实现实时个性化。更多示例可参考 Weaviate 官方文档与 Google cookbook 仓库。

总结

本教程面向有编程基础的开发者,讲解如何用 Weaviate 向量数据库与 Gemini API 构建个性化商品描述生成系统。内容涵盖 Weaviate 集群连接、Schema 定义、数据批量导入、向量搜索与混合搜索、autocut 与筛选器、生成式反馈循环,以及通过交叉引用构建 Products、Personas、Personalized 三集合知识图谱。读者将掌握嵌入、语义检索、LLM 生成回写与用户画像定制的完整工程链路,并了解常见错误与生产优化方向。

内容来源与验证

继续系统学习

站内还有更多完整实战教程

加入会员,解锁全部教程、完整代码与持续更新内容。

加入会员
查看全部API 与工程实践教程