InternLM+LlamaIndex RAG 实践

本期实战训练营介绍了使用书生葡语的InternLM和LlamaIndex框架进行RAG项目的实践。内容分为三个部分:回顾InternLM的发展历程,介绍RAG的基本概念和应用,以及实践一个RAG项目。RAG技术结合了检索与生成,通过外部知识库增强大模型的能力,解决生成幻觉、过时知识等问题。最后,使用LlamaIndex搭建RAG系统,展示如何通过向量数据库实现实时信息检索和生成准确回答。

亮点:
本期课程主要介绍如何利用书生浦语和llama index框架实践R AG项目。RAG技术结合了检索与生成,旨在提升大模型的能力,通过利用外部知识库,实现更准确的回答与推理过程。
-书生葡语的发展历程令人瞩目,自2023年7月发布的7B模型以来,逐步推出了更高性能的版本。其开源工具链涵盖从训练到应用的完整流程,极大便利了开发者的使用。
-R AG技术(搜索增强生成技术)通过外部知识库增强大模型的能力,解决了生成幻觉和过时知识等问题。通过检索相关信息,使得生成的回答更加准确、丰富。
-R AG的基本工作原理涉及知识库的索引和编码,将外部知识存储在向量数据库中。这种方法使得用户在提问时,可以获取更及时和专业的信息,有效提升了模型的应用效率。

该视频介绍了向量数据库在R AG(Retrival Augmented Generation)系统中的重要性。它强调了通过检索用户问题并将其编码为向量,找到相关文档块,以生成高质量答案的基本流程。
-向量数据库承担了数据存储任务,通过预训练模型将文本转化为向量。这些向量能捕捉文本的语义信息,以便在检索时提高相关性和准确性。
-RAG的早期概念最初由Meta提出,它主要应用于问答系统和信息检索。随着技术的发展,R AG系统现在还可以进行摘要生成和内容推荐,满足更多需求。
-模块化R AG是应对多模态任务和连续对话系统的主流方式。通过模块化的设计,优化每个模块,可以有效提高查询和生成的质量。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

12:08 RG和微调是模型优化的重要方法,二者并不是对立的,而是相辅相成的。选择合适的方法取决于任务需求和外部知识的可用性,以达到最佳效果。
-RAG是一种非参数记忆方法,利用外部知识库提供实时更新的信息,适合处理高度实时化的任务,如开放域问答和实时新闻摘要。其优势在于动态知识的更新能力。
-微调(SFT)是一种参数记忆方法,通过对特定任务的数据重新训练模型来提高适应性,适用于特定领域的文本分类和情感分析等任务。其局限在于需要大量标注数据。
-整个模型优化过程是相辅相成的,根据外部知识需求和模型适配度的不同,选择RAG或微调,或两者结合,以实现最佳的性能和实时性。需要根据具体场景进行选择。
在这里插入图片描述
在这里插入图片描述

**用于评测大型模型的检索和生成能力的评估框架。**评估包括检索质量、生成质量以及多种评估维度,如准确率、召回率等,帮助用户全面理解模型性能。
-评估维度涵盖了检索内容的匹配度和生成内容的质量。常用的评估指标包括准确率、召回率和不同类型的评分,确保评测结果的全面性和可靠性。
在这里插入图片描述
-视频中提到的技术框架如lang chain和Llama index,能够帮助用户快速实现相关应用。这些框架提供了高效的文本索引和检索功能,便于用户处理大规模数据。
-在RAG的实际应用中,Llama index展现出优越的数据处理能力和检索机制。它支持多种数据源,并能与多种大模型兼容,极大地提升了应用的灵活性。
在这里插入图片描述

大模型的应用过程可以通过LLAMAINDEX进行模块化管理,使得数据加载、索引、存储和查询等环节变得更加高效和便捷。通过这一工具,我们可以快速搭建一个完整的RG系统,提升模型的灵活性和响应速度。
-LAMAINDEX支持多种数据源的加载,方便用户直接调用现成的连接器读取数据。通过集成如PDF等工具,可以大幅提升数据处理的效率和准确性。
-在建立索引的过程中,用户可以灵活选择嵌入模型的方式和策略,极大地方便了数据的管理和调用。这样能够避免重复索引,提升系统的整体效率和响应速度。
-LAMAINDEX提供了多种现成的查询策略,包括子查询和混合查询,用户只需选择适合项目需求的方法,而无需自己编写代码。这种灵活性使得用户能够快速适应不同的项目要求。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

通过在向量库数据库中检索,找到与问题最匹配的数据块,然后将这些内容用作生成模型的提示词,以便生成准确的答案。这种方法无需改变参数或进行训练,就能有效利用外部数据库的知识。
-在生成模型中引入外部数据库的知识,可以提升模型的回答准确性。这种方式允许在没有训练的情况下,迅速获取新信息,使得模型能够更好地适应用户需求。
-整个流程通过检索和生成模块的结合,形成了一种高效灵活的微调数据库。这种方法不仅节省了时间,还能在不同场景下快速应用,以解决特定问题。
-在实际操作中,用户可以通过简单的步骤进行环境搭建和数据库连接。这种用户友好的设计使得技术门槛降低,更多人能够参与到这一技术应用中。

使用RAG前

调用模型

from llama_index.llms.huggingface import HuggingFaceLLM
from llama_index.core.llms import ChatMessage
llm = HuggingFaceLLM(
    model_name="/root/model/internlm2-chat-1_8b",
    tokenizer_name="/root/model/internlm2-chat-1_8b",
    model_kwargs={"trust_remote_code":True},
    tokenizer_kwargs={"trust_remote_code":True}
)

rsp = llm.chat(messages=[ChatMessage(content="xtuner是什么?")])
print(rsp)

输出结果
在这里插入图片描述

使用RAG后

调用模型:尽管设置了全局的 llm 属性,但在索引构建的过程中并没有显式地用到这个大模型 (HuggingFaceLLM)。这是因为向量索引的构建过程主要依赖于文本嵌入(即将文档转换为向量表示),而不是大模型的推理或生成能力。

  1. 解释各步骤的作用
    文本嵌入模型 (HuggingFaceEmbedding): 你通过 HuggingFaceEmbedding 实例化了一个文本嵌入模型,它用于将文本转换为向量表示.在 VectorStoreIndex.from_documents(documents) 这一步,系统会使用这个嵌入模型将文档转换为向量并存储在向量索引中。
    大模型 (HuggingFaceLLM): HuggingFaceLLM 是一个用于自然语言处理任务的大语言模型 (LLM)。它通常用于处理自然语言生成、问答、对话等任务。在代码中,虽然设置了全局的 llm 属性,但构建索引的过程主要是基于嵌入模型(用于将文本转换为向量),而不是基于大语言模型的生成能力。
    关键: 大模型通常在查询阶段发挥作用,而不是在索引构建阶段。
    索引构建与查询阶段的区别:
    索引构建阶段: 这里主要依赖嵌入模型 (embed_model),将文档转换为向量并存储在索引中。此阶段不涉及大模型的生成或推理能力。
    查询阶段: 当你进行查询时,系统会检索相关的向量,并使用大模型 (llm) 来生成自然语言的响应。如果你在查询过程中使用了某些高级功能(比如自然语言理解、生成等),这时候会调用大语言模型来处理查询结果。
    哪一步使用了大模型?
    在你提供的代码中,大模型会在你调用 query_engine.query(“xtuner是什么?”) 这一步时被使用。如果查询引擎的实现需要自然语言生成或进一步处理查询结果,它会调用大模型来生成最终的回答。

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings

from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.huggingface import HuggingFaceLLM

#初始化一个HuggingFaceEmbedding对象,用于将文本转换为向量表示
embed_model = HuggingFaceEmbedding(
#指定了一个预训练的sentence-transformer模型的路径
    model_name="/root/model/sentence-transformer"
)
#将创建的嵌入模型赋值给全局设置的embed_model属性,
#这样在后续的索引构建过程中就会使用这个模型。
Settings.embed_model = embed_model

llm = HuggingFaceLLM(
    model_name="/root/model/internlm2-chat-1_8b",
    tokenizer_name="/root/model/internlm2-chat-1_8b",
    model_kwargs={"trust_remote_code":True},
    tokenizer_kwargs={"trust_remote_code":True}
)
#设置全局的llm属性,这样在索引查询时会使用这个模型。
Settings.llm = llm

#从指定目录读取所有文档,并加载数据到内存中
documents = SimpleDirectoryReader("/root/llamaindex_demo/data").load_data()
#创建一个VectorStoreIndex,并使用之前加载的文档来构建索引。
# 此索引将文档转换为向量,并存储这些向量以便于快速检索。
index = VectorStoreIndex.from_documents(documents)
# 创建一个查询引擎,这个引擎可以接收查询并返回相关文档的响应。
query_engine = index.as_query_engine()
response = query_engine.query("xtuner是什么?")

print(response)

输出结果
在这里插入图片描述

在安装环境时,确保按照固定版本的命令进行安装,以避免不兼容的问题。这样不仅可以提高安装效率,还能减少后续调试的困难。
-安装PyTorch和其他必要的Python依赖包是环境配置的第一步,确保环境的顺利搭建。遇到下载慢的情况是正常的,可以选择不常用的包进行下载以提升效率。
-在使用过程中,建议直接复制官方提供的安装命令,避免自行手动输入导致的错误。这样可以确保使用的版本与教程一致,从而减少不兼容问题的产生。
-下载模型时,选择支持中文的轻量级模型是一个好选择。可以使用sentence transformer等开源模型,并确保使用国内镜像以提高下载速度。
本视频介绍了如何使用NLTK数据包进行模型下载和运行,特别是1.8B模型的应用。通过自动化过程和模型的软链接,用户能够轻松地设置和运行所需的模型,以满足特定需求。
-视频中提到的1.8B模型体积较大,因此将其放入共享文件夹中,方便用户快速访问。用户只需创建软链接即可,将模型放入自己的目录,简化了操作流程。
-当运行模型时,程序会自动创建一个名为lla index的文件,并调用HuggingFace的大模型组件。此过程展示了如何有效利用模型生成相关信息,以满足用户的需求。
-在模型运行结束后,用户能够查看关于特定问题的回答。此时,模型可能会出现一些不准确的回答,这需要通过后续的RAG过程来优化和解决这些问题。
通过使用HuggingFace和llama index,我们构建了一个简单的RAG模型,能够识别和处理文档信息。该模型展示了如何通过向量化处理,提高大语言模型的准确性与效率。
在这里插入图片描述
查询过程:
在这里插入图片描述
代码:

import streamlit as st
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.huggingface import HuggingFaceLLM

# streamlit run app.py
# ssh -p {ssh端口,从InternStudio获取} root@ssh.intern-ai.org.cn -CNg -L 8501:127.0.0.1:8501 -o StrictHostKeyChecking=no
# 打开本地localhost:7860, 如果未配置开发机公钥,还需要输入密码,从InternStudio获取。上面这一步是将开发机上的8501(web界面占用的端口)映射到
# 本地机器的端口,之后可以访问http://localhost:8501/ 打开界面。

st.set_page_config(page_title="llama_index_demo", page_icon="🦜🔗")
st.title("llama_index_demo")

# 初始化模型
@st.cache_resource
def init_models():
    embed_model = HuggingFaceEmbedding(
        model_name="/root/model/sentence-transformer"
    )
    Settings.embed_model = embed_model

    llm = HuggingFaceLLM(
        model_name="/root/model/internlm2-chat-1_8b",
        tokenizer_name="/root/model/internlm2-chat-1_8b",
        model_kwargs={"trust_remote_code": True},
        tokenizer_kwargs={"trust_remote_code": True}
    )
    Settings.llm = llm
    # 在这段代码中,model_name 和 tokenizer_name 被设置为相同的值 /root/model/internlm2-chat-1_8b,可能有以下原因:
    # 该模型的架构设计使得模型文件本身就包含了相应的分词器(tokenizer)逻辑。在这种情况下,使用同一个文件路径来指定模型和分词器是合理的。
    # 例如,某些大型语言模型的发布可能将模型和其配套的分词器打包在同一个目录或文件结构中,以便于统一管理和使用。
    # 1. 开发人员经过测试和验证,确定对于这个特定的模型,使用相同的路径配置能够正常工作并且满足应用的需求。
    # 2. 比如,在特定的项目环境中,经过多次尝试和优化,发现这样的设置能够保证模型和分词器的协同工作,实现预期的效果。
    # 3. 可能是为了简化配置和减少代码的复杂性。
    # 4. 如果模型和分词器的关系非常紧密,并且在大多数情况下不需要分别配置不同的路径,将它们设置为相同可以减少配置项,降低出错的可能性。
    # 可能在 LlamaIndex 的内部实现或者其他未展示的相关代码中,会根据 Settings.llm 的设置来进行一些初始化、优化或者其他与模型相关的操作,但这些操作并没有在当前展示的这部分生成响应的代码中直接体现。

    documents = SimpleDirectoryReader("/root/llamaindex_demo/data").load_data()
    #     SimpleDirectoryReader 通常会尝试加载指定目录(/root/llamaindex_demo/data)中的常见格式的文件。但具体哪些格式的文件被加载并向量化,取决于 SimpleDirectoryReader 的默认设置和配置。
    # 一般来说,常见的文本格式文件,如 .txt、.md 、.html 等很可能会被加载和处理。但如果存在一些特殊格式的文件,可能需要额外的配置或自定义的读取逻辑才能被正确加载和向量化。
    # 例如,如果目录中包含了 .pdf 或 .doc 这样的格式,可能需要额外的库和处理步骤才能有效地提取文本内容并进行向量化。
    index = VectorStoreIndex.from_documents(documents)
    query_engine = index.as_query_engine()
    #     整个过程主要依赖于 LlamaIndex 提供的类和方法来实现数据的读取、索引的构建以及查询引擎的创建。
    # 然而,需要注意的是,虽然表面上看起来主要与 LlamaIndex 相关,但在实际应用中,这个 query_engine 的工作效果可能会受到之前配置的 LLM 等因素的影响。
    # 例如,LLM 的性能和参数设置可能会间接影响到查询引擎在生成响应时的准确性和质量。

    return query_engine

# 检查是否需要初始化模型
if 'query_engine' not in st.session_state:
    st.session_state['query_engine'] = init_models()

def greet2(question):
    response = st.session_state['query_engine'].query(question)
    return response

      
# Store LLM generated responses
if "messages" not in st.session_state.keys():
    st.session_state.messages = [{"role": "assistant", "content": "你好,我是你的助手,有什么我可以帮助你的吗?"}]    

    # Display or clear chat messages
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.write(message["content"])

def clear_chat_history():
    st.session_state.messages = [{"role": "assistant", "content": "你好,我是你的助手,有什么我可以帮助你的吗?"}]

st.sidebar.button('Clear Chat History', on_click=clear_chat_history)

# Function for generating LLaMA2 response
def generate_llama_index_response(prompt_input):
    return greet2(prompt_input)

# User-provided prompt
if prompt := st.chat_input():
    st.session_state.messages.append({"role": "user", "content": prompt})
    with st.chat_message("user"):
        st.write(prompt)

# Gegenerate_llama_index_response last message is not from assistant
if st.session_state.messages[-1]["role"] != "assistant":
    with st.chat_message("assistant"):
        with st.spinner("Thinking..."):
            response = generate_llama_index_response(prompt)
            placeholder = st.empty()
            placeholder.markdown(response)
    message = {"role": "assistant", "content": response}
    st.session_state.messages.append(message)


在这段代码中,LlamaIndex 主要起到了以下作用:

  1. 数据读取和索引构建:
    • 通过 SimpleDirectoryReader 从指定的目录(/root/llamaindex_demo/data)读取文档数据。
    • 使用 VectorStoreIndex.from_documents 基于读取的文档构建索引。这个索引有助于快速搜索和检索与用户输入相关的信息。
  2. 提供查询引擎:
    • 通过 index.as_query_engine 创建了一个查询引擎 query_engine
  3. 回答用户问题:
    • greet2 函数中,使用 query_engine.query 方法处理用户输入的问题(question),并返回相应的响应。

例如,当用户通过聊天输入一个问题时,代码会调用 generate_llama_index_response 函数,进而调用 greet2 函数,greet2 会使用之前构建的索引和查询引擎来查找与问题相关的信息,并生成回答返回给用户。这样,LlamaIndex 帮助提高了回答用户问题的效率和准确性,能够从大量的文档数据中快速提取有用的信息来满足用户的需求。

-在使用HuggingFace的过程中,我们需要设置主模型为1.8B,并确保文档正确加载。这一过程涉及到调用内置的默认方式进行向量化,从而有效处理数据。
LLM 加载的模型 /root/model/internlm2-chat-1_8b 的性能和参数设置可以通过以下几种方式间接影响查询引擎生成响应的准确性和质量:

  1. 模型的规模和架构:模型的大小(例如层数、神经元数量等)和架构设计会影响其语言理解和生成能力。更复杂和大规模的模型可能能够捕捉更细微的语言模式和语义关系,从而提供更准确和全面的响应。

    例如,如果模型规模较小,可能在处理复杂的问题或多义性的语言时表现不佳,导致查询引擎给出的回答不够准确或完整。

  2. 训练数据和领域适应性:模型在训练过程中所使用的数据以及其对特定领域的覆盖程度会影响响应的相关性和准确性。如果模型没有在与查询相关的领域进行充分训练,可能无法理解和回答特定领域的问题。

    比如,如果查询涉及到非常专业的医学或法律领域知识,而模型的训练数据主要集中在通用领域,那么生成的响应可能缺乏专业性和准确性。

  3. 参数调整:诸如学习率、优化器选择、正则化参数等的设置会影响模型的训练效果和泛化能力。不合适的参数设置可能导致模型过拟合或欠拟合训练数据,从而影响其在实际应用中的表现。

    例如,过高的学习率可能导致模型在训练过程中不稳定,无法收敛到较好的性能,进而影响查询引擎的响应质量。

  4. 推理设置:在生成响应时的一些参数,如生成的长度限制、温度(控制随机性)等,也会影响回答的质量和风格。

    比如,较高的温度设置会使生成的回答更具随机性和多样性,但可能在准确性上有所牺牲;较低的温度则会使回答更确定性,但可能缺乏创造性。

综上所述,LLM 加载的模型的性能和参数设置在多个方面都会对查询引擎最终生成的响应的准确性和质量产生重要的间接影响。

-Xtuner作为一个微调工具库,支持大语言模型的灵活应用。通过文档的有效识别,它能够快速提供准确的答案,增强用户体验。
-在将命令行模式转换为界面模式时,使用streamlit框架可以提升可视化效果。通过简单的设置,用户能够更直观地与RAG系统进行交互,提升使用便利性。

任务要求:基于 LlamaIndex 构建自己的 RAG 知识库,寻找一个问题 A 在使用 LlamaIndex 之前InternLM2-Chat-1.8B模型不会回答,借助 LlamaIndex 后 InternLM2-Chat-1.8B 模型具备回答 A 的能力。
提问:RT-DETR是什么?回答不出来还会用表情糊弄啊哈哈哈哈好可爱
在这里插入图片描述
有RAG的话还会用向量库里的知识胡乱回答:
在这里插入图片描述
直接用internlm2-chat-1_8b进行提问:什么是RT- DETR?
在这里插入图片描述

RAG的文件就是一篇RT- DETR论文:https://arxiv.org/abs/2407.17140
在这里插入图片描述

参考视频:https://www.bilibili.com/video/BV19E4m1X79q/?spm_id_from=333.788&vd_source=d5e90f8fa067b4804697b319c7cc88e4
参考文档:https://github.com/InternLM/Tutorial/blob/camp3/docs/L1/LlamaIndex/readme.md

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,可以得知prompt+RAG的流程如下: 1. 首先,使用Retriever部分在知识库中检索出top-k个匹配的文档zi。 2. 然后,将query和k个文档拼接起来作为QA的prompt,送入seq2seq模型。 3. seq2seq模型生成回复y。 4. 如果需要进行Re-rank,可以使用LLM来rerank,给LLM写好prompt即可。 下面是一个简单的示例代码,演示如何使用prompt+RAG: ```python from transformers import RagTokenizer, RagRetriever, RagSequenceForGeneration # 初始化tokenizer、retriever和seq2seq模型 tokenizer = RagTokenizer.from_pretrained('facebook/rag-token-base') retriever = RagRetriever.from_pretrained('facebook/rag-token-base', index_name='exact', use_dummy_dataset=True) model = RagSequenceForGeneration.from_pretrained('facebook/rag-token-base') # 设置query和context query = "What is the capital of France?" context = "France is a country located in Western Europe. Paris, the capital city of France, is known for its romantic ambiance and iconic landmarks such as the Eiffel Tower." # 使用Retriever部分检索top-k个匹配的文档 retrieved_docs = retriever(query) # 将query和k个文档拼接起来作为QA的prompt input_dict = tokenizer.prepare_seq2seq_batch(query, retrieved_docs[:2], return_tensors='pt') generated = model.generate(input_ids=input_dict['input_ids'], attention_mask=input_dict['attention_mask']) # 输出生成的回复 generated_text = tokenizer.batch_decode(generated, skip_special_tokens=True)[0] print(generated_text) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值