基于Deepseek的RAG私有知识库问答系统实战
2026/9/8 10:39:04 网站建设 项目流程

1. 为什么你的大模型缺少“私域知识”

最近很多开发者朋友问我同一个问题:直接用 ChatGPT、Deepseek 这类大模型做问答,效果挺好的,但一问到公司内部文档、个人笔记、私有资料里的内容,它就“一问三不知”。要么胡编乱造,要么干脆告诉你“没有相关信息”。这个问题的本质,不是大模型不够聪明,而是大模型的知识边界只停留在训练时刻的数据集上。只要你的资料不在它的训练集里,它就不可能知道。

解决这个问题有两种主流思路:一种是微调(Fine-tuning),让大模型把新知识“记进”参数里;另一种就是本文要讲的 RAG(Retrieval-Augmented Generation,检索增强生成),通过“先检索、再生成”的方式,把外部知识库的内容动态接入问答链路。两种方案各有适用场景,但对大多数开发者来说,RAG 是更轻、更快、更可控的选择。

这篇文章会围绕一个核心主题展开:用 Deepseek 作为大模型底座,搭建一套完整的 RAG 私有知识库问答系统。我会从 RAG 的原理讲起,然后给出可运行的源码示例、核心模块拆解、运行验证方式和常见问题排查清单。无论你是刚开始接触大模型应用开发,还是已经在做 Agent、知识库类产品,都能通过这篇文章跑通一套最小可用系统,并理解 RAG 每个环节背后的设计逻辑。

2. RAG 核心原理与概念拆解

2.1 什么是 RAG

RAG 的全称是 Retrieval-Augmented Generation,中文通常翻译为“检索增强生成”。它的核心思想非常朴素:别让大模型凭空回答,先让它去你的知识库里“查资料”,查完再回答

传统的大模型问答流程是:

用户提问 → 直接送入大模型 → 大模型根据参数记忆生成回答

RAG 的问答流程变成了:

用户提问 → 从知识库检索相关内容 → 把用户问题和检索到的内容一起送入大模型 → 大模型基于证据生成回答

这一步变化看似简单,实际上解决了几个很关键的问题:

  • 解决知识陈旧问题:模型训练数据有截止日期,但知识库可以实时更新。
  • 解决私有知识问题:公司内部文档、个人笔记、产品手册不需要进入模型参数,只需要进入向量数据库。
  • 解决幻觉问题:大模型生成时有了检索到的片段作为上下文依据,回答会更有边界感,也能给出出处。
  • 降低更新成本:加一份新文档,只需要重新做切片和向量化,不需要重新训练模型。

2.2 RAG 的三个核心阶段

一套完整的 RAG 系统可以分成三个子模块,这也是后续代码实现的主线:

1. 索引阶段(Indexing)

把原始文档切分成合理的片段(Chunk),然后通过 Embedding 模型把每个片段转换成向量,最后写入向量数据库。这个阶段解决的是“知识怎么存”的问题。

2. 检索阶段(Retrieval)

用户提问时,先把问题通过同一个 Embedding 模型转换成向量,然后在向量数据库中做相似度检索,找到最相关的 Top K 个文档片段。这个阶段解决的是“知识怎么找”的问题。

3. 生成阶段(Generation)

把用户问题、检索到的文档片段、系统提示词一起组装成 Prompt,送入大模型(本文使用 Deepseek),让模型基于这些材料生成最终回答。这个阶段解决的是“答案怎么组织”的问题。

三个阶段的流程可以用下面的表格做一个直观对比:

阶段输入处理方式输出
索引原始文档切分 + Embedding + 写入向量库文档向量
检索用户问题问题向量化 + 相似度搜索Top K 相关片段
生成问题 + 相关片段组装 Prompt + LLM 生成最终答案

2.3 为什么选择 Deepseek 作为底座模型

RAG 架构中的“生成”环节需要一个底座大模型。为什么这篇文章选择 Deepseek?主要有几个原因:

接口兼容成熟。Deepseek 提供了兼容 OpenAI 接口风格的 API,开发者不需要额外学习一套新的 SDK,直接使用常见的 HTTP 请求方式就能接入。

中文效果有优势。Deepseek 在中文理解和生成上的表现处于第一梯队,而 RAG 知识库问答最常见的场景恰恰是中文文档。

