news 2026/9/3 5:38:38

开箱即用!Qwen2.5-0.5B网页推理命名实体识别实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
开箱即用!Qwen2.5-0.5B网页推理命名实体识别实战

开箱即用!Qwen2.5-0.5B网页推理命名实体识别实战

1. 背景与目标:轻量级大模型实现高效NER任务

随着大语言模型(LLM)在自然语言理解领域的广泛应用,命名实体识别(Named Entity Recognition, NER)这一基础任务也迎来了新的技术范式。传统基于BiLSTM-CRF或BERT微调的方案虽然稳定,但在多语言支持、结构化输出和指令泛化能力上存在局限。

本文聚焦于阿里云最新发布的轻量级大模型 Qwen2.5-0.5B-Instruct,结合其强大的指令遵循与JSON结构化输出能力,在无需复杂架构设计的前提下,快速构建一个高精度中文NER系统。通过部署CSDN星图平台提供的预置镜像,实现“开箱即用”的网页端推理服务。

本实践的核心优势在于: - ✅零代码部署:基于预训练镜像一键启动服务 - ✅结构化输出原生支持:直接生成标准JSON格式结果 - ✅低资源消耗:仅需4×4090D即可完成训练与推理 - ✅多语言兼容性:未来可轻松扩展至英文等其他语种

我们将以CLUE Benchmark中的CLUENER2020数据集为基准,验证该方案在真实场景下的有效性。


2. 技术选型与环境准备

2.1 Qwen2.5 模型特性解析

Qwen2.5是通义千问系列的最新迭代版本,参数范围覆盖从0.5B72B的多个变体。本次选用的Qwen2.5-0.5B-Instruct版本专为轻量级应用场景优化,在保持较小体积的同时具备出色的指令理解能力。

相比前代Qwen2,主要改进包括:

改进维度具体提升
知识密度显著增强,尤其在编程与数学领域表现突出
指令遵循更精准地响应复杂系统提示
长文本处理支持最长 128K tokens 上下文输入
输出控制可生成最多 8K tokens 的结构化内容
多语言支持覆盖超过 29 种语言,含中、英、日、韩、阿等主流语种

📌官方ModelScope地址:https://modelscope.cn/models/Qwen/Qwen2.5-0.5B-Instruct

2.2 数据集介绍:CLUENER2020 中文命名实体识别基准

