LLM RAG 多种方式装载LLM的实践

一、大模型系统中检索增强生成(RAG)的意义

当前大模型在处理特定领域或者高度专业化的查询时表现出知识缺失,当所需信息超出模型训练数据范围或需要最新数据时,大模型可能无法提供准确答案。基于行业SOP、行业标准、互联网实时信息等领域外部知识构建私域知识向量模型,设计RAG系统用于多文档、多源数据、多维数据的检索器,设计优化双编码、联合编码等方法的信息生成器,使得生成组件能够更深入地理解问题背后的上下文,并产生更加信息丰富的回答。

二、LLM-RAG的框架设计

整体框架包括 大部分:私域知识的嵌入;文档知识的分割;私域知识的向量化;大模型的装载;问答链的组装;
在这里插入图片描述
1、私域知识的嵌入
借助langchain及llama-index开发框架可满足目前大部分知识形式的嵌入,包括数据库、PDF、word、excel、csv、txt、markdown、知识图谱(neo4j)、图片等。
在这里插入图片描述
Llama-index提供的知识嵌入工具
在这里插入图片描述
Langchain 知识嵌入工具
2、文档知识的分割
我们知道目前的大模型对处理信息的多少有限制,输入到大模型系统内的信息量及其组合将直接影响大模型给出答案的相关性、准确性和及时性。因此对文档知识的合理分割是提升大模型检索增强及生成问答的关键。
文本分割主要考虑两个因素:1)embedding模型的Tokens限制情况;2)语义完整性对整体的检索效果的影响。一些常见的文本分割方式如下:
句分割:以”句”的粒度进行切分,保留一个句子的完整语义。常见切分符包括:句号、感叹号、问号、换行符等。
固定长度分割:根据embedding模型的token长度限制,将文本分割为固定长度(例如256/512个tokens),这种切分方式会损失很多语义信息,一般通过在头尾增加一定冗余量来缓解。

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500, chunk_overlap=150)
split_docs = text_splitter.split_documents(docs)

3、私域知识的向量化
向量化是一个将文本数据转化为向量矩阵的过程,该过程会直接影响到后续检索的效果。目前常见的embedding模型如表中所示,这些embedding模型基本能满足大部分需求,但对于特殊场景(例如涉及一些罕见专有词或字等)或者想进一步优化效果,则可以选择开源Embedding模型微调或直接训练适合自己场景的Embedding模型。
在这里插入图片描述
知识向量化的几种方式:

#modelscope下载:国内推荐
from langchain.embeddings import ModelScopeEmbeddings
model_id = "damo/nlp_corom_sentence-embedding_chinese-base"
#damo/nlp_corom_sentence-embedding_chinese-base
#damo/nlp_corom_sentence-embedding_english-base
embeddings = ModelScopeEmbeddings(model_id=model_id)
#hunggingface下载:国外推荐
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")
#from langchain.embeddings import SentenceTransformerEmbeddings
#embeddings = SentenceTransformerEmbeddings(model_name="all-MiniLM-L6-v2")
# 构建向量数据库
# 加载数据库
vectordb = Chroma.from_documents(
    documents=split_docs,
    embedding=embeddings,
    )

4、大模型的装载
目前基于大模型的应用开发有多种框架,如何根据硬件、场景需求等高效、便捷装载大模型是开发LLM-RAG系统的关键。以下汇总了多种装载方式:
1)基于llama.cpp的cpu低成本装载:主要模型文件来自于hunggingface;
2)基于chatglm.cpp的CPU低成本装载:包括langchian[api]、openai[api]等形式。
3)基于langchain及Hugging Face Local Pipelines装载:支持的模型参考langchian文档中心。
5、问答链的组装
同样的,langchain为我们准备了一些构造好的问答链(langchain chains),包括sql数据库查询链、CSV查询链、html查询链、问答链等。

三、LLM-RAG的实践

1、多种方式低成本装载LLM
① langchain local_model形式

from langchain.llms.base import LLM
from typing import Any, List, Optional
from langchain.callbacks.manager import CallbackManagerForLLMRun
from transformers import AutoTokenizer, AutoModelForCausalLM,pipeline
import torch
from langchain.llms.huggingface_pipeline import HuggingFacePipeline
model_path = "Qwen/Qwen-1_8B-Chat"
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True).to(torch.bfloat16).cuda(0)
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer, max_new_tokens=200000)
llm = HuggingFacePipeline(pipeline=pipe)

