编程大模型之—Qwen2.5-Coder
Qwen2.5-Coder是阿里云通义大模型团队推出的专门针对代码的大型语言模型系列。
Qwen2.5-Coder 模型基础架构
Qwen2.5-Coder基于Qwen2.5架构构建,采用了先进的Transformer结构,专为代码生成和理解进行了优化。通过引入多层自注意力机制,模型能够高效捕捉代码中的长距离依赖关系和复杂语法结构。
Qwen2.5-Coder 模型大小
Qwen2.5-Coder 提供了六种模型的大小, 分别是:
- 0.5B
- 1.5B
- 3B
- 7B
- 14B
- 32B
B代表“Billion”,即“十亿”。这里的数字(如0.5、3、14)表示模型参数的数量,以十亿为单位。因此,0.5B表示模型有5亿个参数,3B表示模型有30亿个参数,14B表示模型有140亿个参数。
在机器学习和自然语言处理领域,模型参数的数量是衡量模型大小和能力的一个重要指标。一般来说,参数越多的模型能够学习更复杂的模式,处理更复杂的任务,但也需要更多的计算资源和时间来训练和推理。
Qwen2.5-Coder 的使用
现在使用大模型最熟悉和方便的方式就是类似ChatGPT的聊天窗口了, 在魔搭社区,提供了Qwen2.5-Coder 的聊天方式,地址是:
https://modelscope.cn/studios/Qwen/Qwen2.5-Coder-demo/
打开后的界面如下:
- 这里提供了多个模型大小的切换
- 对话上面默认有一个系统的Prompt
- 中间区块是聊天记录的显示
- 下面输入框输入需要问询的内容
- 最下方就是两个按钮,一个是清除历史记录,一个是发送输入内容的。
这里让Qwen2.5-Coder产生一段计算闰年的Java代码,在输入框中输入的 Prompt如下:
完成一个Java的计算闰年的函数,只需要输出代码就可以
因为任务比较简单,输出的内容符合预期,而且的确是只输出了代码,没有其他的多余信息,这个要求对于使用AI来自动处理代码来说是很有用的。接下来比较一下0.5B ~32B 产生的差异。
0.5B ~ 32B不同模型大小的产生效果的差异
为了让之前的记录不影响后面的结果,点击 Clear History清除历史记录, 因为GAI是叠加历史记录进行询问的,也就是会参考之前的聊天内容产生新的内容。
0.5B
同样是上面的Prompt: 完成一个Java的计算闰年的函数,只需要输出代码就可以
产生的效果如下:
当然!以下是一个简单的Java程序,用于计算闰年的函数:
public class LeapYearChecker {
public static void main(String[] args) {
int year = 2024; // 替换为你想要检查的年份
if (isLeapYear(year)) {
System.out.println(year + " 是闰年。");
} else {
System.out.println(year + " 不是闰年。");
}
}
public static boolean isLeapYear(int year) {
if (year % 4 == 0) {
if (year % 100 != 0) {
return true;
} else if (year % 400 == 0) {
return true;
}
}
return false;
}
}
这个程序定义了一个`LeapYearChecker`类,其中包含一个`main`方法来测试计算闰年的功能。`isLeapYear`方法接受一个整数作为参数,并返回一个布尔值,表示该年份是否为闰年。
你可以将`year`变量替换为你想要检查的年份。运行这个程序,它会输出相应的结果。
纳尼, 代码是产生了,但是还是产生了代码之外的说明内容, 难道是 只需要输出代码就可以
不过明确吗?
修改一下Prompt,完成一个Java的计算闰年的函数,不需要任何解释性的内容,只需要输出代码就可以
, 更明确的指定不要解释性内容。
看一下产生的内容:
public class LeapYearChecker {
public static boolean isLeapYear(int year) {
if (year % 4 == 0) {
if (year % 100 != 0 || year % 400 == 0) {
return true;
}
}
return false;
}
public static void main(String[] args) {
int year = 2020;
if (isLeapYear(year)) {
System.out.println(year + " 是闰年");
} else {
System.out.println(year + " 不是闰年");
}
}
}
这个代码定义了一个`LeapYearChecker`类,并包含一个静态方法`isLeapYear`来判断一个年份是否为闰年。`main`方法演示了如何调用这个方法并输出结果
解释性的内容是少了,但是还是有, 好吧,看看其他大小的效果
1.5B
~~~java
public class LeapYearChecker {
public static boolean isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
public static void main(String[] args) {
int[] years = {2000, 2001, 2004, 2005, 2008, 2009, 2012, 2013, 2016, 2017, 2020};
for (int year : years) {
System.out.println(year + " is a leap year: " + isLeapYear(year));
}
}
}
~~~
这个程序定义了一个`isLeapYear`方法来判断一个年份是否是闰年。然后在`main`方法中测试了多个年份,并打印出每个年份是否为闰年。
结果: 代码产生了,还是有解释性内容
3B
~~~java
public class LeapYearCalculator {
public static boolean isLeapYear(int year) {
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
return true;
} else {
return false;
}
}
public static void main(String[] args) {
int year = 2024; // 可以更改这个年份来测试其他年份
if (isLeapYear(year)) {
System.out.println(year + " 是闰年");
} else {
System.out.println(year + " 不是闰年");
}
}
}
~~~
这段代码定义了一个名为`isLeapYear`的方法,用于判断给定的年份是否为闰年。在`main`方法中,我们调用`isLeapYear`方法并打印结果。你可以根据需要修改`year`变量的值来测试不同的年份。
- 结果: 代码产生了,还是有解释性内容
7B
public class LeapYearCalculator {
public static boolean isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
public static void main(String[] args) {
int year = 2024; // 示例年份
if (isLeapYear(year)) {
System.out.println(year + " 是闰年");
} else {
System.out.println(year + " 不是闰年");
}
}
}
- 结果: 代码产生了,没有解释性内容
14 B
public class LeapYearCalculator {
public static boolean isLeapYear(int year) {
if (year % 4 == 0) {
if (year % 100 == 0) {
return year % 400 == 0;
} else {
return true;
}
} else {
return false;
}
}
public static void main(String[] args) {
int year = 2024;
System.out.println(year + " is a leap year: " + isLeapYear(year));
}
}
- 结果: 代码产生了,没有解释性内容
结论
- 0.5B ~ 7B : 能产生内容,但是会产生预期外的内容
- 14B ~ 32B: 产生的内容相对精确
代码方式调用模型
对于程序员来说,更感兴趣的应该还是通过代码的方式调用模型,这样的话就可以批量或是借助AI干更多的事情, 代码的方式调用模型的方式一般有两种:
-
调用各模型提供的API, 调用API是需要费用的。
计费是按输入和输出的Token数量来运算,一般是每百万 Token为单位, QWen 是按千Token进行收入,大致收费标准如下:
-
直接调用模型。
下载训练好的数据集,通过Python调用获取回复。
第一种方式需要获取 API的地址和验证的Token,这里主要介绍直接调用模型的方式,为了演示的简单性,这是使用 0.5B大小的模型, 也就是 Qwen2.5-Coder-0.5B-Instruct。
为什么不是调用 Qwen2.5-Coder-0.5B 模型呢?
-
Qwen2.5-Coder-[0.5-32]B-Instruct 是用于聊天的指令模型
-
Qwen2.5-Coder-[0.5-32]B 是一个基础模型,通常用于补全任务,作为微调的一个更好的起点。
调用 Qwen2.5-Coder-0.5B-Instruct 模型
如何下载模型
要调用模型,首先要下载模型相关的文件,0.5B 的模型文件的大小是 900 多兆, 其他模型的文件大小从几个G到几十个G不等。
模型文件可以到 Hugging Face ( https://huggingface.co/)下载, 比如 Qwen2.5-Coder-0.5B-Instruct的地址是:https://huggingface.co/Qwen/Qwen2.5-Coder-0.5B-Instruct
Hugging Face起初是一家总部位于纽约的聊天机器人初创服务商,后来转型为提供机器学习模型和数据集托管的平台,类似于AI领域的GitHub。它汇聚了大量预训练的模型以及相关的工具和资源。
如果无法访问Hugging Face 或是访问速度慢的话,可以到ModelScope进行下载。
ModelScope (魔搭社区)是一个由阿里巴巴集团推出的开源模型即服务(MaaS)共享平台,旨在简化模型应用的流程,并为AI开发者提供灵活、易用、低成本的一站式模型服务。
下载和运行步骤
- 安装modelscope库:
pip install modelscope
- 新增文件: Qwen2.5-Coder-0.5B.py, 内容如下:
from modelscope import AutoModelForCausalLM, AutoTokenizer
model_name = "Qwen/Qwen2.5-0.5B-Instruct"
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
input_text = "请完成一个Java的计算闰年的函数,不需要任何解释性的内容,只需要输出代码就可以"
messages = [
{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},
{"role": "user", "content": input_text}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
# Use `max_new_tokens` to control the maximum output length.
generated_ids = model.generate(model_inputs.input_ids, max_new_tokens=1024, do_sample=False)[0]
# The generated_ids include prompt_ids, so we only need to decode the tokens after prompt_ids.
output_text = tokenizer.decode(generated_ids[len(model_inputs.input_ids[0]):], skip_special_tokens=True)
print(f"Prompt: {input_text}\n\nGenerated text: {output_text}")
导入必要的库和模型
AutoModelForCausalLM
:这是用于因果语言建模(Causal Language Modeling,通常指文本生成)的自动模型类。AutoTokenizer
:这是用于文本分词的自动分词器类
设置模型名称model_name
:指定了要使用的预训练模型名称,这里是Qwen/Qwen2.5-0.5B-Instruct
。
加载模型和分词器- 使用
from_pretrained
方法加载指定的预训练模型和分词器。
指定了torch_dtype="auto"
(自动选择数据类型)和device_map="auto"
(自动映射设备,这里可能对于分布式训练有用,但在单GPU或CPU上可能不起作用或不需要)。
准备输入文本:input_text
:这是用户请求的文本,要求生成一个Java的计算闰年的函数。
构建消息模板:- 创建一个包含系统消息和用户消息的列表
messages
。系统消息定义了模型的角色(这里是“Qwen”,一个由阿里云创建的助手)。 - 使用
tokenizer.apply_chat_template
方法将消息转换为模型可以理解的格式。这里tokenize=False
表示不立即对文本进行分词,add_generation_prompt=True
表示添加生成提示(可能是为了引导模型更好地理解输入并生成响应)。
准备模型输入: - 使用分词器对处理后的文本进行分词,并转换为PyTorch张量(
return_tensors="pt"
)。 - 将张量移动到模型所在的设备(
model.device
)。
生成文本:
- 使用模型的
generate
方法生成文本。这里指定了max_new_tokens=1024
来控制生成文本的最大长度(不包括输入提示的长度)。 do_sample=False
表示使用贪心解码(即每次选择概率最高的下一个词),而不是随机采样
解码生成的ID并输出:- 由于生成的ID包括输入提示的ID,所以需要跳过这些ID,只解码后面的部分。
- 使用
tokenizer.decode
方法将生成的ID解码为文本。 - 打印出输入提示和生成的文本。
- 运行 python 文件
这里在VS Code中运行,运行的时候会先下载模型 文件到下面路径:
C:\Users\xxx\.cache\modelscope\hub\Qwen\Qwen2___5-0___5B-Instruct
下载的过程如下:
下载后的目录结构:
这个目录包含了一些 JSON文件和.safetensors 文件。
.safetensors后缀文件是由Hugging Face推出的一种新型安全模型存储格式。.safetensors文件特别关注模型的安全性,通过优化的二进制格式和支持内存映射,显著提高了大模型文件的加载速度。
- 执行完成后的结果
这里产生的结果和上面使用Chat对话框产生的结果基本是一致的,使用 32B 产生的效果应该是比较好的。
问题解决
KeyError: ‘qwen2’
如果出现 KeyError: 'qwen2'
的错误, 原因就是transformers 库的版本太低了。 细节的错误信息如下:
File "C:\inssoftware\python\Lib\site-packages\transformers\models\auto\auto_factory.py", line 526, in from_pretrained
config, kwargs = AutoConfig.from_pretrained(
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\inssoftware\python\Lib\site-packages\transformers\models\auto\configuration_auto.py", line 1064, in from_pretrained
config_class = CONFIG_MAPPING[config_dict["model_type"]]
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\inssoftware\python\Lib\site-packages\transformers\models\auto\configuration_auto.py", line 761, in __getitem__
raise KeyError(key)
KeyError: 'qwen2'
QWen 2.5 的环境要求
- python>=3.9
- transformers>4.37.0
使用py --version
查看Python版本, 使用pip list
查看 transformers 库的版本:
如果transformers 版本过低, 使用 pip install --upgrade transformers
进行升级。
参考
- 完整代码参考: https://github.com/osxm/ai_ency/blob/main/ai_python_ency/Qwen2.5-Coder-0.5B.py
- Qwen2.5-Coder官方介绍: https://qwenlm.github.io/blog/qwen2.5-coder/
- Qwen2.5-Coder官方介绍[中文]:https://qwenlm.github.io/zh/blog/qwen2.5-coder/
- Qwen2.5-Coder GitHub: https://github.com/QwenLM/Qwen2.5-Coder
- Qwen2.5-Coder-7B-Instruct Hugging Face: https://huggingface.co/spaces/Qwen/Qwen2.5-Coder-7B-Instruct
- 魔搭社区在线Chat: https://modelscope.cn/studios/Qwen/Qwen2.5-Coder-demo/