AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


基于高阶RAG的本地知识库问答机器人
发布日期:2024-05-05 07:37:06 浏览次数: 2237


项目开源地址

https://github.com/stay-leave/enhance_llm


检索增强生成(Retrieval Augmented Generation, RAG)是一种结合语言模型和信息检索的技术,用于生成更准确且与上下文相关的输出。

本项目即是搭建了一个高级RAG系统,实现本地知识库问答。


优势

  1. 即时性:通过检索外部信息源,RAG 能够即时更新模型的知识,让其对实时性、非公开或离线的数据也能提供有效回应。

  2. 准确性:注入的相关信息提升了模型输出的准确性,减少了幻觉问题。

  3. 数据安全:可以在内部构建知识库,从而确保敏感数据不会外泄。


工作流程

 1.检索(Retrieve):

    输入查询:用户通过输入查询或问题来开始这个流程。

    相似性搜索:系统将用户查询通过嵌入模型转换为向量,并在外部知识源中的向量数据库中进行相似性搜索。

    返回相关信息:搜索会返回与查询最接近的前 k 个数据对象(上下文信息),这些对象来自于知识库、数据库或其他数据源。


2. 增强(Augment):

    填入模板:用户查询与检索到的上下文信息被填入到一个提示模板中。

    构建完整提示:这个模板整合了查询和相关信息,构建出一个完整的提示词,用于指导模型生成。


3. 生成(Generate):

    输入到 LLM:构建好的提示被输入到大型语言模型(LLM),比如 GPT 或 Qwen。

    生成内容:模型根据提示词中的信息生成相关内容,包括回答、文本或其他输出。



系统架构

分为两个阶段:

1.indexing:数据读取、文档切分、向量嵌入、向量入库。

2.Retrieval and generation:检索、prompt增强、生成。


indexing阶段


1.数据读取

使用Langchain的文件读取类,将pdf、txt、image、html等解析为document。

from langchain_community.document_loaders.csv_loader import CSVLoader
from langchain_community.document_loaders import PyPDFLoader
# 读取csv,返回list
def load_csv(path):
   # 每条记录为一个元素
   loader = CSVLoader(
       file_path="project_1/data/clean.csv",
       encoding='utf-8' # 编码
   )
   data = loader.load()
   return data
# 读取pdf,返回list
def load_pdf(path):
   # 是以每页为一个元素的
   loader = PyPDFLoader("project_1/data/1.pdf")
   pages = loader.load_and_split()
   return pages

读取结果如上图。可以看到是csv是默认按每条记录为一个document的。


2.文档切块

使用RecursiveCharacterTextSplitter,通过特定字符来分割,默认的字符列表是 [“\n\n”, “\n”, " ", “”],对于中文文段的分割不是很理想。


