RAG 索引阶段
2026/7/8 2:25:18 网站建设 项目流程

索引阶段是 RAG 的离线建库流程:先把原始数据源加载出来,再切成 Chunk,生成 Embedding,写入向量库,最后做入库验证和版本管理。只有索引阶段做得好,后面的检索生成阶段才可能答得准。

一句话理解

数据源 -> 文档加载 -> 文档切分 -> 嵌入编码 -> Milvus 入库 -> 入库验证 -> 版本更新

索引阶段不直接回答用户问题,它的目标是提前把知识整理成“可检索”的形式。

  • 输入:PDF、Word、Markdown、Excel、CSV、网页、API、数据库等原始数据源。
  • 处理中间态:Document、Chunk、Embedding。
  • 输出:可检索的向量数据、原文片段、元数据、索引版本和验证结果。

为什么索引阶段重要

RAG 的核心是“先检索,再生成”。检索质量很大程度取决于索引阶段。

如果索引阶段没做好,会出现这些问题:

  • 文档加载不完整:答案缺少依据。
  • 文档切分太粗:检索结果噪声大。
  • 文档切分太碎:上下文语义不完整。
  • Embedding 模型不合适:相似度匹配不准。
  • 元数据缺失:无法按来源、页码、业务类型过滤。
  • 向量库索引不合理:检索慢、成本高、召回差。

1. 数据源

数据源是知识库的原始输入。

常见来源:

类型示例处理重点
文本文件.txt.md保留标题、段落、列表结构
办公文档.docx.xlsx.csv处理表格、标题层级、单元格语义
PDF电子 PDF、扫描 PDF、混合 PDF处理版面、OCR、表格、图片、页码
网页HTML、文档站点去除导航、广告、页脚等噪声
API业务接口、知识接口统一字段结构和更新时间
数据库MySQL、PostgreSQL、ES明确哪些字段适合入库

索引阶段第一步要先判断数据源是什么类型,因为不同类型的数据源适合不同加载方式。

2. 文档加载

文档加载负责把不同格式的数据统一读取成程序可处理的文档对象。

在 LangChain 这类框架中,加载后的文档通常抽象为Document

Document - page_content:正文文本 - metadata:元数据,比如 source、page、file_name - id:可选,文档唯一标识

文档加载的目标

  • 把不同格式统一成同一种结构。
  • 尽量保留来源、页码、标题等元数据。
  • 为后续切分、嵌入、检索做准备。

Markdown 加载

Markdown 是半结构化文本,适合做知识库文档。

原因:

  • ###可以表达标题层级。
  • -1.可以表达列表。
  • 代码块、引用块、表格等结构比较清晰。

加载 Markdown 时要尽量保留标题层级,因为标题可以帮助后续 Chunk 判断语义边界。

Word 加载

.docx本质上是 XML 压缩包,机器可以读取段落和文本块。

难点在于:Word 用户不一定使用标准“标题 1 / 标题 2”样式。有些文档只是把字体加粗、放大,看起来像标题,但对解析程序来说可能还是普通段落。

处理建议:

  • 如果 Word 标题样式规范,可以直接用文档加载器。
  • 如果标题层级混乱,加载后要检查解析结果。
  • 对结构要求高的文档,可以先转成 Markdown 或用专业解析工具处理。

PDF 加载

PDF 是最复杂的文档类型之一。

常见问题:

  • 有些 PDF 是扫描图片,需要 OCR。
  • 有些 PDF 是双栏排版,直接抽文本可能顺序错乱。
  • 表格、公式、图片、页眉页脚容易混在正文里。
  • 页码、水印、目录可能变成无效噪声。

PDF 解析时要关注两个结果:

  • 文本是否完整。
  • 文本顺序是否符合人类阅读顺序。

MinerU 这类文档解析工具可以把 PDF 转成 Markdown、JSON 等机器可读格式。对于复杂 PDF,可以先解析成结构化 Markdown,再进入 RAG 流程,通常比直接抽纯文本更稳定。

3. 文档切分

加载后的文档通常很长,不能整篇直接拿去做检索,所以要切分成多个 Chunk。

Document -> Chunk([text])

为什么要切分

问题不切分的后果
Token 限制长文档可能超过模型上下文窗口
检索不精确返回整篇文档会带入大量噪声
向量化成本高整篇文档生成 Embedding 成本更高
语义被稀释长文本向量容易丢失局部重点

