【书生·浦语大模型实战营】第三期(夏季闯关)·基础篇

书生·浦语大模型实战营第 3 期,基于官方飞书云文档GitHub Repo开展学习并记录笔记。

第 1 关 书生大模型全链路开源体系

书生·浦语是致力于大模型研究与开发工具链的开源组织,为所有 AI 开发者提供高效、易用的开源平台,让最前沿的大模型与算法技术触手可及。

开源历程

2023 年 6 月 7 日,发布浦语系列首个千亿参数模型。

2023 年 7 月 6 日,InternLM-7B 开源率先免费商用,发布全链条开源工具体系。

2023 年 9 月 20 日,InternLM-20B 开源,开源工具链全线升级。

2023 年 9 月 27 日,开源书生·浦语灵笔(InternLM-XComposer),首个图文混合创作大模型。

2024 年 1 月 17 日,开源 InternLM2,性能超最新同量级开源模型。

2024 年 1 月 23 日,发布 InternLM2-Math,首个同时支持形式化数学语言及解题过程评价的开源模型。

2024 年 1 月 29 日,发布书生·浦语灵笔2(InternLM-XComposer2),支持个性化高质量图文创作和对话。

2024 年 5 月 24 日,开源 InternLM2-Math-Plus,刷新开源数学模型性能上限。

2024 年 6 月 4 日,开源 InternLM2-WQX,以 200 亿参数量在 2024 年高考中取得接近 GPT-4o 的成绩。

2024 年 7 月 4 日,InternLM2.5 开源。

大模型开源工具链体系

数据
  • 60 亿图像、8 亿片段视频、1 万亿 tokens 语料、1 百万 3D 模型、2 万小时音频。
  • 数据提取工具 Miner U,数据标注工具 Label LLM、Label U。
模型
  • InternLM:一系列多语言基础模型和聊天模型。
  • InternLM-Math:最先进的双语数学推理 LLM。
  • InternLM-XComposer:基于 InternLM 的视觉语言大型模型 (VLLM),用于高级文本图像理解和合成。
工具链
  • InternEvo:用于大规模模型预训练和微调的轻量级框架。
  • XTuner:用于高效微调 LLM 的工具包,支持各种模型和微调算法。
  • LMDeploy:用于压缩、部署和服务 LLM 的工具包。
  • Lagent:允许用户高效构建基于 LLM 的代理的轻量级框架。
  • AgentLego:一个多功能工具 API 库,用于扩展和增强基于 LLM 的代理,与 Lagent、Langchain 等兼容。
  • OpenCompass:一个大型模型评估平台,提供了一个公平、开放和可重现的基准。
  • OpenAOE:一个优雅、开箱即用的聊天 UI,用于比较多个模型。
应用
  • HuixiangDou:基于 LLM 的特定领域助手,可在群聊中处理复杂的技术问题。
  • MindSearch:基于 LLM 的多代理网络搜索引擎框架。

第 2 关 8G 显存玩转书生大模型 Demo

创建一个 10% 的开发机,镜像为 Cuda12.2,创建完成后进入开发机,在 Terminal 视图下进行环境配置。

通过下面的命令创建一个 demo 环境。

# 创建环境
conda create -n demo python=3.10 -y
# 激活环境
conda activate demo
# 安装 torch
conda install pytorch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 pytorch-cuda=12.1 -c pytorch -c nvidia -y
# 安装其他依赖
pip install transformers==4.38
pip install sentencepiece==0.1.99
pip install einops==0.8.0
pip install protobuf==5.27.2
pip install accelerate==0.33.0
pip install streamlit==1.37.0

等待环境创建完成,开始通过 CLI 部署 InternLM2-Chat-1.8B 模型。

首先,切换到 Code Server 视图,如果没有删除 L0 的文件,也没有手动清理云盘,那么根目录下应该有一个 demo 文件夹。在该文件夹下创建一个 cli_demo.py 文件,将下面的代码复制到里面。

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM


model_name_or_path = "/root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b"

tokenizer = AutoTokenizer.from_pretrained(
    model_name_or_path, trust_remote_code=True, device_map="cuda:0"
)
model = AutoModelForCausalLM.from_pretrained(
    model_name_or_path,
    trust_remote_code=True,
    torch_dtype=torch.bfloat16,
    device_map="cuda:0",
)
model = model.eval()

system_prompt = """You are an AI assistant whose name is InternLM (书生·浦语).
- InternLM (书生·浦语) is a conversational language model that is developed by Shanghai AI Laboratory (上海人工智能实验室). It is designed to be helpful, honest, and harmless.
- InternLM (书生·浦语) can understand and communicate fluently in the language chosen by the user such as English and 中文.
"""

messages = [(system_prompt, "")]

print("=============Welcome to InternLM chatbot, type 'exit' to exit.=============")

