# TCVectorDB 向量数据库实践:腾讯云托管检索与 Python 生产封装

TCVectorDB 是腾讯云的托管向量数据库。它更适合国内云上部署、企业内网访问、合规链路清晰、需要低延迟接入腾讯云生态的 RAG 和语义检索系统。

如果说 FAISS 更像本地向量检索内核,Pinecone 更像海外云上托管向量库,那么 TCVectorDB 的价值在于:把向量存储、索引、相似度检索、metadata 过滤、实例运维、私有网络接入和云账号权限放在国内云环境里统一管理。

但生产里不能只把它当成 add_texts() 的替代品。真正要设计的是数据库和集合怎么拆、Embedding 模型怎么固定、索引字段怎么声明、metadata 如何过滤、文档更新如何幂等、LangChain 封装和原生 SDK 的边界在哪里。

# TCVectorDB 的核心层级

TCVectorDB 的层级和常见云向量数据库类似。

概念 作用 生产理解
Instance 云数据库实例 网络、规格、鉴权、成本和运维边界
Database 数据库 按业务域、环境或系统模块隔离数据
Collection 集合 存储同一 schema、同一向量维度和索引策略下的数据
Document 记录 一条可检索数据,包含 id、vector 或 text、metadata 字段
Index 索引 决定向量检索方式和可过滤字段

这里最重要的是 Collection。它不是随便起个名字就结束了,而是决定了向量维度、索引类型、相似度计算方式、可过滤字段和后续查询能力。

生产里常见的拆法:

拆分维度 建议
环境 dev、staging、prod 分开 database 或 collection
租户 小租户可通过 metadata 过滤,大租户或强隔离租户可独立 collection
知识库 同租户多知识库可用 metadata,也可按规模拆 collection
索引版本 大版本重建时建议新 collection 灰度切换
Embedding 模型 不同维度或不同模型不要混写到同一 collection

# 安装与连接参数

TCVectorDB 官方 Python SDK 包名是 tcvectordb:

pip install -U tcvectordb
1

如果使用 LangChain Community 封装,还需要:

pip install -U langchain-community langchain-openai
1

环境变量建议统一管理:

export TC_VECTOR_DB_URL="http://your-vdb-endpoint"
export TC_VECTOR_DB_USERNAME="root"
export TC_VECTOR_DB_KEY="your-vdb-key"
export TC_VECTOR_DB_DATABASE="llmops"
export TC_VECTOR_DB_TIMEOUT="30"
export OPENAI_API_KEY="your-openai-api-key"
1
2
3
4
5
6

生产里不要把连接地址、账号和密钥写进代码。更稳的方式是通过密钥管理系统、容器环境变量或配置中心注入,并在服务启动时做一次配置校验。

# 原生 SDK 连接

原生 SDK 更适合做数据库和集合管理、批量写入、更新、删除、统计、运维任务。

import os

from tcvectordb import VectorDBClient
from tcvectordb.model.enum import ReadConsistency


client = VectorDBClient(
    url=os.environ["TC_VECTOR_DB_URL"],
    username=os.environ.get("TC_VECTOR_DB_USERNAME", "root"),
    key=os.environ["TC_VECTOR_DB_KEY"],
    read_consistency=ReadConsistency.EVENTUAL_CONSISTENCY,
    timeout=int(os.environ.get("TC_VECTOR_DB_TIMEOUT", "30")),
)

database = client.database(os.environ["TC_VECTOR_DB_DATABASE"])
collection = database.collection("help_center_v1")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

read_consistency 要结合业务看。知识库检索通常可以接受最终一致性,但如果你在后台刚写入一批内容,马上要验证召回结果,就要理解写入后可见性的延迟边界。

# 创建 Collection 的生产关注点

Collection 创建时最容易漏掉两件事:

第一,向量字段的维度和相似度指标必须和 Embedding 模型一致。

第二,后续要参与过滤的 metadata 字段必须提前声明索引。

示例结构如下:

from tcvectordb.model.enum import FieldType, IndexType, MetricType
from tcvectordb.model.index import FilterIndex, HNSWParams, VectorIndex


