与RAG集成的高级模式
本文档介绍如何将MaxKB知识库与检索增强生成(RAG)系统集成,实现更智能的知识检索和问答能力。
RAG基础架构
RAG工作流程
RAG的基本工作流程包括:
- 查询处理:解析和优化用户输入的查询
- 知识检索:从知识库中检索相关信息
- 上下文增强:将检索到的信息作为上下文提供给语言模型
- 回答生成:语言模型基于上下文生成回答
MaxKB与RAG集成架构
+----------------+
用户查询 --------> | 查询处理 |
+-------+--------+
|
v
+----------------+ +----------------+
| MaxKB检索 | <----> | 知识库存储 |
+-------+--------+ +----------------+
|
v
+----------------+
| 上下文构建 |
+-------+--------+
|
v
+----------------+
| LLM生成 |
+-------+--------+
|
v
回答
基础集成
简单RAG集成
使用MaxKB作为检索引擎的基本RAG实现:
from maxkb import MaxKB
import openai
# 初始化MaxKB客户端
client = MaxKB(config_path="config.yaml")
kb = client.get_knowledge_base("产品知识库")
# 定义RAG函数
def simple_rag(query, max_tokens=500):
# 1. 从MaxKB检索相关文档
retrieved_docs = kb.query(
query=query,
top_k=5,
similarity_threshold=0.7
)
# 2. 构建上下文提示
context = "\n\n".join([doc.content for doc in retrieved_docs])
prompt = f"""根据以下信息回答问题。如果信息中没有答案,请说明无法回答。
问题: {query}
信息:
{context}
回答:"""
# 3. 调用LLM生成回答
response = openai.Completion.create(
model="gpt-4",
prompt=prompt,
max_tokens=max_tokens,
temperature=0.3
)
return {
"answer": response.choices[0].text.strip(),
"sources": [{"title": doc.metadata.get("title", "未知"), "url": doc.metadata.get("url", "")}
for doc in retrieved_docs]
}
高级RAG模式
查询重写
通过查询重写提高检索质量:
def advanced_rag_with_query_rewriting(query, max_tokens=500):
# 1. 查询重写
rewrite_prompt = f"""将以下用户问题重写为更适合文档检索的形式,保留所有重要信息:
原始问题: {query}
重写后的问题:"""
rewrite_response = openai.Completion.create(
model="gpt-3.5-turbo-instruct",
prompt=rewrite_prompt,
max_tokens=100,
temperature=0.2
)
rewritten_query = rewrite_response.choices[0].text.strip()
# 2. 使用重写后的查询进行检索
retrieved_docs = kb.query(
query=rewritten_query,
top_k=5,
similarity_threshold=0.7
)
# 3. 构建上下文提示并生成回答
# ... 与简单RAG相同
多步骤RAG
将复杂查询分解为多个子查询,然后综合信息:
def multi_step_rag(query, max_tokens=500):
# 1. 分解查询
decompose_prompt = f"""将以下复杂问题分解为2-3个简单的子问题,每个子问题应该能独立回答:
问题: {query}
子问题:"""
decompose_response = openai.Completion.create(
model="gpt-4",
prompt=decompose_prompt,
max_tokens=200,
temperature=0.3
)
sub_queries = [q.strip() for q in decompose_response.choices[0].text.split("\n") if q.strip()]
# 2. 对每个子查询进行检索
all_docs = []
for sub_query in sub_queries:
sub_docs = kb.query(
query=sub_query,
top_k=3,
similarity_threshold=0.7
)
all_docs.extend(sub_docs)
# 3. 去重
unique_docs = {}
for doc in all_docs:
doc_id = doc.id
if doc_id not in unique_docs:
unique_docs[doc_id] = doc
# 4. 构建上下文提示并生成回答
context = "\n\n".join([doc.content for doc in unique_docs.values()])
prompt = f"""根据以下信息回答问题。如果信息中没有答案,请说明无法回答。
问题: {query}
信息:
{context}
回答:"""
response = openai.Completion.create(
model="gpt-4",
prompt=prompt,
max_tokens=max_tokens,
temperature=0.3
)
return {
"answer": response.choices[0].text.strip(),
"sources": [{"title": doc.metadata.get("title", "未知"), "url": doc.metadata.get("url", "")}
for doc in unique_docs.values()]
}
反馈循环RAG
实现包含用户反馈循环的RAG系统:
def feedback_loop_rag(query, feedback=None, max_tokens=500):
if feedback:
# 根据用户反馈调整检索策略
if "需要更多信息" in feedback:
# 增加检索数量
top_k = 8
similarity_threshold = 0.65
elif "信息太多" in feedback:
# 减少检索数量,提高相关度要求
top_k = 3
similarity_threshold = 0.80
else:
# 默认设置
top_k = 5
similarity_threshold = 0.70
else:
# 初始设置
top_k = 5
similarity_threshold = 0.70
# 执行检索
retrieved_docs = kb.query(
query=query,
top_k=top_k,
similarity_threshold=similarity_threshold
)
# 生成回答
# ... 生成回答逻辑
return {
"answer": answer,
"sources": sources,
"feedback_options": [
"需要更多信息",
"信息太多",
"信息不相关",
"回答满意"
]
}
与LLM集成
MaxKB与不同LLM的集成
MaxKB支持与多种LLM集成:
OpenAI GPT集成
def maxkb_with_openai(query):
# 从MaxKB检索
docs = kb.query(query, top_k=5)
context = "\n\n".join([doc.content for doc in docs])
# OpenAI调用
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[
{"role": "system", "content": "你是一个知识助手,根据提供的信息回答问题。"},
{"role": "user", "content": f"根据以下信息回答问题:\n\n{context}\n\n问题: {query}"}
]
)
return response.choices[0].message.content
Anthropic Claude集成
import anthropic
def maxkb_with_claude(query):
# 从MaxKB检索
docs = kb.query(query, top_k=5)
context = "\n\n".join([doc.content for doc in docs])
# Anthropic调用
client = anthropic.Client(api_key="your_api_key")
response = client.completion(
prompt=f"{anthropic.HUMAN_PROMPT} 根据以下信息回答问题:\n\n{context}\n\n问题: {query} {anthropic.AI_PROMPT}",
model="claude-2",
max_tokens_to_sample=500,
temperature=0.3
)
return response.completion
本地部署的LLM集成
from llama_cpp import Llama
def maxkb_with_local_llm(query):
# 从MaxKB检索
docs = kb.query(query, top_k=5)
context = "\n\n".join([doc.content for doc in docs])
# 本地LLM调用
llm = Llama(model_path="models/llama-2-13b-chat.gguf", n_ctx=4096)
prompt = f"""<s>[INST] <<SYS>>
你是一个知识助手,根据提供的信息回答问题。
<</SYS>>
根据以下信息回答问题:
{context}
问题: {query} [/INST]"""
response = llm(prompt, max_tokens=500, temperature=0.3, stop=["</s>"])
return response["choices"][0]["text"]
高级应用场景
对话式RAG
维护对话历史的RAG系统:
def conversational_rag(query, conversation_history=None):
if conversation_history is None:
conversation_history = []
# 生成上下文感知查询
if conversation_history:
# 利用历史对话生成更好的查询
context_query_prompt = f"""基于以下对话历史,将用户的最新问题转换为包含完整上 下文的搜索查询:
对话历史:
{"".join([f"{'用户' if i%2==0 else '助手'}: {msg}\n" for i, msg in enumerate(conversation_history)])}
用户最新问题:{query}
完整搜索查询:"""
context_query_response = openai.Completion.create(
model="gpt-3.5-turbo-instruct",
prompt=context_query_prompt,
max_tokens=100,
temperature=0.3
)
enhanced_query = context_query_response.choices[0].text.strip()
else:
enhanced_query = query
# 执行检索
docs = kb.query(enhanced_query, top_k=5)
# 构建完整对话历史提示
messages = [{"role": "system", "content": "你是一个知识助手,根据提供的信息回答问题。"}]
# 添加对话历史
for i, msg in enumerate(conversation_history):
messages.append({
"role": "user" if i % 2 == 0 else "assistant",
"content": msg
})
# 添加上下文和当前问题
context = "\n\n".join([doc.content for doc in docs])
messages.append({
"role": "user",
"content": f"根据以下信息回答我的问题:\n\n{context}\n\n我的问题是:{query}"
})
# 调用LLM生成回答
response = openai.ChatCompletion.create(
model="gpt-4",
messages=messages,
temperature=0.7
)
answer = response.choices[0].message.content
# 更新对话历史
conversation_history.append(query)
conversation_history.append(answer)
return {
"answer": answer,
"conversation_history": conversation_history,
"sources": [{"title": doc.metadata.get("title", "未知"), "url": doc.metadata.get("url", "")} for doc in docs]
}
自动学习RAG
能够从查询和反馈中学习的RAG系统:
def learning_rag_system():
# 初始化反馈收集器
feedback_collector = FeedbackCollector()
# 定义查询函数
def query_with_learning(query, user_id):
# 执行RAG查询
result = simple_rag(query)
# 记录查询和结果
query_id = feedback_collector.record_query(
user_id=user_id,
query=query,
retrieved_docs=[doc.id for doc in result["sources"]],
answer=result["answer"]
)
# 添加反馈ID供后续使用
result["feedback_id"] = query_id
return result
# 定义反馈处理函数
def process_feedback(feedback_id, is_helpful, comments=None):
feedback_collector.record_feedback(
query_id=feedback_id,
is_helpful=is_helpful,
comments=comments
)
# 每积累50条反馈,执行一次学习
if feedback_collector.count_since_last_learning() >= 50:
learn_from_feedback()
# 定义学习函数
def learn_from_feedback():
# 获取积累的反馈
feedback_data = feedback_collector.get_all_feedback()
# 分析正面和负面反馈的模式
positive_patterns = analyze_patterns(
[item for item in feedback_data if item["is_helpful"]]
)
negative_patterns = analyze_patterns(
[item for item in feedback_data if not item["is_helpful"]]
)
# 基于模式调整检索策略
adjust_retrieval_strategy(positive_patterns, negative_patterns)
# 重置学习计数器
feedback_collector.reset_learning_counter()
# 返回函数集
return {
"query": query_with_learning,
"feedback": process_feedback
}