Chunk 是后续存储和检索的基本单位。

切分要平衡什么

切分不是越细越好,也不是越大越好,需要平衡三个因素:

维度目标问题
长度控制每个 Chunk 大小适中太大噪声多,太小语义不完整
语义完整尽量保留完整段落或句子切断句子会影响理解
边界合理优先按标题、段落、句号切强行截断会丢上下文

常见切分策略

策略原理优点缺点
固定长度切分按字符数或 Token 数切简单稳定容易切断语义
语义切分根据语义变化切分语义完整性好成本高,块大小不稳定
递归字符切分按分隔符优先级逐级切工程上常用,平衡效果和成本需要调分隔符和大小

递归字符切分器

实际项目里常用递归字符切分,因为它在“语义完整”和“长度可控”之间比较平衡。

核心思想:

优先按大边界切,不行再降级到小边界

常见分隔符优先级:

separators = ["\n\n", "\n", "。", "!", "?", ",", " ", ""]

理解方式:

分隔符语义边界
\n\n段落
\n
句子
短句
""字符级兜底

示例:

from langchain_text_splitters import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter( chunk_size=500, chunk_overlap=50, separators=["\n\n", "\n", "。", "!", "?", ",", ""], ) chunks = text_splitter.split_documents(docs)

chunk_size 和 chunk_overlap

chunk_size控制每个 Chunk 的最大长度。

chunk_overlap控制相邻 Chunk 的重叠长度。

为什么要 overlap:

没有 overlap:边界信息可能丢失 有 overlap:相邻块共享一小段上下文,减少断裂

常见经验:

  • 普通知识文档:chunk_size可从 500-800 字符开始试。
  • 代码、配置、表格类文档:要按结构切,不要只按长度切。
  • chunk_overlap不宜太大,否则重复内容多,存储和检索成本会上升。

4. 嵌入编码

切分后,每个 Chunk 还是普通文本。计算机无法直接理解“语义相似”,所以要用 Embedding 模型把文本转成向量。

Chunk([text]) -> Embedding([float])

Embedding 是一组浮点数。语义相近的文本,在向量空间里距离通常更近。

为什么需要 Embedding

检索阶段要做的是:

用户问题向量 vs 文档 Chunk 向量

然后通过余弦相似度、内积或 L2 距离找到最相似的内容。

如果没有 Embedding,只能做关键词匹配,无法很好处理同义词、近义词和语义表达差异。

常见模型选择

模型维度特点
bge-small-zh512轻量,中文可用
bge-base-zh768中文场景常用
bge-large-zh1024精度更高,成本更高
bge-m31024多语言,支持稠密和稀疏向量
text-embedding-3-small1536OpenAI 云端模型,性价比高
text-embedding-3-large3072OpenAI 云端模型,精度更高

选择模型时要考虑:

  • 中文效果。
  • 向量维度。
  • 速度和成本。
  • 是否需要本地部署。
  • 是否需要稠密 + 稀疏混合检索。

文档向量和查询向量

索引阶段生成的是文档向量:

doc_vectors = embeddings.embed_documents([ "第一段文档", "第二段文档", ])

检索阶段生成的是查询向量:

query_vector = embeddings.embed_query("用户问题")

注意:文档和查询最好使用同一个 Embedding 模型,至少要保证维度一致、语义空间兼容。

Embedding 抽象接口

Embedding 抽象接口就是把“文本转向量”这件事封装成统一入口。

一句话理解:

Embedding 抽象接口 = 不管底层用什么模型,对外都提供统一的向量生成方法

它的作用是让 RAG 系统不用直接依赖某一个具体 Embedding 模型。比如现在用bge-m3,以后换成 OpenAI Embedding 或其他本地模型时,索引流程和查询流程不用大改,只需要替换接口背后的模型实现。

文档 Chunk -> Embedding 接口 -> 文档向量 用户问题 -> Embedding 接口 -> 查询向量

常见接口一般会分成两个方法:

方法用来干什么使用阶段
embed_documents()把多个文档 Chunk 转成文档向量索引阶段
embed_query()把用户问题转成查询向量查询阶段

示例:

doc_vectors = embeddings.embed_documents(["第一段文档", "第二段文档"]) query_vector = embeddings.embed_query("RAG 的索引阶段是什么?")