from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(    chunk_size=200, # 指定每个文本块的目标大小,这里设置为200个字符。    chunk_overlap=50, # 指定文本块之间的重叠字符数,这里设置为50个字符。    length_function=len, # 用于测量文本长度的函数,这里使用Python内置的`len`函数。    is_separator_regex=False, # 指定`separators`中的分隔符是否应被视为正则表达式,这里设置为False,表示分隔符是字面字符。    separators=["\n\n",  "\n",   " ",    ".",    ",",     ",",  "。", ] # 定义用于分割文本的分隔符列表。)
pages = load_pdf("project_1/data/1.pdf")
texts = text_splitter.split_documents([pages[0].page_content])


3.向量化

针对特定领域,采取通用的向量模型会不适应当前数据集,影响其性能。因此进行了微调。

微调过程见http://t.csdnimg.cn/tLYek


from langchain.embeddings import HuggingFaceBgeEmbeddingsmodel_name = "project_2/bge-large-zh-v1.5"model_kwargs = {'device': 'cuda'}# # 当向量都被规范化(归一化)后,它们的范数都是1。# 余弦相似度的计算只需要向量的点积运算,从而减少了计算的复杂度,加快了处理速度。hf = HuggingFaceBgeEmbeddings(    encode_kwargs = {'normalize_embeddings': True}     model_name=model_name,    model_kwargs=model_kwargs,    encode_kwargs=encode_kwargs,    query_instruction="为这个句子生成表示以用于检索相关文章:")
embedding = hf.embed_query("你好!")len(embedding)


4.向量存储

向量数据库比较流行的有milvus、faiss、chroma等。

本项目使用chroma。

# 快速创建数据库from langchain_chroma import Chromadb = Chroma.from_documents(   documents = texts,    embedding = hf,   ids = None,   collection_name = 'test1',   collection_metadata = {"hnsw:space": "cosine"},   persist_directory = 'project_1/chroma_db'   )
# 相似度方法通过查询文本检索数据,会自动调用向量模型query = "网络首发是什么"docs = db.similarity_search(query)print(docs[0].page_content)


Retrieval and generation阶段

经过indexing阶段,已经有了一个可供向量检索的数据库和本地存储的集合了。进入到真正的应用流程。

1.检索

可以直接将Chroma转换为检索器,会根据相关性分数返回。Langchain集成的Chroma默认采用的是余弦相似度。

由于用户的query不一定适合在数据库中成功检索,比如在数码领域,用户输入“平果”,意思是想询问有关“苹果品牌”的信息,但是直接拿来检索跟本意就差了十万八千里。因此要进行query改写,也是使用大模型解决。

# 创建一个检索器retriever = vectorstore.as_retriever(search_kwargs={"k": 10})
query = "萧炎是谁?"
# Get relevant documents ordered by relevance scoredocs = retriever.invoke(query)


可以看到检索返回也是一个list


对于向量召回的文本块,还需要重排,使得相关性强的文本块能排在前面。

重排也使用BGE的reranker模型,将query与召回的文本块挨个计算相似度,再按照得分倒排。

该模型基于交叉熵损失进行优化,相关性得分不受特定范围的限制。根据我的实验,小于0是一定不行的。

# 重排        tokenizer = AutoTokenizer.from_pretrained(self.config.rerank_model)        model = AutoModelForSequenceClassification.from_pretrained(self.config.rerank_model)        model.eval()        pairs = [[new_query, doc.page_content] for doc in docs]        with torch.no_grad():            inputs = tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512)            scores = model(**inputs, return_dict=True).logits.view(-1, ).float()



2.生成

将检索返回的内容组成一个字符串,填充到提示词模版里,进行推理。

对于大模型也是有必要进行垂域的微调的,相关内容可见http://t.csdnimg.cn/kWA6S


# 实例化自定义模型llm = Qwen(mode_name_or_path = "/root/autodl-tmp/Qwen1.5-7B-Chat")
prompt = ChatPromptTemplate.from_template(PROMPT_TEMPLATE)
output_parser = StrOutputParser()
# 构建 chainchain = prompt | llm | output_parser
res = chain.invoke( { "context": format_docs(reordered_docs), "question": "小医仙是谁?" } )
print(res)


原始模型的回答:

sft后模型的回答:(太冷漠了)

dpo后模型的回答:(人类偏好优化就是强)

3.多轮对话——真正的qa机器人

手动构造了聊天记录缓存的功能,每次询问都会加上当前的聊天记录,模型同时使用聊天记录和向量召回的相关文本回答当前的query。


prompt = ChatPromptTemplate.from_template(PROMPT_TEMPLATE)
       chat_llm_chain = LLMChain(            llm=self.llm,            prompt=prompt,            verbose=True,        )
       # 生成回复        res = chat_llm_chain.predict(                                # 格式化聊天记录为JSON字符串                                chat_history = "\n".join([f"{entry['role']}: {entry['content']}" for entry in self.memory]),                                # chat_history = "\n".join(self.memory),                                context=context,                                question=query                                )                # res = chat_llm_chain.invoke({"context": context,"question": query})        logger.info(f"模型回复:{res}")
       # 更新聊天历史        self.memory.append({'role': 'user', 'content': query})        self.memory.append({'role': 'assistant', 'content': res})        print(self.memory)
       return res


看看效果,下面是我的query



sft后的模型效果,跟上面一样,表现太差,应该是训练轮次太少


dpo后的模型效果,非常好,这次dpo训了近十轮


原始的模型表现也不错


参考

  1. https://huggingface.co/docs/transformers/main_classes/text_generation

  2. https://zhuanlan.zhihu.com/p/688926320

  3. https://api.python.langchain.com/en/latest/vectorstores/langchain_community.vectorstores.chroma.Chroma.html#langchain_community.vectorstores.chroma.Chroma.from_documents

  4. https://www.cnblogs.com/AlwaysSui/p/18144181

  5. https://github.com/datawhalechina/self-llm

  6. https://python.langchain.com/docs/expression_language/get_started/



53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询