client.create_collection_if_not_exists(
    database_name="llmops",
    collection_name="help_center_v1",
    shard=2,
    replicas=1,
    indexes=[
        FilterIndex(name="id", field_type=FieldType.String, index_type=IndexType.PRIMARY_KEY),
        VectorIndex(
            name="vector",
            field_type=FieldType.Vector,
            index_type=IndexType.HNSW,
            dimension=1536,
            metric_type=MetricType.COSINE,
            params=HNSWParams(m=16, efconstruction=200),
        ),
        FilterIndex(name="tenant_id", field_type=FieldType.String, index_type=IndexType.FILTER),
        FilterIndex(name="knowledge_base_id", field_type=FieldType.String, index_type=IndexType.FILTER),
        FilterIndex(name="document_id", field_type=FieldType.String, index_type=IndexType.FILTER),
        FilterIndex(name="status", field_type=FieldType.String, index_type=IndexType.FILTER),
        FilterIndex(name="page", field_type=FieldType.Uint64, index_type=IndexType.FILTER),
    ],
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

实际项目里,创建 collection 通常不放在 Web 服务启动流程里,而是放在初始化脚本、发布流水线、运维控制台或数据库迁移流程里。应用启动时只连接已存在的 collection。

# 内置 Embedding 与外部 Embedding

TCVectorDB 支持把文本写入后由平台侧完成向量化,也支持业务侧先生成向量再写入。

方式 优点 风险
内置 Embedding 接入简单,少维护一个模型服务 模型选择受平台支持范围影响,跨库迁移时要重新评估
外部 Embedding 模型、版本、缓存、成本更可控 需要自己处理限流、重试、维度一致性和批处理

生产 RAG 我更偏向外部 Embedding。原因不是内置能力不好,而是业务通常需要固定模型版本、做 Embedding 缓存、离线评估、灰度迁移和跨数据库备份。外部 Embedding 更容易把这条链路纳入自己的工程治理。

# LangChain 接入

LangChain Community 中仍然有 TencentVectorDB 封装,可以用它快速接入 Retriever。

import os

from langchain_community.vectorstores import TencentVectorDB
from langchain_community.vectorstores.tencentvectordb import ConnectionParams
from langchain_openai import OpenAIEmbeddings


embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

vector_store = TencentVectorDB(
    embedding=embeddings,
    connection_params=ConnectionParams(
        url=os.environ["TC_VECTOR_DB_URL"],
        username=os.environ.get("TC_VECTOR_DB_USERNAME", "root"),
        key=os.environ["TC_VECTOR_DB_KEY"],
        timeout=int(os.environ.get("TC_VECTOR_DB_TIMEOUT", "30")),
    ),
    database_name=os.environ["TC_VECTOR_DB_DATABASE"],
    collection_name="help_center_v1",
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

检索:

docs = vector_store.similarity_search(
    "如何申请发票",
    k=5,
)
1
2
3
4

带分数:

results = vector_store.similarity_search_with_score(
    "如何申请发票",
    k=5,
)

for doc, score in results:
    print(score, doc.page_content, doc.metadata)
1
2
3
4
5
6
7

生产里建议把 LangChain 的 TencentVectorDB 当成 RAG 检索层,而不是完整运维层。复杂的 collection 创建、字段索引、批量更新、删除、审计和数据修复,优先走 tcvectordb 原生 SDK 或后台任务。

# metadata 字段必须显式设计

TCVectorDB 和 LangChain 封装里有一个容易踩的点:metadata 不是随便传就一定会被保存、过滤和返回。需要参与存储或过滤的字段,要在 collection schema 或 LangChain 初始化参数里声明清楚。

LangChain 封装里可以声明 meta_fields:

from langchain_community.vectorstores.tencentvectordb import (
    META_FIELD_TYPE_STRING,
    META_FIELD_TYPE_UINT64,
    MetaField,
)


vector_store = TencentVectorDB(
    embedding=embeddings,
    connection_params=connection_params,
    database_name="llmops",
    collection_name="help_center_v1",
    meta_fields=[
        MetaField(name="text", data_type=META_FIELD_TYPE_STRING),
        MetaField(name="tenant_id", data_type=META_FIELD_TYPE_STRING),
        MetaField(name="knowledge_base_id", data_type=META_FIELD_TYPE_STRING),
        MetaField(name="document_id", data_type=META_FIELD_TYPE_STRING),
        MetaField(name="status", data_type=META_FIELD_TYPE_STRING),
        MetaField(name="page", data_type=META_FIELD_TYPE_UINT64),
    ],
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

这里把 text 也放进 metadata,是为了让检索结果能稳定构造 Document.page_content。有些封装在外部 Embedding 模式下只写入向量,若没有保存原文,召回时就会出现“查到了向量,但拿不到正文”的尴尬情况。

# 写入文本与稳定 id

不要依赖自动生成 id。稳定 id 是生产里更新、删除、去重、审计和重放的基础。

from langchain_core.documents import Document


documents = [
    Document(
        page_content="企业用户可以在控制台申请发票,审批通过后进入开票流程。",
        metadata={
            "text": "企业用户可以在控制台申请发票,审批通过后进入开票流程。",
            "tenant_id": "tenant-a",
            "knowledge_base_id": "kb-help-center",
            "document_id": "invoice-policy",
            "status": "published",
            "page": 1,
        },
    )
]

ids = ["invoice-policy#chunk-0001"]

vector_store.add_documents(
    documents=documents,
    ids=ids,
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

稳定 id 的生成规则可以这样设计:

def build_chunk_id(document_id: str, chunk_index: int, chunk_version: str) -> str:
    return f"{document_id}:{chunk_version}:chunk-{chunk_index:04d}"
1
2

如果文档重切分了,不要复用旧 chunk id。把 chunk_version 加进去,后续可以按版本灰度、回滚和清理。

# 过滤表达式

TCVectorDB 查询过滤通常使用表达式形式,例如:

docs = vector_store.similarity_search_with_score(
    "发票申请流程",
    k=5,
    expr='tenant_id="tenant-a" and knowledge_base_id="kb-help-center" and status="published"',
)
1
2
3
4
5

数值范围:

docs = vector_store.similarity_search_with_score(
    "发票申请流程",
    k=5,
    expr='page>=1 and page<=10',
)
1
2
3
4
5

集合匹配:

docs = vector_store.similarity_search(
    "售后政策",
    k=5,
    expr='status in ("published", "gray")',
)
1
2
3
4
5

过滤字段必须提前建索引。很多线上问题不是查询表达式写错,而是 collection 创建时没有把字段声明为可过滤字段,导致后续检索无法按权限、状态、页面、知识库收敛。

# 和 Pinecone 的区别

维度 Pinecone TCVectorDB
部署生态 海外托管服务为主 腾讯云生态和国内网络更友好
Python SDK pinecone tcvectordb
LangChain 集成 独立包 langchain-pinecone Community 集成 TencentVectorDB
隔离方式 index、namespace、metadata instance、database、collection、metadata
过滤表达 JSON 风格 filter 表达式风格 expr
适合场景 国际化 SaaS、海外云 国内云上 RAG、腾讯云账号和网络体系

这两个工具不是谁替代谁,而是部署地域、合规、团队云栈、成本模型和生态选择不同。国内业务如果已经在腾讯云上,TCVectorDB 的网络和运维整合成本通常更低。

# 和 FAISS 的区别

维度 FAISS TCVectorDB
形态 本地向量检索库 托管向量数据库
运维 自己维护索引文件和发布 云服务负责实例和高可用
过滤 主要靠封装层和候选过滤 原生 metadata 过滤
更新删除 需要自己设计索引版本和文件发布 支持在线数据治理
多租户 需要自行拆索引或补权限层 可结合 database、collection、metadata 设计

FAISS 更适合本地开发、离线评估、小型知识库和完全自管场景。TCVectorDB 更适合线上服务、国内云环境、需要可用性和运维托管的系统。

# 生产封装建议

不要让业务代码到处拼接 TCVectorDB 参数。封装一个配置对象和工厂函数:

from dataclasses import dataclass

from langchain_community.vectorstores import TencentVectorDB
from langchain_community.vectorstores.tencentvectordb import ConnectionParams


@dataclass(frozen=True)
class TCVectorDBSettings:
    url: str
    username: str
    key: str
    database_name: str
    collection_name: str
    timeout: int
    embedding_model: str
    dimension: int
    metric: str


def build_tcvectordb_vector_store(settings: TCVectorDBSettings, embeddings):
    return TencentVectorDB(
        embedding=embeddings,
        connection_params=ConnectionParams(
            url=settings.url,
            username=settings.username,
            key=settings.key,
            timeout=settings.timeout,
        ),
        database_name=settings.database_name,
        collection_name=settings.collection_name,
    )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

同时保存一份 manifest:

{
    "database_name": "llmops",
    "collection_name": "help_center_v1",
    "embedding_model": "text-embedding-3-small",
    "dimension": 1536,
    "metric": "cosine",
    "chunk_version": "chunk-v3",
    "schema_version": "schema-v2"
}
1
2
3
4
5
6
7
8
9

manifest 的价值是排查。线上检索质量变差时,你需要知道当前 collection 用的模型、维度、metric、chunk 策略和字段版本。

# 上线前检查清单

  • Collection 的向量维度是否和 Embedding 模型一致。
  • 相似度 metric 是否和模型归一化策略一致。
  • metadata 字段是否提前声明并建立过滤索引。
  • tenant_id、knowledge_base_id、status 是否能参与过滤。
  • 写入 id 是否稳定、可重放、可删除。
  • 外部 Embedding 是否有缓存、限流、重试和批处理。
  • 文档更新是否支持 delete + upsert 或 collection 版本切换。
  • 是否记录 query、expr、k、score、latency 和命中文档 id。
  • 是否有固定评估集验证 Recall@K、MRR 和答案质量。
  • 是否有实例权限、网络访问控制和密钥轮换策略。

# 问题

TCVectorDB 最容易踩的坑不在连接,而在 schema 和治理。

第一,Collection 创建时没有声明过滤字段。后续需要按租户、知识库、状态、页面过滤时才发现查不动。

第二,外部 Embedding 模式下没有保存原文。向量能召回,但构造不出可给模型阅读的上下文。

第三,Embedding 模型版本混乱。同一个 collection 混写不同维度或不同语义空间的向量,排序会失真。

第四,id 不稳定。每次写入都生成新 id,会造成重复 chunk、删除困难、更新不可控。

第五,把 LangChain 封装当成完整数据库 SDK。检索可以走 VectorStore,批量治理和运维最好回到原生 SDK。

# 拓展

TCVectorDB 可以继续往四个方向扩展。

第一,混合检索。把向量召回、关键词召回和 reranker 组合起来,提高专业术语、编号、产品名、语义相似问题的整体命中。

第二,索引版本化。每次 chunk 策略或 Embedding 模型变化,都创建新 collection 或新版本字段,通过评估后再切流。

第三,多租户治理。小租户用 metadata 过滤,大租户或高敏数据独立 collection,强权限字段从认证态注入,不接受前端自由传入。

第四,可观测闭环。记录每次检索的 query、expr、召回文档、score、耗时和最终答案反馈,建立 RAG 质量回放能力。

# 实际生产是否使用

会使用。

TCVectorDB 适合国内云上 RAG、企业知识库、智能客服、推荐召回、语义搜索等场景。尤其是业务已经在腾讯云、希望走内网访问、需要托管运维和国内合规链路时,它比自建 FAISS 更省工程成本。

但生产里不会只写一个 LangChain 示例。真正可上线的系统还要包括文档解析、chunk 版本、Embedding 缓存、稳定 id、metadata schema、collection 发布、评估集、权限过滤、审计日志和成本监控。

# 现在是否抛弃

没有抛弃。

tcvectordb SDK 仍在维护,LangChain Community 当前也能查到 TencentVectorDB 集成。需要放弃的是早期 demo 写法:不声明 metadata、不保存原文、不固定 id、不区分检索接口和数据治理接口。

新项目应该把 TCVectorDB 当成生产向量数据库使用,而不是把它当成一段示例代码里的向量存储对象。

# 最新生产如何实现

当前更推荐这样落地:

第一,基础设施层创建实例、database 和 collection,固定 dimension、metric、索引字段和网络访问策略。

第二,文档入库链路使用外部 Embedding,统一模型版本、批量大小、缓存和重试。

第三,写入时显式传入稳定 ids、原文 text 和 metadata,保证可召回、可删除、可审计。

第四,在线检索层可以使用 LangChain TencentVectorDB 转成 retriever,方便进入 LCEL 或 RAG 链路。

第五,批量更新、删除、重建、统计和修复任务优先使用 tcvectordb 原生 SDK。

第六,权限过滤字段必须来自服务端认证态,不能由浏览器或客户端自由决定。

最小生产查询结构:

def quote_expr_value(value: str) -> str:
    if not value.replace("-", "").replace("_", "").isalnum():
        raise ValueError("invalid filter value")
    return f'"{value}"'


def build_in_expr(field: str, values: list[str]) -> str:
    if not values:
        raise ValueError("empty filter values")
    quoted_values = ", ".join(quote_expr_value(value) for value in values)
    return f"{field} in ({quoted_values})"


def search_knowledge(vector_store: TencentVectorDB, query: str, auth_context):
    tenant_id = auth_context.tenant_id
    allowed_kb_ids = auth_context.allowed_knowledge_base_ids

    expr = (
        f"tenant_id={quote_expr_value(tenant_id)} "
        f"and {build_in_expr('knowledge_base_id', allowed_kb_ids)} "
        f'and status="published"'
    )

    return vector_store.similarity_search_with_score(
        query,
        k=5,
        expr=expr,
    )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

真实项目里不要直接字符串拼接用户输入。上面的结构表达的是权限过滤必须在服务端生成。落地时应使用安全的表达式构造器、白名单字段和日志审计,避免把过滤语法暴露给用户。

# 总结

TCVectorDB 的优势是国内云上托管、低运维成本、metadata 过滤、腾讯云网络和账号体系整合。它适合把 RAG 从本地实验推进到企业级线上服务。

但它不会替你设计知识库工程。生产质量取决于 collection schema、Embedding 版本、metadata 字段、稳定 id、权限过滤、批量治理、评估集和可观测闭环。

参考: