首批通过分布式安全可靠测评,为关键业务系统打造
OceanBase Vector 与 Hugging Face 集成
更新时间:2026-04-09 14:12:04
OceanBase 数据库提供了向量类型存储、向量索引、embedding 向量搜索的能力。可以将向量化后的数据存储在 OceanBase 数据库,供下一步的搜索使用。
Hugging Face 是一个开源机器学习平台,提供预训练模型、数据集和工具,让开发者能够轻松使用和部署 AI 模型。
前提条件
您已完成部署 OceanBase 数据库 V4.4.0 及以上版本并且创建了 MySQL 模式租户。创建租户 后,再参考下述步骤操作。
您的环境中已存在可以使用的 MySQL 租户和 MySQL 数据库和账号,并已对数据库账号授读写权限。
安装 Python 3.11 及以上版本。
安装依赖。
python3 -m pip install pyobvector sqlalchemy datasets transformers torch确保您已经在租户中设置了
ob_vector_memory_limit_percentage配置项,以启用向量检索功能。V4.3.5 BP3 之前的版本推荐设置值为30,从 V4.3.5 BP3 版本开始推荐保持默认值0。如需更精确设置此配置项,请参考 ob_vector_memory_limit_percentage 计算此值。
步骤一:获取数据库连接信息
联系 OceanBase 数据库部署人员或者管理员获取相应的数据库连接串,例如:
obclient -h$host -P$port -u$user_name -p$password -D$database_name
参数说明:
$host:提供 OceanBase 数据库连接 IP。OceanBase 数据库代理(OceanBase Database Proxy,ODP)连接方式使用的是一个 ODP 地址;直连方式使用的是 OBServer 节点的 IP 地址。$port:提供 OceanBase 数据库连接端口。ODP 连接的方式默认是2883,在部署 ODP 时可自定义;直连方式默认是2881,在部署 OceanBase 数据库时可自定义。$database_name:需要访问的数据库名称。注意
连接租户的用户需要拥有该数据库的
CREATE、INSERT、DROP和SELECT权限。更多有关用户权限的信息,请参见 MySQL 模式下的权限分类。$user_name:提供租户的连接账户。ODP 连接的常用格式:用户名@租户名#集群名或者集群名:租户名:用户名;直连方式格式:用户名@租户名。$password:提供账户密码。
更多连接串的信息,请参见 通过 OBClient 连接 OceanBase 租户。
步骤二:构建您的 AI 助手
设置环境变量
获取 Hugging Face API 密钥,并同 OceanBase连接信息配置到环境变量中。
export OCEANBASE_DATABASE_URL=YOUR_OCEANBASE_DATABASE_URL
export OCEANBASE_DATABASE_USER=YOUR_OCEANBASE_DATABASE_USER
export OCEANBASE_DATABASE_DB_NAME=YOUR_OCEANBASE_DATABASE_DB_NAME
export OCEANBASE_DATABASE_PASSWORD=YOUR_OCEANBASE_DATABASE_PASSWORD
export HUGGING_FACE_API_KEY=YOUR_HUGGING_FACE_API_KEY
示例代码片段
准备数据
Hugging Face 提供了多种嵌入模型,用户可以根据自己的需求选择对应的模型使用。 这里以 sentence-transformers/all-MiniLM-L6-v2 为例,用于调用 Hugging Face 嵌入 API 准备数据:
import os,shutil,torch,requests
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
from datasets import load_dataset
from sqlalchemy import Column, Integer, String
from pyobvector import ObVecClient, VECTOR, IndexParam, l2_distance
# delete cache directory
if os.path.exists("./cache"):
shutil.rmtree("./cache")
HUGGING_FACE_API_KEY = os.getenv('HUGGING_FACE_API_KEY')
DATASET = "squad" # Name of dataset from HuggingFace Datasets
INSERT_RATIO = 0.001 # Ratio of example dataset to be inserted
data = load_dataset(DATASET, split="validation", cache_dir="./cache")
# Generates a fixed subset. To generate a random subset, remove the seed.
data = data.train_test_split(test_size=INSERT_RATIO, seed=42)["test"]
# Clean up the data structure in the dataset.
data = data.map(
lambda val: {"answer": val["answers"]["text"][0]},
remove_columns=["id", "answers", "context"],
)
# HuggingFace API config
import os
from sentence_transformers import SentenceTransformer
# 设置HF Mirror用于下载模型
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
print("正在下载模型...")
model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
print("模型下载完成!")
def encode_text(batch):
questions = batch["question"]
# 使用本地模型进行推理
embeddings = model.encode(questions)
# 格式化embeddings
formatted_embeddings = []
for embedding in embeddings:
formatted_embedding = [round(float(val), 6) for val in embedding]
formatted_embeddings.append(formatted_embedding)
batch["embedding"] = formatted_embeddings
return batch
INFERENCE_BATCH_SIZE = 64 # Batch size of model inference
data = data.map(encode_text, batched=True, batch_size=INFERENCE_BATCH_SIZE)
data_list = data.to_list()
定义向量表结构并将向量存入 OceanBase
创建一个名为 huggingface_oceanbase_demo_documents 的表,包含存储文本的 title 列、question 列、answer 列、存储嵌入向量的 embedding 列和向量索引信息。并将向量数据存入 OceanBase:
OCEANBASE_DATABASE_URL = os.getenv('OCEANBASE_DATABASE_URL')
OCEANBASE_DATABASE_USER = os.getenv('OCEANBASE_DATABASE_USER')
OCEANBASE_DATABASE_DB_NAME = os.getenv('OCEANBASE_DATABASE_DB_NAME')
OCEANBASE_DATABASE_PASSWORD = os.getenv('OCEANBASE_DATABASE_PASSWORD')
client = ObVecClient(uri=OCEANBASE_DATABASE_URL, user=OCEANBASE_DATABASE_USER,password=OCEANBASE_DATABASE_PASSWORD,db_name=OCEANBASE_DATABASE_DB_NAME)
table_name = "huggingface_oceanbase_demo_documents"
client.drop_table_if_exist(table_name)
cols = [
Column("id", Integer, primary_key=True, autoincrement=True),
Column("title", String(255), nullable=False),
Column("question", String(255), nullable=False),
Column("answer", String(255), nullable=False),
Column("embedding", VECTOR(384))
]
# Create vector index
vector_index_params = IndexParam(
index_name="idx_question_embedding",
field_name="embedding",
index_type="HNSW",
distance_metric="l2"
)
client.create_table_with_index_params(
table_name=table_name,
columns=cols,
vidxs=[vector_index_params]
)
print('- Inserting Data to OceanBase...')
client.insert(table_name, data=data_list)
语义搜索
通过 Hugging Face 嵌入 API 生成查询文本的嵌入向量,然后根据文本的嵌入向量查询与向量表中的每个嵌入向量的l2距离,搜索最相关的文档:
# Step 5. Query the most relevant document based on the query.
questions = {
"question": [
"What is LGM?",
"When did Massachusetts first mandate that children be educated in schools?",
]
}
# Generate question embeddings
question_embeddings = encode_text(questions)["embedding"]
for i, question in enumerate(questions["question"]):
print(f"Question: {question}")
# Search across OceanBase
search_results = client.ann_search(
table_name,
vec_data=question_embeddings[i],
vec_column_name="embedding",
distance_func=l2_distance,
with_dist=True,
topk=3,
output_column_names=["id", "answer", "question"],
)
# Print out results
results_list = list(search_results)
for r in results_list:
print({
"answer": r[1],
"score": r[3] if len(r) > 3 else "N/A",
"original question": r[2],
"id": r[0]
})
print("\n")
预期结果
- Inserting Data to OceanBase...
Question: What is LGM?
{'answer': 'Last Glacial Maximum', 'score': 0.29572604605808755, 'original question': 'What does LGM stands for?', 'id': 10}
{'answer': 'coordinate the response to the embargo', 'score': 1.2553772660960183, 'original question': 'Why was this short termed organization created?', 'id': 9}
{'answer': '"Reducibility Among Combinatorial Problems"', 'score': 1.2691888905109625, 'original question': 'What is the paper written by Richard Karp in 1972 that ushered in a new era of understanding between intractability and NP-complete problems?', 'id': 11}
Question: When did Massachusetts first mandate that children be educated in schools?
{'answer': '1852', 'score': 0.2408329167590669, 'original question': 'In what year did Massachusetts first require children to be educated in schools?', 'id': 1}
{'answer': 'several regional colleges and universities', 'score': 1.1474774558319025, 'original question': 'In 1890, who did the university decide to team up with?', 'id': 4}
{'answer': '1962', 'score': 1.2703532682776688, 'original question': 'When were stromules discovered?', 'id': 2}