请在此添加图片描述

请在此添加图片描述

点击蓝字,关注我们

请在此添加图片描述

本文共计5255字 预计阅读时长16分钟

一、引言

众所周知,RAG 已不再是早期的 Native RAG,而是作为 Agent 中的核心组件,作为企业级应用的决策大脑,是 Agent 获取知识、执行复杂任务的底层支持。当然,检索也不再是静态的一次性动作,而是根据任务需求,主动、多次、精准的调用内外部知识。

于企业而言,如何在保证数据绝对安全的前提下,构建一套高精度又可以适配业务的生产级 RAG 系统,支撑到上游各个业务部门稳定调用,是所有企业AI落地的核心命题。

企业 RAG 的三大痛点:

  • 数据安全:数据是核心资产,必须在受控的环境下流转。
  • 检索准确度:私域数据搜不到或搜不准,模型再强也是徒劳。
  • 业务适配灵活性:不同的数据权限,不同业务场景,链路与参数都有不同的诉求。

本文将介绍一套在私有化环境下,兼顾极致搜索准确度与数据安全的黄金组合。

二、架构设计

为了彻底解决前文提到的数据安全、检索准确度与业务适配灵活性这三大痛点,我们设计了基于 VPC(虚拟私有网络) 为安全底座,腾讯云 ES 为检索核心,Dify 为逻辑编排引擎的闭环架构。

架构组件概览:

  • 安全边界(VPC层): 整个系统部署在企业私有网络内。Dify 应用服务器与 ES 集群处于同一子网(Subnet),通过内网 IP 直接通信,数据不出域。
  • 计算大脑(Dify层): 负责与 LLM(可采用私有化部署模型或通过专线接入的 API)对接,处理工作流编排、Prompt 模板及权限校验逻辑。
  • 存储引擎(ES层): 存储企业全量知识库。利用其强大的分词、向量索引及元数据过滤能力,承担高精度的混合搜索任务。
  • 推理引擎(模型层):主要包含 Embedding、Rerank 及 LLM 服务,在数据预处理与 RAG 各链路进行调用,可基于 ES 机器学习节点,也可以调用云端 API 服务。

请在此添加图片描述

接下来,笔者将基于腾讯云 ES 以及相关服务,实操搭建一套企业级 RAG 框架。

三、场景实践

1.创建 ES 集群,获取 ES 访问地址

ES 作为整个框架的核心底层引擎,用于文本、向量的存储和检索,是整个 RAG 框架的前置条件。

我们首先需要购买一个 ES 集群,具体操作参考官网文档:

https://cloud.tencent.com/document/product/845/19536

具体配置参考:

  • 用于测试验证计费模式可选按量计费
  • 产品版本选择 AI 搜索增强版,专用于对搜索能力、查询性能和稳定性有极高要求的搜索和 RAG 场景。
  • Elasticsearch 版本选择 9.1.3,向量能力主要集中在 8.x 以上版本。
  • 其余配置选择默认即可,注意保存集群访问密码。