这个抽象接口主要解决三个问题:

  • 统一调用方式:不管底层是 BGE、OpenAI 还是本地模型,外层代码都调用同一套方法。
  • 方便替换模型:模型升级时,只改接口实现,不改整个 RAG 流程。
  • 保证维度一致:Embedding 输出维度必须和 Milvus Collection 里的向量字段维度一致。

需要特别注意:

文档向量和查询向量最好使用同一个 Embedding 模型。

比如文档入库用的是bge-m3生成的1024维向量,查询阶段也应该用bge-m3生成1024维查询向量。否则两边不在同一个向量空间里,Milvus 检索出来的相似度就不可靠。

稠密向量和稀疏向量

BGE-M3 比较适合用来理解稠密向量和稀疏向量,因为它可以在同一个模型里同时生成:

稠密向量 dense_vector:负责语义相似 稀疏向量 sparse_vector:负责关键词匹配
稠密向量

稠密向量就是一组连续浮点数。以bge-m3为例,它的稠密向量是1024维,也就是每段文本会被转换成1024个数字。

简化示例:

文本:RAG 的索引阶段会把文档切分成 Chunk,再生成 Embedding 存入 Milvus。 bge-m3 稠密向量: [0.018, -0.034, 0.126, ..., 0.052]

这个向量真正存储时不是几个数字,而是1024个浮点数。它的作用是表达整段文本的语义。

稠密向量更擅长处理“意思相近但关键词不完全一样”的问题。

例子:

用户问题:RAG 怎么把资料放进向量库? 文档 Chunk:索引阶段会把文档切分成 Chunk,再生成 Embedding 存入 Milvus。

这两句话没有完全相同的表达,但意思接近。bge-m3生成查询向量后,可以通过稠密向量检索找到这个 Chunk。

稀疏向量

稀疏向量也是向量,但它不是每一维都有值,而是只给重要 token 分配权重。大部分位置都是0,所以叫“稀疏”。

简化示例:

文本:Milvus 的 HNSW 索引参数包括 M、efConstruction 和 ef。 bge-m3 稀疏向量可以理解成: { "Milvus": 0.92, "HNSW": 0.88, "efConstruction": 0.95, "ef": 0.71, "索引": 0.63 }

真实存储时通常不是直接存中文词,而是存 token id 和权重,可以简单理解为:

{ 1842: 0.92, 9135: 0.88, 12077: 0.95 }

稀疏向量更擅长处理关键词、术语、编号、参数名、错误码这类精确匹配。

例子:

用户问题:efConstruction 是什么? 文档 Chunk:Milvus 的 HNSW 索引参数包括 M、efConstruction 和 ef。

这里efConstruction是关键。如果只靠语义,系统可能召回很多“索引优化”相关内容;稀疏向量会更容易命中包含efConstruction这个精确术语的 Chunk。

BGE-M3 输出示例

使用bge-m3时,可以同时拿到稠密向量和稀疏向量:

from FlagEmbedding import BGEM3FlagModel model = BGEM3FlagModel("BAAI/bge-m3") output = model.encode( ["Milvus 的 HNSW 索引参数包括 M、efConstruction 和 ef。"], return_dense=True, return_sparse=True, ) dense_vector = output["dense_vecs"][0] sparse_vector = output["lexical_weights"][0]

可以这样理解输出结果:

输出含义用途
dense_vecs稠密向量,1024维浮点数语义检索
lexical_weights稀疏向量,重要 token 的权重关键词检索
在 Milvus 里怎么用

如果用 BGE-M3 做混合检索,Milvus Collection 可以设计两个向量字段:

dense_vector -> FLOAT_VECTOR,存 bge-m3 的稠密向量 sparse_vector -> SPARSE_FLOAT_VECTOR,存 bge-m3 的稀疏向量

查询时也生成两种向量:

用户问题 -> bge-m3 -> 查询稠密向量 + 查询稀疏向量

然后分别检索:

稠密检索:找语义相似的 Chunk 稀疏检索:找关键词匹配的 Chunk 融合排序:把两路结果合并,得到最终 Top-K
对比总结
类型bge-m3 输出擅长例子
稠密向量dense_vecs语义相似“怎么入库”和“索引阶段”语义接近
稀疏向量lexical_weights关键词匹配HNSWefConstruction、错误码、参数名