成本可控。相比一些大型闭源模型,Deepseek 的 API 价格更适合个人开发者和中小团队跑通原型、做产品验证。

本地化部署路径清晰。如果你有私有化部署需求,Deepseek 的开源模型权重和量化为本地部署提供了比较成熟的社区方案。

需要说明的是,RAG 架构本身并不绑定任何特定模型。你今天用的是 Deepseek,明天换成其他 LLM,替换的只是“生成”模块的 API 调用,索引和检索模块完全不需要改动。这也是 RAG 架构能够广泛流行的原因之一——它足够模块化。

3. 系统架构设计与技术选型

3.1 系统整体架构

本文要搭建的 RAG 知识库问答系统,整体架构如下:

+----------------+ +------------------+ +------------------+ | 原始文档 | | Embedding 向量 | | 向量数据库 | | Markdown/PDF | ---> | 模型 | ---> | (Chroma) | +----------------+ +------------------+ +------------------+ | 用户提问 -------------------------------------------------+ | v +------------------+ +------------------+ +------------------+ | 问题向量化 | ---> | 相似度检索 TopK | ---> | Prompt 组装 | +------------------+ +------------------+ +------------------+ | v +------------------+ | Deepseek API | | 生成回答 | +------------------+

3.2 技术选型说明

模块技术选型选择理由
底座大模型Deepseek API中文效果好,接口兼容 OpenAI 风格
Embedding 模型text2vec 或 OpenAI 兼容接口中文向量化效果好,本地可运行
向量数据库Chroma轻量、纯 Python、适合学习和原型开发
文档加载LangChain / 自研解析支持 Markdown、PDF、TXT 等常见格式
开发语言Python 3.9+AI 生态系统最完善

如果你的项目是大型生产系统,可以把 Chroma 替换为 Milvus、Qdrant 或 Elasticsearch;如果数据量很小,甚至可以直接把向量保存在内存里。本文保持“最小可用系统”优先,后续在最佳实践部分再讲生产化改造方案。

4. 环境准备与依赖安装

4.1 环境要求

在开始写代码之前,需要准备以下环境:

  • Python 3.9 或更高版本,建议用 3.10 或 3.11,兼容性更好。
  • 一个 Deepseek 开放平台账号,并在控制台创建 API Key。
  • 能够访问外网的环境(Deepseek API 调用需要联网)。
  • 推荐使用虚拟环境,避免依赖冲突。

4.2 创建 Python 虚拟环境

建议每个项目使用独立的虚拟环境。打开终端执行:

mkdir rag-knowledge-base cd rag-knowledge-base python3 -m venv venv source venv/bin/activate

Windows 系统激活命令略有不同:

venv\Scripts\activate

激活提示符出现(venv)前缀后,说明虚拟环境已经生效。

4.3 安装依赖

本项目需要的核心依赖有:

  • chromadb:向量数据库,存储文档向量。
  • sentence-transformers:加载本地 Embedding 模型。
  • openai:Deepseek API 兼容 OpenAI 协议,直接用 openai SDK 调用。
  • python-dotenv:读取 .env 配置文件。
  • langchain-text-splitters:仅使用 LangChain 中的文档切分器,避免引入整个框架。
  • pypdf:解析 PDF 文件。

执行安装命令:

pip install chromadb sentence-transformers openai python-dotenv pypdf pip install langchain-text-splitters

如果你在安装sentence-transformerschromadb时遇到依赖冲突,建议先升级 pip 再重试:

pip install --upgrade pip

4.4 配置 Deepseek API Key

在项目根目录创建.env文件:

DEEPSEEK_API_KEY=你的_api_key DEEPSEEK_BASE_URL=https://api.deepseek.com DEEPSEEK_MODEL=deepseek-chat

再创建config.py,用于读取环境变量:

# 文件路径:config.py import os from dotenv import load_dotenv load_dotenv() DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY") DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL", "https://api.deepseek.com") DEEPSEEK_MODEL = os.getenv("DEEPSEEK_MODEL", "deepseek-chat")

注意:不要把.env文件提交到 Git 仓库,建议在.gitignore中加上.envvenv/

5. 核心流程拆解:从文档到问答

在编写完整代码之前,先理清我们要实现哪些功能模块。整个系统由四个 Python 文件组成,职责划分如下:

文件职责对应阶段
config.py加载环境变量通用
data_processing.py文档加载、切分索引阶段
knowledge_base.py向量化、写入向量库索引阶段
rag_query.py检索 + 生成回答检索与生成阶段

这个划分是典型的“高内聚、低耦合”设计:文档处理不关心后面用什么向量库,问答模块也不关心前期文档是怎么切分的。替换任何一个模块,都不需要大规模改动其他代码。

5.1 文档加载与切分

文档加载要解决的问题是把不同格式的资料统一成纯文本。切片要解决的问题,是让文本的长度适合 Embedding 和检索。

切片为什么重要?如果切片太长,检索回来的内容可能包含大量无关信息,浪费上下文窗口;如果切片太短,一个完整概念可能被切成两半,语义不完整。所以切片长度和重叠是 RAG 中需要反复调参的关键参数。

切分逻辑使用RecursiveCharacterTextSplitter,它会以层级方式递归切分文本,优先保证段落和句子的完整性。实现如下:

# 文件路径:data_processing.py from langchain_text_splitters import RecursiveCharacterTextSplitter from pypdf import PdfReader def load_markdown(file_path: str) -> str: with open(file_path, "r", encoding="utf-8") as f: return f.read() def load_pdf(file_path: str) -> str: reader = PdfReader(file_path) text = [] for page in reader.pages: page_text = page.extract_text() if page_text: text.append(page_text) return "\n".join(text) def split_text(text: str, chunk_size: int = 500, chunk_overlap: int = 100) -> list: splitter = RecursiveCharacterTextSplitter( chunk_size=chunk_size, chunk_overlap=chunk_overlap, separators=["\n\n", "\n", "。", "!", "?", ";", " ", ""] ) chunks = splitter.split_text(text) return [chunk.strip() for chunk in chunks if chunk.strip()]

这里的关键逻辑在separators参数。它定义了文本切分的优先顺序:先按空行切,再按换行切,再按中文句号、感叹号、问号切。这样能够最大程度避免把一个完整句子拦腰截断。

注意:PyPDF对扫描版 PDF 无能为力。如果你的文档是图片型 PDF,需要先做 OCR 再进入 RAG 流程。这是很多新手容易踩的坑。

5.2 向量化与向量库写入

Embedding 阶段需要完成两件事:第一,用文本向量模型将每个切片转成向量;第二,把向量和原始文本一起写入向量数据库。

本项目的 Embedding 模型采用本地加载的sentence-transformers模型,好处是数据不需要传到第三方,适合有隐私要求的场景。当然也可以换成 Deepseek 或 OpenAI 的 Embedding API,这里展示本地方案:

# 文件路径:knowledge_base.py import chromadb from sentence_transformers import SentenceTransformer from data_processing import load_markdown, load_pdf, split_text CHROMA_DIR = "./chroma_data" COLLECTION_NAME = "knowledge_base" EMBEDDING_MODEL = "shibing624/text2vec-base-chinese" class VectorStore: def __init__(self): self.embedding_model = SentenceTransformer(EMBEDDING_MODEL) self.client = chromadb.PersistentClient(path=CHROMA_DIR) self.collection = self.client.get_or_create_collection( name=COLLECTION_NAME, metadata={"hnsw:space": "cosine"} ) def add_documents(self, texts: list, source_file: str): if not texts: return embeddings = self.embedding_model.encode(texts).tolist() ids = [ f"{source_file}_{idx}" for idx in range(len(texts)) ] metadatas = [ {"source": source_file, "chunk_index": idx} for idx in range(len(texts)) ] self.collection.add( ids=ids, embeddings=embeddings, documents=texts, metadatas=metadatas ) def query(self, question: str, top_k: int = 4): question_embedding = self.embedding_model.encode(question).tolist() results = self.collection.query( query_embeddings=[question_embedding], n_results=top_k ) return results def build_index(file_paths: list): store = VectorStore() for file_path in file_paths: if file_path.endswith(".md"): text = load_markdown(file_path) elif file_path.endswith(".pdf"): text = load_pdf(file_path) else: print(f"不支持的文件格式: {file_path}") continue chunks = split_text(text) print(f"文件 {file_path} 被切成 {len(chunks)} 个片段") store.add_documents(chunks, source_file=file_path) if __name__ == "__main__": build_index(["./docs/员工手册.md"])

