主流RAG框架可以分为以下五个主要的进化方向:成本控制型(适合初创公司)、实时互动型(适用于财经/新闻场景)、域专家类型、认知增强型、安全与合规类型。接下来,让我们详细了解一下这25种RAG变体。
一个基本的RAG系统由检索模块和生成模块组成。系统会对查询进行编码,检索相关的文档块,然后为基于transformer的LLM构建丰富的提示。
fromtransformersimportAutoTokenizer, AutoModel
importtorch
tokenizer = AutoTokenizer.from_pretrained("facebook/dpr-question_encoder-single-nq-base")
model = AutoModel.from_pretrained("facebook/dpr-question_encoder-single-nq-base")
defencode_query(query: str)-> torch.Tensor:
inputs = tokenizer(query, return_tensors="pt", truncation=True, max_length=128)
returnmodel(**inputs).pooler_output
importnltk
nltk.download('punkt')
fromnltk.tokenizeimportsent_tokenize
defsegment_document(document: str, window_size: int =5, overlap: int =2)-> list:
sentences = sent_tokenize(document)
return[" ".join(sentences[i:i+window_size])foriinrange(0, len(sentences), window_size - overlap)]
importfaiss, numpyasnp
defbuild_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)
returnindex
defconstruct_prompt(query: str, retrieved_chunks: list)-> str:
delimiter ="[DOC]"
context =" ".join([f"{delimiter}{chunk}{delimiter}"forchunkinretrieved_chunks])
returnf"{query}\n{context}"
关键事实:标准RAG将外部知识动态注入生成过程,而无需修改LLM本身,就像是给LLM戴上了一副能随时获取新知识的“眼镜”。
CRAG在标准RAG的基础上增加了迭代反馈循环。它能够检测低置信度或不准确的输出,并重新查询外部知识库进行更正。
fromtransformersimportAutoModelForCausalLM
gen_tokenizer = AutoTokenizer.from_pretrained("gpt2")
gen_model = AutoModelForCausalLM.from_pretrained("gpt2")
defgenerate_response(prompt: str, max_length: int =200)-> str:
inputs = gen_tokenizer.encode(prompt, return_tensors="pt", truncation=True, max_length=1024)
outputs = gen_model.generate(inputs, max_length=max_length, num_beams=5, early_stopping=True)
returngen_tokenizer.decode(outputs[0], skip_special_tokens=True)
defevaluate_confidence(output_ids: torch.Tensor)-> float:
outputs = gen_model(output_ids, labels=output_ids)
returntorch.exp(-outputs.loss).item()
defiterative_crag(prompt: str, threshold: float =0.8, max_iters: int =3)-> str:
current_prompt = prompt
for_inrange(max_iters):
response = generate_response(current_prompt)
output_ids = gen_tokenizer.encode(response, return_tensors="pt")
conf = evaluate_confidence(output_ids)
ifconf >= threshold:
returnresponse
current_prompt +="\n[REFINE]"
returnresponse
关键事实:CRAG的迭代校正通过强制执行重新检索周期,直到输出达到预定义的置信度,从而最大限度地减少幻觉,让AI的回答更加靠谱。
Speculative RAG采用双模型策略:轻量级专家模型起草多个候选回答,重量级通才模型验证并选择最佳候选。
defgenerate_candidates(prompt: str, num_candidates: int =3)-> list:
inputs = gen_tokenizer.encode(prompt, return_tensors="pt", truncation=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)forcincandidates_ids]
defselect_best_candidate(candidates: list)-> str:
best_candidate =None
best_score = -float('inf')
forcandidateincandidates:
inputs = gen_tokenizer.encode(candidate, return_tensors="pt", truncation=True, max_length=1024)
outputs = gen_model(inputs, labels=inputs)
score = torch.exp(-outputs.loss).item()
ifscore > best_score:
best_score = score
best_candidate = candidate
returnbest_candidate
defspeculative_rag(prompt: str)-> str:
candidates = generate_candidates(prompt, num_candidates=3)
returnselect_best_candidate(candidates)
关键事实:通过将生成解耦为起草和验证,Speculative RAG利用并行性提高了速度和准确性,就像多个助手同时工作,然后挑选出最佳方案。
Fusion RAG集成了多种检索策略和各种数据源,以丰富提示。它同时使用语义(密集嵌入)和词法(基于关键字)检索方法。
# Placeholder for BM25 retrieval (e.g., using rank_bm25 library)
defbm25_retrieve(query: str, corpus: list, k: int =5):
fromrank_bm25importBM25Okapi
tokenized_corpus = [doc.split()fordocincorpus]
bm25 = BM25Okapi(tokenized_corpus)
tokenized_query = query.split()
scores = bm25.get_scores(tokenized_query)
top_k = np.argsort(scores)[-k:]
returntop_k
defhybrid_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)))
returnmerged_indices
Agentic RAG采用模块化“代理”,专门用于特定任务,如查询重新表述、文档检索和响应合成,允许动态、实时调整。
importrequests
defquery_reformulator(raw_query: str)-> str:
response = requests.post("http://agent-service/reformulate", json={"query": raw_query})
returnresponse.json().get("reformulated_query", raw_query)
defdocument_retriever(query: str)-> list:
response = requests.post("http://agent-service/retrieve", json={"query": query})
returnresponse.json().get("documents", [])
defresponse_synthesizer(original_query: str, documents: list)-> str:
payload = {"query": original_query,"documents": documents}
response = requests.post("http://agent-service/synthesize", json=payload)
returnresponse.json().get("response","")
defagentic_rag(raw_query: str)-> str:
reformulated_query = query_reformulator(raw_query)
docs = document_retriever(reformulated_query)
returnresponse_synthesizer(raw_query, docs)
关键事实:Agentic RAG的分散式设计通过在专业服务之间划分检索生成过程,实现了精细的控制和可扩展性,就像一个分工明确的团队高效协作。
Self-RAG是一种独特的RAG变体,它赋予LLM根据自身生成的响应检索上下文的能力,从而构建起一个迭代的自我提升循环,就像为模型注入了自我反思的“智慧”。
在初始生成阶段,模型会先依据输入生成一个初步的响应。随后,Self-RAG会对这个响应进行重新编码,这一过程被称为“自我嵌入”。通过自我嵌入,模型能够精准地识别出自身知识的缺口,明确哪些地方的信息还不够完善,哪些表述可能存在模糊之处。例如,在回答“2024年人工智能领域的重大突破有哪些”时,模型初步生成的答案中可能遗漏了部分关键突破,通过自我嵌入,就能发现这些缺失的信息。
基于自我评估所发现的知识差距,模型会启动内部反馈机制。它会依据这些自我评估的结果,从外部知识库或自身存储的信息中检索额外的上下文信息。这一过程就像是模型在主动查阅资料,为自己补充“营养”,让回答更加全面和准确。比如,模型在发现自己对“2024年人工智能领域的重大突破”回答不足后,会去检索相关的学术论文、新闻报道等资料,获取更多详细信息。
在获取到额外的上下文信息后,Self-RAG会更新输入提示,并将其重新输入到模型中进行新一轮的生成。这个过程会不断重复,直到模型对输出结果的置信度达到较高水平。每一次迭代都是对答案的优化和完善,使得模型的输出更加精准、可靠。例如,经过多次迭代,模型对“2024年人工智能领域的重大突破”的回答可能会从最初的简单列举,变得详细且深入,涵盖突破的技术原理、应用场景以及对行业的影响等多方面内容。
defself_rag(prompt: str, iterations: int =3)-> str:
current_prompt = prompt
for_inrange(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}"
returnresponse
在这段代码中,self_rag函数接收一个提示prompt和迭代次数iterations作为参数。在循环中,模型首先根据当前提示生成响应response,接着对响应进行编码得到response_emb,然后添加额外的上下文信息additional_context到当前提示中,最后返回最终的响应。通过这样的循环迭代,实现了Self-RAG的自我提升过程。
Self-RAG的关键优势在于,它借助内部自我评估来迭代提升输出质量。一旦模型识别到足够的上下文信息,就能够减少对外部资源的依赖,在保证回答质量的同时,提升了模型的自主性和效率。这意味着在一些外部资源受限的场景下,Self-RAG依然能够给出高质量的回答,展现出更强的适应性和灵活性。
Self-RAG为LLM的发展开辟了新的路径,通过自我反思和优化机制,让模型在不断迭代中变得更加智能和可靠。在未来的人工智能应用中,Self-RAG有望在智能问答、文档生成等领域发挥重要作用,为用户提供更优质的服务和体验。
自适应RAG的核心在于引入了一种门控机制,这种机制能够动态地决定模型是依靠自身内部的知识进行输出,还是调用外部检索来获取更全面的信息。这一设计就像是为模型配备了一个智能“开关”,使其能根据具体情况灵活调整策略,在保证回答质量的同时,最大限度地提高资源利用效率。
门控网络是自适应RAG的关键组件之一,它基于内部标记概率来计算置信度分数。简单来说,模型会对输入的查询进行分析,根据自身对该查询的理解程度给出一个置信度数值。这个数值反映了模型对利用内部知识回答问题的信心。如果模型对某个问题非常“熟悉”,其内部知识足以给出可靠的答案,那么置信度分数就会较高;反之,如果模型觉得这个问题比较陌生,内部知识可能不足以准确回答,置信度分数就会较低。
基于门控网络计算出的置信度分数,自适应RAG会进行动态切换。当置信度低于设定的阈值时,系统会判定模型内部知识不足,进而触发外部检索。在外部检索过程中,模型会从预先构建的数据库或知识源中查找相关信息,以补充自身的知识储备。而当置信度高于阈值时,模型则会直接依赖内部知识进行回答,这样可以避免不必要的外部检索,节省计算资源和时间成本。
根据门控结果,自适应RAG会有条件地构建丰富的提示。如果触发了外部检索,模型会将检索到的相关信息与原始查询相结合,形成一个包含更多上下文的提示,为后续的回答生成提供更充足的信息。反之,如果直接依赖内部知识,提示则可能仅包含原始查询。这种自适应的提示构建方式,能够根据实际情况为模型提供最恰当的引导,帮助模型生成更准确、更符合需求的回答。
defgating_decision(query: str, threshold: float =0.85)-> bool:
query_emb = encode_query(query)
confidence = query_emb.norm().item() /100
returnconfidence < threshold
defadaptive_rag(query: str, dense_index: faiss.IndexFlatL2)-> str:
ifgating_decision(query):
distances, indices = retrieve_documents(encode_query(query), dense_index, k=5)
retrieved_docs = [chunks[i]foriinindices[0]]
prompt = construct_prompt(query, retrieved_docs)
else:
prompt = query
returngenerate_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有望在智能问答、信息检索等多个领域发挥更大的作用,为用户带来更加优质的体验。
REFEED,即检索反馈(Retrieval Feedback),是RAG技术中的一个重要变体,它通过在模型初始输出后反馈外部证据的方式,有效地“纠正”答案,从而显著提升生成响应的质量。这一技术为大语言模型在处理复杂问题时提供了更可靠的解决方案,让模型的回答更加准确和完善。下面,我们就来详细了解REFEED的工作原理、具体实现步骤以及它的关键优势。
在REFEED的工作流程中,模型首先会根据输入的问题生成一个初步答案。这个初始答案是基于模型自身的知识和训练经验得出的,它为后续的优化提供了基础框架。虽然初始答案可能并不完美,但它包含了模型对问题的初步理解和分析,为进一步的改进指明了方向。
得到初始答案后,REFEED会对这个答案进行深入分析,识别其中可能存在的信息差距或不准确之处。基于这些分析结果,模型会启动新的检索过程,从外部知识库或相关数据源中查找能够补充和完善答案的信息。例如,如果初始答案在某个关键知识点上表述模糊或缺失,反馈检索就会针对性地寻找相关的详细解释、案例或数据,以填补这些知识缺口。
在获取到额外的上下文信息后,REFEED会将这些信息与原始提示进行合并,构建一个包含更丰富信息的新提示。然后,模型会基于这个新提示再次生成回答。通过这种方式,模型能够将新获取的知识融入到答案中,对初始答案进行优化和完善,从而生成一个更加准确、全面的最终回答。这种优化过程就像是为初始答案打上了一个个“补丁”,让答案的质量得到了显著提升。
defrefeed_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]foriinindices[0]])
new_prompt =f"{query}\n[REFEED CONTEXT]{additional_context}"
returngenerate_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有望在更多场景中得到应用和拓展,为用户提供更加优质的知识服务。
REALM将检索紧密集成到预训练和推理过程中,让模型从本质上就具备检索感知能力。
在预训练阶段,模型会对标记进行屏蔽,然后结合内部上下文与外部检索到的文档来预测这些标记。这一过程就像是模型在“学习”如何利用外部知识来填补文本中的空缺,从而提升对语言的理解和生成能力。
检索器和生成器会以端到端的方式一起进行优化。在这个过程中,两者相互协作,检索器为生成器提供更丰富准确的信息,生成器则根据这些信息不断调整,使得整体模型在生成文本时更加准确和合理。
对transformer架构进行了修改,虽然具体代码因模型而异,但关键步骤包括:
REALM在训练阶段对架构进行修改,使得检索成为语言建模的内在组成部分,而不是在推理时才进行的附加操作。这一设计让模型在处理各种语言任务时,能够更自然、高效地利用外部知识,提升了模型的性能和泛化能力。
RAPTOR将大型文档组织成一个分层树结构,为检索和生成提供了多级抽象能力。
利用k-means等算法对文档进行分段处理,并将相似的数据块聚集在一起。这一步就像是把一本厚厚的书按照主题和内容相似性分成不同的章节和段落,方便后续快速查找和管理。
通过递归地汇总聚类结果,构建出分层树。在这个树结构中,每个节点都代表了一定层次的信息汇总,从宏观到微观,形成了一个有序的知识体系。
在查询时,模型会遍历这棵树,既可以获取高级别的摘要信息,也能深入到细节层面获取精细的内容。这就好比在查阅一本目录清晰的书籍时,既能快速了解各章节的核心要点,又能根据需要深入阅读具体段落。
defcluster_chunks(embeddings: torch.Tensor, num_clusters: int =10):
fromsklearn.clusterimportKMeans
emb_np = embeddings.detach().cpu().numpy()
kmeans = KMeans(n_clusters=num_clusters)
labels = kmeans.fit_predict(emb_np)
returnlabels, kmeans.cluster_centers_
defbuild_tree(chunks: list, labels: list):
tree = {}
forlabelinset(labels):
tree[label] = [chunks[i]fori, labinenumerate(labels)iflab == label]
returntree
# 在查询时:
deftree_retrieve(query: str, tree: dict):
aspects = query.split() # 用于适当分解的占位符
retrieved = []
foraspectinaspects:
forkey, docsintree.items():
ifaspect.lower()in" ".join(docs).lower():
retrieved.extend(docs)
returnlist(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的多级检索策略,能够同时提供广泛和详细的上下文信息,这对于需要深入推理的任务来说至关重要。通过这种树状结构的组织和检索方式,模型可以更全面、准确地理解问题,并给出更有深度和准确性的回答。
REVEAL通过将视觉和文本数据整合到统一的表示形式中,把RAG技术拓展到了多模态领域。
使用共享编码器将图像和文本映射到同一个嵌入空间,使得模型能够在同一“语言”下理解和处理不同模态的数据。这就像是为图像和文本搭建了一座沟通的桥梁,让它们可以在模型内部自由交互。
可以同时检索与上下文相关的文本和视觉信息,为模型生成内容提供更丰富的素材。比如在描述一幅图片时,模型不仅能根据图片本身的特征,还能结合相关的文本描述来生成更准确、生动的内容。
在transformer架构中利用注意力层来整合多模态数据。注意力层就像是模型的“聚焦器”,可以让模型根据任务需求,有重点地关注不同模态的数据,从而更好地融合它们。
REVEAL的架构专门针对跨模态检索进行了优化,这对于视觉问答、图像描述等多模态任务来说至关重要。它让模型能够充分利用不同模态的数据信息,生成更加准确和丰富的回答,为多模态人工智能应用开辟了新的道路。
ReAct将推理与明确的行动交织在一起,使模型在生成过程中能够执行诸如API调用等操作。
模型会生成一个包含推理步骤的解释序列,展示其思考过程。这就好比一个人在解决问题时,会逐步阐述自己的思路,让他人能够理解其思考逻辑。
通过特殊的标记,指示模型执行特定的操作,例如查询数据库获取相关信息。这些标记就像是模型的“行动指令”,引导模型与外部资源进行交互。
最终输出不仅包含推理的路径,还包括执行行动的结果。这样可以让用户清楚地看到模型是如何思考以及根据思考采取了哪些行动,结果又是什么。
defgenerate_with_actions(prompt: str)-> str:
inputs = gen_tokenizer.encode(prompt, return_tensors="pt", truncation=True, max_length=300)
outputs = gen_model.generate(inputs, max_length=300, num_beams=5)
returngen_tokenizer.decode(outputs[0], skip_special_tokens=True)
ReAct的交错设计需要精心设计提示工程,以便在同一生成周期内同时触发推理和可执行的输出。这种设计让模型能够在思考的同时采取实际行动,获取更多信息来完善回答,提升了模型的实用性和智能性,但也对提示设计提出了更高的要求。
REPLUG把大语言模型视为一个“黑匣子”,在不修改模型的前提下,通过在输入前添加外部检索到的文档来增强其输入内容。
利用像FAISS这样独立的检索系统来收集相关文档,为模型提供丰富的外部知识支持。这就好比给模型配备了一个强大的“知识助手”,帮助它获取更多信息。
将检索到的文档添加到查询前面,在保持大语言模型原始架构不变的情况下,丰富模型的输入内容,引导模型生成更好的回答。
把增强后的提示输入到大语言模型中,让模型基于这些丰富的信息进行处理和生成。
defreplug_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]foriinindices[0]]
enriched_prompt = construct_prompt(query, retrieved)
returngenerate_response(enriched_prompt, gen_model, gen_tokenizer)
REPLUG提供了一种模块化的方法,通过外部检索提升大语言模型的性能,同时保持核心模型不变。这种方式简单高效,方便在不同场景中快速应用,为优化大语言模型的表现提供了一种便捷途径。
Memo RAG集成了一个内存组件,它能将大型数据集压缩成“全局内存”,并生成检索线索来引导外部搜索。
运用知识蒸馏等技术压缩大型数据集,将海量的信息浓缩成更易于管理和使用的形式,存储在“全局内存”中。
针对给定的查询,模型会生成检索提示,这些提示就像“线索”一样,帮助模型在外部搜索时更精准地定位相关信息。
将生成的线索与检索到的数据进行合并,构建最终的提示,为模型生成回答提供更有针对性的信息。
# 假设memory_module是一个预训练模块,具有generate_clue方法。
defmemo_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]foriinindices[0]]
prompt = construct_prompt(query, retrieved)
returngenerate_response(prompt, gen_model, gen_tokenizer)
Memo RAG借助内部内存机制提高了外部检索的精度,尤其在处理模糊或复杂查询时表现出色。通过生成线索引导检索,模型能够更准确地找到相关信息,从而生成更符合需求的高质量回答。
在检索增强生成(RAG)技术的不断演进中,诞生了诸多创新的变体,为大语言模型(LLM)的发展注入了新的活力。今天,让我们一同深入探索从15. ATLAS开始的多种RAG变体,揭开它们提升模型性能的神秘面纱。
ATLAS的独特之处在于,它将检索与注意力机制巧妙融合,通过把检索到的文档直接整合到transformer的注意力层,让模型在处理文本时能够更充分地利用外部知识。
defscaled_dot_product_attention(Q, K, V, mask=None):
importmath
d_k = Q.size(-1)
scores = torch.matmul(Q, K.transpose(-2,-1)) / math.sqrt(d_k)
ifmaskisnotNone:
scores = scores.masked_fill(mask ==0,-1e9)
attention_weights = torch.softmax(scores, dim=-1)
output = torch.matmul(attention_weights, V)
returnoutput, attention_weights
其中,和均来自检索到的数据。
RETRO另辟蹊径,将检索功能融入transformer的架构之中。它把输入文本划分为固定大小的块,然后利用交叉注意力机制从外部数据库中查找相似序列。
defretro_retrieve(block_embedding, index, k=5):
distances, indices = index.search(block_embedding.detach().cpu().numpy().astype('float32'), k)
returnindices
output = scaled_dot_product_attention(Q, K, V)[0]
自动RAG引入了自主迭代循环机制,模型能够自我评估输出,并根据评估结果决定是否需要进一步检索。
defauto_rag(prompt: str, max_iterations: int =3, threshold: float =0.8)-> str:
current_prompt = prompt
foriinrange(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)
ifconf >= threshold:
break
current_prompt +="\n[RETRIEVE_MORE]"
returnresponse
CORAG聚焦于在资源受限的环境中优化检索过程,它采用蒙特卡洛树搜索(MCTS)等策略,平衡检索质量与计算成本。
defmcts_retrieval(query: str, index: faiss.IndexFlatL2, iterations: int =10):
best_set =None
best_score = -float('inf')
for_inrange(iterations):
candidate_set = sample_candidate_set(index)
quality = evaluate_candidate_quality(candidate_set, query)
cost = evaluate_candidate_cost(candidate_set)
score = quality - cost
ifscore > best_score:
best_score = score
best_set = candidate_set
returnbest_set
EACO - RAG借助边缘计算的优势,将检索过程分布到各个边缘节点,有效降低延迟并平衡计算负载。
defedge_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]foriinindices[0]]
defcollaborative_retrieve(query: str, edge_indices: list)-> list:
results = []
foridxinedge_indices:
results.extend(edge_retrieve(query, idx))
returnrank_results(results)
规则RAG通过应用明确的特定领域规则,指导检索和合成过程,确保最终输出仅包含高度相关的文档信息。
defapply_rules(query: str, documents: list, keyword: str ="RAG")-> list:
return[docfordocindocumentsifkeyword.lower()indoc.lower()]
defrule_rag(query: str, dense_index: faiss.IndexFlatL2)-> str:
_, indices = retrieve_documents(encode_query(query), dense_index, k=10)
raw_docs = [chunks[i]foriinindices[0]]
filtered_docs = apply_rules(query, raw_docs, keyword="RAG")
prompt = construct_prompt(query, filtered_docs)
returngenerate_response(prompt, gen_model, gen_tokenizer)
对话式RAG专为多轮对话系统设计,它能够根据对话历史持续更新检索上下文,提供更符合对话情境的回答。
defconversational_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]foriinindices[0]]
prompt = construct_prompt(full_query, retrieved)
returngenerate_response(prompt, gen_model, gen_tokenizer)
迭代RAG通过多次检索和生成循环,不断优化响应,直至答案满足预设的收敛标准。
defiterative_rag(query: str, dense_index: faiss.IndexFlatL2, max_iters: int =3)-> str:
current_prompt = query
for_inrange(max_iters):
response = generate_response(current_prompt, gen_model, gen_tokenizer)
if"unclear"notinresponse:
returnresponse
_, indices = retrieve_documents(encode_query(response), dense_index, k=5)
additional_context =" ".join([chunks[i]foriinindices[0]])
current_prompt =f"{query}\n{additional_context}"
returnresponse
这种RAG变体将复杂查询分解为子查询的树状层次结构,全面探索问题的各个方面。
defdecompose_query(query: str)-> list:
# 为演示目的,按标点分割;如有需要,可替换为高级主题建模方法
returnquery.split(";")
deftree_retrieve(aspects: list, dense_index: faiss.IndexFlatL2)-> list:
tree_results = []
foraspectinaspects:
_, indices = retrieve_documents(encode_query(aspect), dense_index, k=3)
tree_results.extend([chunks[i]foriinindices[0]])
returnlist(set(tree_results))
deftree_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)
returngenerate_response(prompt, gen_model, gen_tokenizer)
CRAT将检索和因果推理融入翻译过程,有效处理模糊或特定领域的术语翻译。
defdetect_unknown_terms(text: str)-> list:
return[wordforwordintext.split()ifword.isupper()]
defconstruct_transkg(terms: list)-> dict:
return{term:f"translated_{term}"forterminterms}
defcrat_translate(text: str)-> str:
unknown_terms = detect_unknown_terms(text)
transkg = construct_transkg(unknown_terms)
forterm, translationintranskg.items():
text = text.replace(term, translation)
returntext
Graph RAG借助结构化知识图谱,捕捉实体之间的关系,并将这些结构化上下文融入文本生成过程。
importspacy, networkxasnx
nlp = spacy.load("en_core_web_sm")
defextract_entities_relations(text: str)-> (list, list):
doc = nlp(text)
entities = [ent.textforentindoc.ents]
relations = [(entities[i], entities[j])foriinrange(len(entities))forjinrange(i+1, len(entities))]
returnentities, relations
defbuild_graph(documents: list)-> nx.Graph:
G = nx.Graph()
fordocindocuments:
entities, relations = extract_entities_relations(doc)
forentityinentities:
G.add_node(entity)
for(e1, e2)inrelations:
G.add_edge(e1, e2)
returnG
defgraph_based_prompt(query: str, G: nx.Graph)-> str:
relevant_nodes = [nodefornodeinG.nodesifnode.lower()inquery.lower()]
graph_context =" ".join(relevant_nodes)
returnf"{query}\n[GRAPH_CONTEXT]{graph_context}"
主流RAG框架可以分为以下五个主要的进化方向:成本控制型(适合初创公司)、实时互动型(适用于财经/新闻场景)、域专家类型、认知增强型、安全与合规类型。接下来,让我们详细了解一下这25种RAG变体。
一个基本的RAG系统由检索模块和生成模块组成。系统会对查询进行编码,检索相关的文档块,然后为基于transformer的LLM构建丰富的提示。
fromtransformersimportAutoTokenizer, AutoModel
importtorch
tokenizer = AutoTokenizer.from_pretrained("facebook/dpr-question_encoder-single-nq-base")
model = AutoModel.from_pretrained("facebook/dpr-question_encoder-single-nq-base")
defencode_query(query: str)-> torch.Tensor:
inputs = tokenizer(query, return_tensors="pt", truncation=True, max_length=128)
returnmodel(**inputs).pooler_output
importnltk
nltk.download('punkt')
fromnltk.tokenizeimportsent_tokenize
defsegment_document(document: str, window_size: int =5, overlap: int =2)-> list:
sentences = sent_tokenize(document)
return[" ".join(sentences[i:i+window_size])foriinrange(0, len(sentences), window_size - overlap)]
importfaiss, numpyasnp
defbuild_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)
returnindex
defconstruct_prompt(query: str, retrieved_chunks: list)-> str:
delimiter ="[DOC]"
context =" ".join([f"{delimiter}{chunk}{delimiter}"forchunkinretrieved_chunks])
returnf"{query}\n{context}"
关键事实:标准RAG将外部知识动态注入生成过程,而无需修改LLM本身,就像是给LLM戴上了一副能随时获取新知识的“眼镜”。
CRAG在标准RAG的基础上增加了迭代反馈循环。它能够检测低置信度或不准确的输出,并重新查询外部知识库进行更正。
fromtransformersimportAutoModelForCausalLM
gen_tokenizer = AutoTokenizer.from_pretrained("gpt2")
gen_model = AutoModelForCausalLM.from_pretrained("gpt2")
defgenerate_response(prompt: str, max_length: int =200)-> str:
inputs = gen_tokenizer.encode(prompt, return_tensors="pt", truncation=True, max_length=1024)
outputs = gen_model.generate(inputs, max_length=max_length, num_beams=5, early_stopping=True)
returngen_tokenizer.decode(outputs[0], skip_special_tokens=True)
defevaluate_confidence(output_ids: torch.Tensor)-> float:
outputs = gen_model(output_ids, labels=output_ids)
returntorch.exp(-outputs.loss).item()
defiterative_crag(prompt: str, threshold: float =0.8, max_iters: int =3)-> str:
current_prompt = prompt
for_inrange(max_iters):
response = generate_response(current_prompt)
output_ids = gen_tokenizer.encode(response, return_tensors="pt")
conf = evaluate_confidence(output_ids)
ifconf >= threshold:
returnresponse
current_prompt +="\n[REFINE]"
returnresponse
关键事实:CRAG的迭代校正通过强制执行重新检索周期,直到输出达到预定义的置信度,从而最大限度地减少幻觉,让AI的回答更加靠谱。
Speculative RAG采用双模型策略:轻量级专家模型起草多个候选回答,重量级通才模型验证并选择最佳候选。
defgenerate_candidates(prompt: str, num_candidates: int =3)-> list:
inputs = gen_tokenizer.encode(prompt, return_tensors="pt", truncation=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)forcincandidates_ids]
defselect_best_candidate(candidates: list)-> str:
best_candidate =None
best_score = -float('inf')
forcandidateincandidates:
inputs = gen_tokenizer.encode(candidate, return_tensors="pt", truncation=True, max_length=1024)
outputs = gen_model(inputs, labels=inputs)
score = torch.exp(-outputs.loss).item()
ifscore > best_score:
best_score = score
best_candidate = candidate
returnbest_candidate
defspeculative_rag(prompt: str)-> str:
candidates = generate_candidates(prompt, num_candidates=3)
returnselect_best_candidate(candidates)
关键事实:通过将生成解耦为起草和验证,Speculative RAG利用并行性提高了速度和准确性,就像多个助手同时工作,然后挑选出最佳方案。
Fusion RAG集成了多种检索策略和各种数据源,以丰富提示。它同时使用语义(密集嵌入)和词法(基于关键字)检索方法。
# Placeholder for BM25 retrieval (e.g., using rank_bm25 library)
defbm25_retrieve(query: str, corpus: list, k: int =5):
fromrank_bm25importBM25Okapi
tokenized_corpus = [doc.split()fordocincorpus]
bm25 = BM25Okapi(tokenized_corpus)
tokenized_query = query.split()
scores = bm25.get_scores(tokenized_query)
top_k = np.argsort(scores)[-k:]
returntop_k
defhybrid_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)))
returnmerged_indices
Agentic RAG采用模块化“代理”,专门用于特定任务,如查询重新表述、文档检索和响应合成,允许动态、实时调整。
importrequests
defquery_reformulator(raw_query: str)-> str:
response = requests.post("http://agent-service/reformulate", json={"query": raw_query})
returnresponse.json().get("reformulated_query", raw_query)
defdocument_retriever(query: str)-> list:
response = requests.post("http://agent-service/retrieve", json={"query": query})
returnresponse.json().get("documents", [])
defresponse_synthesizer(original_query: str, documents: list)-> str:
payload = {"query": original_query,"documents": documents}
response = requests.post("http://agent-service/synthesize", json=payload)
returnresponse.json().get("response","")
defagentic_rag(raw_query: str)-> str:
reformulated_query = query_reformulator(raw_query)
docs = document_retriever(reformulated_query)
returnresponse_synthesizer(raw_query, docs)
关键事实:Agentic RAG的分散式设计通过在专业服务之间划分检索生成过程,实现了精细的控制和可扩展性,就像一个分工明确的团队高效协作。
Self-RAG是一种独特的RAG变体,它赋予LLM根据自身生成的响应检索上下文的能力,从而构建起一个迭代的自我提升循环,就像为模型注入了自我反思的“智慧”。
在初始生成阶段,模型会先依据输入生成一个初步的响应。随后,Self-RAG会对这个响应进行重新编码,这一过程被称为“自我嵌入”。通过自我嵌入,模型能够精准地识别出自身知识的缺口,明确哪些地方的信息还不够完善,哪些表述可能存在模糊之处。例如,在回答“2024年人工智能领域的重大突破有哪些”时,模型初步生成的答案中可能遗漏了部分关键突破,通过自我嵌入,就能发现这些缺失的信息。
基于自我评估所发现的知识差距,模型会启动内部反馈机制。它会依据这些自我评估的结果,从外部知识库或自身存储的信息中检索额外的上下文信息。这一过程就像是模型在主动查阅资料,为自己补充“营养”,让回答更加全面和准确。比如,模型在发现自己对“2024年人工智能领域的重大突破”回答不足后,会去检索相关的学术论文、新闻报道等资料,获取更多详细信息。
在获取到额外的上下文信息后,Self-RAG会更新输入提示,并将其重新输入到模型中进行新一轮的生成。这个过程会不断重复,直到模型对输出结果的置信度达到较高水平。每一次迭代都是对答案的优化和完善,使得模型的输出更加精准、可靠。例如,经过多次迭代,模型对“2024年人工智能领域的重大突破”的回答可能会从最初的简单列举,变得详细且深入,涵盖突破的技术原理、应用场景以及对行业的影响等多方面内容。
defself_rag(prompt: str, iterations: int =3)-> str:
current_prompt = prompt
for_inrange(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}"
returnresponse
在这段代码中,self_rag函数接收一个提示prompt和迭代次数iterations作为参数。在循环中,模型首先根据当前提示生成响应response,接着对响应进行编码得到response_emb,然后添加额外的上下文信息additional_context到当前提示中,最后返回最终的响应。通过这样的循环迭代,实现了Self-RAG的自我提升过程。
Self-RAG的关键优势在于,它借助内部自我评估来迭代提升输出质量。一旦模型识别到足够的上下文信息,就能够减少对外部资源的依赖,在保证回答质量的同时,提升了模型的自主性和效率。这意味着在一些外部资源受限的场景下,Self-RAG依然能够给出高质量的回答,展现出更强的适应性和灵活性。
Self-RAG为LLM的发展开辟了新的路径,通过自我反思和优化机制,让模型在不断迭代中变得更加智能和可靠。在未来的人工智能应用中,Self-RAG有望在智能问答、文档生成等领域发挥重要作用,为用户提供更优质的服务和体验。
自适应RAG的核心在于引入了一种门控机制,这种机制能够动态地决定模型是依靠自身内部的知识进行输出,还是调用外部检索来获取更全面的信息。这一设计就像是为模型配备了一个智能“开关”,使其能根据具体情况灵活调整策略,在保证回答质量的同时,最大限度地提高资源利用效率。
门控网络是自适应RAG的关键组件之一,它基于内部标记概率来计算置信度分数。简单来说,模型会对输入的查询进行分析,根据自身对该查询的理解程度给出一个置信度数值。这个数值反映了模型对利用内部知识回答问题的信心。如果模型对某个问题非常“熟悉”,其内部知识足以给出可靠的答案,那么置信度分数就会较高;反之,如果模型觉得这个问题比较陌生,内部知识可能不足以准确回答,置信度分数就会较低。
基于门控网络计算出的置信度分数,自适应RAG会进行动态切换。当置信度低于设定的阈值时,系统会判定模型内部知识不足,进而触发外部检索。在外部检索过程中,模型会从预先构建的数据库或知识源中查找相关信息,以补充自身的知识储备。而当置信度高于阈值时,模型则会直接依赖内部知识进行回答,这样可以避免不必要的外部检索,节省计算资源和时间成本。
根据门控结果,自适应RAG会有条件地构建丰富的提示。如果触发了外部检索,模型会将检索到的相关信息与原始查询相结合,形成一个包含更多上下文的提示,为后续的回答生成提供更充足的信息。反之,如果直接依赖内部知识,提示则可能仅包含原始查询。这种自适应的提示构建方式,能够根据实际情况为模型提供最恰当的引导,帮助模型生成更准确、更符合需求的回答。
defgating_decision(query: str, threshold: float =0.85)-> bool:
query_emb = encode_query(query)
confidence = query_emb.norm().item() /100
returnconfidence < threshold
defadaptive_rag(query: str, dense_index: faiss.IndexFlatL2)-> str:
ifgating_decision(query):
distances, indices = retrieve_documents(encode_query(query), dense_index, k=5)
retrieved_docs = [chunks[i]foriinindices[0]]
prompt = construct_prompt(query, retrieved_docs)
else:
prompt = query
returngenerate_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有望在智能问答、信息检索等多个领域发挥更大的作用,为用户带来更加优质的体验。
REFEED,即检索反馈(Retrieval Feedback),是RAG技术中的一个重要变体,它通过在模型初始输出后反馈外部证据的方式,有效地“纠正”答案,从而显著提升生成响应的质量。这一技术为大语言模型在处理复杂问题时提供了更可靠的解决方案,让模型的回答更加准确和完善。下面,我们就来详细了解REFEED的工作原理、具体实现步骤以及它的关键优势。
在REFEED的工作流程中,模型首先会根据输入的问题生成一个初步答案。这个初始答案是基于模型自身的知识和训练经验得出的,它为后续的优化提供了基础框架。虽然初始答案可能并不完美,但它包含了模型对问题的初步理解和分析,为进一步的改进指明了方向。
得到初始答案后,REFEED会对这个答案进行深入分析,识别其中可能存在的信息差距或不准确之处。基于这些分析结果,模型会启动新的检索过程,从外部知识库或相关数据源中查找能够补充和完善答案的信息。例如,如果初始答案在某个关键知识点上表述模糊或缺失,反馈检索就会针对性地寻找相关的详细解释、案例或数据,以填补这些知识缺口。
在获取到额外的上下文信息后,REFEED会将这些信息与原始提示进行合并,构建一个包含更丰富信息的新提示。然后,模型会基于这个新提示再次生成回答。通过这种方式,模型能够将新获取的知识融入到答案中,对初始答案进行优化和完善,从而生成一个更加准确、全面的最终回答。这种优化过程就像是为初始答案打上了一个个“补丁”,让答案的质量得到了显著提升。
defrefeed_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]foriinindices[0]])
new_prompt =f"{query}\n[REFEED CONTEXT]{additional_context}"
returngenerate_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有望在更多场景中得到应用和拓展,为用户提供更加优质的知识服务。
REALM将检索紧密集成到预训练和推理过程中,让模型从本质上就具备检索感知能力。
在预训练阶段,模型会对标记进行屏蔽,然后结合内部上下文与外部检索到的文档来预测这些标记。这一过程就像是模型在“学习”如何利用外部知识来填补文本中的空缺,从而提升对语言的理解和生成能力。
检索器和生成器会以端到端的方式一起进行优化。在这个过程中,两者相互协作,检索器为生成器提供更丰富准确的信息,生成器则根据这些信息不断调整,使得整体模型在生成文本时更加准确和合理。
对transformer架构进行了修改,虽然具体代码因模型而异,但关键步骤包括:
REALM在训练阶段对架构进行修改,使得检索成为语言建模的内在组成部分,而不是在推理时才进行的附加操作。这一设计让模型在处理各种语言任务时,能够更自然、高效地利用外部知识,提升了模型的性能和泛化能力。
RAPTOR将大型文档组织成一个分层树结构,为检索和生成提供了多级抽象能力。
利用k-means等算法对文档进行分段处理,并将相似的数据块聚集在一起。这一步就像是把一本厚厚的书按照主题和内容相似性分成不同的章节和段落,方便后续快速查找和管理。
通过递归地汇总聚类结果,构建出分层树。在这个树结构中,每个节点都代表了一定层次的信息汇总,从宏观到微观,形成了一个有序的知识体系。
在查询时,模型会遍历这棵树,既可以获取高级别的摘要信息,也能深入到细节层面获取精细的内容。这就好比在查阅一本目录清晰的书籍时,既能快速了解各章节的核心要点,又能根据需要深入阅读具体段落。
defcluster_chunks(embeddings: torch.Tensor, num_clusters: int =10):
fromsklearn.clusterimportKMeans
emb_np = embeddings.detach().cpu().numpy()
kmeans = KMeans(n_clusters=num_clusters)
labels = kmeans.fit_predict(emb_np)
returnlabels, kmeans.cluster_centers_
defbuild_tree(chunks: list, labels: list):
tree = {}
forlabelinset(labels):
tree[label] = [chunks[i]fori, labinenumerate(labels)iflab == label]
returntree
# 在查询时:
deftree_retrieve(query: str, tree: dict):
aspects = query.split() # 用于适当分解的占位符
retrieved = []
foraspectinaspects:
forkey, docsintree.items():
ifaspect.lower()in" ".join(docs).lower():
retrieved.extend(docs)
returnlist(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的多级检索策略,能够同时提供广泛和详细的上下文信息,这对于需要深入推理的任务来说至关重要。通过这种树状结构的组织和检索方式,模型可以更全面、准确地理解问题,并给出更有深度和准确性的回答。
REVEAL通过将视觉和文本数据整合到统一的表示形式中,把RAG技术拓展到了多模态领域。
使用共享编码器将图像和文本映射到同一个嵌入空间,使得模型能够在同一“语言”下理解和处理不同模态的数据。这就像是为图像和文本搭建了一座沟通的桥梁,让它们可以在模型内部自由交互。
可以同时检索与上下文相关的文本和视觉信息,为模型生成内容提供更丰富的素材。比如在描述一幅图片时,模型不仅能根据图片本身的特征,还能结合相关的文本描述来生成更准确、生动的内容。
在transformer架构中利用注意力层来整合多模态数据。注意力层就像是模型的“聚焦器”,可以让模型根据任务需求,有重点地关注不同模态的数据,从而更好地融合它们。
REVEAL的架构专门针对跨模态检索进行了优化,这对于视觉问答、图像描述等多模态任务来说至关重要。它让模型能够充分利用不同模态的数据信息,生成更加准确和丰富的回答,为多模态人工智能应用开辟了新的道路。
ReAct将推理与明确的行动交织在一起,使模型在生成过程中能够执行诸如API调用等操作。
模型会生成一个包含推理步骤的解释序列,展示其思考过程。这就好比一个人在解决问题时,会逐步阐述自己的思路,让他人能够理解其思考逻辑。
通过特殊的标记,指示模型执行特定的操作,例如查询数据库获取相关信息。这些标记就像是模型的“行动指令”,引导模型与外部资源进行交互。
最终输出不仅包含推理的路径,还包括执行行动的结果。这样可以让用户清楚地看到模型是如何思考以及根据思考采取了哪些行动,结果又是什么。
defgenerate_with_actions(prompt: str)-> str:
inputs = gen_tokenizer.encode(prompt, return_tensors="pt", truncation=True, max_length=300)
outputs = gen_model.generate(inputs, max_length=300, num_beams=5)
returngen_tokenizer.decode(outputs[0], skip_special_tokens=True)
ReAct的交错设计需要精心设计提示工程,以便在同一生成周期内同时触发推理和可执行的输出。这种设计让模型能够在思考的同时采取实际行动,获取更多信息来完善回答,提升了模型的实用性和智能性,但也对提示设计提出了更高的要求。
REPLUG把大语言模型视为一个“黑匣子”,在不修改模型的前提下,通过在输入前添加外部检索到的文档来增强其输入内容。
利用像FAISS这样独立的检索系统来收集相关文档,为模型提供丰富的外部知识支持。这就好比给模型配备了一个强大的“知识助手”,帮助它获取更多信息。
将检索到的文档添加到查询前面,在保持大语言模型原始架构不变的情况下,丰富模型的输入内容,引导模型生成更好的回答。
把增强后的提示输入到大语言模型中,让模型基于这些丰富的信息进行处理和生成。
defreplug_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]foriinindices[0]]
enriched_prompt = construct_prompt(query, retrieved)
returngenerate_response(enriched_prompt, gen_model, gen_tokenizer)
REPLUG提供了一种模块化的方法,通过外部检索提升大语言模型的性能,同时保持核心模型不变。这种方式简单高效,方便在不同场景中快速应用,为优化大语言模型的表现提供了一种便捷途径。
Memo RAG集成了一个内存组件,它能将大型数据集压缩成“全局内存”,并生成检索线索来引导外部搜索。
运用知识蒸馏等技术压缩大型数据集,将海量的信息浓缩成更易于管理和使用的形式,存储在“全局内存”中。
针对给定的查询,模型会生成检索提示,这些提示就像“线索”一样,帮助模型在外部搜索时更精准地定位相关信息。
将生成的线索与检索到的数据进行合并,构建最终的提示,为模型生成回答提供更有针对性的信息。
# 假设memory_module是一个预训练模块,具有generate_clue方法。
defmemo_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]foriinindices[0]]
prompt = construct_prompt(query, retrieved)
returngenerate_response(prompt, gen_model, gen_tokenizer)
Memo RAG借助内部内存机制提高了外部检索的精度,尤其在处理模糊或复杂查询时表现出色。通过生成线索引导检索,模型能够更准确地找到相关信息,从而生成更符合需求的高质量回答。
在检索增强生成(RAG)技术的不断演进中,诞生了诸多创新的变体,为大语言模型(LLM)的发展注入了新的活力。今天,让我们一同深入探索从15. ATLAS开始的多种RAG变体,揭开它们提升模型性能的神秘面纱。
ATLAS的独特之处在于,它将检索与注意力机制巧妙融合,通过把检索到的文档直接整合到transformer的注意力层,让模型在处理文本时能够更充分地利用外部知识。
defscaled_dot_product_attention(Q, K, V, mask=None):
importmath
d_k = Q.size(-1)
scores = torch.matmul(Q, K.transpose(-2,-1)) / math.sqrt(d_k)
ifmaskisnotNone:
scores = scores.masked_fill(mask ==0,-1e9)
attention_weights = torch.softmax(scores, dim=-1)
output = torch.matmul(attention_weights, V)
returnoutput, attention_weights
其中,和均来自检索到的数据。
RETRO另辟蹊径,将检索功能融入transformer的架构之中。它把输入文本划分为固定大小的块,然后利用交叉注意力机制从外部数据库中查找相似序列。
defretro_retrieve(block_embedding, index, k=5):
distances, indices = index.search(block_embedding.detach().cpu().numpy().astype('float32'), k)
returnindices
output = scaled_dot_product_attention(Q, K, V)[0]
自动RAG引入了自主迭代循环机制,模型能够自我评估输出,并根据评估结果决定是否需要进一步检索。
defauto_rag(prompt: str, max_iterations: int =3, threshold: float =0.8)-> str:
current_prompt = prompt
foriinrange(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)
ifconf >= threshold:
break
current_prompt +="\n[RETRIEVE_MORE]"
returnresponse
CORAG聚焦于在资源受限的环境中优化检索过程,它采用蒙特卡洛树搜索(MCTS)等策略,平衡检索质量与计算成本。
defmcts_retrieval(query: str, index: faiss.IndexFlatL2, iterations: int =10):
best_set =None
best_score = -float('inf')
for_inrange(iterations):
candidate_set = sample_candidate_set(index)
quality = evaluate_candidate_quality(candidate_set, query)
cost = evaluate_candidate_cost(candidate_set)
score = quality - cost
ifscore > best_score:
best_score = score
best_set = candidate_set
returnbest_set
EACO - RAG借助边缘计算的优势,将检索过程分布到各个边缘节点,有效降低延迟并平衡计算负载。
defedge_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]foriinindices[0]]
defcollaborative_retrieve(query: str, edge_indices: list)-> list:
results = []
foridxinedge_indices:
results.extend(edge_retrieve(query, idx))
returnrank_results(results)
规则RAG通过应用明确的特定领域规则,指导检索和合成过程,确保最终输出仅包含高度相关的文档信息。
defapply_rules(query: str, documents: list, keyword: str ="RAG")-> list:
return[docfordocindocumentsifkeyword.lower()indoc.lower()]
defrule_rag(query: str, dense_index: faiss.IndexFlatL2)-> str:
_, indices = retrieve_documents(encode_query(query), dense_index, k=10)
raw_docs = [chunks[i]foriinindices[0]]
filtered_docs = apply_rules(query, raw_docs, keyword="RAG")
prompt = construct_prompt(query, filtered_docs)
returngenerate_response(prompt, gen_model, gen_tokenizer)
对话式RAG专为多轮对话系统设计,它能够根据对话历史持续更新检索上下文,提供更符合对话情境的回答。
defconversational_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]foriinindices[0]]
prompt = construct_prompt(full_query, retrieved)
returngenerate_response(prompt, gen_model, gen_tokenizer)
迭代RAG通过多次检索和生成循环,不断优化响应,直至答案满足预设的收敛标准。
defiterative_rag(query: str, dense_index: faiss.IndexFlatL2, max_iters: int =3)-> str:
current_prompt = query
for_inrange(max_iters):
response = generate_response(current_prompt, gen_model, gen_tokenizer)
if"unclear"notinresponse:
returnresponse
_, indices = retrieve_documents(encode_query(response), dense_index, k=5)
additional_context =" ".join([chunks[i]foriinindices[0]])
current_prompt =f"{query}\n{additional_context}"
returnresponse
这种RAG变体将复杂查询分解为子查询的树状层次结构,全面探索问题的各个方面。
defdecompose_query(query: str)-> list:
# 为演示目的,按标点分割;如有需要,可替换为高级主题建模方法
returnquery.split(";")
deftree_retrieve(aspects: list, dense_index: faiss.IndexFlatL2)-> list:
tree_results = []
foraspectinaspects:
_, indices = retrieve_documents(encode_query(aspect), dense_index, k=3)
tree_results.extend([chunks[i]foriinindices[0]])
returnlist(set(tree_results))
deftree_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)
returngenerate_response(prompt, gen_model, gen_tokenizer)
CRAT将检索和因果推理融入翻译过程,有效处理模糊或特定领域的术语翻译。
defdetect_unknown_terms(text: str)-> list:
return[wordforwordintext.split()ifword.isupper()]
defconstruct_transkg(terms: list)-> dict:
return{term:f"translated_{term}"forterminterms}
defcrat_translate(text: str)-> str:
unknown_terms = detect_unknown_terms(text)
transkg = construct_transkg(unknown_terms)
forterm, translationintranskg.items():
text = text.replace(term, translation)
returntext
Graph RAG借助结构化知识图谱,捕捉实体之间的关系,并将这些结构化上下文融入文本生成过程。
importspacy, networkxasnx
nlp = spacy.load("en_core_web_sm")
defextract_entities_relations(text: str)-> (list, list):
doc = nlp(text)
entities = [ent.textforentindoc.ents]
relations = [(entities[i], entities[j])foriinrange(len(entities))forjinrange(i+1, len(entities))]
returnentities, relations
defbuild_graph(documents: list)-> nx.Graph:
G = nx.Graph()
fordocindocuments:
entities, relations = extract_entities_relations(doc)
forentityinentities:
G.add_node(entity)
for(e1, e2)inrelations:
G.add_edge(e1, e2)
returnG
defgraph_based_prompt(query: str, G: nx.Graph)-> str:
relevant_nodes = [nodefornodeinG.nodesifnode.lower()inquery.lower()]
graph_context =" ".join(relevant_nodes)
returnf"{query}\n[GRAPH_CONTEXT]{graph_context}"
| 欢迎光临 链载Ai (https://www.lianzai.com/) | Powered by Discuz! X3.5 |