ai - rag - 入门 sentence-transformers faiss-cpu transformers
访问量: 3
refer to: deepseek
安装环境:
pip install sentence-transformers faiss-cpu transformers
非常漫长的时间,挂好梯子。
然后运行下列代码:
from sentence_transformers import SentenceTransformer
from transformers import pipeline
import faiss
import numpy as np
# 1. 准备知识库
documents = [
"狗是犬科动物,有超过300个品种",
"猫是肉食性动物,擅长捕捉老鼠",
"熊猫是中国的国宝,以竹子为主食"
]
# 2. 加载模型
embedder = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2') # 小型多语言嵌入模型
generator = pipeline('text-generation', model='uer/gpt2-chinese-cluecorpussmall') # 小型中文生成模型
# 3. 构建索引
doc_embeddings = embedder.encode(documents)
index = faiss.IndexFlatL2(doc_embeddings.shape[1])
index.add(np.array(doc_embeddings))
# 4. RAG流程
query = "熊猫吃什么?"
query_embedding = embedder.encode([query])
distances, indices = index.search(query_embedding, k=1) # 检索最相关的1个文档
context = documents[indices[0][0]]
response = generator(f"根据以下内容回答问题:{context}\n问题:{query}")[0]['generated_text']
print(response)
运行。
可以看到,RAG就是基于本地的知识库,来做回答的。不准确。估计需要调试
2025.4.2 更新:
下面是对于回答不准确的解释:
think
嗯,用户问的是为什么他们的RAG模型生成的回答不是预期的“熊猫吃绿色的竹子”,而是一些看起来没有逻辑的文字。我需要仔细分析他们的代码和提供的输出来找出问题所在。
首先,看看用户的代码。他们用了一个Sentence Transformer模型来生成文档的嵌入,然后用FAISS进行检索,最后用GPT-2的中文模型生成回答。输入的文档中确实有正确的信息:“熊猫是中国的国宝,吃绿色的竹子”。所以理论上,当问题“熊猫吃什么?”被提出时,模型应该检索到正确的文档并生成正确的答案。
但用户的输出显示回答是混乱的,比如提到草莓冰淇淋之类的无关内容。这说明生成模型并没有正确利用检索到的上下文信息。可能的问题出在生成模型的输入格式或者模型本身的能力上。
首先,我需要检查生成模型的输入是否正确。用户将上下文和问题拼接成字符串,例如:“根据以下内容回答问题:熊猫是中国的国宝,吃绿色的竹子\n问题:熊猫吃什么?”。然后输入到生成模型中。看起来格式是正确的,但可能生成模型没有正确理解这个结构,或者没有经过足够的训练来按照这种格式回答问题。
接下来,考虑生成模型的选择。用户使用的是uer/gpt2-chinese-cluecorpussmall,这是一个较小的中文GPT-2模型。这类模型可能在生成长文本或遵循指令方面表现不佳,尤其是在需要精确回答的情况下。如果模型没有经过微调,可能倾向于生成自由文本而不是严格按照提供的上下文回答问题。也就是说,模型可能没有学会如何基于给定的上下文生成答案,而是根据自身的训练数据自由发挥,导致不相关的回答。
另外,检查生成模型的调用参数。用户没有设置max_length、temperature等参数,这可能导致生成结果过长或不稳定。例如,默认的生成参数可能允许模型生成过多的文本,从而偏离正确的答案。尝试调整这些参数可能会改善结果,比如限制生成长度,降低temperature以减少随机性。
还有一个可能性是,虽然检索到了正确的上下文,但生成模型在接收输入时格式存在问题,导致模型没有正确识别需要回答的部分。例如,在输入中是否明确指示模型要根据上下文回答问题?可能需要更明确的提示,比如在输入中加入“答案:”或者使用更明确的模板,引导模型正确生成答案。
此外,用户提供的示例输出中有多次重复的问题“熊猫吃什么?”,这可能是因为生成模型在生成过程中重复了输入中的问题部分,而没有正确截断。或者,模型在生成时没有遇到停止符号,导致继续生成无关内容。
还有一个可能性是编码或模型加载的问题,比如模型是否正确地加载了权重,是否有错误发生。不过用户的代码中并没有显示错误信息,只是输出了不符合预期的结果,所以可能问题不在于此。
总结可能的原因:
1. 生成模型(uer/gpt2-chinese-cluecorpussmall)能力有限,无法正确遵循指令生成基于上下文的答案。
2. 生成时的参数设置不合适,如max_length过短或过长,temperature过高导致随机性大。
3. 输入格式不够明确,导致模型无法正确识别需要回答的问题和上下文的关系。
4. 模型在训练时未学习到如何根据给定上下文生成答案,而是倾向于自由生成,尤其是在较小的模型上更为明显。
可能的解决方案:
- 更换生成模型为更适合任务导向的模型,比如使用经过微调的模型,或者更大的模型如GPT-3或者中文的ChatGLM、ERNIE等。
- 调整生成参数,比如设置max_new_tokens=50,temperature=0.1,确保生成内容更集中。
- 优化输入格式,例如使用更明确的模板,如“问题:{query}\n上下文:{context}\n答案:”并在生成时让模型继续补全答案部分。
- 添加后处理步骤,截取生成文本中第一个合理的句子或段落,避免无关内容的延续。
回答:
你的RAG系统生成无逻辑文本的主要原因有以下几点:
生成模型选择不当:
使用的
uer/gpt2-chinese-cluecorpussmall
是基础GPT-2模型,没有经过指令微调(instruct-tuning)GPT-2本身是通用生成模型,不擅长做问答任务
该模型参数规模较小(约100M),理解任务指令能力有限
缺乏明确的指令格式:
当前输入格式
根据以下内容回答问题:{context}\n问题:{query}
不够明确模型无法区分上下文与指令的关系,容易自由发挥
生成参数未优化:
未设置关键参数如
max_length
、temperature
等默认参数可能导致无限续写或高随机性输出
建议的改进方案:
# 改用指令微调模型
generator = pipeline(
'text2text-generation'
,
model=
'uer/t5-base-chinese-cluecorpussmall'
, # 更适合问答的模型架构
max_length=
100
, # 限制输出长度
temperature=
0.1 # 降低随机性
)
# 调整输入格式
prompt = f"请根据以下内容回答问题:\n上下文:
{context}
\n问题:
{query}
\n答案:"
response = generator(prompt)
[
0
]
[
'generated_text'
]
改进方向说明:
更换模型类型:
推荐使用T5等encoder-decoder架构模型(如
uer/t5-base-chinese-cluecorpussmall
)或使用指令微调模型(如
chatglm-6b
等)
优化prompt工程:
# 更清晰的指令格式 prompt = f"""根据上下文回答问题: 上下文: {context} 问题: {query} 答案:"""
关键参数设置:
generator = pipeline( . . . , do_sample= True , max_new_tokens= 50 , # 精确控制生成长度 temperature= 0.3 , # 平衡创造性和准确性 top_p= 0.9 # 限制采样范围 )
后处理优化:
# 提取第一个句号前的内容 answer = response.split( "。" ) [ 0 ] + "。"
修改后系统的工作原理变化:
原始流程: 检索 -> GPT-2自由续写 改进后流程: 检索 -> 结构化prompt -> 受限参数生成 -> 后处理提取
这些改进将引导模型专注于从提供的上下文中提取答案,而不是自由生成无关内容。对于简单的问答任务,甚至可以跳过生成模型,直接返回检索到的文本片段。
完整代码: