1. 内置 Embedding 导入数据与查询
TCVectorDB 向量数据库内置了多种 Embedding 模型,支持五种嵌入方式。以下是各模型的详细信息:
模型名 | 适用语言类型 | 维度 | 最大 Token 数量 | 分类得分 | 聚类得分 | 检索得分 |
---|---|---|---|---|---|---|
bge-base-zh(推荐) | 中文 | 768 | 512 | 67.06 | 47.64 | 69.53 |
m3e-base | 中文 | 768 | 512 | 67.52 | 47.68 | 56.91 |
text2vec-large-chinese | 中文 | 1024 | 512 | 60.66 | 30.02 | 41.94 |
e5-large-v2 | 英文 | 1024 | 512 | 75.24 | 44.49 | 50.56 |
multilingual-e5-base | 多语言 | 768 | 514 | 63.35 | 40.68 | 40.68 |
使用内置的 Embedding 模型可以显著提高处理速度(目前,LangChain 封装的 TCVectorDB 使用内置 Embedding 没有已知问题),但也存在一些限制,特别是在迁移数据库时,所有文本需要重新生成 Embedding。
2. 内置 Embedding 模型文档说明&计费
有关内置 Embedding 模型的详细文档与计费信息,请参阅以下文档:
3. 代码示例
import os
import dotenv
from langchain_community.vectorstores import TencentVectorDB
from langchain_community.vectorstores.tencentvectordb import (
ConnectionParams,
)
from langchain_openai import OpenAIEmbeddings
dotenv.load_dotenv()
embedding = OpenAIEmbeddings(model="text-embedding-3-small")
db = TencentVectorDB(
embedding=None,
connection_params=ConnectionParams(
url=os.environ.get("TC_VECTOR_DB_URL"),
username=os.environ.get("TC_VECTOR_DB_USERNAME"),
key=os.environ.get("TC_VECTOR_DB_KEY"),
timeout=int(os.environ.get("TC_VECTOR_DB_TIMEOUT")),
),
database_name=os.environ.get("TC_VECTOR_DB_DATABASE"),
collection_name="dataset-builtin",
)
texts = [
"笨笨是一只很喜欢睡觉的猫咪",
"我喜欢在夜晚听音乐,这让我感到放松。",
"猫咪在窗台上打盹,看起来非常可爱。",
"学习新技能是每个人都应该追求的目标。",
"我最喜欢的食物是意大利面,尤其是番茄酱的那种。",
"昨晚我做了一个奇怪的梦,梦见自己在太空飞行。",
"我的手机突然关机了,让我有些焦虑。",
"阅读是我每天都会做的事情,我觉得很充实。",
"他们一起计划了一次周末的野餐,希望天气能好。",
"我的狗喜欢追逐球,看起来非常开心。",
]
ids = db.add_texts(texts)
print("添加文档id列表:", ids)
print(db.similarity_search_with_score("我养了一只猫,叫笨笨"))
输出示例:
添加文档id列表: ['1721204162283324200-8452797147690134545-0', '1721204162283324200-4748609318240602995-1', '1721204162283324200-5687737768520280782-2', '1721204162283324200--327905253905429573-3', '1721204162283324200--4217514370195306218-4', '1721204162283324200-5510932568003309936-5', '1721204162283324200-7945499047074485108-6', '1721204162283324200-8077162730065074156-7', '1721204162283324200-36196153077512649-8', '1721204162283324200-3472252428185052217-9']
[(Document(page_content='笨笨是一只很喜欢睡觉的猫咪'), 0.874507), (Document(page_content='我的狗喜欢追逐球,看起来非常开心。'), 0.757709), (Document(page_content='猫咪在窗台上打盹,看起来非常可爱。'), 0.748665), (Document(page_content='昨晚我做了一个奇怪的梦,梦见自己在太空飞行。'), 0.735823)]
4. 外部 Embedding 导入数据与查询
除了使用内置的 Embedding 模型,TCVectorDB 也支持自定义文本嵌入模型。然而,在 LangChain 中封装的 TencentVectorDB
存在一个已知的 bug。当使用外部 Embedding 模型时,必须进行以下配置:
- 配置
meta_fields
属性: 指定需要存储的元数据字段。 - 指定字段名称为
text
: 确保metadatas
中包含text
字段,这样向量数据库才能记录原文信息。
如果未配置 meta_fields
或未添加 text
字段,metadata
中的所有字段将不会被保存。这会导致在检索操作时,由于找不到原文信息而无法创建 Document
文档,从而引发错误。
4.1 示例配置
# 示例代码(请根据实际需求调整)
from some_module import TencentVectorDB
# 初始化腾讯向量数据库实例
tencent_vdb = TencentVectorDB(...)
# 设置 meta_fields 属性
meta_fields = ['text'] # 确保 'text' 字段被包含
# 添加文本和元数据
metadatas = [{'text': '原文本内容', '其他字段': '其他值'}]
embeddings = [...] # 自定义的嵌入向量
# 添加数据到数据库
tencent_vdb.add_vectors(embeddings, metadatas, meta_fields=meta_fields)
5. Bug 源码分析
在TencentVectorDB
的实现中,如果 meta_fields
未被正确设置,metadata 中的字段将不会被存储。这是导致无法记录原文信息的原因,因此在进行检索时创建 Document
文档会失败。
为了避免这个问题,请确保在使用自定义 Embedding
模型时,正确配置 meta_fields
并包含 text
字段。
了解更多关于该问题的详细信息和解决方案,请参考LangChain
文档。
# langchain_community/vectorstores/tencentvectordb.py->TencentVectorDB::add_texts
def add_texts(
self,
texts: Iterable[str],
metadatas: Optional[List[dict]] = None,
timeout: Optional[int] = None,
batch_size: int = 1000,
ids: Optional[List[str]] = None,
**kwargs: Any,
) -> List[str]:
...
if embeddings:
doc_attrs["vector"] = embeddings[id]
else:
doc_attrs["text"] = texts[id]
...
Bug修复示例:
import os
import dotenv
from langchain_community.vectorstores import TencentVectorDB
from langchain_community.vectorstores.tencentvectordb import (
ConnectionParams,
MetaField,
META_FIELD_TYPE_STRING,
)
from langchain_openai import OpenAIEmbeddings
dotenv.load_dotenv()
embedding = OpenAIEmbeddings(model="text-embedding-3-small")
db = TencentVectorDB(
embedding=embedding,
connection_params=ConnectionParams(
url=os.environ.get("TC_VECTOR_DB_URL"),
username=os.environ.get("TC_VECTOR_DB_USERNAME"),
key=os.environ.get("TC_VECTOR_DB_KEY"),
timeout=int(os.environ.get("TC_VECTOR_DB_TIMEOUT")),
),
database_name=os.environ.get("TC_VECTOR_DB_DATABASE"),
collection_name="dataset-external",
meta_fields=[
# 配置text字段,防止LangChain在检索时,找不到字段构建Document文档,从而触发错误
MetaField(name="text", data_type=META_FIELD_TYPE_STRING),
]
)
texts = [
"笨笨是一只很喜欢睡觉的猫咪",
"我喜欢在夜晚听音乐,这让我感到放松。",
"猫咪在窗台上打盹,看起来非常可爱。",
"学习新技能是每个人都应该追求的目标。",
"我最喜欢的食物是意大利面,尤其是番茄酱的那种。",
"昨晚我做了一个奇怪的梦,梦见自己在太空飞行。",
"我的手机突然关机了,让我有些焦虑。",
"阅读是我每天都会做的事情,我觉得很充实。",
"他们一起计划了一次周末的野餐,希望天气能好。",
"我的狗喜欢追逐球,看起来非常开心。",
]
# 将原始文本数据合并到metadata中,
metadata = [{"text": text, "page": index} for index, text in enumerate(texts)]
ids = db.add_texts(texts, metadata)
print("添加文档id列表:", ids)
print(db.similarity_search("我养了一只猫,叫笨笨"))
输出内容:
添加文档id列表: ['1721204290046443100--7979142186803955240-0', '1721204290046443100--2991801275249710134-1', '1721204290046443100-7229055024046586038-2', '1721204290046443100-6820010242590464795-3', '1721204290046443100-1761951776563722534-4', '1721204290046443100-7105227574091896456-5', '1721204290046443100-385681627517092469-6', '1721204290046443100-2611196434988287836-7', '1721204290046443100-5925412479147078471-8', '1721204290046443100--5880598133876375674-9']
[Document(page_content='笨笨是一只很喜欢睡觉的猫咪', metadata={'text': '笨笨是一只很喜欢睡觉的猫咪'}), Document(page_content='猫咪在窗台上打盹,看起来非常可爱。', metadata={'text': '猫咪在窗台上打盹,看起来非常可爱。'}), Document(page_content='我的狗喜欢追逐球,看起来非常开心。', metadata={'text': '我的狗喜欢追逐球,看起来非常开心。'}), Document(page_content='我的手机突然关机了,让我有些焦虑。', metadata={'text': '我的手机突然关机了,让我有些焦虑。'})]