前言

最近在学习大模型本地部署和实际应用开发时,我选择从一个相对容易落地的任务入手:文本分类。

相比聊天机器人、智能问答、知识库检索这些更复杂的场景,文本分类的目标更明确,也更适合用来练习大模型的完整调用流程。比如我们可以让模型判断一段评论是正向还是负向,也可以让模型识别用户问题属于“账号问题”“订单问题”“售后问题”还是“其他问题”。

本文会从零开始,基于魔搭社区的 Qwen2-1.5B-Instruct 模型,实现一个可以在本地运行的文本分类小项目。文章内容包括环境准备、模型下载、模型加载、提示词设计、单条分类、批量分类以及常见问题总结。

这篇文章更偏向实战记录,适合刚开始接触大模型本地部署、ModelScope 和 Transformers 的同学。

一、为什么选择 Qwen2-1.5B-Instruct?

在本地跑大模型时,模型大小非常重要。参数越大的模型通常效果越好,但对显存、内存和推理速度的要求也越高。

我选择 Qwen2-1.5B-Instruct,主要有几个原因:

  1. 模型体积适中,适合入门实战。
  2. 是指令微调模型,能较好理解分类任务的提示词。
  3. 支持中文场景,适合做中文文本分类。
  4. 可以通过魔搭社区下载,在国内环境下使用更方便。
  5. 代码调用方式和更大规模的 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 推理会慢一些,适合学习和调试,不太适合大量数据批处理。

五、文本分类思路

传统文本分类通常需要准备训练数据,然后训练一个分类模型。大模型的优势是:即使没有专门训练,也可以通过提示词完成零样本或少样本文本分类。

本文采用的基本思路是:

  1. 预先定义分类标签。
  2. 把待分类文本和标签说明写进 prompt。
  3. 要求模型只输出指定标签。
  4. 对模型输出做清洗和校验。

例如我们定义一个评论情感分类任务:

标签:
正向
负向
中性

输入文本:

这家店的发货速度很快,客服态度也不错,下次还会再买。

模型应该输出:

正向

六、实现单条文本分类

新建 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. 显存不够怎么办?

可以尝试:

  1. 换用 CPU 运行。
  2. 使用更小模型。
  3. 使用量化版本模型。
  4. 减小 max_new_tokens
  5. 关闭其他占用显存的程序。

3. 模型输出不稳定怎么办?

可以从三个方向优化:

  1. 把分类规则写清楚。
  2. 添加示例。
  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 实现了一个本地文本分类实战项目。

整体流程可以总结为:

  1. 准备 Python 环境。
  2. 安装 modelscopetransformerstorch 等依赖。
  3. 下载并加载 Qwen2-1.5B-Instruct 模型。
  4. 设计分类 prompt。
  5. 实现单条文本分类。
  6. 扩展到 CSV 批量分类。
  7. 通过标签说明、少样本示例和输出校验提升稳定性。

通过这个案例,我对大模型本地部署和实际任务落地有了更清晰的认识。大模型并不只是用来聊天,它也可以作为一个通用的语言理解模块,帮助我们快速完成分类、抽取、改写、总结等任务。

当然,本文实现的还是一个入门版本。如果要用于真实业务,还需要继续考虑推理速度、并发能力、分类准确率评估、异常兜底和数据安全等问题。

但从学习角度来看,这个项目已经完整走通了“模型下载 -> 本地加载 -> prompt 设计 -> 任务调用 -> 批量处理”的基础链路,非常适合作为大模型应用开发的第一个练手项目。

参考资料

  1. Qwen2-1.5B-Instruct 模型页面:https://huggingface.co/Qwen/Qwen2-1.5B-Instruct
  2. Hugging Face Transformers 官方文档:https://huggingface.co/docs/transformers
  3. ModelScope 官方文档:https://modelscope.cn/docs
  4. 魔搭社区:https://modelscope.cn
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