BGE-M3 的价值在于:一个模型就能同时提供语义检索能力和关键词检索能力,后续可以在 Milvus 里做混合检索。

5. 向量存储

向量生成后,需要存到支持相似度检索的向量库里。

Embedding([float]) -> VectorStore

向量库通常不只存向量,还要存:

  • 原文 Chunk。
  • 元数据。
  • 主键 ID。
  • 稠密向量字段。
  • 稀疏向量字段。
  • 业务过滤字段。

为什么不用普通数据库直接查

普通数据库擅长精确匹配和范围查询,比如:

where id = 1 where created_at > '2026-01-01'

向量检索要找的是“语义最相似”,不是字段完全相等。如果在普通数据库里对所有向量逐个计算相似度,会接近全表扫描,数据量大后性能很差。

向量库的核心价值:

  • 支持高维向量相似度检索。
  • 支持 ANN、HNSW 等索引加速。
  • 支持 Top-K 检索。
  • 支持向量字段和元数据字段一起查询。

常见向量库

向量库适用场景
FAISS本地实验、高性能相似度搜索库
Chroma快速原型、轻量知识库
Milvus当前使用;生产环境、大规模向量检索
pgvectorPostgreSQL 项目里增加向量能力
Redis已使用 Redis,且需要内存级响应
Elasticsearch统一管理全文检索、结构化数据和向量检索

6. Milvus 入库设计

本笔记按当前实际选择:向量数据库使用 Milvus。可以把 Milvus 理解成“向量世界的数据库”:它专门用于高维向量的存储、索引和相似度检索。

Collection

Collection类似关系型数据库里的表。

创建 Collection 时要先定义 Schema。

一个典型 RAG Collection 可以包含:

字段类型作用
idINT64主键
tenant_idVARCHAR租户或业务隔离
doc_idVARCHAR文档 ID
chunk_idVARCHARChunk ID
sourceVARCHAR来源文件或 URL
pageINT64页码
versionVARCHAR索引版本
textVARCHARChunk 原文
metadataJSON扩展元数据
vectorFLOAT_VECTOR稠密向量,用于语义检索
sparse_vectorSPARSE_FLOAT_VECTOR稀疏向量,用于关键词检索
created_atINT64创建时间,便于排查和更新

示例:

from pymilvus import MilvusClient, DataType schema = ( MilvusClient.create_schema(auto_id=True) .add_field(field_name="id", datatype=DataType.INT64, is_primary=True) .add_field(field_name="tenant_id", datatype=DataType.VARCHAR, max_length=64) .add_field(field_name="doc_id", datatype=DataType.VARCHAR, max_length=128) .add_field(field_name="chunk_id", datatype=DataType.VARCHAR, max_length=128) .add_field(field_name="source", datatype=DataType.VARCHAR, max_length=512) .add_field(field_name="page", datatype=DataType.INT64) .add_field(field_name="version", datatype=DataType.VARCHAR, max_length=64) .add_field(field_name="text", datatype=DataType.VARCHAR, max_length=1500) .add_field(field_name="metadata", datatype=DataType.JSON) .add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=1024) .add_field(field_name="sparse_vector", datatype=DataType.SPARSE_FLOAT_VECTOR) .add_field(field_name="created_at", datatype=DataType.INT64) )

向量字段和索引

向量写入后,如果没有索引,每次检索都要暴力比较,速度会很慢。

这里要区分字段类型索引类型

向量类型Milvus 字段类型常见索引说明
稠密向量FLOAT_VECTORHNSWRAG 常用,召回和速度比较平衡
稠密向量FLOAT_VECTORFLAT暴力精确检索,适合小数据或评估基线
稠密向量FLOAT_VECTORIVF_FLAT数据量较大时常用,可以通过参数平衡召回和速度
稀疏向量SPARSE_FLOAT_VECTORSPARSE_INVERTED_INDEX类似倒排索引,适合关键词权重匹配
稀疏向量SPARSE_FLOAT_VECTORSPARSE_WAND稀疏检索加速,适合更关注查询速度的场景

注意:

SPARSE_FLOAT_VECTOR 是字段类型,不是索引类型。

也就是说:

sparse_vector 字段类型:SPARSE_FLOAT_VECTOR sparse_vector 常见索引:SPARSE_INVERTED_INDEX 或 SPARSE_WAND