这段代码里有几个值得留意的设计点:

持久化存储。用PersistentClient而不是临时内存客户端,这样向量数据会落盘到./chroma_data目录。下次启动程序时不需要重新索引。

余弦相似度。向量检索的相似度度量选择cosine,这是文本向量场景最常用的度量方式。还有l2欧式距离和ip内积两种选择,但 cosine 对向量长度不敏感,更适合语义相似度计算。

元数据(Metadata)。每一条向量都记录了来源文件和 chunk 索引。这样在后续问答时,我们可以追溯答案出自哪份文档,做“引用溯源”。

5.3 检索与生成

检索阶段把用户问题转化为向量,然后在向量库里搜索最接近的 Top K 个片段。生成阶段则把问题与检索片段组成 Prompt 发送给 Deepseek。

这里是最核心的代码,因为 Prompt 的组装方式直接决定了回答质量。一个高质量的 RAG Prompt 需要明确告诉模型:哪些信息是检索到的证据,回答时只能基于证据,证据不足时要说不知道,而不是编造。

# 文件路径:rag_query.py from openai import OpenAI from knowledge_base import VectorStore from config import DEEPSEEK_API_KEY, DEEPSEEK_BASE_URL, DEEPSEEK_MODEL SYSTEM_PROMPT = """你是一个严谨的知识库问答助手。请基于以下检索到的文档片段回答用户问题。 规则: 1. 只能使用提供的文档片段中的信息来回答问题。 2. 如果文档片段中没有相关信息,请明确回复“知识库中没有找到相关信息”,不要编造。 3. 在回答末尾,列出引用的文档来源片段编号。 检索到的文档片段: {context} """ def search_knowledge(question: str, top_k: int = 4): store = VectorStore() results = store.query(question, top_k=top_k) documents = results["documents"][0] metadatas = results["metadatas"][0] context_lines = [] for idx, (doc, meta) in enumerate(zip(documents, metadatas)): source = meta.get("source", "未知来源") chunk_index = meta.get("chunk_index", 0) context_lines.append(f"[{idx + 1}] 来源: {source} 片段: {chunk_index}\n{doc}") return "\n\n".join(context_lines) def ask_question(question: str, top_k: int = 4): context = search_knowledge(question, top_k=top_k) client = OpenAI( api_key=DEEPSEEK_API_KEY, base_url=DEEPSEEK_BASE_URL ) response = client.chat.completions.create( model=DEEPSEEK_MODEL, messages=[ {"role": "system", "content": SYSTEM_PROMPT.format(context=context)}, {"role": "user", "content": question} ], stream=False, temperature=0.3 ) return response.choices[0].message.content if __name__ == "__main__": question = input("请输入问题: ") answer = ask_question(question) print("\n===== 回答 =====") print(answer)

代码中temperature=0.3是一个刻意设置的值。RAG 场景的核心诉求是“忠实于知识库”,而不是“发挥创造力”。温度越低,生成的随机性越小,回答越稳定。如果你做的是创意写作类应用,可以调高到 0.7 以上,但知识库问答建议固定在一个偏低的范围。

5.4 批量导入脚本

为了让知识库便于维护,我们再写一个批量导入脚本。后续新增文档时,只需要把文件放入docs/目录,运行脚本即可:

# 文件路径:import_docs.py import os from knowledge_base import build_index def get_all_docs(docs_dir: str = "./docs"): file_paths = [] for root, dirs, files in os.walk(docs_dir): for file in files: if file.endswith((".md", ".txt", ".pdf")): full_path = os.path.join(root, file) file_paths.append(full_path) return file_paths if __name__ == "__main__": files = get_all_docs() print(f"共发现 {len(files)} 个文档") build_index(files)

这个脚本的价值在于:知识库的维护不再依赖手动编写 Python 代码,而是变成“把文件放进去,跑一次脚本”的简单操作。

6. 运行结果与效果验证

6.1 运行步骤

假设你的docs/目录下已经有一份名为员工手册.md的文档,内容包含公司考勤制度、请假流程、加班规则等信息。

第一步,导入文档建立索引:

python import_docs.py

预期输出:

共发现 1 个文档 文件 ./docs/员工手册.md 被切成 6 个片段