while True:
    input_text = input("\nUser  >>> ")
    input_text = input_text.replace(" ", "")
    if input_text == "exit":
        break

    length = 0
    for response, _ in model.stream_chat(tokenizer, input_text, messages):
        if response is not None:
            print(response[length:], flush=True, end="")
            length = len(response)

切换到 Terminal 视图,执行下面的命令启动 demo。

python /root/demo/cli_demo.py

对话效果如下图:

在这里插入图片描述

这里有一点小问题,出现在写代码这段对话,我最开始打字的时候是先输入的 Python 字段,后来我回退改成了 C,但是最终输出的还是 Python 代码,不清楚是不是缓存问题。

输入 exit 后回车可以结束对话。

按照任务要求,生成 300 字小故事,效果如下图:

在这里插入图片描述

内容如下:

在一片宁静的森林中,有一只名叫小兔的兔子。小兔非常喜欢探险,经常去森林里寻找新的发现和挑战。有一天,小兔发现了一片茂密的草地,上面长满了各种各样的野花。小兔感到非常兴奋,决定要去探索一下这片草地。

小兔走了很长时间,终于来到了一片开阔的草地。这里有许多不同种类的野花,小兔感到非常惊喜。它们的颜色各异,形状也各不相同。小兔一边欣赏着这些美丽的花朵,一边想着如何把它们带回家。

突然,小兔发现了一朵非常特别的花。它有着鲜艳的红色花瓣,还有着深蓝色的叶子。小兔感到非常惊讶,因为它从未见过这样的花朵。小兔决定把它带回家,看看它是否可以变成美丽的花瓶。

小兔回到家,开始制作花瓶。它小心翼翼地将花插在花瓶里,并装饰上一些绿叶。小兔感到非常满意,因为它终于成功地将这朵美丽的花制作成了花瓶。

小兔拿着自己的作品,感到非常自豪。它知道,只要用心去发现,就一定能够创造出美丽的事物。小兔也明白,每一次探索和尝试,都是对自己的一次挑战,只要坚持不懈,就能够收获到更多的成功。

第 3 关 浦语提示词工程实践

继续使用第 2 关的开发机,在 Terminal 视图下,通过下面的命令创建一个 langgpt 环境。

# 创建虚拟环境
conda create -n langgpt python=3.10 -y
# 激活环境
conda activate langgpt
# 安装一些必要的库
conda install pytorch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 pytorch-cuda=12.1 -c pytorch -c nvidia -y

# 安装其他依赖
pip install transformers==4.43.3

pip install streamlit==1.37.0
pip install huggingface_hub==0.24.3
pip install openai==1.37.1
pip install lmdeploy==0.5.2

然后在根目录下创建一个 langgpt 文件夹,在开始之前运行下面的命令安装必要的软件。

apt-get install tmux

接下来参考文档,基于 LMDeploy 将开源的 InternLM2-chat-1_8b 模型部署为 OpenAI 格式的通用接口。

使用 intern-studio 开发机,可以直接在路径 /share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b 下找到模型。

服务需要持续运行,需要将进程维持在后台,这里使用tmux软件创建新的命令窗口。

运行如下命令创建窗口。

tmux new -t langgpt

进入命令窗口后,需要在新窗口中再次激活环境。

conda activate langgpt

然后,使用 LMDeploy 进行部署。

CUDA_VISIBLE_DEVICES=0 lmdeploy serve api_server /share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b --server-port 23333 --api-keys internlm2

在这里插入图片描述

部署成功后,利用如下脚本调用部署的 InternLM2-chat-1_8b 模型并测试是否部署成功。

from openai import OpenAI

client = OpenAI(api_key="internlm2", base_url="http://0.0.0.0:23333/v1")

response = client.chat.completions.create(
    model=client.models.list().data[0].id,
    messages=[{"role": "system", "content": "请介绍一下你自己"}],
)

print(response.choices[0].message.content)

在这里插入图片描述

部署完成后,按 Ctrl + B 进入 tmux 的控制模式,然后按 D 退出 langgpt 窗口。

注意,按下 Ctrl + B 后有 * 提示,不要按 Ctrl + C,会退出服务。

在实战营项目 GitHub Repotools 文件夹下找到 chat_ui.py 文件,复制其中的内容。

import streamlit as st
from openai import OpenAI
import os
import json
import time


