![](https://s5-media.51cto.com/aigc/pc/static/noavatar.gif)
2W8000字深度剖析25种RAG变体:全网最全没有之一 精华
主流RAG框架可以分为以下五个主要的进化方向:成本控制型(适合初创公司)、实时互动型(适用于财经/新闻场景)、域专家类型、认知增强型、安全与合规类型。接下来,让我们详细了解一下这25种RAG变体。
1. 标准RAG
一个基本的RAG系统由检索模块和生成模块组成。系统会对查询进行编码,检索相关的文档块,然后为基于transformer的LLM构建丰富的提示。
- 查询编码器:使用预训练的转换器(例如DPR)生成密集的查询嵌入。代码实现如下:
from transformers import AutoTokenizer, AutoModel
import torch
tokenizer = AutoTokenizer.from_pretrained("facebook/dpr-question_encoder-single-nq-base")
model = AutoModel.from_pretrained("facebook/dpr-question_encoder-single-nq-base")
def encode_query(query: str) -> torch.Tensor:
inputs = tokenizer(query, return_tensors="pt", truncatinotallow=True, max_length=128)
return model(**inputs).pooler_output
- 文档分割:将文档拆分为多个块(可以使用句子分词或滑动窗口的方法)。代码如下:
import nltk
nltk.download('punkt')
from nltk.tokenize import sent_tokenize
def segment_document(document: str, window_size: int = 5, overlap: int = 2) -> list:
sentences = sent_tokenize(document)
return [" ".join(sentences[i:i+window_size]) for i in range(0, len(sentences), window_size - overlap)]
- 索引和检索:嵌入每个块并通过FAISS为它们编制索引。在查询期间,执行最近邻搜索。相关代码:
import faiss, numpy as np
def build_faiss_index(embeddings: torch.Tensor) -> faiss.IndexFlatL2:
emb_np = embeddings.detach().cpu().numpy().astype('float32')
d = emb_np.shape[1]
index = faiss.IndexFlatL2(d)
index.add(emb_np)
return index
- 提示构造函数和生成:将检索到的块与原始查询(使用特殊分隔符)相结合,并将提示传递给LLM(例如GPT-2/GPT-4)进行生成。代码如下:
def construct_prompt(query: str, retrieved_chunks: list) -> str:
delimiter = "[DOC]"
context = " ".join([f"{delimiter} {chunk} {delimiter}" for chunk in retrieved_chunks])
return f"{query}\n{context}"
关键事实:标准RAG将外部知识动态注入生成过程,而无需修改LLM本身,就像是给LLM戴上了一副能随时获取新知识的“眼镜”。
2. 矫正RAG(CRAG)
CRAG在标准RAG的基础上增加了迭代反馈循环。它能够检测低置信度或不准确的输出,并重新查询外部知识库进行更正。
- 初始生成:使用标准RAG生成初步答案。
- 置信度评分:使用令牌级softmax概率评估输出。代码如下:
from transformers import AutoModelForCausalLM
gen_tokenizer = AutoTokenizer.from_pretrained("gpt2")
gen_model = AutoModelForCausalLM.from_pretrained("gpt2")
def generate_response(prompt: str, max_length: int = 200) -> str:
inputs = gen_tokenizer.encode(prompt, return_tensors="pt", truncatinotallow=True, max_length=1024)
outputs = gen_model.generate(inputs, max_length=max_length, num_beams=5, early_stopping=True)
return gen_tokenizer.decode(outputs[0], skip_special_tokens=True)
def evaluate_confidence(output_ids: torch.Tensor) -> float:
outputs = gen_model(output_ids, labels=output_ids)
return torch.exp(-outputs.loss).item()
- 反馈回路:如果置信度低于阈值,重新运行检索(可能会调整查询词)并重新生成答案。代码如下:
def iterative_crag(prompt: str, threshold: float = 0.8, max_iters: int = 3) -> str:
current_prompt = prompt
for _ in range(max_iters):
response = generate_response(current_prompt)
output_ids = gen_tokenizer.encode(response, return_tensors="pt")
conf = evaluate_confidence(output_ids)
if conf >= threshold:
return response
current_prompt += "\n[REFINE]"
return response
关键事实:CRAG的迭代校正通过强制执行重新检索周期,直到输出达到预定义的置信度,从而最大限度地减少幻觉,让AI的回答更加靠谱。
3. Speculative RAG
Speculative RAG采用双模型策略:轻量级专家模型起草多个候选回答,重量级通才模型验证并选择最佳候选。
- 专家模型(制图):从各种检索子集并行生成多个候选响应。代码:
def generate_candidates(prompt: str, num_candidates: int = 3) -> list:
inputs = gen_tokenizer.encode(prompt, return_tensors="pt", truncatinotallow=True, max_length=1024)
candidates_ids = gen_model.generate(inputs, max_length=200, num_return_sequences=num_candidates, num_beams=5)
return [gen_tokenizer.decode(c, skip_special_tokens=True) for c in candidates_ids]
- 通才模型(验证):对每个候选项进行评分(使用似然或专门的验证指标)并选择最准确的一个。代码:
def select_best_candidate(candidates: list) -> str:
best_candidate = None
best_score = -float('inf')
for candidate in candidates:
inputs = gen_tokenizer.encode(candidate, return_tensors="pt", truncatinotallow=True, max_length=1024)
outputs = gen_model(inputs, labels=inputs)
score = torch.exp(-outputs.loss).item()
if score > best_score:
best_score = score
best_candidate = candidate
return best_candidate
def speculative_rag(prompt: str) -> str:
candidates = generate_candidates(prompt, num_candidates=3)
return select_best_candidate(candidates)
关键事实:通过将生成解耦为起草和验证,Speculative RAG利用并行性提高了速度和准确性,就像多个助手同时工作,然后挑选出最佳方案。
4. 融合RAG
Fusion RAG集成了多种检索策略和各种数据源,以丰富提示。它同时使用语义(密集嵌入)和词法(基于关键字)检索方法。
- 混合检索:执行并行检索管道,一个使用密集嵌入,另一个使用传统的BM25或关键字匹配。代码如下:
# Placeholder for BM25 retrieval (e.g., using rank_bm25 library)
def bm25_retrieve(query: str, corpus: list, k: int = 5):
from rank_bm25 import BM25Okapi
tokenized_corpus = [doc.split() for doc in corpus]
bm25 = BM25Okapi(tokenized_corpus)
tokenized_query = query.split()
scores = bm25.get_scores(tokenized_query)
top_k = np.argsort(scores)[-k:]
return top_k
def hybrid_retrieve(query: str, dense_index: faiss.IndexFlatL2, corpus: list, k: int = 5):
query_emb = encode_query(query)
_, indices_dense = retrieve_documents(query_emb, dense_index, k)
indices_bm25 = bm25_retrieve(query, corpus, k)
# Merge indices (simple union, can use weighted merging)
merged_indices = list(set(indices_dense[0]).union(set(indices_bm25)))
return merged_indices
- 数据融合:根据相关性量度对从不同来源检索到的数据进行动态加权和合并。 关键事实:Fusion RAG通过结合多种技术最大限度地提高检索召回率和精度,提供更强大的外部环境,让AI能获取更全面的信息。
5. Agentic RAG
Agentic RAG采用模块化“代理”,专门用于特定任务,如查询重新表述、文档检索和响应合成,允许动态、实时调整。
- 微服务架构:每个代理都作为独立的服务(通常通过REST API)运行,通过消息队列进行通信。
- 动态协调:代理根据他人的反馈调整行动,例如,Query Reformulator可能会根据初始检索性能调整查询。代码如下:
import requests
def query_reformulator(raw_query: str) -> str:
response = requests.post("http://agent-service/reformulate", jsnotallow={"query": raw_query})
return response.json().get("reformulated_query", raw_query)
def document_retriever(query: str) -> list:
response = requests.post("http://agent-service/retrieve", jsnotallow={"query": query})
return response.json().get("documents", [])
def response_synthesizer(original_query: str, documents: list) -> str:
payload = {"query": original_query, "documents": documents}
response = requests.post("http://agent-service/synthesize", jsnotallow=payload)
return response.json().get("response", "")
def agentic_rag(raw_query: str) -> str:
reformulated_query = query_reformulator(raw_query)
docs = document_retriever(reformulated_query)
return response_synthesizer(raw_query, docs)
关键事实:Agentic RAG的分散式设计通过在专业服务之间划分检索生成过程,实现了精细的控制和可扩展性,就像一个分工明确的团队高效协作。
6. Self-RAG:开启LLM自我进化循环
Self-RAG是一种独特的RAG变体,它赋予LLM根据自身生成的响应检索上下文的能力,从而构建起一个迭代的自我提升循环,就像为模型注入了自我反思的“智慧”。。
自我嵌入:精准定位知识短板
在初始生成阶段,模型会先依据输入生成一个初步的响应。随后,Self-RAG会对这个响应进行重新编码,这一过程被称为“自我嵌入”。通过自我嵌入,模型能够精准地识别出自身知识的缺口,明确哪些地方的信息还不够完善,哪些表述可能存在模糊之处。例如,在回答“2024年人工智能领域的重大突破有哪些”时,模型初步生成的答案中可能遗漏了部分关键突破,通过自我嵌入,就能发现这些缺失的信息。
内部反馈:知识检索补充信息
基于自我评估所发现的知识差距,模型会启动内部反馈机制。它会依据这些自我评估的结果,从外部知识库或自身存储的信息中检索额外的上下文信息。这一过程就像是模型在主动查阅资料,为自己补充“营养”,让回答更加全面和准确。比如,模型在发现自己对“2024年人工智能领域的重大突破”回答不足后,会去检索相关的学术论文、新闻报道等资料,获取更多详细信息。
迭代优化:反复打磨输出质量
在获取到额外的上下文信息后,Self-RAG会更新输入提示,并将其重新输入到模型中进行新一轮的生成。这个过程会不断重复,直到模型对输出结果的置信度达到较高水平。每一次迭代都是对答案的优化和完善,使得模型的输出更加精准、可靠。例如,经过多次迭代,模型对“2024年人工智能领域的重大突破”的回答可能会从最初的简单列举,变得详细且深入,涵盖突破的技术原理、应用场景以及对行业的影响等多方面内容。
代码示例:Self-RAG的实现逻辑
def self_rag(prompt: str, iterations: int = 3) -> str:
current_prompt = prompt
for _ in range(iterations):
response = generate_response(current_prompt, gen_model, gen_tokenizer)
response_emb = encode_query(response)
additional_context = " [ADDITIONAL EVIDENCE REQUIRED]"
current_prompt = f"{prompt}\n{additional_context}"
return response
在这段代码中,self_rag函数接收一个提示prompt和迭代次数iterations作为参数。在循环中,模型首先根据当前提示生成响应response,接着对响应进行编码得到response_emb ,然后添加额外的上下文信息additional_context到当前提示中,最后返回最终的响应。通过这样的循环迭代,实现了Self-RAG的自我提升过程。
关键事实:减少依赖,提升自主性
Self-RAG的关键优势在于,它借助内部自我评估来迭代提升输出质量。一旦模型识别到足够的上下文信息,就能够减少对外部资源的依赖,在保证回答质量的同时,提升了模型的自主性和效率。这意味着在一些外部资源受限的场景下,Self-RAG依然能够给出高质量的回答,展现出更强的适应性和灵活性。
Self-RAG为LLM的发展开辟了新的路径,通过自我反思和优化机制,让模型在不断迭代中变得更加智能和可靠。在未来的人工智能应用中,Self-RAG有望在智能问答、文档生成等领域发挥重要作用,为用户提供更优质的服务和体验。
7. 自适应RAG:智能决策的RAG变体
自适应RAG的核心在于引入了一种门控机制,这种机制能够动态地决定模型是依靠自身内部的知识进行输出,还是调用外部检索来获取更全面的信息。这一设计就像是为模型配备了一个智能“开关”,使其能根据具体情况灵活调整策略,在保证回答质量的同时,最大限度地提高资源利用效率。
门控网络:精准评估,智能决策
门控网络是自适应RAG的关键组件之一,它基于内部标记概率来计算置信度分数。简单来说,模型会对输入的查询进行分析,根据自身对该查询的理解程度给出一个置信度数值。这个数值反映了模型对利用内部知识回答问题的信心。如果模型对某个问题非常“熟悉”,其内部知识足以给出可靠的答案,那么置信度分数就会较高;反之,如果模型觉得这个问题比较陌生,内部知识可能不足以准确回答,置信度分数就会较低。
动态切换:灵活应变,高效输出
基于门控网络计算出的置信度分数,自适应RAG会进行动态切换。当置信度低于设定的阈值时,系统会判定模型内部知识不足,进而触发外部检索。在外部检索过程中,模型会从预先构建的数据库或知识源中查找相关信息,以补充自身的知识储备。而当置信度高于阈值时,模型则会直接依赖内部知识进行回答,这样可以避免不必要的外部检索,节省计算资源和时间成本。
自适应提示:按需构建,精准引导
根据门控结果,自适应RAG会有条件地构建丰富的提示。如果触发了外部检索,模型会将检索到的相关信息与原始查询相结合,形成一个包含更多上下文的提示,为后续的回答生成提供更充足的信息。反之,如果直接依赖内部知识,提示则可能仅包含原始查询。这种自适应的提示构建方式,能够根据实际情况为模型提供最恰当的引导,帮助模型生成更准确、更符合需求的回答。
代码示例:直观展现,深入理解
def gating_decision(query: str, threshold: float = 0.85) -> bool:
query_emb = encode_query(query)
confidence = query_emb.norm().item() / 100
return confidence < threshold
def adaptive_rag(query: str, dense_index: faiss.IndexFlatL2) -> str:
if gating_decision(query):
distances, indices = retrieve_documents(encode_query(query), dense_index, k=5)
retrieved_docs = [chunks[i] for i in indices[0]]
prompt = construct_prompt(query, retrieved_docs)
else:
prompt = query
return generate_response(prompt, gen_model, gen_tokenizer)
在上述代码中,gating_decision函数用于判断是否需要进行外部检索。它首先对查询进行编码得到query_emb,然后通过计算query_emb的范数并除以100来得到置信度confidence,最后将置信度与阈值进行比较,返回判断结果。adaptive_rag函数则根据gating_decision的结果进行相应操作,如果需要外部检索,就执行检索、构建提示等步骤;如果不需要,则直接将原始查询作为提示。最后,调用generate_response函数生成回答。
关键事实:优化资源,提升性能
自适应RAG的关键优势在于,它能够根据实时的置信度测量来决定检索的必要性,从而实现对资源的优化利用。在面对大量查询时,这种方式可以避免模型在不必要的情况下进行复杂的外部检索,有效减少计算资源的消耗和响应时间,提升模型的整体性能。无论是在处理日常简单问题,还是应对复杂的专业领域问题时,自适应RAG都能根据具体情况做出最佳决策,为用户提供高效、准确的服务。
自适应RAG通过创新的门控机制和动态决策过程,为RAG技术的应用带来了更高的灵活性和效率。它在优化资源利用的同时,也提升了模型的性能表现,为大语言模型在更多领域的深入应用奠定了坚实基础。未来,随着技术的不断发展,自适应RAG有望在智能问答、信息检索等多个领域发挥更大的作用,为用户带来更加优质的体验。
8. REFEED(检索反馈):优化回答的智慧“补丁”
REFEED,即检索反馈(Retrieval Feedback),是RAG技术中的一个重要变体,它通过在模型初始输出后反馈外部证据的方式,有效地“纠正”答案,从而显著提升生成响应的质量。这一技术为大语言模型在处理复杂问题时提供了更可靠的解决方案,让模型的回答更加准确和完善。下面,我们就来详细了解REFEED的工作原理、具体实现步骤以及它的关键优势。
初始生成:奠定基础,开启优化之旅
在REFEED的工作流程中,模型首先会根据输入的问题生成一个初步答案。这个初始答案是基于模型自身的知识和训练经验得出的,它为后续的优化提供了基础框架。虽然初始答案可能并不完美,但它包含了模型对问题的初步理解和分析,为进一步的改进指明了方向。
反馈检索:深度挖掘,填补知识缺口
得到初始答案后,REFEED会对这个答案进行深入分析,识别其中可能存在的信息差距或不准确之处。基于这些分析结果,模型会启动新的检索过程,从外部知识库或相关数据源中查找能够补充和完善答案的信息。例如,如果初始答案在某个关键知识点上表述模糊或缺失,反馈检索就会针对性地寻找相关的详细解释、案例或数据,以填补这些知识缺口。
输出优化:融合信息,打造精准回答
在获取到额外的上下文信息后,REFEED会将这些信息与原始提示进行合并,构建一个包含更丰富信息的新提示。然后,模型会基于这个新提示再次生成回答。通过这种方式,模型能够将新获取的知识融入到答案中,对初始答案进行优化和完善,从而生成一个更加准确、全面的最终回答。这种优化过程就像是为初始答案打上了一个个“补丁”,让答案的质量得到了显著提升。
代码示例:清晰呈现,掌握技术细节
def refeed_rag(query: str, dense_index: faiss.IndexFlatL2) -> str:
initial_response = generate_response(query, gen_model, gen_tokenizer)
feedback_query = f"{query} {initial_response}"
distances, indices = retrieve_documents(encode_query(feedback_query), dense_index, k=5)
additional_context = " ".join([chunks[i] for i in indices[0]])
new_prompt = f"{query}\n[REFEED CONTEXT] {additional_context}"
return generate_response(new_prompt, gen_model, gen_tokenizer)
在这段代码中,refeed_rag函数实现了REFEED的核心逻辑。它首先调用generate_response函数生成初始答案initial_response,然后将初始答案与原始查询结合形成feedback_query。接着,通过retrieve_documents函数进行反馈检索,获取相关的上下文信息additional_context。最后,将原始查询和新获取的上下文信息组合成新的提示new_prompt,并再次调用generate_response函数生成优化后的回答。
关键事实:高效精准,无需重新训练
REFEED的关键优势在于,它能够在不重新训练模型的前提下,通过结合基于初始输出反馈的二次检索,显著提高回答的准确性。这种方式不仅避免了重新训练模型带来的高昂成本和时间消耗,还能让模型在面对新问题时快速适应,及时调整回答策略。无论是在处理突发的热点问题,还是解决专业性较强的复杂问题时,REFEED都能通过高效的反馈检索和输出优化机制,为用户提供更加准确、可靠的答案,提升用户体验。
REFEED作为RAG技术的重要变体,通过独特的检索反馈机制,为大语言模型的回答优化提供了一种高效、灵活的解决方案。它在不改变模型基础架构的情况下,有效提升了模型的回答质量,为智能问答、信息服务等领域带来了新的发展机遇。随着技术的不断进步,REFEED有望在更多场景中得到应用和拓展,为用户提供更加优质的知识服务。
9. REALM:检索融入语言建模的新探索
REALM将检索紧密集成到预训练和推理过程中,让模型从本质上就具备检索感知能力。
利用检索进行掩码语言建模
在预训练阶段,模型会对标记进行屏蔽,然后结合内部上下文与外部检索到的文档来预测这些标记。这一过程就像是模型在“学习”如何利用外部知识来填补文本中的空缺,从而提升对语言的理解和生成能力。
联合训练
检索器和生成器会以端到端的方式一起进行优化。在这个过程中,两者相互协作,检索器为生成器提供更丰富准确的信息,生成器则根据这些信息不断调整,使得整体模型在生成文本时更加准确和合理。
过程
- A)预训练:对标记进行屏蔽,并检索外部上下文信息,帮助模型学习如何利用外部知识来理解和生成文本。
- B)联合优化:通过反向传播算法,让检索器和生成器同时优化,以提高模型整体性能。
- C)推理:在生成文本的过程中,模型针对每个掩码标记向检索器发起查询,获取相关信息来生成更准确的内容。
实现细节
对transformer架构进行了修改,虽然具体代码因模型而异,但关键步骤包括:
- 在transformer模块中集成交叉注意力层,这一操作可以帮助模型更好地关注检索到的信息。
- 在训练时,基于预测的标记和检索输出共同计算损失函数,以此来引导模型学习到更有效的知识。
关键事实
REALM在训练阶段对架构进行修改,使得检索成为语言建模的内在组成部分,而不是在推理时才进行的附加操作。这一设计让模型在处理各种语言任务时,能够更自然、高效地利用外部知识,提升了模型的性能和泛化能力。
10. RAPTOR(递归抽象与树状结构检索):构建层次化知识体系的检索利器
RAPTOR将大型文档组织成一个分层树结构,为检索和生成提供了多级抽象能力。
文档分块和聚类
利用k-means等算法对文档进行分段处理,并将相似的数据块聚集在一起。这一步就像是把一本厚厚的书按照主题和内容相似性分成不同的章节和段落,方便后续快速查找和管理。
树构造
通过递归地汇总聚类结果,构建出分层树。在这个树结构中,每个节点都代表了一定层次的信息汇总,从宏观到微观,形成了一个有序的知识体系。
分层检索
在查询时,模型会遍历这棵树,既可以获取高级别的摘要信息,也能深入到细节层面获取精细的内容。这就好比在查阅一本目录清晰的书籍时,既能快速了解各章节的核心要点,又能根据需要深入阅读具体段落。
def cluster_chunks(embeddings: torch.Tensor, num_clusters: int = 10):
from sklearn.cluster import KMeans
emb_np = embeddings.detach().cpu().numpy()
kmeans = KMeans(n_clusters=num_clusters)
labels = kmeans.fit_predict(emb_np)
return labels, kmeans.cluster_centers_
def build_tree(chunks: list, labels: list):
tree = {}
for label in set(labels):
tree[label] = [chunks[i] for i, lab in enumerate(labels) if lab == label]
return tree
# 在查询时:
def tree_retrieve(query: str, tree: dict):
aspects = query.split() # 用于适当分解的占位符
retrieved = []
for aspect in aspects:
for key, docs in tree.items():
if aspect.lower() in" ".join(docs).lower():
retrieved.extend(docs)
return list(set(retrieved))
# 使用方法:
labels, _ = cluster_chunks(chunk_embeddings, num_clusters=10)
raptor_tree = build_tree(chunks, labels)
tree_docs = tree_retrieve(query, raptor_tree)
raptor_prompt = construct_prompt(query, tree_docs)
raptor_response = generate_response(raptor_prompt, gen_model, gen_tokenizer)
关键事实
RAPTOR的多级检索策略,能够同时提供广泛和详细的上下文信息,这对于需要深入推理的任务来说至关重要。通过这种树状结构的组织和检索方式,模型可以更全面、准确地理解问题,并给出更有深度和准确性的回答。
11. REVEAL(检索增强视觉语言预训练):开启多模态检索新时代
REVEAL通过将视觉和文本数据整合到统一的表示形式中,把RAG技术拓展到了多模态领域。
多模态编码
使用共享编码器将图像和文本映射到同一个嵌入空间,使得模型能够在同一“语言”下理解和处理不同模态的数据。这就像是为图像和文本搭建了一座沟通的桥梁,让它们可以在模型内部自由交互。
动态检索
可以同时检索与上下文相关的文本和视觉信息,为模型生成内容提供更丰富的素材。比如在描述一幅图片时,模型不仅能根据图片本身的特征,还能结合相关的文本描述来生成更准确、生动的内容。
融合机制
在transformer架构中利用注意力层来整合多模态数据。注意力层就像是模型的“聚焦器”,可以让模型根据任务需求,有重点地关注不同模态的数据,从而更好地融合它们。
实现细节
- 对于图像-文本对,可以借助CLIP等模型获取联合嵌入,让图像和文本在嵌入空间中建立紧密联系。
- 检索过程与标准RAG类似,但操作的是混合数据库,其中包含了转换为嵌入形式的图像和文本数据。
关键事实
REVEAL的架构专门针对跨模态检索进行了优化,这对于视觉问答、图像描述等多模态任务来说至关重要。它让模型能够充分利用不同模态的数据信息,生成更加准确和丰富的回答,为多模态人工智能应用开辟了新的道路。
12. ReAct(推理和行动):推理与行动交织的智能模式
ReAct将推理与明确的行动交织在一起,使模型在生成过程中能够执行诸如API调用等操作。
思维链生成
模型会生成一个包含推理步骤的解释序列,展示其思考过程。这就好比一个人在解决问题时,会逐步阐述自己的思路,让他人能够理解其思考逻辑。
行动令牌
通过特殊的标记,指示模型执行特定的操作,例如查询数据库获取相关信息。这些标记就像是模型的“行动指令”,引导模型与外部资源进行交互。
集成跟踪
最终输出不仅包含推理的路径,还包括执行行动的结果。这样可以让用户清楚地看到模型是如何思考以及根据思考采取了哪些行动,结果又是什么。
def generate_with_actions(prompt: str) -> str:
inputs = gen_tokenizer.encode(prompt, return_tensors="pt", truncatinotallow=True, max_length=300)
outputs = gen_model.generate(inputs, max_length=300, num_beams=5)
return gen_tokenizer.decode(outputs[0], skip_special_tokens=True)
关键事实
ReAct的交错设计需要精心设计提示工程,以便在同一生成周期内同时触发推理和可执行的输出。这种设计让模型能够在思考的同时采取实际行动,获取更多信息来完善回答,提升了模型的实用性和智能性,但也对提示设计提出了更高的要求。
13. REPLUG(检索插件):无损增强大语言模型的便捷方式
REPLUG把大语言模型视为一个“黑匣子”,在不修改模型的前提下,通过在输入前添加外部检索到的文档来增强其输入内容。
外部检索
利用像FAISS这样独立的检索系统来收集相关文档,为模型提供丰富的外部知识支持。这就好比给模型配备了一个强大的“知识助手”,帮助它获取更多信息。
提示增强
将检索到的文档添加到查询前面,在保持大语言模型原始架构不变的情况下,丰富模型的输入内容,引导模型生成更好的回答。
模型调用
把增强后的提示输入到大语言模型中,让模型基于这些丰富的信息进行处理和生成。
def replug_rag(query: str, dense_index: faiss.IndexFlatL2) -> str:
query_emb = encode_query(query)
_, indices = retrieve_documents(query_emb, dense_index, k=5)
retrieved = [chunks[i] for i in indices[0]]
enriched_prompt = construct_prompt(query, retrieved)
return generate_response(enriched_prompt, gen_model, gen_tokenizer)
关键事实
REPLUG提供了一种模块化的方法,通过外部检索提升大语言模型的性能,同时保持核心模型不变。这种方式简单高效,方便在不同场景中快速应用,为优化大语言模型的表现提供了一种便捷途径。
14. Memo RAG:融合记忆机制的智能检索增强
Memo RAG集成了一个内存组件,它能将大型数据集压缩成“全局内存”,并生成检索线索来引导外部搜索。
内存模块
运用知识蒸馏等技术压缩大型数据集,将海量的信息浓缩成更易于管理和使用的形式,存储在“全局内存”中。
线索生成
针对给定的查询,模型会生成检索提示,这些提示就像“线索”一样,帮助模型在外部搜索时更精准地定位相关信息。
上下文集成
将生成的线索与检索到的数据进行合并,构建最终的提示,为模型生成回答提供更有针对性的信息。
# 假设memory_module是一个预训练模块,具有generate_clue方法。
def memo_rag(query: str, dense_index: faiss.IndexFlatL2, memory_module) -> str:
clue = memory_module.generate_clue(query)
feedback_query = f"{query} {clue}"
_, indices = retrieve_documents(encode_query(feedback_query), dense_index, k=5)
retrieved = [chunks[i] for i in indices[0]]
prompt = construct_prompt(query, retrieved)
return generate_response(prompt, gen_model, gen_tokenizer)
关键事实
Memo RAG借助内部内存机制提高了外部检索的精度,尤其在处理模糊或复杂查询时表现出色。通过生成线索引导检索,模型能够更准确地找到相关信息,从而生成更符合需求的高质量回答。
解锁RAG的进阶奥秘:ATLAS及其他变体深度解析
在检索增强生成(RAG)技术的不断演进中,诞生了诸多创新的变体,为大语言模型(LLM)的发展注入了新的活力。今天,让我们一同深入探索从15. ATLAS开始的多种RAG变体,揭开它们提升模型性能的神秘面纱。
15. ATLAS(基于注意力的RAG):检索与注意力的深度融合
ATLAS的独特之处在于,它将检索与注意力机制巧妙融合,通过把检索到的文档直接整合到transformer的注意力层,让模型在处理文本时能够更充分地利用外部知识。
- 密集嵌入与检索:ATLAS运用密集嵌入技术,从海量数据中精准检索出语义相似的文档,为后续的处理提供丰富的信息来源。
- 交叉注意力集成:在编码器 - 解码器框架内,ATLAS借助交叉注意力层,将检索到的上下文信息无缝融入到模型的处理过程中,使得模型在生成文本时能够更好地关注相关信息。
- 联合优化:为了实现更高效的信息整合,ATLAS对检索器和生成器进行联合训练,确保两者协同工作,优化整体性能。
- 实现细节:在技术实现上,ATLAS对transformer架构进行了优化,新增的交叉注意力层将检索到的嵌入作为键和值。这里运用到的标准注意力公式为:
def scaled_dot_product_attention(Q, K, V, mask=None):
import math
d_k = Q.size(-1)
scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(d_k)
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)
attention_weights = torch.softmax(scores, dim=-1)
output = torch.matmul(attention_weights, V)
return output, attention_weights
其中,和均来自检索到的数据。
- 关键事实:ATLAS的设计将外部上下文紧密地与令牌级预测相结合,这一特性使得模型在处理知识密集型任务时表现卓越,显著提升了性能。
16. RETRO(检索增强变压器):Transformer架构中的检索创新
RETRO另辟蹊径,将检索功能融入transformer的架构之中。它把输入文本划分为固定大小的块,然后利用交叉注意力机制从外部数据库中查找相似序列。
- 块分割:首先,RETRO会把输入文本切割成固定大小的块,为后续的检索和处理做好准备。
- 最近邻检索:针对每个文本块,RETRO使用FAISS等工具从大型索引语料库中检索相似的块,获取相关信息。
- 交叉注意力层:通过额外的交叉注意力机制,RETRO将检索到的块融入到文本生成过程中,增强模型对信息的利用效率。
def retro_retrieve(block_embedding, index, k=5):
distances, indices = index.search(block_embedding.detach().cpu().numpy().astype('float32'), k)
return indices
output = scaled_dot_product_attention(Q, K, V)[0]
- 关键事实:RETRO通过在令牌生成阶段高效整合外部信息,成功实现了以较少的参数提升模型性能的目标。
17. 自动RAG:自主优化的迭代循环
自动RAG引入了自主迭代循环机制,模型能够自我评估输出,并根据评估结果决定是否需要进一步检索。
- 自我评估:在初始生成文本后,自动RAG模型会对输出的置信度进行评估,判断当前答案的可靠性。
- 动态迭代:如果输出置信度较低,模型会触发额外的检索循环,并更新提示信息,再次生成文本,不断优化答案。
- 终止标准:这一过程会持续进行,直到模型输出达到预设的收敛阈值,确保最终答案的质量。
def auto_rag(prompt: str, max_iterations: int = 3, threshold: float = 0.8) -> str:
current_prompt = prompt
for i in range(max_iterations):
response = generate_response(current_prompt, gen_model, gen_tokenizer)
output_ids = gen_tokenizer.encode(response, return_tensors="pt")
conf = evaluate_confidence(output_ids)
if conf >= threshold:
break
current_prompt += "\n[RETRIEVE_MORE]"
return response
- 关键事实:自动RAG基于内部置信度评估,通过自动化的迭代重新检索循环,有效提升了输出质量。
18. CORAG(成本受限的RAG):资源约束下的检索优化
CORAG聚焦于在资源受限的环境中优化检索过程,它采用蒙特卡洛树搜索(MCTS)等策略,平衡检索质量与计算成本。
- MCTS检索:CORAG将候选检索组合视为搜索树中的节点,通过MCTS算法对这些节点进行探索,寻找最优的检索方案。
- 成本建模:为了控制计算成本,CORAG引入成本函数,对高成本的检索路径进行惩罚,引导模型选择更经济高效的检索方式。
- 自适应配置:在资源限制的前提下,CORAG会选择能够最大化检索质量的配置,确保在有限资源下实现最佳检索效果。
def mcts_retrieval(query: str, index: faiss.IndexFlatL2, iterations: int = 10):
best_set = None
best_score = -float('inf')
for _ in range(iterations):
candidate_set = sample_candidate_set(index)
quality = evaluate_candidate_quality(candidate_set, query)
cost = evaluate_candidate_cost(candidate_set)
score = quality - cost
if score > best_score:
best_score = score
best_set = candidate_set
return best_set
- 关键事实:CORAG的成本感知优化策略,确保了在资源有限的场景下,检索过程依然高效且有效。
19. EACO - RAG(边缘辅助和协作RAG):分布式检索的新范式
EACO - RAG借助边缘计算的优势,将检索过程分布到各个边缘节点,有效降低延迟并平衡计算负载。
- 本地知识库:每个边缘节点都维护着本地化且及时更新的索引,方便快速检索本地相关信息。
- 协作检索:边缘节点之间通过消息队列进行通信,协同完成检索任务,实现资源的高效利用。
- 贝叶斯多臂强盗算法:为了动态分配资源,EACO - RAG采用贝叶斯多臂强盗算法,根据节点的实时性能指标,合理分配检索任务。
def edge_retrieve(query: str, local_index: faiss.IndexFlatL2) -> list:
q_emb = encode_query(query)
_, indices = retrieve_documents(q_emb, local_index, k=5)
return [chunks[i] for i in indices[0]]
def collaborative_retrieve(query: str, edge_indices: list) -> list:
results = []
for idx in edge_indices:
results.extend(edge_retrieve(query, idx))
return rank_results(results)
- 关键事实:EACO - RAG利用分布式计算,在大规模部署中实现了低延迟、可扩展的检索。
20. 规则RAG:特定领域的精准检索
规则RAG通过应用明确的特定领域规则,指导检索和合成过程,确保最终输出仅包含高度相关的文档信息。
- 规则引擎:规则RAG使用Python或外部规则引擎,实施确定性规则,对文档进行筛选和排序。
- 检索前后过滤:在检索前,规则用于优化查询条件;检索后,规则则对检索结果进行进一步筛选,确保输出的相关性。
def apply_rules(query: str, documents: list, keyword: str = "RAG") -> list:
return [doc for doc in documents if keyword.lower() in doc.lower()]
def rule_rag(query: str, dense_index: faiss.IndexFlatL2) -> str:
_, indices = retrieve_documents(encode_query(query), dense_index, k=10)
raw_docs = [chunks[i] for i in indices[0]]
filtered_docs = apply_rules(query, raw_docs, keyword="RAG")
prompt = construct_prompt(query, filtered_docs)
return generate_response(prompt, gen_model, gen_tokenizer)
- 关键事实:规则RAG的确定性筛选机制,通过严格的标准确保只有符合要求的文档才会参与最终输出,极大地增强了在专业领域的相关性。
21. 对话式RAG:多轮对话的智能伙伴
对话式RAG专为多轮对话系统设计,它能够根据对话历史持续更新检索上下文,提供更符合对话情境的回答。
- 上下文跟踪:对话式RAG会维护一个对话历史缓冲区,记录每一轮对话的内容。
- 动态检索:在每一轮对话中,它会结合累积的上下文信息,查询外部数据源,获取更全面的信息。
- 集成合成:将对话历史与新检索到的内容进行融合,生成连贯、准确的回复。
def conversational_rag(dialogue_history: list, query: str, dense_index: faiss.IndexFlatL2) -> str:
context = " ".join(dialogue_history)
full_query = f"{context} {query}"
_, indices = retrieve_documents(encode_query(full_query), dense_index, k=5)
retrieved = [chunks[i] for i in indices[0]]
prompt = construct_prompt(full_query, retrieved)
return generate_response(prompt, gen_model, gen_tokenizer)
- 关键事实:对话式RAG能够在多轮交互中保留上下文信息,实现动态检索,准确反映整个对话的意图。
22. 迭代RAG:精益求精的答案优化
迭代RAG通过多次检索和生成循环,不断优化响应,直至答案满足预设的收敛标准。
- 初始生成:首先生成一个基线响应,作为后续优化的基础。
- 差距分析:对基线响应进行分析,找出其中置信度较低或缺失信息的部分。
- 细化循环:针对这些差距重新进行查询,并迭代更新提示信息,逐步完善答案。
def iterative_rag(query: str, dense_index: faiss.IndexFlatL2, max_iters: int = 3) -> str:
current_prompt = query
for _ in range(max_iters):
response = generate_response(current_prompt, gen_model, gen_tokenizer)
if "unclear" not in response:
return response
_, indices = retrieve_documents(encode_query(response), dense_index, k=5)
additional_context = " ".join([chunks[i] for i in indices[0]])
current_prompt = f"{query}\n{additional_context}"
return response
- 关键事实:迭代RAG的重复循环机制,对于复杂或多方面的查询,能够有效提升响应质量。
23. 上下文驱动的树状结构检索:复杂查询的拆解与解答
这种RAG变体将复杂查询分解为子查询的树状层次结构,全面探索问题的各个方面。
- 方面分解:把复杂查询解析为多个子主题,明确问题的不同维度。
- 树构造:按照层次结构组织这些子主题,每个分支代表一个特定的方面。
- 分支检索与聚合:针对每个分支独立检索文档,最后将结果合并,给出全面的答案。
def decompose_query(query: str) -> list:
# 为演示目的,按标点分割;如有需要,可替换为高级主题建模方法
return query.split(";")
def tree_retrieve(aspects: list, dense_index: faiss.IndexFlatL2) -> list:
tree_results = []
for aspect in aspects:
_, indices = retrieve_documents(encode_query(aspect), dense_index, k=3)
tree_results.extend([chunks[i] for i in indices[0]])
return list(set(tree_results))
def tree_rag(query: str, dense_index: faiss.IndexFlatL2) -> str:
aspects = decompose_query(query)
tree_docs = tree_retrieve(aspects, dense_index)
prompt = construct_prompt(query, tree_docs)
return generate_response(prompt, gen_model, gen_tokenizer)
- 关键事实:树状结构的方法确保了复杂查询的每个方面都能得到处理,最终生成更全面的回复。
24. CRAT(因果增强反射翻译):翻译领域的智能升级
CRAT将检索和因果推理融入翻译过程,有效处理模糊或特定领域的术语翻译。
- 未知术语检测:首先识别可能在翻译中存在问题的术语,为后续处理做准备。
- 双语知识图谱构建:构建一个双语知识图谱(TransKG),映射术语及其跨语言关系。
- 因果反思:运用因果推理验证检索到的翻译是否符合上下文语境。
- 最终翻译合成:将经过验证的外部数据与模型内部的翻译输出进行融合,得出最终准确的翻译结果。
def detect_unknown_terms(text: str) -> list:
return [word for word in text.split() if word.isupper()]
def construct_transkg(terms: list) -> dict:
return {term: f"translated_{term}" for term in terms}
def crat_translate(text: str) -> str:
unknown_terms = detect_unknown_terms(text)
transkg = construct_transkg(unknown_terms)
for term, translation in transkg.items():
text = text.replace(term, translation)
return text
- 关键事实:CRAT通过整合经过因果推理验证的外部双语信息,确保了翻译的准确性。
25. Graph RAG:结构化知识的力量
Graph RAG借助结构化知识图谱,捕捉实体之间的关系,并将这些结构化上下文融入文本生成过程。
- 实体和关系提取:使用命名实体识别(NER)和关系提取工具(如SpaCy)解析文档,提取其中的实体和关系。
- 知识图谱构建:利用NetworkX或Neo4j等工具构建知识图谱,直观呈现实体间的联系。
- 图嵌入和遍历:通过图神经网络(GNN)生成节点嵌入,并遍历图谱,找到与上下文相关的子图。
- 提示增强:将结构化的图谱数据(如关键实体、关系)融入提示信息,辅助模型生成更准确的文本。
import spacy, networkx as nx
nlp = spacy.load("en_core_web_sm")
def extract_entities_relations(text: str) -> (list, list):
doc = nlp(text)
entities = [ent.text for ent in doc.ents]
relations = [(entities[i], entities[j]) for i in range(len(entities)) for j in range(i+1, len(entities))]
return entities, relations
def build_graph(documents: list) -> nx.Graph:
G = nx.Graph()
for doc in documents:
entities, relations = extract_entities_relations(doc)
for entity in entities:
G.add_node(entity)
for (e1, e2) in relations:
G.add_edge(e1, e2)
return G
def graph_based_prompt(query: str, G: nx.Graph) -> str:
relevant_nodes = [node for node in G.nodes if node.lower() in query.lower()]
graph_context = " ".join(relevant_nodes)
return f"{query}\n[GRAPH_CONTEXT] {graph_context}"
- 关键事实:图形RAG通过将结构化关系融入生成提示,提供了更深入的上下文理解,提高了复杂信息检索的准确性。
![](https://s5-media.51cto.com/aigc/pc/static/noavatar.gif)