第二步,运行问答程序:

python rag_query.py

输入问题:

请简单介绍一下这里的考勤制度

预期输出效果(大模型生成的内容,具体文字会有差异,但结构和引用格式应当一致):

根据知识库中的《员工手册》信息,考勤制度的主要内容包括: 1. 工作时间为每个工作日的 9:00 至 18:00,午休一小时。 2. 每日上下班需要在考勤系统打卡,公差外出需要提前提交申请。 3. 每月可享有两次迟到豁免机会,超过部分计入月度考勤统计。 引用来源: [1] 来源: ./docs/员工手册.md 片段: 0 [2] 来源: ./docs/员工手册.md 片段: 3

6.2 如何判断系统效果是否正常

从三个维度验证:

检索相关性。如果回答中的信息确实来自知识库文档,且能对应到正确的文档片段,说明检索链路正常。如果回答内容与文档无关,需要检查切分结果和 Embedding 模型是否合适。

回答忠实度。将回答与原始文档逐条对照,确认没有出现文档中不存在的信息。Deepseek 的能力很强,但一旦 Prompt 里给了上下文,它有时会把上下文当作“参考资料”加上自己训练知识中的内容混合输出。所以 Prompt 规则里的“不要编造”需要反复强调,必要时可以添加更严格的约束。

引用可追溯性。回答末尾应该列出引用来源。如果引用的片段编号与实际内容对不上,说明元数据或检索结果映射出了问题。

6.3 一个失败案例的排查演示

假设你输入了“公司年假是多少天”,回答却是“知识库中没有找到相关信息”。这时候不要急着改 Prompt,按下面的顺序排查:

  1. 确认文档中确实包含年假条款。
  2. 打印检索到的 Top 4 片段,看是否含有关键词“年假”。
  3. 如果片段中有年假内容但回答仍说“找不到”,说明是 Prompt 或模型生成链路的问题。
  4. 如果片段中没有年假内容,说明是切分或检索的问题,可能需要调整chunk_sizetop_k

很多 RAG 项目效果不好,问题不在大模型,而在检索阶段。优先排查检索结果,是 RAG 排错的第一原则。

7. 常见问题与排查思路

下面这张表汇总了 RAG 知识库开发中最常遇到的问题和对应的排查方向。

问题现象可能原因排查方式解决方案
答案总说“找不到信息”检索 Top K 太小或切分太细导致语义不完整打印检索结果查看相关性增大 Top K,调整 chunk_size
回答中出现知识库没有的内容Prompt 约束不够严格检查是否开启了高 temperature降低 temperature,在 Prompt 中加入强制约束
向量化速度极慢本地 CPU 运行 Embedding 模型查看 CPU 占用率换更大的机器,或改用 API 版 Embedding
导入文档时报编码错误文档不是 UTF-8 编码查看文件编码格式统一转成 UTF-8 编码
Chroma 目录越来越大反复导入导致数据重复检查 collection 中记录数导入前根据 source+content 做去重
扫描版 PDF 提取不到文字PDF 是图片型,没有文本层用 PdfReader 打印提取结果先 OCR 再导入
答案过渡依赖某一段切分粒度太大,跨主题文本混在一个 chunk检查 chunk 内容主题纯度减小 chunk_size,增加 overlap
API 调用报 401API Key 配置错误或已过期打印 config 中 Key 的前几位重新生成 Key,检查 .env 文件

排查 RAG 问题有一个简单原则:从数据流的方向查,先查输入数据,再查检索结果,最后查生成结果。不要一上来就怀疑大模型不行。大多数情况下,问题出在数据清洗和检索参数上。

8. 工程化最佳实践与优化方向

跑通最小可用系统之后,如果你想把这个项目推向生产环境,有几件事是绕不开的。

8.1 切分策略优化

切片是 RAG 中影响最大的变量之一。500 字固定切分只是起点,生产环境要根据文档类型做差异化处理。

  • 策略型文档(制度、规范):按标题层级切分,优先保持章节完整。
  • 问答型文档(FAQ):每个问答对作为一个 chunk。
  • 技术文档:按代码块和方法定义边界切分。

更进阶的做法是使用“父子切分”(Parent-Child Chunking):检索时用较短的子片段提高召回精度,送入大模型时把子片段所属的父段落一起送上,保证上下文完整。有相关热词也在讨论类似的做法,核心解决的就是检索精度和上下文完整性的矛盾。