我们采用中文语言理解测评基准 CLUE 提供的CLUENER2020数据集进行实验。该数据集包含以下10类实体标签:

  • 地址(address
  • 书名(book
  • 公司(company
  • 游戏(game
  • 政府机构(government
  • 电影(movie
  • 姓名(name
  • 组织机构(organization
  • 职位(position
  • 景点(scene

原始数据样例如下:

{ "text": "浙商银行企业信贷部叶老桂博士则从另一个角度对五道门槛进行了解读。", "label": { "name": {"叶老桂": [[9, 11]]}, "company": {"浙商银行": [[0, 3]]} } }

由于原始标注包含字符位置信息,而我们的目标是让模型直接输出实体名称列表,因此需对数据格式进行转换。

2.3 数据预处理:简化标签结构便于模型学习

为适配大模型的生成式NER任务设定,我们将原始带有位置索引的数据转换为仅保留实体名称的扁平结构:

import json def trans(file_path, save_path): with open(save_path, "a", encoding="utf-8") as w: with open(file_path, "r", encoding="utf-8") as r: for line in r: line = json.loads(line) text = line['text'] label = {} for key, items in line['label'].items(): label[key] = list(items.keys()) # 仅提取实体名称 trans = { "text": text, "label": label } line = json.dumps(trans, ensure_ascii=False) w.write(line + "\n") w.flush() if __name__ == '__main__': trans("ner_data_origin/train.json", "ner_data/train.json") trans("ner_data_origin/dev.json", "ner_data/val.json")

转换后格式示例:

{ "text": "彭小军认为,国内银行现在走的是台湾的发卡模式", "label": {"address": ["台湾"], "name": ["彭小军"]} }

此格式更利于模型学习“输入句子 → 输出JSON实体”之间的映射关系。


3. 实战部署:基于预置镜像的网页推理全流程

3.1 镜像部署与服务启动

使用 CSDN 星图平台提供的Qwen2.5-0.5B-Instruct预置镜像,可省去繁琐的环境配置过程:

  1. 登录 CSDN星图算力平台
  2. 搜索并选择Qwen2.5-0.5B-Instruct镜像
  3. 分配资源:建议选择4×NVIDIA 4090D GPU
  4. 启动应用,等待初始化完成
  5. 进入「我的算力」页面,点击「网页服务」访问交互界面

此时即可在浏览器中直接与模型对话,进行初步功能测试。

3.2 构建自定义NER数据集类

为了后续微调训练,我们需要封装一个符合 PyTorch 接口规范的 Dataset 类:

# ner_dataset.py from torch.utils.data import Dataset import torch import json import numpy as np class NerDataset(Dataset): def __init__(self, data_path, tokenizer, max_source_length, max_target_length) -> None: super().__init__() self.tokenizer = tokenizer self.max_source_length = max_source_length self.max_target_length = max_target_length self.max_seq_length = self.max_source_length + self.max_target_length self.data = [] if data_path: with open(data_path, "r", encoding='utf-8') as f: for line in f: if not line or line.strip() == "": continue json_line = json.loads(line) text = json_line["text"] label = json.dumps(json_line["label"], ensure_ascii=False) self.data.append({"text": text, "label": label}) print(f"data loaded, size: {len(self.data)}") def preprocess(self, text, label): messages = [ {"role": "system", "content": "你的任务是做NER任务提取,根据用户输入提取出完整的实体信息,并以JSON格式输出。"}, {"role": "user", "content": text} ] prompt = self.tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) instruction = self.tokenizer( prompt, add_special_tokens=False, max_length=self.max_source_length, padding="max_length", pad_to_max_length=True, truncation=True ) response = self.tokenizer( label, add_special_tokens=False, max_length=self.max_target_length, padding="max_length", pad_to_max_length=True, truncation=True ) input_ids = instruction["input_ids"] + response["input_ids"] + [self.tokenizer.eos_token_id] attention_mask = instruction["attention_mask"] + response["attention_mask"] + [1] labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [self.tokenizer.eos_token_id] return input_ids, attention_mask, labels def __getitem__(self, index): item_data = self.data[index] input_ids, attention_mask, labels = self.preprocess(**item_data) return { "input_ids": torch.LongTensor(np.array(input_ids)), "attention_mask": torch.LongTensor(np.array(attention_mask)), "labels": torch.LongTensor(np.array(labels)) } def __len__(self): return len(self.data)

关键点说明: - 使用apply_chat_template自动构造对话模板 - 输入部分(instruction)用于拼接 system + user 消息 - 输出部分(response)作为模型应生成的目标 JSON - 使用-100掩码忽略输入部分的 loss 计算

3.3 全参数微调训练脚本

采用全量参数微调策略,充分发挥小模型的快速收敛特性:

# train_ner.py import torch from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter from transformers import AutoModelForCausalLM, AutoTokenizer from ner_dataset import NerDataset from tqdm import tqdm import time, sys def train_model(model, train_loader, val_loader, optimizer, device, num_epochs, model_output_dir, writer): batch_step = 0 for epoch in range(num_epochs): time1 = time.time() model.train() for index, data in enumerate(tqdm(train_loader, file=sys.stdout, desc=f"Train Epoch: {epoch}")): input_ids = data['input_ids'].to(device) attention_mask = data['attention_mask'].to(device) labels = data['labels'].to(device) optimizer.zero_grad() outputs = model(input_ids=input_ids, attention_mask=attention_mask, labels=labels) loss = outputs.loss loss.backward() optimizer.step() writer.add_scalar('Loss/train', loss.item(), batch_step) batch_step += 1 if index % 100 == 0 or index == len(train_loader) - 1: time2 = time.time() tqdm.write(f"Step {index}, Loss: {loss:.4f}, Time per step: {(time2 - time1)/(index + 1e-6):.4f}s") # Validation model.eval() val_loss = validate_model(model, device, val_loader) writer.add_scalar('Loss/val', val_loss, epoch) print(f"Validation Loss: {val_loss:.4f}, Saving model to {model_output_dir}") model.save_pretrained(model_output_dir) def validate_model(model, device, val_loader): running_loss = 0.0 with torch.no_grad(): for data in tqdm(val_loader, file=sys.stdout, desc="Validating"): input_ids = data['input_ids'].to(device) attention_mask = data['attention_mask'].to(device) labels = data['labels'].to(device) outputs = model(input_ids=input_ids, attention_mask=attention_mask, labels=labels) running_loss += outputs.loss.item() return running_loss / len(val_loader) def main(): model_name = "model/Qwen2.5-0.5B-Instruct" train_json_path = "ner_data/train.json" val_json_path = "ner_data/val.json" max_source_length = 50 max_target_length = 140 epochs = 30 batch_size = 15 lr = 1e-4 model_output_dir = "output_ner" logs_dir = "logs" device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True) training_set = NerDataset(train_json_path, tokenizer, max_source_length, max_target_length) training_loader = DataLoader(training_set, batch_size=batch_size, shuffle=True, num_workers=4) val_set = NerDataset(val_json_path, tokenizer, max_source_length, max_target_length) val_loader = DataLoader(val_set, batch_size=batch_size, shuffle=False, num_workers=4) writer = SummaryWriter(logs_dir) optimizer = torch.optim.AdamW(params=model.parameters(), lr=lr) model = model.to(device) train_model( model=model, train_loader=training_loader, val_loader=val_loader, optimizer=optimizer, device=device, num_epochs=epochs, model_output_dir=model_output_dir, writer=writer ) writer.close() if __name__ == '__main__': main()

训练过程中可通过 TensorBoard 查看损失曲线:

tensorboard --logdir=logs --bind_all

访问http://<ip>:6006即可监控训练状态。


4. 模型测试与效果验证

完成微调后,加载本地保存的模型权重进行推理测试:

# test_ner.py from transformers import AutoModelForCausalLM, AutoTokenizer import torch def main(): model_path = "output_ner" # 微调后的模型路径 tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True) device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") model.to(device) test_cases = [ "三星WCG2011北京赛区魔兽争霸3最终名次", "新华网孟买3月10日电(记者聂云)印度国防部10日说,印度政府当天批准", "证券时报记者肖渔" ] for case in test_cases: messages = [ {"role": "system", "content": "你的任务是做NER任务提取,根据用户输入提取出完整的实体信息,并以JSON格式输出。"}, {"role": "user", "content": case} ] prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) inputs = tokenizer([prompt], return_tensors="pt").to(device) outputs = model.generate( inputs.input_ids, max_new_tokens=140, top_k=1 # greedy decoding ) generated_ids = [out[len(inp):] for inp, out in zip(inputs.input_ids, outputs)] result = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] print("-" * 50) print(f"Input: {case}") print(f"Output: {result}") if __name__ == '__main__': main()

典型输出示例:

{"organization": ["三星"], "game": ["魔兽争霸3"], "address": ["北京"]} {"organization": ["新华网"], "name": ["聂云"], "government": ["印度国防部", "印度政府"]} {"company": ["证券时报"], "position": ["记者"], "name": ["肖渔"]}

可以看出,模型已成功学会从非结构化文本中抽取出多种类型的命名实体,并以标准 JSON 格式返回,满足实际工程需求。


5. 总结

本文完整展示了如何利用Qwen2.5-0.5B-Instruct预置镜像,快速搭建一套高效的中文命名实体识别系统。整个流程涵盖数据预处理、模型微调、服务部署与推理测试四大环节,充分体现了现代大模型“轻量化+结构化输出”的技术优势。

核心收获总结如下:

  1. 低成本高效率:0.5B级别模型可在消费级GPU上完成训练与部署
  2. 结构化输出天然支持:无需额外解码逻辑,直接输出JSON格式结果
  3. 指令驱动灵活定制:通过system prompt即可定义任务行为
  4. 易于集成上线:配合CSDN星图平台实现网页端即开即用

该方案特别适用于中小型企业或个人开发者在有限算力条件下快速构建智能信息抽取系统。


💡获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 17:58:01

用CLOC快速验证代码架构设计

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个CLOC原型验证工具&#xff0c;能够对比不同代码架构方案的统计指标。功能包括&#xff1a;1) 上传/选择多个设计方案 2) 自动生成对比报告&#xff08;代码量、模块分布等…

作者头像 李华
网站建设 2026/9/2 21:41:02

GITLENS功能详细介绍零基础入门指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个GITLENS功能详细介绍学习应用&#xff0c;提供交互式教程和新手友好的界面。点击项目生成按钮&#xff0c;等待项目生成完整后预览效果 今天想和大家分享一下我在学习GitL…

作者头像 李华
网站建设 2026/9/2 22:27:47

如何用AI解决PROMPT校验失败问题

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个AI辅助调试工具&#xff0c;能够自动分析PROMPT OUTPUTS FAILED VALIDATION: CHECKPOINTLOADERSIMPLE: - VALUE NOT IN LIS错误。工具应能&#xff1a;1. 解析错误信息结构…

作者头像 李华
网站建设 2026/9/2 22:27:47

AMD Ryzen处理器完全掌控指南:从入门到精通的专业调试技巧

AMD Ryzen处理器完全掌控指南&#xff1a;从入门到精通的专业调试技巧 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https:…

作者头像 李华
网站建设 2026/9/3 1:51:34

AMD Ryzen处理器深度调试实战:从入门到精通的高效调优方案

AMD Ryzen处理器深度调试实战&#xff1a;从入门到精通的高效调优方案 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https:…

作者头像 李华
网站建设 2026/9/2 23:58:37

AMD Ryzen性能优化神器:SMUDebugTool完全实战指南

AMD Ryzen性能优化神器&#xff1a;SMUDebugTool完全实战指南 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gitcod…

作者头像 李华