② langchain chatglm.cpp形式
参考chatglm.cpp GitHub网站:https://github.com/li-plus/chatglm.cpp

#安装chatglm.cpp库
!pip install --upgrade pip
!pip install chatglm.cpp[api]
#下载chatglm3-6b cpu量化文件
!git clone https://www.modelscope.cn/tiansz/chatglm3-6b-ggml.git
#启动 chatglm3-6b langchain-api服务
MODEL=./chatglm3-6b-ggml/chatglm3-ggml.bin uvicorn chatglm_cpp.langchain_api:app --host 127.0.0.1 --port 8000

获得chatglm3-6b langchain-api服务地址:http://127.0.0.1:8000
将chatglm3-6b接入langchain框架

endpoint_url = "http://127.0.0.1:8000"
llm = ChatGLM(
    endpoint_url=endpoint_url,
    max_token=1024,
    history=[
        ["我是数据分析师,可以向我查询任何关于数据分析的问题。"]
    ],
    top_p=0.9,
    model_kwargs={"sample_model_args": False},
)

③ langchian llama.cpp形式
llama.cpp是使用原始C ++的项目来重写LLaMa(长格式语言模型)等开源大模型推理代码。这使得可以在各种硬件上本地运行大模型。

#安装llama-cpp
!pip install llama-cpp-python
#从modelscope或者hunggingface下载量化模型:gguf
from modelscope.hub.file_download import model_file_download
model_dir = model_file_download(model_id='mikeee/TheBloke-openbuddy-zephyr-7B-v14.1-GGUF',file_path='openbuddy-zephyr-7b-v14.1.Q4_K_S.gguf',cache_dir='./Qwen')
#载入大模型
from langchain.llms import LlamaCpp
from langchain.prompts import PromptTemplate
from langchain.callbacks.manager import CallbackManager
callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])

n_gpu_layers =0  # Change this value based on your model and your GPU VRAM pool.
n_batch = 5120  # Should be between 1 and n_ctx, consider the amount of VRAM in your GPU.
callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])
# Make sure the model path is correct for your system!
llm = LlamaCpp(
    model_path="./Qwen/mikeee/TheBloke-openbuddy-zephyr-7B-v14.1-GGUF/openbuddy-zephyr-7b-v14.1.Q4_K_S.gguf",
    n_gpu_layers=n_gpu_layers,
    n_batch=n_batch,
    max_tokens=200000,
    n_ctx=8912,
    callback_manager=callback_manager,
    verbose=True,  # Verbose is required to pass to the callback manager
)

2、私有知识的装载及向量化
① 多文档处理

#装载文件
def get_doc(dir_path):
    file_lst = os.listdir(dir_path)
    docs = []
    i = 1
    for file in file_lst:
        file_type = file.split('.')[-1]
       
        #print(file_type)
        if  file_type == 'docx':
            loader = UnstructuredWordDocumentLoader(dir_path+'/'+file)
        elif file_type == 'csv':
            loader = UnstructuredCSVLoader(dir_path+'/'+file)
        elif file_type == 'pdf':
            loader = UnstructuredPDFLoader(dir_path+'/'+file)
        else:
            # 如果是不符合条件的文件,直接跳过
            continue
        docs.extend(loader.load())
        print(str(i)+'-----'+file+'------完成装载')
        i = +1
    return docs

文档分割及向量化

#载入开源向量化模型
from langchain.embeddings import ModelScopeEmbeddings
model_id = "damo/nlp_corom_sentence-embedding_chinese-base"
#damo/nlp_corom_sentence-embedding_chinese-base
#damo/nlp_corom_sentence-embedding_english-base
embeddings = ModelScopeEmbeddings(model_id=model_id)
#文档分割
docs = get_doc('./Qwen')
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500, chunk_overlap=150)
#文档向量化
split_docs = text_splitter.split_documents(docs)
vectordb = Chroma.from_documents(
    documents=split_docs,
    embedding=embeddings
    )

② 单文档处理

#pdf
loader = UnstructuredPDFLoader('./Qwen/2304.08485.pdf')
docs=loader.load()
#docx
loader = UnstructuredWordDocumentLoader('./Qwen/《主数据质量检查报告》LL.docx')
docs=loader.load()
#csv
from langchain.document_loaders.csv_loader import CSVLoader
loader = CSVLoader(file_path="./Qwen/正则式.csv")
docs = loader.load()
#web文件
from langchain.document_loaders import AsyncHtmlLoader
urls = ["https://price.21food.cn/yurou/", "https://price.21food.cn/fushipin/"]
loader = AsyncHtmlLoader(urls)
docs = loader.load()

3、文档:RAG Q&A
使用 RetrievalQA 作为问答链

from langchain.prompts import PromptTemplate

# 我们所构造的 Prompt 模板
template = """你是一个数据治理工程师同时也是一个知识搜索查询工程师,请根据可参考的上下文回答用户的问题,如果用户的问题不清晰且不是给定的上下文覆盖的,请不要乱回答,请回答 抱歉!我尚未学习该知识。
问题: {question}
可参考的上下文:
···
{context}
···
基于用户给定的信息,重新汇总上下文生成精准的回答。
如果给定的上下文无法让你做出回答,请回答你不知道。
有用的回答:"""
# 调用 LangChain 的方法来实例化一个 Template 对象,该对象包含了 context 和 question 两个变量,在实际调用时,这两个变量会被检索到的文档片段和用户提问填充
QA_CHAIN_PROMPT = PromptTemplate(input_variables=["context","question"],template=template)

from langchain.chains import RetrievalQA
qa_chain = RetrievalQA.from_chain_type(llm,retriever=vectordb.as_retriever(),return_source_documents=True,chain_type_kwargs={"prompt":QA_CHAIN_PROMPT})
#Q&A
question = "千信金属产业园主要业务数据以及业务术语有哪些?"
result = qa_chain({"query": question})
print("检索问答链回答 question 的结果:")
print(result["result"])

使用 ConversationalRetrievalChain 问答链检索增强生成

from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
bot = ConversationalRetrievalChain.from_llm(llm, retriever=vectordb.as_retriever(),memory=memory,verbose=True,return_source_documents=False)

query = "根基提供的上下文,千信产业园主要业务术语及主数据,并给出数据治理的建议"
result = bot.invoke({"question": query})
result["answer"]

4、问答结果探讨
将某企业的数据治理方向的一些文档做成私有知识库,基于私有知识库回答数据治理方面的问题。
在这里插入图片描述
私有知识库文档
问题一:

query = "根基提供的上下文,千信产业园主数据质量分析情况"
result = bot.invoke({"question": query})
result["answer"]

结果分析:对于私有知识库内确定的知识,整个RAG系统能比较精准的定位检索到用户问题所需的文档及文档块,并给出精准的答案。
在这里插入图片描述
问题二:

query = "根基提供的上下文,千信产业园仓储管理系统主数据质量评分都是多少"
result = bot.invoke({"question": query})
result["answer"]

结果分析:对于文档内存在的表格,目前简单的检索链和问答链无法给出精准的回答,分析原因应该是表格数据的检索还是需要使用CSV文件的嵌入以及CSV-chain才能获取精准的答案。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/343397.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】Qt:QCustomPlot图表绘制库配置与示例

😏★,:.☆( ̄▽ ̄)/$:.★ 😏 这篇文章主要介绍QCustomPlot图表绘制库配置与示例。 学其所用,用其所学。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下,下次…

哈夫曼算法详细讲解(算法+源码)

博主介绍:✌全网粉丝喜爱、前后端领域优质创作者、本质互联网精神、坚持优质作品共享、掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战✌有需要可以联系作者我哦! 🍅文末获取源码联系🍅 👇&…

开发实战角度:distinct实现原理及具体优化总结

1.背景 Distinct是一种常用的操作,在所有数据库的SQl语言中都是一个非常重要的操作,在Hive中,Distinct去重原理是通过MapReduce来实现的,Distinct操作可以应用于单个列,亦可以应用于多个列。基本原理是将输入的数据集…

基于SpringBoot的教务管理系统设计与实现(源码+调试)

项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于SpringBoot的教务管…

StableDiffusion新版汉化

新旧版不同,这里以新版为例,用的是带链接,可以更新的方法。 步骤: 1.找到这个位置,依次点击,注意选项。 2.点击加载,等待刷新。 ctrlF搜索 zh_CN Localization 右边点击install&#xff0c…

[Linux 杂货铺] —— 权限(文件权限和目录配置)

目录 🌈前言 📁 文件的属性 📁 权限的概念 📂拥有者和所属组(角色): 📂用户(具体的人): 📁 权限的管理 📂1. chmod…

Object.defineProperty、Proxy、Reflect-个人总结

Object.defineProperty 前言 用于给一个对象添加或者修改一个属性,返回操作后的对象。 写法:Object.defineProperty(对象,属性,配置对象) 配置对象 通过对配置对象不同的配置,可以将属性分为数据属性和存取属性。 数据…

[Linux]HTTP状态响应码列举

1xx:信息响应类,表示接收到请求并且继续处理 2xx:处理成功响应类,表示动作被成功接收、理解和接受 3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理 4xx:客户端错误&#x…

7.Feign远程调用

2.Feign远程调用 先来看我们以前利用RestTemplate发起远程调用的代码: 存在下面的问题: •代码可读性差,编程体验不统一 •参数复杂URL难以维护 Feign是一个声明式的http客户端,官方地址:https://github.com/OpenF…

RabbitMQ消息应答与发布

消息应答 RabbitMQ一旦向消费者发送了一个消息,便立即将该消息,标记为删除. 消费者完成一个任务可能需要一段时间,如果其中一个消费者处理一个很长的任务并仅仅执行了一半就突然挂掉了,在这种情况下,我们将丢失正在处理的消息,后续给消费者发送的消息也就无法接收到了. 为了…

【BIAI】Lecture 6 - Somatosensory systems

Lecture 6- Somatosensory systems 专业术语 somatosensory system 体感系统 Thermoreceptors 温度感受器 Photoreceptors 光感受器 Chemoreceptoprs 化学感受器 hairy skin 毛发皮肤 glabrous skin 光滑皮肤 sensory receptors 感觉受体 dermal 真皮的 epidermal 表皮的 axon…

外包干了2个多月,技术退步明显。。。。。

先说一下自己的情况,本科生,19年通过校招进入广州某软件公司,干了接近3年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

创建高打开率邮件标题的技巧:吸引潜在客户的秘诀

邮件打开率是指什么? 邮件打开率是指打开邮件的人数占发送的收件人总人数的比例。 邮件的打开率是衡量营销效果如何的一个非常重要的指标,而邮件标题又是影响邮件打开率非常重要的因素之一。所以,我们要要重视邮件标题。那我们应该如何编辑…

《移动通信原理与应用》——QPSK调制解调仿真

目录 一、QPSK调制与解调流程图: 二、仿真运行结果: 三、MATLAB仿真代码: 一、QPSK调制与解调流程图: QPSK调制流程图: QPSK解调流程图: 二、仿真运行结果: 1、Figure1:为发送端比特流情…

深入了解WPF控件:常用属性与用法(七)

掌握WPF控件:熟练常用属性(七) Menu 用于为应用程序指定命令或选项的项列表。它允许用户通过选择不同的菜单项来执行不同的命令或操作。 每个 Menu 可以包含多个 MenuItem 控件。 每个 MenuItem 都可以调用命令或调用 Click 事件处理程序。…

竞赛保研 电影评论情感分析 - python 深度学习 情感分类

1 前言 🔥学长分享优质竞赛项目,今天要分享的是 🚩 GRU的 电影评论情感分析 - python 深度学习 情感分类 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分工作量:3分创新点:4分 这…

vue3-组件基础

什么是组件 组件允许我们将 UI 划分为独立的、可重用的部分,并且可以对每个部分进行处理。在实际应用中,组件常常被组织成层层嵌套的树状结构。 定义一个组件 我们一般会将 Vue 组件定义在一个单独的 .vue 文件中,这被叫做单文件组件 (简称…

【加速】Ubuntu 22.04 LTS Steam++ Watt Toolkit 加速 github

项目地址 SteamTools: 🛠「Watt Toolkit」是一个开源跨平台的多功能 Steam 工具箱。 下载linux版本 wget https://gitee.com/rmbgame/SteamTools/releases/download/3.0.0-rc.3/Steam%20%20_v3.0.0-rc.3_linux_x64.tgz 解压到/opt/steam sudo mkdir /opt/steam…

【C语言】扫雷游戏完整代码实现

目录 1.game.h 2.game.c 3.progress.c 4.运行结果 1.game.h #define _CRT_SECURE_NO_WARNINGS#include <string.h> #include <stdio.h> #include <time.h> #include<stdlib.h>#define ROW 9 #define COL 9 #define ROWS 11 #define COLS 11 #defin…

ctfshow-反序列化(web271-web276)

目录 web271 web272-273 web274 web275 web276 为什么不用分析具体为什么能成功 ,后面会有几个专题 会对php框架进行更深入的了解 这里面会专门的研究 为什么能够实现RCE 前面作为初步的熟悉 首先知道一下他的框架 知道框架的风格 知道啥版本可以用什么来打 首先先不用太研…