# Create a chatbot UI with Streamlit and OpenAI
def chat_ui():
    state = st.session_state
    # Set the title of the app
    st.title("浦语提示词工程实践")
    st.caption("浦语提示词工程实践所用Web UI")

    # Create a client for the OpenAI API
    if "client" not in state:
        st.info("请配置Chatbot的基本设置,其中API Key和Base URL是必须的。")
        pass
    else:
        # if "message_history" not in state:
        #     state.message_history = []
        #     pass
        # if "system_prompt" in state:
        #     state.message_history.append({"role": "system", "content": state.system_prompt})
        user_input = st.chat_input("输入消息")
        if user_input:
            state.message_history.append({"role": "user", "content": user_input})
            # Generate a response from the chatbot
            if "max_tokens" in state:
                response = state.client.chat.completions.create(
                    model=state.client.models.list().data[0].id,
                    messages=state.message_history,
                    max_tokens=state.max_tokens,
                    temperature=state.temperature,
                )
            else:
                response = state.client.chat.completions.create(
                    model=state.client.models.list().data[0].id,
                    messages=state.message_history,
                    temperature=state.temperature,
                )
            state.message_history.append(
                {"role": "assistant", "content": response.choices[0].message.content}
            )
            pass
        for message in state.message_history:
            if message["role"] == "system":
                continue
            else:
                st.chat_message(message["role"]).write(message["content"])

    # Create a text input for the user to type their message

    pass


# define a side bar for the setting of the chatbot, such as the max token length, temperature, api_key, base_url, system prompt, etc.
def side_bar():
    st.sidebar.title("设置")
    state = st.session_state
    # Set a form of the settings
    with st.sidebar.form(key="settings"):
        # Set the max token length for the chatbot
        max_tokens = st.number_input(
            "最大token长度", min_value=0, max_value=2048, value=100, step=1
        )
        # Set the temperature for the chatbot
        temperature = st.number_input(
            "Temperature", min_value=0.0, max_value=1.0, value=0.0, step=0.01
        )
        # Set the api key for the OpenAI API
        api_key = st.text_input("API Key", value="internlm2")
        # Set the base url for the OpenAI API
        base_url = st.text_input("Base URL", value="http://0.0.0.0:23333/v1")
        # Set the system prompt for the chatbot
        system_prompt = st.text_area("系统提示", value="")
        # Add a submit button to the form
        submit = st.form_submit_button("保存设置")
        # If the submit button is pressed, save the settings
        if submit:
            if max_tokens != 0:
                state.max_tokens = max_tokens
            state.temperature = temperature
            state.api_key = api_key
            state.base_url = base_url
            state.message_history = []
            if system_prompt != "":
                state.system_prompt = system_prompt
                state.message_history.append(
                    {"role": "system", "content": system_prompt}
                )
            state.client = OpenAI(api_key=state.api_key, base_url=state.base_url)
            pass
    if st.sidebar.button("开启新对话"):
        if not os.path.exists("chat_history"):
            os.mkdir("chat_history")
            pass
        with open(f"chat_history/{time.time()}.json", "w") as f:
            json.dump(state.message_history, f, ensure_ascii=False)
            pass
        state.message_history = []
        st.rerun()

    pass


if __name__ == "__main__":
    side_bar()
    chat_ui()
    pass

在 Code Server 视图下,在 langgpt 文件夹中新建一个 chat_ui.py 文件,回到 Terminal 视图,在 langgpt 环境下运行该文件。

python -m streamlit run langgpt/chat_ui.py

输出如下信息。

Collecting usage statistics. To deactivate, set browser.gatherUsageStats to false.


  You can now view your Streamlit app in your browser.

  Local URL: http://localhost:8501
  Network URL: http://192.168.224.255:8501
  External URL: http://192.168.224.255:8501

开发机占有的 Web 端口为 8501,在本地 PowerShell 中输入端口映射命令。

ssh -p xxxxx root@ssh.intern-ai.org.cn -CNg -L 7860:127.0.0.1:8501 -o StrictHostKeyChecking=no

访问后界面如下图:

在这里插入图片描述

左侧边栏保存设置后可以启动对话界面。

在这里插入图片描述

接下来开始完成任务:利用 LangGPT 优化提示词,使 LLM 对比浮点数字的大小,并输出正确结果。

下面是我设置的系统提示:

# Role: Floating-Point Number Comparator

## Profile
- author: huang2fire
- version: 1.0
- language: 中文/英文
- description: 你是高精度浮点数比较机,擅长精确比较两个浮点数,确保在处理近似值或极小差异时能够正确区分大小关系。

## Skills
1. 接受两个浮点数作为输入。
2. 精确计算并比较两个浮点数的大小、相等或近似相等。
3. 处理浮点数可能产生的精度误差,确保结果准确可靠。
4. 在比较后提供清晰的结果,如“第一个数更大”、“第二个数更大”或“两个数相等/近似相等”。

## Rules
1. 使用高精度算法进行浮点数比较,以减少误差。
2. 在结果中指出浮点数之间的精确差异,若有必要,提示使用者检查精度设定。
3. 提供详细的计算步骤和理由,若有近似相等的情况,说明阈值和原因。
4. 提供示例输入输出格式,以帮助使用者理解如何进行比较。