示例:

index_params = MilvusClient.prepare_index_params() index_params.add_index( field_name="vector", index_type="HNSW", metric_type="COSINE", ) index_params.add_index( field_name="sparse_vector", index_type="SPARSE_INVERTED_INDEX", metric_type="IP", )

相似度 metric 怎么选

向量度量用来判断“两个向量有多相似”。Milvus 里常见的度量可以这样理解:

度量英文 / Milvus 常见写法看什么常见场景
欧式距离L2两个向量的直线距离,越小越相似图像、空间距离、通用向量
余弦相似度COSINE两个向量方向是否接近,越接近越相似文本语义匹配,RAG 常用
内积IP两个向量点乘结果,越大越相似归一化后的文本向量、稀疏向量
汉明距离HAMMING二进制向量有多少位不同二进制向量
Jaccard 距离JACCARD两个集合的重叠程度集合、标签、二进制特征

工程上可以这样选择:如果文本 Embedding 已做归一化,IPCOSINE的排序通常接近,IP计算更快;如果不确定是否归一化,优先使用COSINE更稳。L2更适合需要空间距离语义的向量场景。

7. 完整入库流程

索引阶段最终要把前面几步串起来:

加载文档 -> 切分文档 -> 生成向量 -> 组装字段 -> 插入 Milvus

伪代码:

import time # 1. 加载文档 docs = loader.load() # 2. 切分文档 chunks = text_splitter.split_documents(docs) # 3. 生成向量 texts = [chunk.page_content for chunk in chunks] vectors = embedding_model.encode(texts) # 4. 组装入库数据 rows = [] for chunk, vector in zip(chunks, vectors): rows.append({ "tenant_id": "default", "doc_id": chunk.metadata["doc_id"], "chunk_id": chunk.metadata["chunk_id"], "source": chunk.metadata["source"], "page": chunk.metadata.get("page", 0), "version": "rag_index_v1", "vector": vector, "text": chunk.page_content, "metadata": chunk.metadata, "created_at": int(time.time()), }) # 5. 插入向量库 client.insert(collection_name="rag_collection", data=rows)

如果使用 BGE-M3 同时生成稠密和稀疏向量,则入库数据可以包含两个向量字段:

rows.append({ "tenant_id": "default", "doc_id": chunk.metadata["doc_id"], "chunk_id": chunk.metadata["chunk_id"], "source": chunk.metadata["source"], "page": chunk.metadata.get("page", 0), "version": "rag_index_v1", "vector": dense_vector, "sparse_vector": sparse_vector, "text": chunk.page_content, "metadata": chunk.metadata, "created_at": int(time.time()), })

8. 入库后验证

向量写入 Milvus 后,不代表索引阶段就结束了,还要确认“数据真的可检索”。

可以按这几项验证:

验证项看什么
插入数量insert_count是否等于本次准备写入的 Chunk 数
向量维度文档向量维度是否和 Collection Schema 的dim一致
字段完整性doc_idchunk_idsourcepageversion是否写入
索引状态稠密向量和稀疏向量是否创建了对应索引
抽样检索随机选一个 Chunk,用相关问题检索,看能否召回
元数据过滤doc_idsourcetenant_id过滤,看结果是否正确

最小验证流程:

插入数据 -> 确认写入数量 -> 确认字段和维度 -> 加载 Collection -> 抽样做一次 Top-K 检索 -> 检查返回 Chunk、score、source、page

如果抽样检索都召回不到刚入库的内容,通常要回头检查:

  • Embedding 模型是否和查询阶段一致。
  • 向量维度是否一致。
  • metric_type 是否和索引一致。
  • metadata filter 是否过滤过严。
  • Chunk 是否切得过碎或过大。

9. 索引版本与更新

知识库不是一次建完就不变,后面会遇到文档新增、文档修改、文档删除、模型升级,所以要管理索引版本。

为什么要有版本

这些变化都会影响检索结果:

  • 换 Embedding 模型。
  • 调整chunk_sizechunk_overlap
  • 修改文档解析方式。
  • 修改 Milvus Schema。
  • 新增或删除文档。

建议给每批索引数据记录版本:

version: rag_index_v1 embedding_model: bge-m3 chunk_size: 800 chunk_overlap: 100 created_at: 当前时间戳

常见更新方式

