基于魔搭社区 Qwen2-1.5B-Instruct 实现本地文本分类实战
前言
最近在学习大模型本地部署和实际应用开发时,我选择从一个相对容易落地的任务入手:文本分类。
相比聊天机器人、智能问答、知识库检索这些更复杂的场景,文本分类的目标更明确,也更适合用来练习大模型的完整调用流程。比如我们可以让模型判断一段评论是正向还是负向,也可以让模型识别用户问题属于“账号问题”“订单问题”“售后问题”还是“其他问题”。
本文会从零开始,基于魔搭社区的 Qwen2-1.5B-Instruct 模型,实现一个可以在本地运行的文本分类小项目。文章内容包括环境准备、模型下载、模型加载、提示词设计、单条分类、批量分类以及常见问题总结。
这篇文章更偏向实战记录,适合刚开始接触大模型本地部署、ModelScope 和 Transformers 的同学。
一、为什么选择 Qwen2-1.5B-Instruct?
在本地跑大模型时,模型大小非常重要。参数越大的模型通常效果越好,但对显存、内存和推理速度的要求也越高。
我选择 Qwen2-1.5B-Instruct,主要有几个原因:
- 模型体积适中,适合入门实战。
- 是指令微调模型,能较好理解分类任务的提示词。
- 支持中文场景,适合做中文文本分类。
- 可以通过魔搭社区下载,在国内环境下使用更方便。
- 代码调用方式和更大规模的 Qwen 模型基本一致,后续迁移成本低。
需要说明的是,Qwen2-1.5B-Instruct 本质上是一个生成式语言模型,并不是传统意义上专门训练好的分类模型。本文的做法是通过提示词约束,让模型按照指定标签输出分类结果。
二、项目环境准备
1. 推荐环境
本文使用的环境如下:
Python >= 3.9
PyTorch >= 2.0
transformers >= 4.37.0
modelscope
accelerate
如果有 NVIDIA 显卡,推荐使用 CUDA 环境;如果没有显卡,也可以使用 CPU 运行,只是速度会明显慢一些。
2. 创建虚拟环境
conda create -n qwen_cls python=3.10 -y
conda activate qwen_cls
也可以使用 venv:
python -m venv qwen_cls
qwen_cls\Scripts\activate
Linux 或 macOS 下激活方式为:
source qwen_cls/bin/activate
3. 安装依赖
pip install torch transformers accelerate modelscope pandas
如果你使用的是 CUDA 版本 PyTorch,建议根据自己的 CUDA 版本到 PyTorch 官网选择对应安装命令。
这里特别注意:Qwen2 需要较新的 transformers 版本。如果版本太旧,可能会出现类似下面的报错:
KeyError: 'qwen2'
遇到这个问题,可以升级:
pip install -U transformers accelerate
三、下载模型
模型可以通过两种方式准备:一种是使用代码自动下载,另一种是进入官网手动下载后保存到本地目录。
方式一:使用 ModelScope 自动下载
我们可以使用魔搭社区的 snapshot_download 下载模型到本地。
新建 download_model.py:
from modelscope import snapshot_download
model_dir = snapshot_download("qwen/Qwen2-1.5B-Instruct")
print("模型下载路径:", model_dir)
运行:
python download_model.py
下载完成后,终端会输出模型所在目录。后面加载模型时可以直接使用这个本地路径,也可以继续使用模型名称让程序自动查找缓存。
方式二:官网手动下载到本地目录
如果不想在代码中自动下载,也可以直接进入模型官网页面,手动下载模型文件,然后保存到自己的本地目录中。
例如我这里把模型保存到了:
E:\qwen2.5\Qwen2.5-0.5B-Instruct
这种方式的好处是路径清晰,后续迁移、备份和重复加载都比较方便。加载模型时,只需要把 model_name 改成本地模型目录即可:
model_name = r"E:\qwen2.5\Qwen2.5-0.5B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
这里要注意:如果文章中使用的是 Qwen2-1.5B-Instruct,而你本地下载的是 Qwen2.5-0.5B-Instruct,代码中的模型路径就要以本地实际目录为准。不同模型的参数规模不同,但对于本文的文本分类流程来说,整体调用方式基本一致。
四、加载 Qwen2-1.5B-Instruct
新建 load_model.py:
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "qwen/Qwen2-1.5B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
print("模型加载完成")
如果你的机器没有 GPU,也可以这样写:
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float32,
device_map="cpu"
)
不过 CPU 推理会慢一些,适合学习和调试,不太适合大量数据批处理。
五、文本分类思路
传统文本分类通常需要准备训练数据,然后训练一个分类模型。大模型的优势是:即使没有专门训练,也可以通过提示词完成零样本或少样本文本分类。
本文采用的基本思路是:
- 预先定义分类标签。
- 把待分类文本和标签说明写进 prompt。
- 要求模型只输出指定标签。
- 对模型输出做清洗和校验。
例如我们定义一个评论情感分类任务:
标签:
正向
负向
中性
输入文本:
这家店的发货速度很快,客服态度也不错,下次还会再买。
模型应该输出:
正向
六、实现单条文本分类
新建 text_classification.py:
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "qwen/Qwen2-1.5B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
def classify_text(text: str) -> str:
labels = ["正向", "负向", "中性"]
prompt = f"""
你是一个文本分类助手。请根据用户输入的内容,判断文本情感类别。
只能从以下标签中选择一个输出:
{labels}
分类规则:
1. 表达满意、喜欢、认可、推荐,归为“正向”。
2. 表达不满、抱怨、差评、失望,归为“负向”。
3. 没有明显情绪倾向,或者只是客观描述,归为“中性”。
待分类文本:
{text}
请只输出一个标签,不要解释原因。
"""
messages = [
{"role": "system", "content": "你是一个严谨的中文文本分类助手。"},
{"role": "user", "content": prompt}
]
input_text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
model_inputs = tokenizer([input_text], return_tensors="pt").to(model.device)
generated_ids = model.generate(
**model_inputs,
max_new_tokens=20,
temperature=0.01,
do_sample=False
)
output_ids = generated_ids[0][len(model_inputs.input_ids[0]):]
response = tokenizer.decode(output_ids, skip_special_tokens=True).strip()
for label in labels:
if label in response:
return label
return "无法判断"
if __name__ == "__main__":
test_texts = [
"物流很快,包装也很好,整体非常满意。",
"等了十天才收到,客服也没人回复,太差了。",
"商品已经收到,颜色是黑色,尺寸正常。"
]
for item in test_texts:
result = classify_text(item)
print(f"文本:{item}")
print(f"分类:{result}")
print("-" * 40)
运行:
python text_classification.py
可能输出:
文本:物流很快,包装也很好,整体非常满意。
分类:正向
----------------------------------------
文本:等了十天才收到,客服也没人回复,太差了。
分类:负向
----------------------------------------
文本:商品已经收到,颜色是黑色,尺寸正常。
分类:中性
----------------------------------------
七、为什么要限制模型输出?
刚开始写 prompt 时,我发现模型经常会输出解释,例如:
该文本表达了用户对物流和包装的满意,因此分类为:正向。
这种输出对人类阅读没问题,但对程序处理不够友好。实际开发中,我们更希望模型只返回一个固定标签。
所以 prompt 中要明确写:
请只输出一个标签,不要解释原因。
同时,代码中也要增加兜底逻辑:
for label in labels:
if label in response:
return label
这样即使模型多输出了一些文字,也能尽量提取出正确标签。
八、使用 JSON 格式输出
如果后续要对接接口或数据库,建议让模型输出 JSON。
示例 prompt:
prompt = f"""
你是一个文本分类助手。请判断下面文本的情感类别。
可选标签:正向、负向、中性
待分类文本:
{text}
请严格按照 JSON 格式输出,不要添加额外解释:
{{
"label": "正向/负向/中性"
}}
"""
模型理想输出:
{
"label": "正向"
}
实际项目中仍然建议配合 json.loads() 解析,并对异常情况做处理。
九、批量文本分类
实际业务中,我们通常不会只处理一条文本,而是处理 CSV 或 Excel 中的大量数据。这里以 CSV 为例。
假设有一个 comments.csv:
text
这个产品质量不错,使用起来很方便
价格有点贵,但是整体还可以
体验很差,页面经常卡死
新建 batch_classification.py:
import pandas as pd
from text_classification import classify_text
input_file = "comments.csv"
output_file = "comments_result.csv"
df = pd.read_csv(input_file)
results = []
for index, row in df.iterrows():
text = str(row["text"])
label = classify_text(text)
results.append(label)
print(f"第 {index + 1} 条处理完成:{label}")
df["label"] = results
df.to_csv(output_file, index=False, encoding="utf-8-sig")
print("批量分类完成,结果已保存到:", output_file)
运行:
python batch_classification.py
输出文件 comments_result.csv 中会新增一列 label,用于保存分类结果。
十、扩展为多类别业务分类
除了情感分类,还可以做更贴近业务的分类任务。例如客服问题分类:
账号问题
支付问题
物流问题
售后问题
产品咨询
其他
对应 prompt 可以改成:
prompt = f"""
你是一个客服工单分类助手。请根据用户问题,将其归入最合适的类别。
可选类别:
1. 账号问题:登录失败、密码找回、账号冻结、实名认证等
2. 支付问题:付款失败、重复扣款、退款到账、发票等
3. 物流问题:发货、快递、签收、配送延迟等
4. 售后问题:退货、换货、维修、质量问题等
5. 产品咨询:功能、规格、使用方法、价格等
6. 其他:无法归入以上类别的问题
用户问题:
{text}
请只输出类别名称,不要解释。
"""
这个思路非常通用,只要把标签和规则换成自己的业务场景,就可以快速得到一个可用的文本分类原型。
十一、提升分类效果的几个方法
1. 标签不要太模糊
标签之间边界越清晰,模型越容易判断。例如“好评”和“正向”可以二选一,不建议同时出现。
2. 给每个标签加解释
只写标签名时,模型可能理解不一致。给标签加上简短说明,效果通常更稳定。
3. 增加少样本示例
如果发现模型经常分错,可以在 prompt 中加入 2 到 5 个示例。
例如:
示例1:
文本:客服回复很快,问题解决得也很好。
标签:正向
示例2:
文本:页面一直打不开,体验很糟糕。
标签:负向
4. 降低随机性
分类任务通常不需要模型发挥创造力,所以可以设置:
temperature=0.01
do_sample=False
这样输出会更稳定。
5. 增加输出校验
不要完全相信模型输出。可以在代码中判断输出是否属于合法标签,如果不是,就返回“无法判断”或重新请求一次。
十二、常见问题
1. 报错 KeyError: ‘qwen2’
原因通常是 transformers 版本过低。
解决方式:
pip install -U transformers
2. 显存不够怎么办?
可以尝试:
- 换用 CPU 运行。
- 使用更小模型。
- 使用量化版本模型。
- 减小
max_new_tokens。 - 关闭其他占用显存的程序。
3. 模型输出不稳定怎么办?
可以从三个方向优化:
- 把分类规则写清楚。
- 添加示例。
- 降低采样随机性。
4. 为什么不用传统分类模型?
传统分类模型在有大量标注数据时效果很好,而且推理速度快、成本低。但它需要数据标注和训练流程。
大模型的优势是冷启动能力强,不需要训练就能快速验证想法。对于早期原型、少量数据、标签经常变化的场景,大模型会更灵活。
十三、完整项目结构
最终项目可以整理成下面这样:
qwen_text_classification/
├── download_model.py
├── load_model.py
├── text_classification.py
├── batch_classification.py
├── comments.csv
└── comments_result.csv
如果后续要继续完善,还可以加入:
├── config.py
├── labels.json
├── prompt_template.txt
└── app.py
其中 labels.json 用于管理分类标签,prompt_template.txt 用于管理提示词模板,app.py 可以封装成 Web 接口。
十四、总结
本文从零开始,使用魔搭社区的 Qwen2-1.5B-Instruct 实现了一个本地文本分类实战项目。
整体流程可以总结为:
- 准备 Python 环境。
- 安装
modelscope、transformers、torch等依赖。 - 下载并加载 Qwen2-1.5B-Instruct 模型。
- 设计分类 prompt。
- 实现单条文本分类。
- 扩展到 CSV 批量分类。
- 通过标签说明、少样本示例和输出校验提升稳定性。
通过这个案例,我对大模型本地部署和实际任务落地有了更清晰的认识。大模型并不只是用来聊天,它也可以作为一个通用的语言理解模块,帮助我们快速完成分类、抽取、改写、总结等任务。
当然,本文实现的还是一个入门版本。如果要用于真实业务,还需要继续考虑推理速度、并发能力、分类准确率评估、异常兜底和数据安全等问题。
但从学习角度来看,这个项目已经完整走通了“模型下载 -> 本地加载 -> prompt 设计 -> 任务调用 -> 批量处理”的基础链路,非常适合作为大模型应用开发的第一个练手项目。
参考资料
- Qwen2-1.5B-Instruct 模型页面:https://huggingface.co/Qwen/Qwen2-1.5B-Instruct
- Hugging Face Transformers 官方文档:https://huggingface.co/docs/transformers
- ModelScope 官方文档:https://modelscope.cn/docs
- 魔搭社区:https://modelscope.cn
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)