向量嵌入技术
本文档介绍了向量搜索中的向量嵌入技术。
什么是向量嵌入?
向量嵌入是一种将非结构化数据转换为数值向量的技术。这些向量能够捕捉非结构化数据的语义信息,使计算机可以"理解"和处理非结构化数据的含义。具体来说:
- 向量嵌入将文本、图像或音视频等非结构化数据映射到高维向量空间中的点。
- 在这个向量空间中,语义相似的非结构化数据会被映射到相近的位置。
- 向量通常由数百个数字组成(如 512 维、1024 维等)。
- 可以用数学方法(如余弦相似度)计算向量之间的相似度。
- 常见的向量嵌入模型包括 Word2Vec、BERT、BGE 等。例如,在开发 RAG 应用时,我们通常需要将文本数据进行嵌入处理转换为向量数据之后存储在向量数据库中,而其他结构化数据存储在关系型数据库中。
seekdb 支持将向量数据作为一种数据类型在关系表中进行存储,使得向量和传统标量数据能够有序、高效地存储在 seekdb 数据库中。
使用 AI 函数服务在 seekdb 中生成向量嵌入
seekdb 支持使用 AI 函数服务生成向量嵌入。用户无需安装任何依赖,只需注册好模型信息,即可在 seekdb 中使用 AI 函数服务生成向量嵌入。详情请参见 AI 函数服务使用及示例。
常见的文本嵌入方法
此部分介绍文本嵌入方法。
操作准备
您需要提前安装好 pip 命令。
使用离线、本地的预训练嵌入模型
使用预训练模型在本地进行文本嵌入是最灵活的方式,但需要较大的计算资源。常用的模型包括:
使用 Sentence Transformers
Sentence Transformers 是一种用于自然语言处理(NLP)的模型,旨在将句子或段落转换为向量嵌入。它们基于深度学习技术,特别是使用了变换器(Transformer)架构,能够有效捕捉文本的语义信息。因为在国内直接访问 hugging face 的域名通常会超时,请提前设置 hugging face 的镜像地址 export HF_ENDPOINT=https://hf-mirror.com,设置完成后再执行下面的代码:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("BAAI/bge-m3")
sentences = [
"That is a happy person",
"That is a happy dog",
"That is a very happy person",
"Today is a sunny day"
]
embeddings = model.encode(sentences)
print(embeddings)
# [[-0.01178016 0.00884024 -0.05844684 ... 0.00750248 -0.04790139
# 0.00330675]
# [-0.03470375 -0.00886354 -0.05242309 ... 0.00899352 -0.02396279
# 0.02985837]
# [-0.01356584 0.01900942 -0.05800966 ... 0.00523864 -0.05689549
# 0.00077098]
# [-0.02149693 0.02998871 -0.05638731 ... 0.01443702 -0.02131325
# -0.00112451]]
similarities = model.similarity(embeddings, embeddings)
print(similarities.shape)
# torch.Size([4, 4])
使用 Hugging Face Transformers
Hugging Face Transformers 是一个开源库,提供了大量预训练的深度学习模型,特别是用于自然语言处理(NLP)任务的模型。由于地域问题,直接访问 hugging face 的域名可能会超时,请提前设置 hugging face 的镜像地址 export HF_ENDPOINT=https://hf-mirror.com,设置完成后再执行下面的代码:
from transformers import AutoTokenizer, AutoModel
import torch
# 加载模型和分词器
tokenizer = AutoTokenizer.from_pretrained("BAAI/bge-m3")
model = AutoModel.from_pretrained("BAAI/bge-m3")
# 准备输入
texts = ["这是示例文本"]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")
# 生成嵌入
with torch.no_grad():
outputs = model(**inputs)
embeddings = outputs.last_hidden_state[:, 0] # 使用 [CLS] token 的输出
print(embeddings)
# tensor([[-1.4136, 0.7477, -0.9914, ..., 0.0937, -0.0362, -0.1650]])
print(embeddings.shape)
# torch.Size([1, 1024])
Ollama
Ollama 是一个开源的模型。运行时,它让用户能够在本地轻松运行、管理和使用各种大语言模型。除了支持 Llama 3 和 Mistral 等开源语言模型外,它还支持 bge-m3 等嵌入模型。
-
部署 Ollama
在 MacOS 和 Windows 上可以直接从官网下载安装包进行安装,安装方法可参考 Ollama 的官网。安装完成后,Ollama 会作为一个服务在后台运行。
在 Linux 上安装 Ollama:
curl -fsSL https://ollama.ai/install.sh | sh -
拉取嵌入模型
Ollama 支持使用 bge-m3 模型用于文本嵌入:
ollama pull bge-m3 -
使用 Ollama 进行文本嵌入
可以通过 HTTP API 或者 Python SDK 等方式来使用 Ollama 的嵌入能力:
-
HTTP API 方式
import requests
def get_embedding(text: str) -> list:
"""使用 Ollama 的 HTTP API 获取文本嵌入"""
response = requests.post(
'http://localhost:11434/api/embeddings',
json={
'model': 'bge-m3',
'prompt': text
}
)
return response.json()['embedding']
# 示例使用
text = "这是一个示例文本"
embedding = get_embedding(text)
print(embedding)
# [-1.4269912242889404, 0.9092104434967041, ...] -
Python SDK 方式
首先安装 Ollama 的 Python SDK:
pip install ollama然后可以这样使用:
import ollama
# 示例使用
texts = ["第一个句子", "第二个句子"]
embeddings = ollama.embed(model="bge-m3", input=texts)['embeddings']
print(embeddings)
# [[0.03486196, 0.0625187, ...], [...]]
-
-
Ollama 的优势和局限
优势:
- 完全本地部署,无需网络连接
- 开源免费,无需 API Key
- 支持多种模型,便于切换和比较
- 资源占用相对较小
局限:
- 嵌入模型选择较少
- 性能可能不如商业服务
- 需要自行维护和更新
- 缺乏企业级支持
在选择是否使用 Ollama 时,需要权衡这些因素。如果您的应用场景对隐私性要求高,或者希望完全离线运行,Ollama 是一个不错的选择。但如果您需要更稳定的服务质量和更好的性能,可能还是需要考虑商业服务。
使用在线、远端的嵌入服务
使用离线的、本地的嵌入模型通常对部署的机器规格要求较高,而且对模型的加载和卸载等过程的管理有较高的要求,许多用户对在线的嵌入服务有较高需求,所以目前许多 AI 推理服务供应商也提供了相应的文本嵌入服务。以通义千问的文本嵌入服务为例,我们首先注册阿里云百炼账号并获取 API Key 后,便可以通过调用其公开的接口来得到文本嵌入的结果。