方式做法适合场景
全量重建重新解析、切分、向量化、写入新版本换模型、换维度、改切分策略
增量更新只处理新增或修改的文档日常文档更新
删除重建删除某个doc_id的旧 Chunk,再写入新 Chunk单篇文档发生变化
版本切换新版本验证通过后,再切换线上检索版本生产环境发布
回滚新版本效果差时,切回旧版本线上检索质量下降

注意:

如果 Embedding 维度变了,不要直接写入旧向量字段。

比如旧模型是768维,新模型是1024维,应该新建 Collection 或新建向量字段,然后重新向量化。

最小更新闭环

计算文档 hash -> 判断文档是否变化 -> 未变化:跳过 -> 新增/变化:重新切分和向量化 -> 删除旧 doc_id 对应 Chunk -> 写入新 Chunk -> 抽样检索验证 -> 更新索引版本

这样可以避免重复入库,也方便后续排查“为什么这次检索结果变了”。

10. 索引阶段检查清单

建知识库时可以按这个清单检查:

文档加载

  • 原文是否完整读取。
  • PDF 页码、文件名、来源是否进入 metadata。
  • 表格和标题是否被正确解析。
  • 是否过滤了页眉、页脚、目录、水印等噪声。

文档切分

  • Chunk 是否太大或太小。
  • 是否保留标题和段落语义。
  • 是否配置了合理 overlap。
  • 抽样查看前几个 Chunk,确认阅读顺序正常。

嵌入编码

  • 文档向量和查询向量是否使用同一模型。
  • 向量维度是否和向量库 Schema 一致。
  • 中文文档是否选择中文效果较好的模型。
  • 是否需要稠密 + 稀疏混合检索。

向量存储

  • 是否存了原文 Chunk。
  • 是否存了 source、page、file_name 等元数据。
  • 是否创建了合适索引。
  • metric_type 是否和检索阶段保持一致。
  • 是否能按元数据过滤。

入库验证

  • 插入数量是否和 Chunk 数一致。
  • 是否能抽样检索到刚入库的内容。
  • sourcepagedoc_id是否能正确返回。
  • metadata filter 是否能正常过滤。

版本更新

  • 是否记录索引版本。
  • 是否记录 Embedding 模型和维度。
  • 是否支持增量更新和删除旧文档。
  • 是否支持新旧版本切换和回滚。

11. 三高设计

索引阶段虽然是离线流程,但真实项目仍然要考虑高并发、高性能、高可用。

高并发

  • 批量文档入库不要阻塞在线问答,使用队列异步处理。
  • Embedding 调用要控制并发,避免打爆模型服务或 API 限流。
  • 大文件解析、OCR、向量化可以拆成任务分片。
  • 在线查询和离线索引最好分开部署,避免互相抢资源。

高性能

  • 文档加载阶段先清洗噪声,减少无效 Chunk。
  • 合理设置chunk_sizechunk_overlap,减少重复向量。
  • 批量调用 Embedding,减少网络和模型启动开销。
  • 向量库使用合适索引,例如 HNSW、倒排索引。
  • 对重复文档做 hash 去重,避免重复入库。

高可用

  • 入库流程要可重试,失败任务要能恢复。
  • 每个 Chunk 要保留 source、page、doc_id,方便回溯。
  • 向量库要定期备份 Collection 或底层存储。
  • 模型、向量库、解析服务都要有超时和错误处理。
  • 索引版本要可追踪,避免新旧数据混乱。
  • 新版本上线前要先抽样检索验证,失败时能回滚旧版本。

12. 记忆口诀

先读:把各种数据源加载成 Document 再切:把长文档切成语义完整的 Chunk 再转:把 Chunk 编码成 Embedding 向量 再存:把向量、原文、元数据写入 VectorStore 再验:抽样检索确认能查到正确 Chunk 再管:用版本控制支持更新和回滚

索引阶段做得越干净,检索阶段就越容易召回正确内容;检索召回越准,生成阶段越不容易胡编。

参考文档

  • Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks
  • LangChain Retrieval
  • LangChain Embedding Models
  • LlamaIndex Embeddings
  • OpenAI Embeddings
  • BGE-M3 Documentation
  • Milvus BGE-M3 Embedding Function
  • Milvus Index Explained
  • Milvus Sparse Vector
  • Milvus Documentation

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

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

立即咨询