
在上一季度的内部知识库重构中,我们面临一个典型困境:公司沉淀了3000+篇内部技术文档和故障复盘报告,但开发者在遇到线上问题时,依然习惯在钉钉群里@老员工,而非翻阅知识库。原因无他——关键词检索(ES)无法理解语义。搜“接口超时”,永远搜不到写“响应延迟”的文档。
本文将记录我们利用腾讯云向量数据库(VectorDB) + 腾讯混元大模型API,在3个工作日内部署上线的一个企业级RAG(检索增强生成)问答系统。全文不聊概念,只讲代码、参数和踩坑。
hunyuan-embedding 在中文长文本语义保留上优于同尺寸开源模型,且内部延时稳定在 < 50ms。hunyuan-embedding生成向量,存入腾讯云VectorDB。pip install tencentcloud-sdk-python>=3.0.1050 # 注意:低于此版本不支持混元Embedding
pip install tcvectordb # 腾讯云向量数据库官方SDK在Windows本地调试时,SDK报错 SSLCertVerificationError。
解决方案:在初始化客户端前强制添加非验证上下文(仅限内网测试环境)。
import ssl
import sys
if sys.platform == 'win32':
ssl._create_default_https_context = ssl._create_unverified_contextfrom tencentcloud.common import credential
from tencentcloud.hunyuan.v20230901 import hunyuan_client, models
# 初始化混元客户端
cred = credential.Credential("你的SecretId", "你的SecretKey")
client = hunyuan_client.HunyuanClient(cred, "ap-guangzhou")
# 初始化向量数据库客户端
from tcvectordb import VectorDBClient
vdb_client = VectorDBClient(
url="http://你的实例地址",
username="root",
key="你的API密钥",
timeout=30
)我们对比了固定长度切片和递归切片(RecursiveCharacterTextSplitter)。
官方SDK封装较厚,为便于异常重试,我们封装了原生请求函数:
import json, requests
def get_embedding(text_list):
"""批量获取向量,单次最多支持 512 条"""
url = "https://hunyuan.tencentcloudapi.com/"
payload = {
"Input": text_list, # 注意:这里传入的是列表
"Model": "hunyuan-embedding"
}
# 签名逻辑省略(建议使用SDK的CommonClient),此处展示核心参数
resp = requests.post(url, headers=headers, json=payload)
return [item["Embedding"] for item in resp.json()["Response"]["Data"]]注意:hunyuan-embedding 输出维度固定为 1024,创建向量库索引时务必匹配。
这里直接给出生产环境使用的参数,重点关注 HNSW 的 M 和 efConstruction 对查询速度的影响。
from tcvectordb.model.enum import FieldType, IndexType, MetricType
from tcvectordb.model.index import Index, VectorIndex, FilterIndex
# 创建索引
index = Index(
FilterIndex(name="id", field_type=FieldType.String, index_type=IndexType.PRIMARY_KEY),
FilterIndex(name="department", field_type=FieldType.String, index_type=IndexType.FILTER), # 用于标量过滤
VectorIndex(name="vector", dimension=1024, index_type=IndexType.HNSW,
metric_type=MetricType.COSINE, params={"M": 32, "efConstruction": 200})
)
vdb_client.create_collection(database_name="kb_db", collection_name="doc_chunks", index=index)调参心得:M 从16调到32后,召回率提升2%,但写入速度下降15%,综合考虑我们选择了32。
def search_knowledge(query, department, top_k=5):
# 1. 问题向量化
q_vector = get_embedding([query])[0]
# 2. 向量检索 + Filter 过滤
results = vdb_client.search(
database_name="kb_db",
collection_name="doc_chunks",
vectors=[q_vector],
limit=top_k,
filter=f'department="{department}"' # 关键:标量过滤减少干扰
)
return [doc["text"] for doc in results[0]]我们发现混元对 System 角色的指令遵循度极高,因此在System中强制加入 “如果上下文无法回答问题,请直接回复‘资料库中暂无相关信息’,严禁捏造”。
def build_prompt(context_list, user_query):
context_str = "\n\n".join([f"[文档片段{i+1}]: {c}" for i, c in enumerate(context_list)])
return {
"system": "你是一个严谨的技术助手。仅根据提供的文档片段回答。",
"user": f"文档片段:\n{context_str}\n\n问题:{user_query}"
}from tencentcloud.hunyuan.v20230901 import models
def chat_stream(system, user):
req = models.ChatCompletionsRequest()
req.Model = "hunyuan-lite" # 追求性价比选lite,复杂逻辑选pro
req.Messages = [
{"Role": "system", "Content": system},
{"Role": "user", "Content": user}
]
req.Stream = True # 开启流式
resp = client.ChatCompletions(req)
for event in resp:
# 解析SSE事件
print(event["Choices"][0]["Delta"]["Content"], end="")我们在生产环境(8核16G服务器)压测了 100并发 查询,结果如下:
这次落地让我们明白,RAG工程化80%的精力不在模型选型,而在数据清洗和切片策略。建议即将上马的同事:务必先花一天时间清洗文档中的特殊字符和失效链接,否则生成的向量全是噪声。
下一步计划:接入腾讯云 CLS(日志服务),将错误日志实时切片并向量化,实现“告警即检索”的秒级根因定位。
混元免费版QPS限制为5,我们采用 Semaphore + 指数退避重试 控制并发,建议在代码中增加如下装饰器:
import time
from functools import wraps
def retry_on_throttle(max_retries=3):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for i in range(max_retries):
try:
return func(*args, **kwargs)
except Exception as e:
if "LimitExceeded" in str(e):
time.sleep(2 ** i) # 退避
continue
raise e
return wrapper
return decorator原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。