HTTP 调用
获取完成之后可通过下面的代码尝试进行文本嵌入,如果您的 Python 环境中没有安装 requests 包,则需要先通过 pip install requests 进行安装以便发送网络请求。
import requests
from typing import List
class RemoteEmbedding():
def __init__(
self,
base_url: str,
api_key: str,
model: str,
dimensions: int = 1024,
**kwargs,
):
self._base_url = base_url
self._api_key = api_key
self._model = model
self._dimensions = dimensions
"""
OpenAI compatible embedding API. Tongyi, Baichuan, Doubao, etc.
"""
def embed_documents(
self,
texts: List[str],
) -> List[List[float]]:
"""Embed search docs.
Args:
texts: List of text to embed.
Returns:
List of embeddings.
"""
res = requests.post(
f"{self._base_url}",
headers={"Authorization": f"Bearer {self._api_key}"},
json={
"input": texts,
"model": self._model,
"encoding_format": "float",
"dimensions": self._dimensions,
},
)
data = res.json()
embeddings = []
try:
for d in data["data"]:
embeddings.append(d["embedding"][: self._dimensions])
return embeddings
except Exception as e:
print(data)
print("Error", e)
raise e
def embed_query(self, text: str, **kwargs) -> List[float]:
"""Embed query text.
Args:
text: Text to embed.
Returns:
Embedding.
"""
return self.embed_documents([text])[0]
embedding = RemoteEmbedding(
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings", # 可参考 https://bailian.console.aliyun.com/#/model-market/detail/text-embedding-v3?tabKey=sdk
api_key="your-api-key", # 填写你的 API Key
model="text-embedding-v3",
)
print("Embedding result:", embedding.embed_query("今天天气不错"), "\n")
# Embedding result: [-0.03573227673768997, 0.0645645260810852, ...]
print("Embedding results:", embedding.embed_documents(["今天天气不错", "明天呢?"]), "\n")
# Embedding results: [[-0.03573227673768997, 0.0645645260810852, ...], [-0.05443647876381874, 0.07368793338537216, ...]]