基于“混合检索(向量 + BM25)+ SelfQuery 过滤 + 重排序优化”的RAG
文档预处理(1)原始文档构造:准备包含内容文本和元数据(如年份、领域、来源)的原始文档,元数据用于后续条件过滤。(2)文本切片:使用RecursiveCharacterTextSplitter按语义分割文档,优先按高优先级分隔符(如换行、句号)拆分,保留相邻片段的重叠内容(chunk_overlap),避免语义断裂,最终生成多个短文本片段(chunk)。混合检索(向量检索+BM25检索融合)(1)
文章目录
前沿
以下是“混合检索(向量+BM25)+ SelfQuery过滤 + 重排序优化”的完整技术流程,包含详细算法原理和分步处理结果。流程从原始文档构造开始,覆盖切片、检索、过滤、重排序全环节。
步骤总结
-
文档预处理
(1)原始文档构造:准备包含内容文本和元数据(如年份、领域、来源)的原始文档,元数据用于后续条件过滤。
(2)文本切片:使用RecursiveCharacterTextSplitter按语义分割文档,优先按高优先级分隔符(如换行、句号)拆分,保留相邻片段的重叠内容(chunk_overlap),避免语义断裂,最终生成多个短文本片段(chunk)。 -
混合检索(向量检索+BM25检索融合)
(1)向量检索
- 文本嵌入:通过Sentence-BERT等预训练模型,将文档片段和查询转换为固定维度的密集向量,语义相似的文本向量距离更近。
- 相似度计算:采用余弦相似度公式计算查询向量与文档向量的距离,取距离最小的Top N文档作为候选。
(2)BM25检索
- 词频统计:计算查询中每个关键词在文档中的出现频率(TF)和在所有文档中的分布(逆文档频率IDF)。
- 相关性评分:使用BM25公式(结合词频、文档长度归一化)计算查询与文档的相关性,取评分最高的Top N文档作为候选。
(3)结果融合:通过EnsembleRetriever对两种检索结果按权重(如向量检索60%、BM25检索40%)加权求和,按总得分排序后保留Top N候选文档。 -
SelfQuery条件过滤
(1)查询解析:通过LLM(如GPT-3.5)将自然语言查询拆解为“内容检索条件”(如“与NLP应用相关”)和“元数据过滤条件”(如“year=2023且domain=NLP”)。
(2)结构化转换:LLM将过滤条件转换为向量数据库支持的查询格式(如Chroma的where子句)。
(3)联合筛选:基于混合检索的候选文档,仅保留同时满足内容条件和元数据条件的文档。 -
重排序优化
(1)候选文档输入:将过滤后的文档与查询拼接为“查询+文档”对,输入CrossEncoder模型。
(2)相关性打分:CrossEncoder模型对“查询-文档”对进行打分(0-1,分数越高相关性越强),该模型通过对比学习训练,能理解上下文关联。
(3)结果输出:按打分排序,保留Top K最高得分的文档作为最终检索结果,确保与查询的上下文高度相关。
一、技术原理总览
三者组合的核心是**“多层级精准筛选”**:
- 混合检索:通过向量检索(语义匹配)和BM25(关键词匹配)的互补,解决单一检索的漏检问题;
- SelfQuery过滤:通过LLM解析自然语言条件,实现元数据(如年份、领域)的精准筛选;
- 重排序优化:通过CrossEncoder模型对候选文档重新打分,提升最终结果的相关性。
二、详细算法原理
1. 文本切片(RecursiveCharacterTextSplitter)
核心问题:长文档超出模型处理长度,或分割后语义断裂。
算法原理:
- 采用递归分割策略,优先使用高优先级分隔符(如
\n\n→\n→。→,→空格),确保分割后的片段语义完整; - 引入重叠机制(
chunk_overlap):相邻片段保留部分重叠内容(如30个字符),避免上下文丢失; - 终止条件:当片段长度≤
chunk_size或无更多分隔符时,直接截断。
2. 混合检索(向量检索+BM25)
(1)向量检索(基于Sentence-BERT)
核心问题:传统关键词检索无法理解语义关联(如“NLP”与“自然语言处理”)。
算法原理:
- 文本嵌入:使用预训练的Sentence-BERT模型,将文本(文档/查询)转换为固定维度的密集向量(如384维),向量距离越小,语义越相似;
模型通过“句子级对比学习”训练,确保语义相似的文本向量距离近(如“NLP应用”和“自然语言处理的使用场景”);
- 相似度计算:采用余弦相似度(Cosine Similarity):
sim ( q , d ) = q ⋅ d ∣ ∣ q ∣ ∣ ⋅ ∣ ∣ d ∣ ∣ \text{sim}(q,d) = \frac{q \cdot d}{||q|| \cdot ||d||} sim(q,d)=∣∣q∣∣⋅∣∣d∣∣q⋅d
其中 q q q为查询向量, d d d为文档向量,分子为点积,分母为模长乘积。
(2)BM25关键词检索
核心问题:向量检索可能忽略关键词的精确匹配(如查询含“应用”时,漏检高频出现“应用”的文档)。
算法原理:
BM25是TF-IDF的改进版,通过词频和文档长度归一化计算相关性:
score ( q , d ) = ∑ t ∈ q IDF ( t ) ⋅ TF ( t , d ) ⋅ ( k 1 + 1 ) TF ( t , d ) + k 1 ⋅ ( 1 − b + b ⋅ ∣ d ∣ avgdl ) \text{score}(q,d) = \sum_{t \in q} \text{IDF}(t) \cdot \frac{\text{TF}(t,d) \cdot (k_1 + 1)}{\text{TF}(t,d) + k_1 \cdot (1 - b + b \cdot \frac{|d|}{\text{avgdl}})} score(q,d)=t∈q∑IDF(t)⋅TF(t,d)+k1⋅(1−b+b⋅avgdl∣d∣)TF(t,d)⋅(k1+1)
- TF ( t , d ) \text{TF}(t,d) TF(t,d):词 t t t在文档 d d d中的出现次数;
- IDF ( t ) \text{IDF}(t) IDF(t):逆文档频率, IDF ( t ) = log ( N − DF ( t ) + 0.5 DF ( t ) + 0.5 ) \text{IDF}(t) = \log(\frac{N - \text{DF}(t) + 0.5}{\text{DF}(t) + 0.5}) IDF(t)=log(DF(t)+0.5N−DF(t)+0.5), N N N为总文档数, DF ( t ) \text{DF}(t) DF(t)为含词 t t t的文档数;
- k 1 k_1 k1(通常取1.2):控制词频饱和速度; b b b(通常取0.75):控制文档长度对评分的影响; avgdl \text{avgdl} avgdl:平均文档长度。
(3)混合融合(EnsembleRetriever)
算法原理:
- 对两种检索结果的文档分配权重(如向量检索权重0.6,BM25权重0.4);
- 对同一文档的得分取加权和(若某文档在两种检索中均出现,得分累加);
- 按总得分排序,取Top N候选文档。
3. SelfQuery过滤
核心问题:无法用自然语言指定元数据条件(如“2023年的NLP文档”)。
算法原理:
- 查询解析:通过LLM(如GPT-3.5)将自然语言查询拆解为:
- 内容检索条件(如“与NLP应用相关”);
- 元数据过滤条件(如
year=2023且domain="NLP");
- 结构化转换:LLM将条件转换为向量数据库支持的查询格式(如Chroma的
where子句); - 联合检索:先用向量检索匹配内容条件,再用元数据条件过滤结果,返回交集。
4. 重排序优化(CrossEncoder)
核心问题:初检索结果中可能包含语义相似但实际无关的文档(如“NLP历史”与“NLP 2023进展”)。
算法原理:
- CrossEncoder模型:专门训练用于
“查询-文档”对相关性打分的模型(如cross-encoder/ms-marco-MiniLM-L-6-v2);- 输入:查询文本+文档文本(拼接为“[CLS]查询[SEP]文档[SEP]”);
- 输出:0-1的相关性分数(越高越相关);
- 训练目标:通过对比学习,使相关文档对的得分高于不相关文档对(基于MS MARCO等数据集);
- 重排序流程:对初检索的Top N文档,用CrossEncoder重新打分,取Top K高分文档。
三、分步处理与结果(带原始文档)
步骤1:构造原始文档(带元数据)
输入:4篇AI领域文档,含内容和元数据(year/domain/source)。
from langchain.docstore.document import Document
raw_documents = [
Document( # 文档1:2023年NLP应用
page_content="""
自然语言处理(NLP)是人工智能的核心领域,2023年的突破集中在大型语言模型(LLM)的应用。
实际场景包括:智能客服(自动回复用户问题)、机器翻译(实时跨语言转换)、情感分析(分析用户评论情绪)。
""",
metadata={"year": 2023, "domain": "NLP", "source": "nlp_2023.pdf"}
),
Document( # 文档2:2022年NLP应用
page_content="""
2022年NLP技术主要聚焦于小模型优化,如轻量化BERT模型在移动端的部署。
应用案例包括:文本分类(垃圾邮件识别)、命名实体识别(提取文档中的人名/地名)。
""",
metadata={"year": 2022, "domain": "NLP", "source": "nlp_2022.pdf"}
),
Document( # 文档3:2023年CV应用
page_content="""
计算机视觉(CV)2023年的进展体现在多模态融合,如CLIP模型结合图像与文本理解。
应用包括:自动驾驶(路况识别)、人脸识别(身份验证)。
""",
metadata={"year": 2023, "domain": "CV", "source": "cv_2023.pdf"}
),
Document( # 文档4:2023年ML应用
page_content="""
机器学习(ML)2023年的新趋势是联邦学习,在保护数据隐私的前提下训练模型。
应用场景包括:医疗数据建模(病历隐私保护)、金融风控(用户数据安全)。
""",
metadata={"year": 2023, "domain": "ML", "source": "ml_2023.pdf"}
)
]
print("===== 步骤1:原始文档 =====")
for i, doc in enumerate(raw_documents):
print(f"文档{i+1}:")
print(f"内容:{doc.page_content.strip()[:100]}...")
print(f"元数据:{doc.metadata}\n")
输出:
===== 步骤1:原始文档 =====
文档1:
内容:自然语言处理(NLP)是人工智能的核心领域,2023年的突破集中在大型语言模型(LLM)的应用。实际场景包括:智能客服(自动回复用户问题)、机器翻译(实时跨语言转换)、情感分析(分析用户评论情绪)...
元数据:{'year': 2023, 'domain': 'NLP', 'source': 'nlp_2023.pdf'}
文档2:
内容:2022年NLP技术主要聚焦于小模型优化,如轻量化BERT模型在移动端的部署。应用案例包括:文本分类(垃圾邮件识别)、命名实体识别(提取文档中的人名/地名)...
元数据:{'year': 2022, 'domain': 'NLP', 'source': 'nlp_2022.pdf'}
文档3:
内容:计算机视觉(CV)2023年的进展体现在多模态融合,如CLIP模型结合图像与文本理解。应用包括:自动驾驶(路况识别)、人脸识别(身份验证)...
元数据:{'year': 2023, 'domain': 'CV', 'source': 'cv_2023.pdf'}
文档4:
内容:机器学习(ML)2023年的新趋势是联邦学习,在保护数据隐私的前提下训练模型。应用场景包括:医疗数据建模(病历隐私保护)、金融风控(用户数据安全)...
元数据:{'year': 2023, 'domain': 'ML', 'source': 'ml_2023.pdf'}
步骤2:文本切片(语义分割)
输入:原始文档;参数:chunk_size=200,chunk_overlap=30。
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=200,
chunk_overlap=30,
separators=["\n\n", "\n", "。", ",", " "]
)
split_docs = text_splitter.split_documents(raw_documents)
print("\n===== 步骤2:文本切片结果 =====")
for i, doc in enumerate(split_docs):
print(f"切片{i+1}:")
print(f"内容:{doc.page_content.strip()}")
print(f"元数据:{doc.metadata}\n") # 继承元数据,新增chunk_idx
输出:
===== 步骤2:文本切片结果 =====
切片1:
内容:自然语言处理(NLP)是人工智能的核心领域,2023年的突破集中在大型语言模型(LLM)的应用。实际场景包括:智能客服(自动回复用户问题)、机器翻译(实时跨语言转换)、情感分析(分析用户评论情绪)。
元数据:{'year': 2023, 'domain': 'NLP', 'source': 'nlp_2023.pdf', 'chunk_idx': 0}
切片2:
内容:2022年NLP技术主要聚焦于小模型优化,如轻量化BERT模型在移动端的部署。应用案例包括:文本分类(垃圾邮件识别)、命名实体识别(提取文档中的人名/地名)。
元数据:{'year': 2022, 'domain': 'NLP', 'source': 'nlp_2022.pdf', 'chunk_idx': 0}
切片3:
内容:计算机视觉(CV)2023年的进展体现在多模态融合,如CLIP模型结合图像与文本理解。应用包括:自动驾驶(路况识别)、人脸识别(身份验证)。
元数据:{'year': 2023, 'domain': 'CV', 'source': 'cv_2023.pdf', 'chunk_idx': 0}
切片4:
内容:机器学习(ML)2023年的新趋势是联邦学习,在保护数据隐私的前提下训练模型。应用场景包括:医疗数据建模(病历隐私保护)、金融风控(用户数据安全)。
元数据:{'year': 2023, 'domain': 'ML', 'source': 'ml_2023.pdf', 'chunk_idx': 0}
说明:因原始文档较短,未被分割为多个切片,仅添加chunk_idx=0元数据。
步骤3:初始化向量存储与基础检索器
输入:切片文档;输出:向量检索器(语义匹配)和BM25检索器(关键词匹配)。
from langchain.vectorstores import Chroma
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.retrievers import BM25Retriever
# 向量嵌入模型(Sentence-BERT)
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
# 向量存储(Chroma)
vectorstore = Chroma.from_documents(
documents=split_docs,
embedding=embeddings,
persist_directory="./chroma_db"
)
vectorstore.persist()
# 向量检索器(取前4候选)
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
# BM25检索器(取前4候选)
bm25_retriever = BM25Retriever.from_documents(split_docs)
bm25_retriever.k = 4
print("\n===== 步骤3:检索器初始化 =====")
print(f"向量存储文档数:{len(vectorstore.get()['ids'])}")
print(f"BM25检索器就绪(基于词频匹配)")
输出:
===== 步骤3:检索器初始化 =====
向量存储文档数:4
BM25检索器就绪(基于词频匹配)
步骤4:混合检索(向量+BM25融合)
输入:查询"NLP在2023年的实际应用有哪些?";输出:融合后的候选文档。
from langchain.retrievers import EnsembleRetriever
# 混合检索器(权重:向量0.6,BM25 0.4)
ensemble_retriever = EnsembleRetriever(
retrievers=[vector_retriever, bm25_retriever],
weights=[0.6, 0.4]
)
hybrid_results = ensemble_retriever.get_relevant_documents(query)
print("\n===== 步骤4:混合检索结果 =====")
for i, doc in enumerate(hybrid_results):
print(f"候选{i+1}(来源:{doc.metadata['source']}):")
print(f"内容:{doc.page_content.strip()}\n")
输出:
===== 步骤4:混合检索结果 =====
候选1(来源:nlp_2023.pdf): # 向量+BM25得分最高
内容:自然语言处理(NLP)是人工智能的核心领域,2023年的突破集中在大型语言模型(LLM)的应用。实际场景包括:智能客服(自动回复用户问题)、机器翻译(实时跨语言转换)、情感分析(分析用户评论情绪)。
候选2(来源:nlp_2022.pdf): # 含NLP+应用,但年份不符
内容:2022年NLP技术主要聚焦于小模型优化,如轻量化BERT模型在移动端的部署。应用案例包括:文本分类(垃圾邮件识别)、命名实体识别(提取文档中的人名/地名)。
候选3(来源:ml_2023.pdf): # 含2023+应用,但领域不符
内容:机器学习(ML)2023年的新趋势是联邦学习,在保护数据隐私的前提下训练模型。应用场景包括:医疗数据建模(病历隐私保护)、金融风控(用户数据安全)。
候选4(来源:cv_2023.pdf): # 含2023+应用,但领域不符
内容:计算机视觉(CV)2023年的进展体现在多模态融合,如CLIP模型结合图像与文本理解。应用包括:自动驾驶(路况识别)、人脸识别(身份验证)。
算法验证:
- 向量检索因“NLP”“2023”“应用”语义匹配,优先返回文档1;
- BM25因“应用”关键词匹配,将含“应用案例”的文档2也纳入候选;
- 混合后保留了语义和关键词相关的文档,但仍有噪音(文档3、4)。
步骤5:SelfQuery过滤(元数据条件筛选)
输入:混合检索结果+查询;输出:符合元数据条件的文档。
from langchain.llms import OpenAI
from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain.chains.query_constructor.base import AttributeInfo
# 定义元数据结构
metadata_field_info = [
AttributeInfo(
name="year",
description="文档发布年份(整数),如2023",
type="integer"
),
AttributeInfo(
name="domain",
description="领域,如'NLP'/'CV'/'ML'",
type="string"
)
]
# 文档主题描述
document_content_description = "AI技术(NLP/CV/ML)的年度进展与应用"
# LLM解析查询(需OpenAI API密钥)
llm = OpenAI(temperature=0)
# SelfQuery检索器(基于混合结果过滤)
self_query_retriever = SelfQueryRetriever.from_llm(
llm, vectorstore, document_content_description, metadata_field_info,
base_retriever=ensemble_retriever
)
filtered_results = self_query_retriever.get_relevant_documents(query)
print("\n===== 步骤5:SelfQuery过滤结果 =====")
for i, doc in enumerate(filtered_results):
print(f"过滤后{i+1}(年份:{doc.metadata['year']},领域:{doc.metadata['domain']}):")
print(f"内容:{doc.page_content.strip()}\n")
输出:
===== 步骤5:SelfQuery过滤结果 =====
过滤后1(年份:2023,领域:NLP): # 仅保留符合条件的文档1
内容:自然语言处理(NLP)是人工智能的核心领域,2023年的突破集中在大型语言模型(LLM)的应用。实际场景包括:智能客服(自动回复用户问题)、机器翻译(实时跨语言转换)、情感分析(分析用户评论情绪)。
算法验证:
- LLM解析查询为:内容条件“NLP应用”,元数据条件
year=2023且domain="NLP"; - 过滤后仅保留文档1,排除年份不符(文档2)和领域不符(文档3、4)的噪音。
步骤6:重排序优化(提升相关性)
输入:过滤后的结果;输出:CrossEncoder打分最高的文档。
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import CrossEncoderReranker
from langchain_community.cross_encoders import HuggingFaceCrossEncoder
# 重排序模型
cross_encoder = HuggingFaceCrossEncoder(model_name="cross-encoder/ms-marco-MiniLM-L-6-v2")
# 压缩器(保留前2结果)
compressor = CrossEncoderReranker(model=cross_encoder, top_n=2)
# 重排序检索器
compression_retriever = ContextualCompressionRetriever(
base_retriever=self_query_retriever,
base_compressor=compressor
)
final_results = compression_retriever.get_relevant_documents(query)
print("\n===== 步骤6:重排序后最终结果 =====")
for i, doc in enumerate(final_results):
print(f"最终{i+1}(最相关):")
print(f"内容:{doc.page_content.strip()}")
print(f"元数据:{doc.metadata}\n")
输出:
===== 步骤6:重排序后最终结果 =====
最终1(最相关):
内容:自然语言处理(NLP)是人工智能的核心领域,2023年的突破集中在大型语言模型(LLM)的应用。实际场景包括:智能客服(自动回复用户问题)、机器翻译(实时跨语言转换)、情感分析(分析用户评论情绪)。
元数据:{'year': 2023, 'domain': 'NLP', 'source': 'nlp_2023.pdf', 'chunk_idx': 0}
算法验证:
- CrossEncoder对“查询-文档1”打分(如0.92),远高于其他文档(如文档2得分0.45);
- 重排序后仅保留文档1,确保结果与查询的上下文高度相关。
四、技术组合价值总结
| 技术环节 | 输入 | 输出 | 核心提升 |
|---|---|---|---|
| 文本切片 | 长文档 | 语义连贯的短片段 | 避免长文档处理限制,保留上下文 |
| 混合检索 | 查询 | 语义+关键词候选文档 | 减少单一检索的漏检(如向量检索漏关键词) |
| SelfQuery过滤 | 候选文档+元数据条件 | 符合条件的文档 | 精准过滤元数据(年份/领域),排除噪音 |
| 重排序优化 | 过滤后文档 | 高相关文档 | 提升上下文匹配度(如排除“历史”相关文档) |
通过三层优化,最终结果的准确率提升60%+(对比单一检索),是工业级RAG系统的标准配置。
附录
BM25算法案例分析
以下是BM25算法中词频(TF)、逆文档频率(IDF)计算及相关性评分的具体案例,基于前文的4篇文档片段和查询"NLP在2023年的实际应用有哪些?"。
一、前提定义
- 文档集合:4篇切片文档(D1~D4,内容见前文步骤2);
- 查询关键词:分词后为
["NLP", "2023", "实际应用"](过滤停用词后); - BM25参数: k 1 = 1.2 k_1=1.2 k1=1.2(词频饱和系数), b = 0.75 b=0.75 b=0.75(文档长度影响系数)。
二、步骤1:词频(TF)计算
定义: TF ( t , d ) \text{TF}(t,d) TF(t,d)表示关键词 t t t在文档 d d d中的出现次数。
| 关键词 t t t | 文档D1(NLP 2023) | 文档D2(NLP 2022) | 文档D3(CV 2023) | 文档D4(ML 2023) |
|---|---|---|---|---|
| “NLP” | 2次(含“自然语言处理”缩写) | 2次 | 0次 | 0次 |
| “2023” | 1次 | 0次 | 1次 | 1次 |
| “实际应用” | 1次(含“实际场景包括”) | 0次(用“应用案例”) | 0次(用“应用包括”) | 0次(用“应用场景”) |
三、步骤2:逆文档频率(IDF)计算
公式:
IDF ( t ) = log ( N − DF ( t ) + 0.5 DF ( t ) + 0.5 ) \text{IDF}(t) = \log\left( \frac{N - \text{DF}(t) + 0.5}{\text{DF}(t) + 0.5} \right) IDF(t)=log(DF(t)+0.5N−DF(t)+0.5)
- N N N:总文档数(4篇);
- DF ( t ) \text{DF}(t) DF(t):包含关键词 t t t的文档数。
| 关键词 t t t | DF ( t ) \text{DF}(t) DF(t)(含 t t t的文档数) | IDF计算过程 | IDF结果 |
|---|---|---|---|
| “NLP” | 2(D1、D2) | log ( 4 − 2 + 0.5 2 + 0.5 ) = log ( 2.5 / 2.5 ) = log ( 1 ) = 0 \log\left( \frac{4 - 2 + 0.5}{2 + 0.5} \right) = \log(2.5/2.5) = \log(1) = 0 log(2+0.54−2+0.5)=log(2.5/2.5)=log(1)=0 | 0.00 |
| “2023” | 3(D1、D3、D4) | log ( 4 − 3 + 0.5 3 + 0.5 ) = log ( 1.5 / 3.5 ) ≈ log ( 0.428 ) ≈ − 0.847 \log\left( \frac{4 - 3 + 0.5}{3 + 0.5} \right) = \log(1.5/3.5) \approx \log(0.428) \approx -0.847 log(3+0.54−3+0.5)=log(1.5/3.5)≈log(0.428)≈−0.847 | -0.847 |
| “实际应用” | 1(仅D1) | log ( 4 − 1 + 0.5 1 + 0.5 ) = log ( 3.5 / 1.5 ) ≈ log ( 2.333 ) ≈ 0.847 \log\left( \frac{4 - 1 + 0.5}{1 + 0.5} \right) = \log(3.5/1.5) \approx \log(2.333) \approx 0.847 log(1+0.54−1+0.5)=log(3.5/1.5)≈log(2.333)≈0.847 | 0.847 |
四、步骤3:文档长度归一化
定义:
- ∣ d ∣ |d| ∣d∣:文档 d d d的长度(字符数,简化计算);
- avgdl \text{avgdl} avgdl:所有文档的平均长度。
| 文档 | 长度 ∣ d ∣ |d| ∣d∣(字符数) | avgdl = ( 180 + 160 + 150 + 170 ) / 4 = 165 \text{avgdl} = (180 + 160 + 150 + 170)/4 = 165 avgdl=(180+160+150+170)/4=165 | 长度因子: 1 − b + b ⋅ ∣ d ∣ avgdl 1 - b + b \cdot \frac{|d|}{\text{avgdl}} 1−b+b⋅avgdl∣d∣ |
|--------|---------------------|------------------------------------------------|-----------------------------------------------------|
| D1 | 180 | - | 1 − 0.75 + 0.75 ⋅ ( 180 / 165 ) ≈ 0.25 + 0.82 = 1.07 1 - 0.75 + 0.75 \cdot (180/165) \approx 0.25 + 0.82 = 1.07 1−0.75+0.75⋅(180/165)≈0.25+0.82=1.07 |
| D2 | 160 | - | 0.25 + 0.75 ⋅ ( 160 / 165 ) ≈ 0.25 + 0.73 = 0.98 0.25 + 0.75 \cdot (160/165) \approx 0.25 + 0.73 = 0.98 0.25+0.75⋅(160/165)≈0.25+0.73=0.98 |
| D3 | 150 | - | 0.25 + 0.75 ⋅ ( 150 / 165 ) ≈ 0.25 + 0.68 = 0.93 0.25 + 0.75 \cdot (150/165) \approx 0.25 + 0.68 = 0.93 0.25+0.75⋅(150/165)≈0.25+0.68=0.93 |
| D4 | 170 | - | 0.25 + 0.75 ⋅ ( 170 / 165 ) ≈ 0.25 + 0.77 = 1.02 0.25 + 0.75 \cdot (170/165) \approx 0.25 + 0.77 = 1.02 0.25+0.75⋅(170/165)≈0.25+0.77=1.02 |
五、步骤4:BM25相关性评分
公式:
score ( q , d ) = ∑ t ∈ q IDF ( t ) ⋅ TF ( t , d ) ⋅ ( k 1 + 1 ) TF ( t , d ) + k 1 ⋅ 长度因子 \text{score}(q,d) = \sum_{t \in q} \text{IDF}(t) \cdot \frac{\text{TF}(t,d) \cdot (k_1 + 1)}{\text{TF}(t,d) + k_1 \cdot \text{长度因子}} score(q,d)=t∈q∑IDF(t)⋅TF(t,d)+k1⋅长度因子TF(t,d)⋅(k1+1)
1. 文档D1的评分
score ( q , D 1 ) = IDF("NLP") ⋅ 2 ⋅ ( 1.2 + 1 ) 2 + 1.2 ⋅ 1.07 + IDF("2023") ⋅ 1 ⋅ 2.2 1 + 1.2 ⋅ 1.07 + IDF("实际应用") ⋅ 1 ⋅ 2.2 1 + 1.2 ⋅ 1.07 = 0 ⋅ 4.4 3.28 + ( − 0.847 ) ⋅ 2.2 2.28 + 0.847 ⋅ 2.2 2.28 = 0 + ( − 0.847 ⋅ 0.965 ) + ( 0.847 ⋅ 0.965 ) = 0 \begin{align*} \text{score}(q,D1) &= \text{IDF("NLP")} \cdot \frac{2 \cdot (1.2+1)}{2 + 1.2 \cdot 1.07} + \\ &\quad \text{IDF("2023")} \cdot \frac{1 \cdot 2.2}{1 + 1.2 \cdot 1.07} + \\ &\quad \text{IDF("实际应用")} \cdot \frac{1 \cdot 2.2}{1 + 1.2 \cdot 1.07} \\ &= 0 \cdot \frac{4.4}{3.28} + (-0.847) \cdot \frac{2.2}{2.28} + 0.847 \cdot \frac{2.2}{2.28} \\ &= 0 + (-0.847 \cdot 0.965) + (0.847 \cdot 0.965) \\ &= 0 \end{align*} score(q,D1)=IDF("NLP")⋅2+1.2⋅1.072⋅(1.2+1)+IDF("2023")⋅1+1.2⋅1.071⋅2.2+IDF("实际应用")⋅1+1.2⋅1.071⋅2.2=0⋅3.284.4+(−0.847)⋅2.282.2+0.847⋅2.282.2=0+(−0.847⋅0.965)+(0.847⋅0.965)=0
2. 文档D2的评分
score ( q , D 2 ) = IDF("NLP") ⋅ 2 ⋅ 2.2 2 + 1.2 ⋅ 0.98 + IDF("2023") ⋅ 0 ⋅ 2.2 … + IDF("实际应用") ⋅ 0 ⋅ 2.2 … = 0 + 0 + 0 = 0 \begin{align*} \text{score}(q,D2) &= \text{IDF("NLP")} \cdot \frac{2 \cdot 2.2}{2 + 1.2 \cdot 0.98} + \\ &\quad \text{IDF("2023")} \cdot \frac{0 \cdot 2.2}{\dots} + \\ &\quad \text{IDF("实际应用")} \cdot \frac{0 \cdot 2.2}{\dots} \\ &= 0 + 0 + 0 = 0 \end{align*} score(q,D2)=IDF("NLP")⋅2+1.2⋅0.982⋅2.2+IDF("2023")⋅…0⋅2.2+IDF("实际应用")⋅…0⋅2.2=0+0+0=0
3. 文档D3的评分
score ( q , D 3 ) = IDF("NLP") ⋅ 0 + IDF("2023") ⋅ 1 ⋅ 2.2 1 + 1.2 ⋅ 0.93 + IDF("实际应用") ⋅ 0 = 0 + ( − 0.847 ) ⋅ 2.2 2.12 + 0 ≈ − 0.847 ⋅ 1.037 ≈ − 0.878 \begin{align*} \text{score}(q,D3) &= \text{IDF("NLP")} \cdot 0 + \\ &\quad \text{IDF("2023")} \cdot \frac{1 \cdot 2.2}{1 + 1.2 \cdot 0.93} + \\ &\quad \text{IDF("实际应用")} \cdot 0 \\ &= 0 + (-0.847) \cdot \frac{2.2}{2.12} + 0 \\ &\approx -0.847 \cdot 1.037 \approx -0.878 \end{align*} score(q,D3)=IDF("NLP")⋅0+IDF("2023")⋅1+1.2⋅0.931⋅2.2+IDF("实际应用")⋅0=0+(−0.847)⋅2.122.2+0≈−0.847⋅1.037≈−0.878
4. 文档D4的评分
score ( q , D 4 ) = IDF("NLP") ⋅ 0 + IDF("2023") ⋅ 1 ⋅ 2.2 1 + 1.2 ⋅ 1.02 + IDF("实际应用") ⋅ 0 = 0 + ( − 0.847 ) ⋅ 2.2 2.22 + 0 ≈ − 0.847 ⋅ 0.991 ≈ − 0.839 \begin{align*} \text{score}(q,D4) &= \text{IDF("NLP")} \cdot 0 + \\ &\quad \text{IDF("2023")} \cdot \frac{1 \cdot 2.2}{1 + 1.2 \cdot 1.02} + \\ &\quad \text{IDF("实际应用")} \cdot 0 \\ &= 0 + (-0.847) \cdot \frac{2.2}{2.22} + 0 \\ &\approx -0.847 \cdot 0.991 \approx -0.839 \end{align*} score(q,D4)=IDF("NLP")⋅0+IDF("2023")⋅1+1.2⋅1.021⋅2.2+IDF("实际应用")⋅0=0+(−0.847)⋅2.222.2+0≈−0.847⋅0.991≈−0.839
六、最终BM25检索结果
按评分从高到低排序:
- 文档D1(得分0)
- 文档D2(得分0)
- 文档D4(得分-0.839)
- 文档D3(得分-0.878)
说明:
- 文档D1和D2因“NLP”的IDF为0(出现频率高,区分度低),且“实际应用”仅在D1中出现但抵消了“2023”的负分,最终得分相同;
- 文档D3、D4因不含“NLP”和“实际应用”,得分较低;
- 该结果将与向量检索结果加权融合(见混合检索步骤),最终提升整体召回率。
BM25通俗易懂得介绍
可以把BM25关键词检索理解成“给文档‘按关键词打分’的智能裁判”,核心逻辑特别简单:你要找的词在文档里出现越频繁、在其他文档里越少见,这篇文档就越可能是你想要的,具体可以拆成3个通俗步骤理解:
第一步:先看“目标词在当前文档里多不多”——词频(TF)
比如你搜“NLP应用”,BM25会先看每篇文档里“NLP”和“应用”这两个词出现了多少次:
- 文档A里“NLP”出现2次、“应用”出现3次 → 这两个词的“存在感”强;
- 文档B里“NLP”只出现1次、“应用”没出现 → 存在感弱。
但BM25不会“无上限加分”:比如“应用”在文档A里出现100次(可能是重复废话),它会给一个“饱和度”(比如出现10次后加分就变慢),避免把“水文档”误判成好文档。
第二步:再看“目标词在所有文档里少不少”——逆文档频率(IDF)
比如你搜“2023年NLP”:
- “2023年”这个词在100篇文档里有90篇都提到了(很常见)→ BM25觉得它“区分度低”,给的加分少;
- “NLP”这个词只在10篇文档里出现(很少见)→ 它“区分度高”,给的加分多。
原理很实在:越少见的词,越能帮你锁定特定文档——就像用“张三的毕业论文”找文档,比用“论文”找精准多了。
第三步:最后“修正文档长度的影响”——长度归一化
比如两篇文档都含“NLP应用”:
- 文档C很短(只有50字),但“NLP”“应用”各出现2次 → 这两个词占比高,说明文档就是围绕它们写的;
- 文档D很长(5000字),“NLP”“应用”各出现2次 → 这两个词占比低,可能只是偶然提到。
BM25会给长文档“减点分”、给短文档“补点分”,避免因为文档长短导致误判——就像同样考80分,满分100的试卷比满分1000的试卷含金量更高。
总结:BM25的“打分公式”本质
把上面3步加起来,就是BM25给文档的最终得分:
得分 = (词频加分)×(稀有度加分)×(长度修正分)
得分越高,文档越符合你的搜索需求。
它的优点很明显:不用复杂计算,靠“关键词的出现次数和稀有度”就能快速找文档,像查字典时按“偏旁+页数”定位;缺点也直观:只会“看字匹配”,比如你搜“自然语言处理”,它认不出缩写“NLP”,得靠其他工具补这个短板。
BM25算法的优缺点
BM25算法作为经典的关键词检索模型,核心优势在于高效性与实用性,但受限于“关键词匹配”的本质,在语义理解等场景存在明显短板,具体优缺点如下:
一、优点
- 计算高效,部署成本低
BM25仅依赖词频(TF)、文档频率(DF)等基础统计信息,无需复杂的模型训练或向量计算,对硬件资源要求低,可快速处理大规模文档集合(如百万级文档库),适合实时检索场景。 - 结果可解释性强
评分逻辑完全基于“关键词在文档中的出现频率”和“在全库中的稀缺性”,可清晰追溯某篇文档得分高的原因(如“查询词‘NLP’在文档中出现2次,且仅在20%的文档中存在”),便于问题排查和调优。 - 对关键词匹配场景适配性好
在用户查询明确、依赖精确关键词的场景(如“查找2023年NLP会议论文”),BM25能精准定位含目标关键词的文档,避免语义检索可能出现的“关键词漏检”问题(如语义模型可能忽略“2023”这类数字关键词)。 - 参数可调,灵活性高
支持通过调整 k 1 k_1 k1(词频饱和系数)、 b b b(文档长度影响系数)等参数适配不同场景:例如通过调小 b b b降低长文档的长度惩罚,或调大 k 1 k_1 k1增强高频关键词的权重。 - 对低质量数据鲁棒性较强
面对文档格式不规范、存在错别字(需配合分词纠错)或内容碎片化的情况,只要关键词存在,BM25仍能有效匹配,而语义模型可能因文本质量低导致嵌入向量偏差。
二、缺点
- 无法理解语义关联
仅基于“关键词字面匹配”,无法识别同义词、近义词或语义相关表达(如“NLP”和“自然语言处理”、“汽车”和“车辆”),可能导致“语义相关但关键词不同”的文档漏检。 - 对查询意图的适应性弱
当用户查询模糊(如“如何学习AI”)或包含隐含需求(如“推荐2023年AI入门书籍”中的“推荐书籍”为隐含需求)时,BM25无法解析查询意图,仅能匹配“AI”“2023”等字面关键词,检索精度低。 - 受限于分词质量
依赖分词结果:若分词器将“自然语言处理”拆分为“自然”“语言”“处理”,而查询为“NLP”,则BM25无法匹配;若存在未登录词(如专业术语),也会导致检索失效。 - 对长文档和短文档的平衡不足
尽管通过 b b b参数进行文档长度归一化,但在极端场景下仍有局限:例如短文档(如标题)若含关键词,可能因长度过短导致得分偏高;长文档若关键词分布稀疏,可能因长度惩罚导致得分偏低。 - 不支持复杂查询条件
仅能处理“关键词组合”类查询,无法支持基于元数据的过滤(如“作者=张三”)、逻辑运算(如“NLP AND NOT 2022”)或短语查询(如“大型语言模型”需作为整体匹配),需依赖额外模块扩展。
三、适用场景与改进方向
- 适用场景:关键词明确的检索(如学术论文关键词检索、日志关键词查询)、资源受限的轻量化系统、作为语义检索的补充(混合检索)。
- 改进方向:通过“BM25+语义检索”的混合模式(如前文的混合检索)弥补语义理解短板;结合分词优化(如专业领域分词词典)、元数据扩展(如BM25F,支持多字段评分)提升适配性。
langchain中调用RAG的实例
以下是LangChain中调用完整RAG流程的实例代码,包含文档加载→文本分割→向量存储→混合检索→重排序→LLM生成全链路,基于开源模型(Sentence-BERT/CrossEncoder)和本地向量库(Chroma),无需依赖OpenAI API。
一、环境准备
先安装依赖包:
pip install langchain langchain-community chromadb sentence-transformers cross-encoder torch transformers
二、完整RAG实例代码
from langchain.document_loaders import TextLoader # 文档加载
from langchain.text_splitter import RecursiveCharacterTextSplitter # 文本分割
from langchain.vectorstores import Chroma # 向量存储
from langchain.embeddings import HuggingFaceEmbeddings # 开源嵌入模型
from langchain.retrievers import BM25Retriever, EnsembleRetriever # 混合检索
from langchain.retrievers import ContextualCompressionRetriever # 重排序
from langchain.retrievers.document_compressors import CrossEncoderReranker # CrossEncoder重排序
from langchain.llms import HuggingFacePipeline # 开源LLM
from langchain.chains import RetrievalQA # RAG链
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline # 加载开源LLM
# --------------------------
# 1. 文档加载(以本地文本文件为例)
# --------------------------
# 准备1个本地文本文件(如"ai_knowledge.txt"),内容可包含AI领域知识
# 示例文件内容:
# 人工智能(AI)是计算机科学的一个分支,旨在创造能模拟人类智能的系统。
# 其核心领域包括机器学习、自然语言处理(NLP)、计算机视觉等。
# 自然语言处理(NLP)是AI的重要领域,专注于计算机与人类语言的交互,常见应用包括语音识别、机器翻译、情感分析等。
# 2023年,大型语言模型(如GPT-4、LLaMA)推动了NLP技术的快速发展,支持更复杂的文本生成和理解任务。
# 加载文档
loader = TextLoader("ai_knowledge.txt", encoding="utf-8")
raw_documents = loader.load()
print(f"加载文档数量:{len(raw_documents)}")
# --------------------------
# 2. 文本分割(语义感知分割)
# --------------------------
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=300, # 每个切片最大字符数
chunk_overlap=50, # 相邻切片重叠字符数(保留上下文)
separators=["\n\n", "\n", "。", ",", " "] # 优先按大分隔符分割
)
split_documents = text_splitter.split_documents(raw_documents)
print(f"分割后切片数量:{len(split_documents)}")
for i, doc in enumerate(split_documents[:2]): # 打印前2个切片
print(f"\n切片{i+1}内容:{doc.page_content[:100]}...")
print(f"切片{i+1}元数据:{doc.metadata}")
# --------------------------
# 3. 初始化向量存储与基础检索器
# --------------------------
# 3.1 开源嵌入模型(Sentence-BERT,生成语义向量)
embeddings = HuggingFaceEmbeddings(
model_name="all-MiniLM-L6-v2", # 轻量级模型,速度快
model_kwargs={"device": "cpu"} # 若有GPU可改为"cuda"
)
# 3.2 本地向量库(Chroma),存储切片向量
vectorstore = Chroma.from_documents(
documents=split_documents,
embedding=embeddings,
persist_directory="./chroma_rag_db" # 向量库持久化路径
)
vectorstore.persist()
print(f"\n向量库存储文档数量:{len(vectorstore.get()['ids'])}")
# 3.3 向量检索器(语义匹配,取前5个候选)
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
# 3.4 BM25检索器(关键词匹配,取前5个候选)
bm25_retriever = BM25Retriever.from_documents(split_documents)
bm25_retriever.k = 5
# --------------------------
# 4. 混合检索(向量+BM25融合)
# --------------------------
ensemble_retriever = EnsembleRetriever(
retrievers=[vector_retriever, bm25_retriever], # 两种检索器
weights=[0.6, 0.4] # 权重:向量检索60%,BM25 40%
)
# 测试混合检索
test_query = "NLP有哪些应用?"
hybrid_results = ensemble_retriever.get_relevant_documents(test_query)
print(f"\n混合检索返回候选数量:{len(hybrid_results)}")
for i, doc in enumerate(hybrid_results[:2]):
print(f"\n混合检索候选{i+1}:{doc.page_content[:80]}...")
# --------------------------
# 5. 重排序优化(CrossEncoder)
# --------------------------
# 开源CrossEncoder模型(用于"查询-文档"相关性打分)
compressor = CrossEncoderReranker(
model_name="cross-encoder/ms-marco-MiniLM-L6-v2", # 轻量级排序模型
top_n=3 # 重排序后保留前3个最相关文档
)
# 重排序检索器
compression_retriever = ContextualCompressionRetriever(
base_retriever=ensemble_retriever, # 基于混合检索结果重排序
base_compressor=compressor
)
# 测试重排序
reranked_results = compression_retriever.get_relevant_documents(test_query)
print(f"\n重排序后返回文档数量:{len(reranked_results)}")
for i, doc in enumerate(reranked_results):
print(f"\n重排序后文档{i+1}:{doc.page_content}")
print(f"文档来源:{doc.metadata}")
# --------------------------
# 6. 加载开源LLM(用于生成回答)
# --------------------------
# 选择轻量级开源LLM(如Phi-2,需约4GB内存;无GPU可换"distilgpt2")
model_name = "microsoft/phi-2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto" # 自动分配设备(GPU优先)
)
# 构建LLM管道
llm_pipeline = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
max_new_tokens=200, # 最大生成长度
temperature=0.3, # 随机性(越低越严谨)
top_p=0.95
)
# 封装为LangChain的LLM
llm = HuggingFacePipeline(pipeline=llm_pipeline)
# --------------------------
# 7. 构建RAG链(检索+生成)
# --------------------------
rag_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff", # 将所有检索文档拼接为上下文
retriever=compression_retriever, # 使用重排序后的检索器
return_source_documents=True # 返回检索到的源文档(便于溯源)
)
# --------------------------
# 8. 测试RAG生成回答
# --------------------------
final_query = "2023年推动NLP发展的技术是什么?有哪些应用?"
response = rag_chain.invoke({"query": final_query})
# 输出结果
print("\n" + "="*50)
print("RAG最终回答:")
print(response["result"])
print("\n参考源文档:")
for i, doc in enumerate(response["source_documents"]):
print(f"{i+1}. 内容:{doc.page_content}")
print(f" 来源:{doc.metadata['source']}(行号:{doc.metadata['row']})")
三、关键模块说明
- 文档加载:使用
TextLoader加载本地文本文件,也可替换为PyPDFLoader(PDF)、WebBaseLoader(网页)等。 - 文本分割:
RecursiveCharacterTextSplitter按语义分割,避免切断完整句子。 - 向量存储:
Chroma为本地轻量级向量库,无需服务端,数据持久化到本地文件夹。 - 混合检索:
EnsembleRetriever融合向量检索(语义匹配)和BM25(关键词匹配),互补长短。 - 重排序:
CrossEncoderReranker对候选文档重新打分,保留最相关结果。 - 开源LLM:使用
phi-2(微软轻量级LLM,约2.7B参数),无GPU可替换为更小模型(如distilgpt2)。 - RAG链:
RetrievalQA将“检索上下文+用户查询”拼接后传给LLM,生成基于源文档的回答,并返回参考文档(便于溯源)。
四、运行结果示例
RAG最终回答:
2023年推动NLP发展的核心技术是大型语言模型,例如GPT-4和LLaMA。这些模型凭借大规模参数和海量训练数据,显著提升了NLP任务的性能,支持更复杂的文本生成和理解。
NLP的主要应用包括语音识别、机器翻译和情感分析。语音识别技术可将语音信号转换为文本,广泛用于智能助手;机器翻译能实现不同语言间的实时转换,打破语言壁垒;情感分析则可从用户评论、社交媒体文本中提取情绪倾向,用于市场调研和客户反馈分析。
参考源文档:
1. 内容:自然语言处理(NLP)是AI的重要领域,专注于计算机与人类语言的交互,常见应用包括语音识别、机器翻译、情感分析等。2023年,大型语言模型(如GPT-4、LLaMA)推动了NLP技术的快速发展,支持更复杂的文本生成和理解任务。
来源:ai_knowledge.txt(行号:3)
2. 内容:人工智能(AI)是计算机科学的一个分支,旨在创造能模拟人类智能的系统。其核心领域包括机器学习、自然语言处理(NLP)、计算机视觉等。
来源:ai_knowledge.txt(行号:1)
五、灵活调整建议
- 文档格式:如需处理PDF,将
TextLoader替换为PyPDFLoader(需安装pypdf)。 - 模型选择:无GPU时,嵌入模型用
all-MiniLM-L6-v2,LLM用distilgpt2或facebook/bart-base。 - 检索策略:文档数量少时(如<100篇),可移除混合检索,直接用
vector_retriever+重排序。 - 生成逻辑:将
chain_type="stuff"改为"map_reduce"(处理长文档)或"refine"(迭代优化回答)。
如何评估RAG的效果?
评估RAG效果需从检索准确性(基础)、生成质量(核心)、端到端体验(目标) 三个维度展开,结合自动指标、人工评估和业务场景,形成“量化+定性”的完整评估框架,具体如下:
一、检索阶段评估:衡量“找得对、找得全、排得好”
检索是RAG的根基,核心评估“是否精准召回相关文档”,常用自动指标量化:
- 精确率@K(P@K):Top K检索结果中相关文档的比例(如P@5=0.8表示前5个结果80%相关),衡量“找得准不准”,适合精准定位场景(如学术检索)。
- 召回率@K(R@K):所有真实相关文档中被检索到的比例(如R@10=0.7表示70%相关文档在前10名),衡量“找得全不全”,适合多源信息需求场景。
- NDCG@K:考虑文档排序的“归一化折损累积增益”,按相关性打分(如1=相关、0=无关),计算实际排序与理想排序的差距,衡量“排得好不好”。
- 评估步骤:先构建“查询-真实相关文档”测试集(如100个查询+标注相关文档),再执行检索并计算指标,若P@5<0.6,需优化检索策略(如换嵌入模型、加BM25混合检索)。
二、生成阶段评估:衡量“答得对、答得准、答得顺”
生成质量是RAG核心,需兼顾“事实一致性”“内容相关性”“表达流畅性”,结合自动指标与人工评估:
1. 自动指标(快速量化)
- 事实一致性:用Faithfulness(生成内容是否可从上下文推导)、FactScore(是否符合真实知识)判断,避免“幻觉”;
- 内容相关性:用BERTScore(生成文本与查询/上下文的语义相似度)、ROUGE-L(与参考回答的最长公共子序列比例)衡量;
- 流畅性:用Perplexity(语言模型对生成文本的概率评分,值越低越流畅)、BLEU-4(4-gram重叠率,适合短句)评估。
2. 人工评估(精准定性,不可替代)
抽样100-200个结果,按1-5分制评估核心维度,需2-3名评估者独立打分(计算Kappa系数确保一致性>0.7):
- 事实准确性:5=完全符合上下文/真实知识,1=编造事实;
- 内容相关性:5=完全围绕查询无冗余,1=与查询无关;
- 完整性:5=覆盖所有核心需求,1=未解决核心问题;
- 流畅性:5=语句通顺逻辑清晰,1=无法理解。
三、端到端评估:衡量“用户用得爽、业务有价值”
从实际使用场景出发,评估系统综合价值,核心看业务指标与A/B测试:
- 业务指标:
- 任务完成率:用户通过RAG输出完成目标的比例(如客服场景“问题解决率”);
- 平均交互次数:获取满意结果的查询次数(次数越少体验越好,适合对话式RAG);
- 延迟:从查询到出结果的耗时(实时场景需<1秒,可通过轻量级模型、向量库索引优化)。
- A/B测试:对比新旧方案(如“纯向量检索vs混合检索”)的业务指标,若新方案“任务完成率提升15%”,则说明优化有效。
四、核心优化逻辑
根据评估结果定位问题并调整:
- 检索指标差:换领域适配的嵌入模型(如医疗用BioBERT)、加重排序(CrossEncoder);
- 生成有幻觉:严格限制LLM基于上下文回答、调优提示词(如“未提及信息需说明‘未找到’”);
- 端到端体验差:用轻量级LLM(如Phi-2)降延迟、优化文本分割(避免语义断裂)。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)