8.2 混合检索与重排序

向量检索擅长语义相似度,但有时会忽略精确关键词匹配。比如文档里写的是“五险一金”,用户问的是“社保”,向量检索能关联上,但精确的条款数字可能需要 BM25 关键词召回。实际项目中推荐“向量检索 + 关键词检索”的混合模式。

在两种模式的结果合并之后,需要加一个重排序(Re-ranking)环节。重排序模型会以更精细的方式评估每个候选片段与用户问题的匹配度,把最相关的结果排到前面。这个环节对回答质量的提升往往非常明显。

8.3 引用溯源与安全边界

RAG 系统的优势之一是答案可溯源。在生产环境中,回答的每一个关键论点都应该能对应到文档原文。实现方式是:不仅返回大模型生成的文本,还要同时返回检索到的文档 ID、片段索引、原文内容。

安全方面需要注意:

  • 知识库文档可能存在敏感信息,需要在上传前做权限分级。
  • 对用户输入做基本的注入防护。知识库 Prompt 中如果嵌入了类似“忽略之前的指令”的内容,模型可能被诱导。
  • 不要把系统 Prompt 设计得过于复杂,避免被反向套出。

关于权限边界,从系统设计一开始就应该考虑谁可以上传文档、谁可以查询哪部分知识,这比上线后再补要省很多成本。

8.4 从原型到生产的架构演进

原型的目录结构适合学习,但生产环境建议按团队和模块拆分,更多依托 Dify、LangChain、LlamaIndex 等成熟框架来承载工程复杂度。

具体演进建议:

  • 将向量数据库替换为 Milvus 或 Qdrant,支持分布式部署和千亿级向量规模。
  • Embedding 模型从本地转 API 或部署成独立服务,避免与主服务抢占资源。
  • 增加缓存层,对高频相同问题直接返回缓存结果,降低 API 调用成本。
  • 增加评测体系,建立“问题-预期答案-检索结果”的评测集,每次修改参数后回归测试。
  • 接入可观测性工具,记录每一次问答的检索片段、模型输出、耗时和 token 消耗。

8.5 多轮对话与 Agent 化演进

目前实现的 RAG 问答是“单轮检索 + 单轮回答”。实际使用中,用户可能会追问细节,也可能一句话里包含两个不同维度的问题。这时候有两种优化方向:

一是多轮对话改写。在检索之前,利用大模型把“它呢”“那年假怎么算”这类追问改写为包含上下文的完整问题,再进入检索流程。

二是 Agent 化。把 RAG 能力封装成 Agent 的一个工具,配合意图识别、工具调用、流程编排,形成 Agentic RAG。例如“帮我把季度销售数据做成图表”这类任务,单靠知识库问答解决不了,但 Agent 可以决定先去知识库找数据定义,再调用数据分析工具。这也是当前 RAG 技术演进比较快的一个方向。

9. 总结

这篇文章从零搭建了一套基于 Deepseek 的 RAG 知识库问答系统,核心代码分成了四个模块:配置管理、文档处理、向量存储、检索问答。整套流程可以概括为“文档切分 → 向量化 → 向量库检索 → Prompt 组装 → 大模型生成”,每一步都有对应的代码实现。

几个容易忽略但影响很大的细节值得再强调一次:

第一,RAG 的核心瓶颈通常在检索,不在生成。回答质量不高时,先检查检索回来的片段是否真的相关、是否完整。

第二,Prompt 设计直接决定 RAG 的底线。温度调低、来源标注、拒绝编造规则,这些虽然看起来简单,但对抗幻觉的效果非常明显。

第三,切分是持续调优的过程。不同文档用同一套切分参数是不合理的,生产环境需要针对文档类型设计切分策略,并用评测集持续验证效果。

如果你是从零学习 RAG,建议拿到代码后先跑通最小示例,然后用自己手头真实的文档替换测试数据,观察切分、检索和生成三个阶段分别发生了什么。对 RAG 的理解,是从“看别人讲解”到“自己调整参数观察变化”之后才真正开始的。下一步可以继续研究混合检索、重排序、多轮对话改写和 Agentic RAG,这些都是基于本文这套基础架构的自然延伸。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询