集群创建成功后,进入对应集群的访问控制(https://console.cloud.tencent.com/es/cluster/detail?instanceId=es-71szkmx7&region=ap-guangzhou&searchQuery=%3FpageIndex%3D1%26pageSize%3D10%26region%3Dap-guangzhou&tab=access-control)下可获取相关信息,用户名为 elastic,密码在创建集群时所设置,如已忘记可以重置。

请在此添加图片描述

2.购买 TKE 集群,部署 Dify

相比自建部署 Dify,我们推荐腾讯云 TKE 和轻应用服务提供的一键部署 Dify 方案,具备高可用、灵活弹性等特点,可以满足企业的生产部署需求,本次实践以 TKE 为例。

具体操作如下:

1.创建 TKE 集群

1. 集群规格根据实际业务情况进行选择

请在此添加图片描述

1. 所在地域与 ES 集群保持一致

请在此添加图片描述

1. VPC 及子网与 ES 集群保持一致

请在此添加图片描述

1. 勾选安装 CFS 存储组件,Dify 的关键组件 API 和 Work 需要共享存储,推荐在 TKE 集群中使用腾讯云 CFS 文件存储

请在此添加图片描述

1. 其余按默认配置即可。

2.进入创建的 TKE 集群

1. 在节点管理中新建节点

请在此添加图片描述

1. 可选用原生节点

请在此添加图片描述

1. 因为 Dify 组件较多,推荐至少 3\*4核8G,如果你需要用到 Dify 的官方插件市场,公网宽带记得勾选「**创建弹性公务 IP**」,这里后续要使用 Embedding 等云端服务,推荐勾选上。

请在此添加图片描述

1. 勾选子网

请在此添加图片描述

1. 其余按默认配置即可。

3.在存储中的 StorageClass 页签中创建命名为 cfs 的 Storageclass 对象,Provisioner选择文件存储cfs,保持子网一致。

请在此添加图片描述

请在此添加图片描述

4.部署 Dify

1. 在应用市场中搜索 Dify 组件

请在此添加图片描述

1. 在创建的 TKE 集群下,创建 Dify 应用,注意确认地域与集群信息

请在此添加图片描述

1. 创建成功后,在应用管理中可查看已经部署的Dify。

请在此添加图片描述

Dify 部署详情方案

3.将向量库设置为 ES

Dify 默认的向量数据库为 Weaviate,默认随 Dify 部署,仅适合 Demo 或较小数据量使用。我们要利用 ES 强大的混合搜索能力,去提升整个 RAG 系统的精准度,所以在这一步,我们需要将默认的向量库配置变更为 ES。

以 TKE 为例(轻应用服务需要登录到机器中,在docker 目录,编辑 .env 配置文件)

1.进入 TKE 集群,在配置管理页面,修改 Dify 的 APIWork 两个配置,操作一致,可以在界面上修改,也可直接编辑YAML,以在页面上更新为例。

请在此添加图片描述

2.点击更新配置,更改如下配置项

  • 将向量库原有 weaviate 改为 elasticsearch。
  • 手动添加es相关配置,包括 Host、Port、Username、Password以及Kibana_Port(dify和es部署在同一vpc,HOST填写内网域名即可)

请在此添加图片描述

具体信息如下:

# VECTOR_STORE 修改为 elasticsearch
VECTOR_STORE=elasticsearch

# ES相关配置
ELASTICSEARCH_HOST=https://xxxxxxx # 注意这里的9200不要重复写
ELASTICSEARCH_PORT=9200
ELASTICSEARCH_USERNAME=elastic
ELASTICSEARCH_PASSWORD=PASSWORD
KIBANA_PORT=5601

3.重启工作负载

因为已经调整了 API 和 Worker 组件,需要重新部署更新,具体操作如下:

请在此添加图片描述

此时 Dify 使用的向量库就被修改成了 ES,我们还缺一个 Dify 服务入口。

4.新建 Ingress

通过 Ingress 和 CLB 负载均衡将 Dify 服务暴露出来,并提供安全的访问方式。

具体操作如下:

1. 在【服务与路由】页面,切到 Ingress 页签,点击新建

请在此添加图片描述

1. 注意在网络模式要**开启负载均衡直连Pod模式**

请在此添加图片描述

1. 后端服务选择后缀为 tke-dify 的服务,路径直接**斜杠**就好,服务端口选择**80**

请在此添加图片描述

1. 创建成功后,获得登录 Dify 地址

请在此添加图片描述

4.登录 Dify,配置模型服务

首次访问 Dify 需要先配置管理员账号,设置界面如下,然后根据设置的邮箱和密码进行登录,注意保存好管理员账号信息

请在此添加图片描述

在搭建 RAG 过程中,除了本身需要文本和向量存储的 ES,还涉及 Embedding、Rerank 以及 LLM 等服务,在 Dify 上支持自定义和编排。

同时腾讯云 ES 提供两种模式的解决方案,进行上述服务的调用。

方案一:原子服务模式(推荐)

请在此添加图片描述

网络说明:

  • 企业用户通过 VPC 内网来访问 Dify, Dify 通过 private link 访问 ES。
  • 原子无状态服务位于腾讯云内网服务,Dify 所在的 VPC 默认开启腾讯云内网单向访问。

重点说明原子服务接口:

  • 物理无存储:该服务被定义为“无状态计算单元”,其架构中不包含任何数据库或文件系统,文本流进入内存后,经由模型计算立即转化为向量或分值,原始文本在内存中停留时间以“毫秒”计,计算完成即释放,不留任何痕迹。
  • 逻辑无留存:数据像自来水经过滤水器一样,只做加工,不做留存,系统日志仅记录 Request ID、User ID 和 Latency,明确禁止记录 Request Body,从源头上规避了日志泄露风险。
  • 结果不可逆:Embedding 返回的是高维浮点数向量(如 1024 维数组)。本质上是有损压缩,在数学上也是多对一的映射,再加上模型内部的权重是复杂的非线性组合,导致这种转化是物理不可逆的。即使向量数据泄露,也无法反推出原始的文档信息。

具体操作:

1.进入Dify的插件页面

请在此添加图片描述

2.选择插件市场(注意在购买节点时要开公网,如因业务需要不能开公网,则需本地上传或直接拉取 Github 仓库:

https://github.com/langgenius/dify-plugins/tree/main/TencentCloud/ES

请在此添加图片描述

3.搜索腾讯云 ES,进行插件安装

请在此添加图片描述

  1. 插件安装成功后,可直接在入库和检索环节调用相关模型服务

请在此添加图片描述

5.在进入设置页面设置模型的秘钥信息

请在此添加图片描述

6.选择模型供应商,配置腾讯云 ES 的原子服务接口调用信息, ID 和 Key 请从云API 获取。

请在此添加图片描述

方案二:机器学习节点模式

请在此添加图片描述

腾讯云 ES 机器学习节点目前仅支持 Embedding、Rerank 模型的部署。

方案安全说明:

  • 企业用户通过 Private link 来访问 Dify。
  • 所有的机器部署于腾讯云私有 VPC 网络中(Dify、服务节点、ES节点),不与公网交互。
  • 腾讯云 VPC 可以开通单向出站访问公网能力(可选)

方案链路说明:

1.因为 Dify 不知道如何直接调用 ES 的 _infer API,因此需要写一个极简的 Python Web 服务(Adapter),将 ES 的私有推理接口转换成 OpenAI 兼容接口。

2.架构: Dify -> Python Adapter (VPC内) -> ES ML Node (_infer API)

实施路径:

1.在 ES 中部署模型: 在 ES 控制台上传模型,注意如要部署模型,需提前购买 ES机器学习节点

请在此添加图片描述

2.部署 Adapter,创建一个简单的 Flask/FastAPI 服务,部署在CVM 上

这里以embedding为例,在 CVM 部署一个简单的协议转换服务。

请在此添加图片描述

  • 登录 CVM,安装Python3

sudo yum update -y
sudo yum install -y python3 git

  • 上传 main.py 文件和 requirements.txt 文件到服务器(可控制台上传),修改ES_URL,ES_USER,ES_PASS,ES_MODEL_ID 为你的 ES 集群的配置

importos
importasyncio
importlogging
fromtypingimportUnion,List

fromfastapiimportFastAPI,HTTPException
frompydanticimportBaseModel
fromelasticsearchimportElasticsearch

# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s- %(name)s- %(levelname)s- %(message)s',
handlers=[
logging.FileHandler('embedding_service.log'), # 输出到文件
logging.StreamHandler() # 同时输出到控制台
]
)
logger=logging.getLogger(__name__)

ES_URL=os.getenv("ES_URL","http://you_es_internal_ip:9200") # ES内网ip
ES_USER=os.getenv("ES_USER","username") # ES用户名
ES_PASS=os.getenv("ES_PASS","password") # ES密码
ES_MODEL_ID=os.getenv("ES_MODEL_ID","es_model_id") # ES部署的模型id

app=FastAPI()

# 全局变量存储ES连接,初始化为None
es=None

classEmbeddingRequest(BaseModel):
input:Union[str,List[str]]
model:str

@app.on_event("startup")
asyncdefstartup_event():
"""应用启动时创建ES连接"""
globales
# 添加证书验证配置,提高连接稳定性
es=Elasticsearch(
ES_URL,
basic_auth=(ES_USER,ES_PASS),
verify_certs=False # 如果是自签名证书或测试环境,关闭证书验证
)
logger.info("Elasticsearch连接已建立")

@app.on_event("shutdown")
asyncdefshutdown_event():
"""应用关闭时关闭ES连接"""
globales
ifes:
es.close()
logger.info("Elasticsearch连接已关闭")

@app.post("/v1/embeddings")
asyncdefcreate_embeddings(request:EmbeddingRequest):
texts= [request.input] ifisinstance(request.input,str)elserequest.input
ifnottexts:
raiseHTTPException(status_code=400,detail="input empty")

`# 构造 ESdocs(字段名需与模型训练时一致,使用text_field字段)`

docs= [{"text_field":t} fortintexts]

loop=asyncio.get_event_loop()
try:
# 使用requests库直接调用ESAPI,避免transport的限制
importrequests
importjson

url=f"{ES_URL}/_ml/trained_models/{ES_MODEL_ID}/_infer"
body= {"docs":docs}

    `# 构建认证头`

auth=(ES_USER,ES_PASS)
headers= {"Content-Type":"application/json"}

resp=awaitloop.run_in_executor(
None,
lambda:requests.post(
url,
auth=auth,
headers=headers,
json=body,
verify=False, # 关闭证书验证
timeout=30
)
)

    `# 检查响应状态`

ifresp.status_code !=200:
raiseException(f"ES API返回错误状态: {resp.status_code}, 响应: {resp.text}")

resp_data=resp.json()
logger.info(f"ES推理响应状态: {resp.status_code}")

exceptExceptionase:
logger.error(f"ES推理错误详情: {e}")
raiseHTTPException(status_code=502,detail=f"ES infer error: {e}")

`# 根据ES返回结构解析predicted_value`

inference_results=resp_data.get("inference_results", [])
embeddings= []

fori,resultinenumerate(inference_results):
predicted_value=result.get("predicted_value")
ifpredicted_value:
embeddings.append(predicted_value)
logger.info(f"成功获取第{i}个文本的嵌入向量,长度: {len(predicted_value)}")
else:
logger.error(f"第{i}个结果中未找到predicted_value,结果结构: {result}")
raiseHTTPException(status_code=500,detail=f"No predicted_value found in result {i}")

ifnotembeddings:
logger.error(f"未找到任何嵌入向量,完整响应: {resp_data}")
raiseHTTPException(status_code=500,detail="No embeddings generated from ES")

return {
"object":"list",
"data": [{"object":"embedding","embedding":emb,"index":i} fori,embinenumerate(embeddings)],
"model":request.model,
"usage": {
"prompt_tokens":sum(len(text)fortextintexts),
"total_tokens":sum(len(text)fortextintexts)
}
}

requirement.txt

fastapi==0.83.0
uvicorn[standard]==0.16.0
elasticsearch==8.11.0
pydantic==1.9.0
requests==2.25.1

  • 创建虚拟环境并安装依赖

python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install -r requirement.txt
deactivate

  • 启动服务

nohup uvicorn main:app --host 0.0.0.0 --port 8000> service.log 2>&1 &

  • 测试服务(ES集群模型部署好再测)

curl -X POST "http://localhost:8000/v1/embeddings" -H "Content-Type: application/json" -d '{ "input": "这是一个测试文本", "model": "bge-base-zh-v1.5"}'

3.Dify 配置模型服务,与原子服务类似,Dify 提供了 OpenAI-API-Compatible 插件,我们需要安装这个插件,将我们的模型服务转发进来

1. 登录 Dify,搜索并安装 **OpenAI-API-compatible 插件**

请在此添加图片描述

1. 设置模型供应商:单击右上角选择**设置**,选择 **OpenAI-API-compatible 插件**,点击**添加模型**,API URL配置为上述CVM中部署的自定义中转服务,我这里没有设置 API key,可随便填即可

请在此添加图片描述

OpenAI-API-Compatible 并非一个需要独立下载的大型插件或运行时环境,它只是 Dify 内部的一个驱动程序或模型协议解析器,所以它也是在 VPC 下的,不涉及出域。

5.测试验证

1.创建知识库,并导入文档

请在此添加图片描述

2.配置 Embedding 和混合检索

请在此添加图片描述

3.完成文档导入和向量化

请在此添加图片描述

4.在 ES 中查看数据是否写入成功,进入 ES 控制台查看对应集群的索引

请在此添加图片描述

5.在知识库中召回测试,召回成功如下

请在此添加图片描述

6.应用编排测试,可进行知识库检索以及LLM调用

请在此添加图片描述

四、结语

在 AI 原生应用的浪潮中,RAG 已经完成了从实验项目到生产工具的蜕变,它正在成为企业决策的核心知识系统。在那些充斥着专业术语、复杂逻辑、且对数据安全有极高要求的企业核心场景里,腾讯云 ES 以其多年的技术积淀,证明了在混合检索、大规模并发及索引管理上的统治力。

构建一套生产级的 RAG 系统并非终点,而是一个持续进化的起点。随着 Agentic RAG 的深入,腾讯云 ES 将在索引构建、查询理解、检索排序到结果生成全链路 AI 化,成为 AI 时代最具竞争力的搜索基础设施,不仅仅服务人类用户,更要成为面向千万级 Agent 的核心检索层。

END

请在此添加图片描述

清明节兼具自然与人文两大内涵,既是自然节气点,也是传统节日。扫墓祭祖与踏青郊游是清明节的两大礼俗主题,这两大传统礼俗在中国自古传承,至今不辍。

请在此添加图片描述

关注腾讯云大数据╳探索数据的无限可能

往期精彩

请在此添加图片描述

请在此添加图片描述

请在此添加图片描述

求点赞

请在此添加图片描述

求分享

请在此添加图片描述

求喜欢

请在此添加图片描述

文章来源于腾讯云开发者社区,点击查看原文