基于Qwen-14b的基础RAG实现及反思

1、概览

        本文主要介绍RAG的基础实现过程,给初学者提供一些帮助,RAG即检索增强生成,主要是两个步骤:检索、生成,下面将基于这两部分进行介绍。

2、检索

        检索的主要目的是在自定义的知识库kb中查询到与问题query相关的候选答案。过程中主要涉及的几个关键内容是:文本向量化模型、向量数据库,文本向量化模型如GTE、BGE等、向量数据库如faiss、weaviate、milvus等,对于选型本文不作介绍,读者可自行了解。

        向量数据库主要用于存放文本向量化模型处理的知识库向量,并为检索相似候选答案提供快速的方法,下面以bge-large-zh及faiss库讲解一下检索的主要内容。

2.1 向量库构建

        向量库构建前需要构建知识库,对知识库的处理五花八门,可以是pdf、docx、txt、pptx、web等等,本文以构建好的txt为例介绍,txt内容举例如下:

文本内容

文本内容

注:文本格式并无要求,可先随机复制一些文本内容,对于质量下文说明

        文本内容的读取使用 langchain_community 工具封装好的方法,如下:

loader = TextLoader('test.txt')

        当我们的文本内容校多时,可以遍历文件夹读取txt文件。

        然后需要将文本内容转化为向量,内容如下,直接给出全部代码:

from langchain_community.document_loaders import TextLoader
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
import os

embed_path = 'path/to/bge_model_weight'
faiss_path = 'faiss_db.index'

filename = os.listdir('data')

data = []

for fn in filename:
    loader = TextLoader(f'data/{fn}')
    data.append(loader.load()[0])

embeddings = HuggingFaceEmbeddings(model_name=embed_path, model_kwargs={'device': 'cuda'})
db = FAISS.from_documents(data, embeddings)
db.save_local(faiss_path)

           其中,FAISS.from_documents(data, embeddings) 方法即为向量数据库构建,通过传入需要构建的数据及向量化模型,然后调用save_local方法将向量存储到向量数据库中,至此,向量数据库已构建完成。

2.2 向量库检索

        向量库检索主要使用Faiss的 as_retriever() 方法,如下:

from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS

embed_path = 'path/to/bge_model_weight'
faiss_path = 'faiss_db.index'

embeddings = HuggingFaceEmbeddings(model_name=embed_path, model_kwargs={'device': 'cuda'})
db = FAISS.load_local(faiss_path, embeddings, allow_dangerous_deserialization=True)


result = db.as_retriever().invoke('什么是RAG', return_scores=True)

print(result)

        其中,result默认会包含最相似的top4个候选答案,至此,向量库构建及检索均已完成,下面介绍生成应用。

3、生成

        以qwen2.5-14b模型为例,搭建rag应用,实现如下:

from modelscope import AutoModelForCausalLM, AutoTokenizer
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS

model_name = "path/to/Qwen2.5-14B-Instruct"
embed_path = 'path/to/bge_model_weight'
faiss_path = 'faiss_db.index'

model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype="auto",
    device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)

RAG_prompt = """
                请根据输入内容总结回答

                """

messages = [
    {"role": "system", "content": RAG_prompt}
    # {"role": "user", "content": prompt}
]

embeddings = HuggingFaceEmbeddings(model_name=embed_path, model_kwargs={'device': 'cuda'})
db = FAISS.load_local(faiss_path, embeddings, allow_dangerous_deserialization=True)

while True:
    query = input("question: ")
    if query == "exit":
        break
    result = db.as_retriever().invoke(query)

    test_text = f"按照要求回答用户问题\n。参考文档:{result[0].page_content}.\n 用户问题是:{query}\n "

    messages.append({"role": "user", "content": test_text})
    text = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=True
    )
    model_inputs = tokenizer([text], return_tensors="pt").to(model.device)

    generated_ids = model.generate(
        **model_inputs,
        max_new_tokens=512
    )
    generated_ids = [
        output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
    ]

    response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

    print("AI: " + response)

    print('*'*30)

        生成过程的关键处理是构建test_text = f"按照要求回答用户问题\n。参考文档:{result[0].page_content}.\n 用户问题是:{query}\n "

        即在构建prompt时传入候选答案,示例中使用了top1,即最相关的参考答案,然后其余步骤是利用大模型的语言能力根据参考答案回答用户问题。

4、思考

4.1 知识库质量 

        知识库质量是影响检索效果的关键因素,如上述的txt文件,每个相对独立的文件我们称为document,要注意你知识库的多个document并不是完全独立的,而是相对独立的,换句话说,至少上下文的语义是有相关性的,因此我们在处理document时要考虑重叠overlap,即docment1中要包含一些document2的内容;反之如果文档都是完全独立的,则不需要考虑,但这在实际情况中较少。

4.2 检索效果调整

        检索效果调整我认为可以分为几个方面,无先后顺序

        a、向量库质量-上文已说明

        b、系统、问答提示词,不断优化prompt增强对大模型的要求

        c、参考文档数量,可以增加参考文档以增强效果,如增加到4个,丰富候选集

        d、重排reranker,增加重排模型,对检索的结果再次进行相似度处理,提升候选集准确率

        e、增加llm参数,换用参数量大的llm,能力强

你可能感兴趣的:(python,llm,人工智能,python,qwen,rag)