## Workflows
1. 用户输入两个浮点数。
2. LLM 接收输入并使用高精度算法比较两者的大小。
3. LLM 返回比较结果,并附带详细的计算说明。
4. 如果两个浮点数近似相等,LLM 说明原因并建议用户如何处理。

下面是结果:

在这里插入图片描述

第 4 关 InternLM + LlamaIndex RAG 实践

创建一个使用 Cuda11.7-conda 的镜像,30% A100 * 1 的开发机。进入开发机后,在 Terminal 视图下创建一个 llamaindex 环境,并安装依赖包。

conda create -n llamaindex python=3.10
conda activate llamaindex
conda install pytorch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2 pytorch-cuda=11.7 -c pytorch -c nvidia
pip install einops
pip install protobuf
pip install llama-index==0.10.38 llama-index-llms-huggingface==0.2.0 "transformers[torch]==4.41.1" "huggingface_hub[inference]==0.23.1" huggingface_hub==0.23.1 sentence-transformers==2.7.0 sentencepiece==0.2.0

开发机配置环境很耗时,可以在这个时间把文档过一遍。

运行命令新建文件夹与文件。

cd ~
mkdir llamaindex_demo
mkdir model
cd ~/llamaindex_demo
touch download_hf.py

复制代码到 download_hf.py

import os

# 设置环境变量
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"

# 下载模型
os.system(
    "huggingface-cli download --resume-download sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 --local-dir /root/model/sentence-transformer"
)

llamaindex 环境下运行 download_hf.py,开始下载 Sentence Transformer 模型。

python download_hf.py

下载可能出现 TimeoutError,可以在 ~/model/sentence-transformer 目录执行命令 ll 查看文件明细,与 HF Mirror 文件目录对比,把缺少的文件下载好,切换到 Code Server 视图上传。

从国内镜像仓库下载 NLTK 资源并解压到服务器上。

