书生·浦语大模型实战营第 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 Repo 的 tools
文件夹下找到 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 格式组织,并且必须包括 datasets
和 models
字段。本次测试配置在 configs
文件夹中。此配置通过继承机制引入所需的数据集和模型配置,并以所需格式组合 datasets
和 models
字段。
在 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
运行结果同上。