cd ~
git clone https://gitee.com/yzy0612/nltk_data.git  --branch gh-pages
cd nltk_data
mv packages/* ./
cd tokenizers
unzip punkt.zip
cd ../taggers
unzip averaged_perceptron_tagger.zip

InternLM2 1.8B 软连接出来。

cd ~/model
ln -s /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b/ ./

新建一个 python 文件。

cd ~/llamaindex_demo
touch llamaindex_internlm.py

复制代码到 llamaindex_internlm.py

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)

运行代码。

python llamaindex_internlm.py

可以看到效果不佳。

在这里插入图片描述

下面使用 RAG 技术让模型实现非参数知识更新。

安装 LlamaIndex 词嵌入向量依赖。

pip install llama-index-embeddings-huggingface llama-index-embeddings-instructor

获取知识库。

cd ~/llamaindex_demo
mkdir data
cd data
git clone https://github.com/InternLM/xtuner.git
mv xtuner/README_zh-CN.md ./

新建一个 python 文件。

cd ~/llamaindex_demo
touch llamaindex_RAG.py

复制代码到 llamaindex_RAG.py 中。

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)
python llamaindex_RAG.py

运行后,可以得到合适的结果。

在这里插入图片描述

下面通过 streamlit 部署 Web。

首先安装依赖,并新建一个 python 文件。

pip install streamlit==1.36.0
cd ~/llamaindex_demo
touch app.py

复制代码到 app.py 文件中。

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

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

    documents = SimpleDirectoryReader("/root/llamaindex_demo/data").load_data()
    index = VectorStoreIndex.from_documents(documents)
    query_engine = index.as_query_engine()

    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)

运行。

streamlit run app.py

端口转发后可以在本地访问,加载需要一些时间。

在这里插入图片描述

第 5 关 XTuner 微调个人小助手认知

创建一个使用 Cuda12.2-conda 的镜像,30% A100 * 1 的开发机。进入开发机后,克隆 Tutorial 仓库到本地。

mkdir -p /root/InternLM/Tutorial
git clone -b camp3  https://github.com/InternLM/Tutorial /root/InternLM/Tutorial

在 Terminal 视图下创建一个 xtuner 虚拟环境。

conda create -n xtuner python=3.10 -y
conda activate xtuner
conda install pytorch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 pytorch-cuda=12.1 -c pytorch -c nvidia -y
pip install transformers==4.39.3
pip install streamlit==1.36.0

配置完成后开始安装 XTuner。

# 创建一个目录,用来存放源代码
mkdir -p /root/InternLM/code
cd /root/InternLM/code
git clone -b v0.1.21  https://github.com/InternLM/XTuner /root/InternLM/code/XTuner
# 进入到源码目录
cd /root/InternLM/code/XTuner
# 执行安装,需要一些时间
pip install -e '.[deepspeed]'
# 验证安装结果
xtuner version

安装完成后,创建一个符号链接,指向开发机的 1.8B 小模型文件。

# 创建一个目录,用来存放微调的所有资料,后续的所有操作都在该路径中进行
mkdir -p /root/InternLM/XTuner
cd /root/InternLM/XTuner
mkdir -p Shanghai_AI_Laboratory
ln -s /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b Shanghai_AI_Laboratory/internlm2-chat-1_8b

通过命令查看目录结构。

apt-get install -y tree
tree -l

应该是这个样子。

.
`-- Shanghai_AI_Laboratory
    `-- internlm2-chat-1_8b -> /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b
        |-- README.md
        |-- config.json
        |-- configuration.json
        |-- configuration_internlm2.py
        |-- generation_config.json
        |-- model-00001-of-00002.safetensors
        |-- model-00002-of-00002.safetensors
        |-- model.safetensors.index.json
        |-- modeling_internlm2.py
        |-- special_tokens_map.json
        |-- tokenization_internlm2.py
        |-- tokenization_internlm2_fast.py
        |-- tokenizer.model
        `-- tokenizer_config.json

2 directories, 14 files

接下来使用 XTuner 微调 InternLM2-Chat-1.8B 实现自己的小助手认知。

先通过网页端的 Demo 来查看微调前的对话效果。

streamlit run /root/InternLM/Tutorial/tools/xtuner_streamlit_demo.py

端口转发后可以在本地访问。

在这里插入图片描述

下面对模型进行微调,让模型认识到它自己是我的一个助手。

为了让模型按照预期结果进行回复,我们需要准备一个内容为对话数据的数据集文件。

cd /root/InternLM/XTuner
mkdir -p datas
touch datas/assistant.json

通过脚本生成的方式简化数据文件的准备,直接复制 tools/xtuner_generate_assistant.py

cp /root/InternLM/Tutorial/tools/xtuner_generate_assistant.py ./

注意:需要将脚本中的 name 字段修改成自己的名字。

执行脚本生成数据文件。

python xtuner_generate_assistant.py

在准备好模型和数据集后,需要根据选择的微调方法结合微调方案来找到最匹配的配置文件,减少对配置文件的修改量。

XTuner 提供多个开箱即用的配置文件,可以通过以下命令查看。

xtuner list-cfg -p internlm2

internlm2-chat-1_8b 模型进行指令微调,最匹配的配置文件是 internlm2_chat_1_8b_qlora_alpaca_e3,所以复制该配置文件。

cd /root/InternLM/XTuner
xtuner copy-cfg internlm2_chat_1_8b_qlora_alpaca_e3 .

下面根据自己的内容对该配置文件进行调整,使其能够满足实际训练的要求。主要是对 PART 1 和 PART 3 进行修改,也可以对一些重要的参数进行调整,如学习率(lr)和训练轮数(max_epochs)。

可以将修改后的配置文件复制到当前目录。

cp /root/InternLM/Tutorial/configs/internlm2_chat_1_8b_qlora_alpaca_e3_copy.py ./

完成准备工作后,开始训练。

xtuner train ./internlm2_chat_1_8b_qlora_alpaca_e3_copy.py

训练完成后的 work_dirs 目录结构如下。如果没有 .pth 文件说明训练失败了,可能是显存不足的原因,确保自己的配置为 30% A100 * 1

.
`-- internlm2_chat_1_8b_qlora_alpaca_e3_copy
    |-- 20240814_121157
    |   |-- 20240814_121157.log
    |   `-- vis_data
    |       |-- 20240814_121157.json
    |       |-- config.py
    |       |-- eval_outputs_iter_499.txt
    |       |-- eval_outputs_iter_767.txt
    |       `-- scalars.json
    |-- internlm2_chat_1_8b_qlora_alpaca_e3_copy.py
    |-- iter_500.pth
    |-- iter_768.pth
    `-- last_checkpoint

3 directories, 10 files

将使用 Pytorch 训练出来的模型权重文件转换为目前通用的 HuggingFace 格式文件,可以通过 xtuner convert pth_to_hf 命令来实现模型格式转换。

cd /root/InternLM/XTuner
# 先获取最后保存的一个pth文件
pth_file=`ls -t ./work_dirs/internlm2_chat_1_8b_qlora_alpaca_e3_copy/*.pth | head -n 1`
export MKL_SERVICE_FORCE_INTEL=1
export MKL_THREADING_LAYER=GNU
xtuner convert pth_to_hf ./internlm2_chat_1_8b_qlora_alpaca_e3_copy.py ${pth_file} ./hf

转换完成后的 hf 目录结构如下。

.
|-- README.md
|-- adapter_config.json
|-- adapter_model.bin
`-- xtuner_config.py

0 directories, 4 files

可以看到模型被转换为 HuggingFace 中常用的 .bin 格式文件,此时,hf 文件夹即为我们平时所理解的所谓 “LoRA 模型文件”。

对于 LoRA 或者 QLoRA 微调出来的模型其实并不是一个完整的模型,而是一个额外的层(Adapter),训练完的这个层最终还是要与原模型进行合并才能被正常的使用。

在 XTuner 中提供了一键合并的命令 xtuner convert merge

cd /root/InternLM/XTuner
export MKL_SERVICE_FORCE_INTEL=1
export MKL_THREADING_LAYER=GNU
xtuner convert merge /root/InternLM/XTuner/Shanghai_AI_Laboratory/internlm2-chat-1_8b ./hf ./merged --max-shard-size 2GB

转换完成后的 merged 目录结构如下。

.
|-- config.json
|-- configuration_internlm2.py
|-- generation_config.json
|-- modeling_internlm2.py
|-- pytorch_model-00001-of-00002.bin
|-- pytorch_model-00002-of-00002.bin
|-- pytorch_model.bin.index.json
|-- special_tokens_map.json
|-- tokenization_internlm2.py
|-- tokenization_internlm2_fast.py
|-- tokenizer.json
|-- tokenizer.model
`-- tokenizer_config.json

0 directories, 13 files

微调完成后,再次运行 xtuner_streamlit_demo.py 来观察微调后的对话效果,在运行之前,需要将脚本中的模型路径修改为微调后的模型的路径。

# 直接修改脚本文件第18行
- model_name_or_path = "/root/InternLM/XTuner/Shanghai_AI_Laboratory/internlm2-chat-1_8b"
+ model_name_or_path = "/root/InternLM/XTuner/merged"
streamlit run /root/InternLM/Tutorial/tools/xtuner_streamlit_demo.py

端口转发后可以在本地访问。

在这里插入图片描述

第 6 关 OpenCompass 评测 InternLM-1.8B 实践

创建一个使用 Cuda11.7-conda 的镜像,10% A100 * 1 的开发机。

在 Terminal 视图下创建一个 opencompass 虚拟环境,并进行配置。

conda create -n opencompass python=3.10
conda activate opencompass
conda install pytorch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 pytorch-cuda=12.1 -c pytorch -c nvidia -y

# 注意:一定要先 cd /root
cd /root
git clone -b 0.2.4 https://github.com/open-compass/opencompass
cd opencompass
pip install -e .

apt-get update
apt-get install cmake
pip install -r requirements.txt
pip install protobuf

解压评测数据集到 /root/opencompass/data/ 处,文件较大,需要一些时间。

cp /share/temp/datasets/OpenCompassData-core-20231110.zip /root/opencompass/
unzip OpenCompassData-core-20231110.zip

列出所有跟 InternLM 及 C-Eval 相关的配置。

python tools/list_configs.py internlm ceval

可以看到。

+----------------------------------------+----------------------------------------------------------------------+
| Model                                  | Config Path                                                          |
|----------------------------------------+----------------------------------------------------------------------|
| hf_internlm2_1_8b                      | configs/models/hf_internlm/hf_internlm2_1_8b.py                      |
| hf_internlm2_20b                       | configs/models/hf_internlm/hf_internlm2_20b.py                       |
| hf_internlm2_7b                        | configs/models/hf_internlm/hf_internlm2_7b.py                        |
| hf_internlm2_base_20b                  | configs/models/hf_internlm/hf_internlm2_base_20b.py                  |
| hf_internlm2_base_7b                   | configs/models/hf_internlm/hf_internlm2_base_7b.py                   |
| hf_internlm2_chat_1_8b                 | configs/models/hf_internlm/hf_internlm2_chat_1_8b.py                 |
| hf_internlm2_chat_1_8b_sft             | configs/models/hf_internlm/hf_internlm2_chat_1_8b_sft.py             |
| hf_internlm2_chat_20b                  | configs/models/hf_internlm/hf_internlm2_chat_20b.py                  |
| hf_internlm2_chat_20b_sft              | configs/models/hf_internlm/hf_internlm2_chat_20b_sft.py              |
| hf_internlm2_chat_20b_with_system      | configs/models/hf_internlm/hf_internlm2_chat_20b_with_system.py      |
| hf_internlm2_chat_7b                   | configs/models/hf_internlm/hf_internlm2_chat_7b.py                   |
| hf_internlm2_chat_7b_sft               | configs/models/hf_internlm/hf_internlm2_chat_7b_sft.py               |
| hf_internlm2_chat_7b_with_system       | configs/models/hf_internlm/hf_internlm2_chat_7b_with_system.py       |
| hf_internlm2_chat_math_20b             | configs/models/hf_internlm/hf_internlm2_chat_math_20b.py             |
| hf_internlm2_chat_math_20b_with_system | configs/models/hf_internlm/hf_internlm2_chat_math_20b_with_system.py |
| hf_internlm2_chat_math_7b              | configs/models/hf_internlm/hf_internlm2_chat_math_7b.py              |
| hf_internlm2_chat_math_7b_with_system  | configs/models/hf_internlm/hf_internlm2_chat_math_7b_with_system.py  |
| hf_internlm_20b                        | configs/models/hf_internlm/hf_internlm_20b.py                        |
| hf_internlm_7b                         | configs/models/hf_internlm/hf_internlm_7b.py                         |
| hf_internlm_chat_20b                   | configs/models/hf_internlm/hf_internlm_chat_20b.py                   |
| hf_internlm_chat_7b                    | configs/models/hf_internlm/hf_internlm_chat_7b.py                    |
| hf_internlm_chat_7b_8k                 | configs/models/hf_internlm/hf_internlm_chat_7b_8k.py                 |
| hf_internlm_chat_7b_v1_1               | configs/models/hf_internlm/hf_internlm_chat_7b_v1_1.py               |
| internlm_7b                            | configs/models/internlm/internlm_7b.py                               |
| lmdeploy_internlm2_chat_20b            | configs/models/hf_internlm/lmdeploy_internlm2_chat_20b.py            |
| lmdeploy_internlm2_chat_7b             | configs/models/hf_internlm/lmdeploy_internlm2_chat_7b.py             |
| ms_internlm_chat_7b_8k                 | configs/models/ms_internlm/ms_internlm_chat_7b_8k.py                 |
+----------------------------------------+----------------------------------------------------------------------+
+--------------------------------+------------------------------------------------------------------+
| Dataset                        | Config Path                                                      |
|--------------------------------+------------------------------------------------------------------|
| ceval_clean_ppl                | configs/datasets/ceval/ceval_clean_ppl.py                        |
| ceval_contamination_ppl_810ec6 | configs/datasets/contamination/ceval_contamination_ppl_810ec6.py |
| ceval_gen                      | configs/datasets/ceval/ceval_gen.py                              |
| ceval_gen_2daf24               | configs/datasets/ceval/ceval_gen_2daf24.py                       |
| ceval_gen_5f30c7               | configs/datasets/ceval/ceval_gen_5f30c7.py                       |
| ceval_internal_ppl_1cd8bf      | configs/datasets/ceval/ceval_internal_ppl_1cd8bf.py              |
| ceval_ppl                      | configs/datasets/ceval/ceval_ppl.py                              |
| ceval_ppl_1cd8bf               | configs/datasets/ceval/ceval_ppl_1cd8bf.py                       |
| ceval_ppl_578f8d               | configs/datasets/ceval/ceval_ppl_578f8d.py                       |
| ceval_ppl_93e5ce               | configs/datasets/ceval/ceval_ppl_93e5ce.py                       |
| ceval_zero_shot_gen_bd40ef     | configs/datasets/ceval/ceval_zero_shot_gen_bd40ef.py             |
+--------------------------------+------------------------------------------------------------------+

开始使用命令行配置参数进行评测。

打开 opencompass/configs/models/hf_internlm/ 目录下的 hf_internlm2_chat_1_8b.py,这个文件有内容的,需要全部替换成以下代码。

from opencompass.models import HuggingFaceCausalLM


models = [
    dict(
        type=HuggingFaceCausalLM,
        abbr="internlm2-1.8b-hf",
        path="/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b",
        tokenizer_path="/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b",
        model_kwargs=dict(
            trust_remote_code=True,
            device_map="auto",
        ),
        tokenizer_kwargs=dict(
            padding_side="left",
            truncation_side="left",
            use_fast=False,
            trust_remote_code=True,
        ),
        max_out_len=100,
        min_out_len=1,
        max_seq_len=2048,
        batch_size=8,
        run_cfg=dict(num_gpus=1, num_procs=1),
    )
]

通过命令评测性能,由于 OpenCompass 默认并行启动评估过程,可以在第一次运行时以 debug 模式启动评估,检查是否存在问题。在 debug 模式下,任务将按顺序执行,并实时打印输出。

export MKL_SERVICE_FORCE_INTEL=1
export MKL_THREADING_LAYER=GNU

cd /root/opencompass
python run.py --datasets ceval_gen --models hf_internlm2_chat_1_8b --debug

完成后可以看到如下信息。

dataset                                         version    metric         mode      internlm2-1.8b-hf
----------------------------------------------  ---------  -------------  ------  -------------------
ceval-computer_network                          db9ce2     accuracy       gen                   47.37
ceval-operating_system                          1c2571     accuracy       gen                   47.37
ceval-computer_architecture                     a74dad     accuracy       gen                   23.81
ceval-college_programming                       4ca32a     accuracy       gen                   27.03
ceval-college_physics                           963fa8     accuracy       gen                   42.11
ceval-college_chemistry                         e78857     accuracy       gen                   37.5
ceval-advanced_mathematics                      ce03e2     accuracy       gen                   26.32
ceval-probability_and_statistics                65e812     accuracy       gen                   22.22
ceval-discrete_mathematics                      e894ae     accuracy       gen                   25
ceval-electrical_engineer                       ae42b9     accuracy       gen                   27.03
ceval-metrology_engineer                        ee34ea     accuracy       gen                   54.17
ceval-high_school_mathematics                   1dc5bf     accuracy       gen                   22.22
ceval-high_school_physics                       adf25f     accuracy       gen                   42.11
ceval-high_school_chemistry                     2ed27f     accuracy       gen                   52.63
ceval-high_school_biology                       8e2b9a     accuracy       gen                   26.32
ceval-middle_school_mathematics                 bee8d5     accuracy       gen                   36.84
ceval-middle_school_biology                     86817c     accuracy       gen                   80.95
ceval-middle_school_physics                     8accf6     accuracy       gen                   47.37
ceval-middle_school_chemistry                   167a15     accuracy       gen                   80
ceval-veterinary_medicine                       b4e08d     accuracy       gen                   43.48
ceval-college_economics                         f3f4e6     accuracy       gen                   32.73
ceval-business_administration                   c1614e     accuracy       gen                   39.39
ceval-marxism                                   cf874c     accuracy       gen                   68.42
ceval-mao_zedong_thought                        51c7a4     accuracy       gen                   70.83
ceval-education_science                         591fee     accuracy       gen                   55.17
ceval-teacher_qualification                     4e4ced     accuracy       gen                   59.09
ceval-high_school_politics                      5c0de2     accuracy       gen                   57.89
ceval-high_school_geography                     865461     accuracy       gen                   47.37
ceval-middle_school_politics                    5be3e7     accuracy       gen                   76.19
ceval-middle_school_geography                   8a63be     accuracy       gen                   75
ceval-modern_chinese_history                    fc01af     accuracy       gen                   52.17
ceval-ideological_and_moral_cultivation         a2aa4a     accuracy       gen                   73.68
ceval-logic                                     f5b022     accuracy       gen                   31.82
ceval-law                                       a110a1     accuracy       gen                   29.17
ceval-chinese_language_and_literature           0f8b68     accuracy       gen                   47.83
ceval-art_studies                               2a1300     accuracy       gen                   42.42
ceval-professional_tour_guide                   4e673e     accuracy       gen                   51.72
ceval-legal_professional                        ce8787     accuracy       gen                   34.78
ceval-high_school_chinese                       315705     accuracy       gen                   36.84
ceval-high_school_history                       7eb30a     accuracy       gen                   65
ceval-middle_school_history                     48ab4a     accuracy       gen                   86.36
ceval-civil_servant                             87d061     accuracy       gen                   42.55
ceval-sports_science                            70f27b     accuracy       gen                   52.63
ceval-plant_protection                          8941f9     accuracy       gen                   40.91
ceval-basic_medicine                            c409d6     accuracy       gen                   68.42
ceval-clinical_medicine                         49e82d     accuracy       gen                   36.36
ceval-urban_and_rural_planner                   95b885     accuracy       gen                   52.17
ceval-accountant                                002837     accuracy       gen                   36.73
ceval-fire_engineer                             bc23f5     accuracy       gen                   38.71
ceval-environmental_impact_assessment_engineer  c64e2d     accuracy       gen                   51.61
ceval-tax_accountant                            3a5e3c     accuracy       gen                   36.73
ceval-physician                                 6e277d     accuracy       gen                   42.86
ceval-stem                                      -          naive_average  gen                   40.59
ceval-social-science                            -          naive_average  gen                   58.21
ceval-humanities                                -          naive_average  gen                   50.16
ceval-other                                     -          naive_average  gen                   45.43
ceval-hard                                      -          naive_average  gen                   33.76
ceval                                           -          naive_average  gen                   47.03

结果图片如下。

在这里插入图片描述

OpenCompass 还允许用户在配置文件中编写完整配置,并通过 run.py 直接运行它。

配置文件以 Python 格式组织,并且必须包括 datasetsmodels 字段。本次测试配置在 configs 文件夹中。此配置通过继承机制引入所需的数据集和模型配置,并以所需格式组合 datasetsmodels 字段。

configs 文件夹下创建 eval_tutorial_demo.py 并贴入代码。

cd /root/opencompass/configs
touch eval_tutorial_demo.py
from mmengine.config import read_base

with read_base():
    from .datasets.ceval.ceval_gen import ceval_datasets
    from .models.hf_internlm.hf_internlm2_chat_1_8b import (
        models as hf_internlm2_chat_1_8b_models,
    )

datasets = ceval_datasets
models = hf_internlm2_chat_1_8b_models

运行任务时,只需将配置文件的路径传递给 run.py

cd /root/opencompass
python run.py configs/eval_tutorial_demo.py --debug

运行结果同上。

  • 13
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值