用Qwen3-0.6B做的第一个AI项目——新闻分类器上线
1. 项目背景与目标
最近在尝试把大模型真正用起来,而不是停留在“调API、跑demo”的阶段。于是决定动手做一个完整的AI小项目:基于Qwen3-0.6B搭建一个新闻自动分类系统,并把它部署上线,实现从输入文本到输出类别的完整推理流程。
选择这个任务有几个原因:
- 文本分类是NLP中最基础也最实用的任务之一,广泛应用于内容推荐、信息聚合、舆情监控等场景。
- Qwen3-0.6B作为通义千问系列中最小的密集模型,参数量仅0.6B,适合在资源有限的环境下运行,比如本地服务器或边缘设备。
- 我想验证一下:像Qwen3这样的Decoder-only大语言模型,在不需要微调的情况下,能否通过提示工程(Prompt Engineering)直接完成结构化分类任务?
最终目标很明确:不训练、不微调,仅靠预训练模型+合理设计的Prompt,让Qwen3-0.6B准确判断一篇新闻属于“世界”、“体育”、“商业”还是“科技”四大类别。
2. 环境准备与模型调用
2.1 启动镜像并进入Jupyter
我使用的是CSDN提供的Qwen3-0.6B镜像环境,一键启动后可以直接访问Jupyter Notebook进行开发调试。整个过程非常简单:
- 在CSDN星图平台搜索
Qwen3-0.6B镜像 - 点击“启动实例”,等待几分钟即可获得GPU算力支持的交互式开发环境
- 打开浏览器中的Jupyter链接,开始编码
该镜像已经预装了LangChain、Transformers、vLLM等常用库,省去了繁琐的依赖配置。
2.2 使用LangChain调用Qwen3-0.6B
调用方式和OpenAI风格完全兼容,只需要指定正确的base_url和model name即可。以下是核心代码:
from langchain_openai import ChatOpenAI import os chat_model = ChatOpenAI( model="Qwen-0.6B", temperature=0.5, base_url="https://gpu-pod694e6fd3bffbd265df09695a-8000.web.gpu.csdn.net/v1", # 实际地址以当前Jupyter服务为准 api_key="EMPTY", # 因为不是OpenAI官方API,所以key为空 extra_body={ "enable_thinking": True, "return_reasoning": True, }, streaming=True, )注意点:
base_url中的IP地址需要根据你实际启动的Jupyter服务动态替换- 端口号固定为
8000extra_body参数用于开启“思维链”(Thinking Chain),可以让模型先输出推理过程再给出答案,提升可解释性
测试一下是否能正常响应:
response = chat_model.invoke("你是谁?") print(response.content)输出结果示例:
我是通义千问Qwen3-0.6B,阿里巴巴集团研发的新一代大语言模型,擅长中文理解和生成任务。说明模型已成功加载,可以进入下一步——构建分类逻辑。
3. 分类逻辑设计:Prompt工程实战
既然不打算做微调,那就要靠高质量的Prompt设计来引导模型完成分类任务。我的思路是:把分类问题转化为一道“选择题”。
3.1 构造结构化Prompt模板
为了让模型更容易理解任务,我设计了一个清晰的选择题格式:
请阅读以下新闻内容,并从下列选项中选出最合适的分类: 新闻内容: {news_content} 问题:这篇新闻最可能属于哪个类别? A. 世界 B. 体育 C. 商业 D. 科技 请按如下格式回答: <think> [你的思考过程] </think> 答案:A / B / C / D这种设计有三个好处:
- 降低歧义:明确限定四个选项,避免模型自由发挥导致类别错乱
- 增强可解释性:要求模型先输出思考过程,便于后期分析错误原因
- 结构化输出:答案部分只需提取最后一个字母,方便程序自动解析
3.2 示例调用与结果分析
我们来测试一段真实的财经新闻:
news = """ 苹果公司宣布将在下个月发布新款iPhone,搭载自研A18芯片,支持更强大的AI功能。分析师预计这款手机将推动公司第三季度营收增长。 """ prompt = f"""请阅读以下新闻内容,并从下列选项中选出最合适的分类: 新闻内容: {news} 问题:这篇新闻最可能属于哪个类别? A. 世界 B. 体育 C. 商业 D. 科技 请按如下格式回答: <think> [你的思考过程] </think> 答案:"""调用模型:
result = chat_model.invoke(prompt) print(result.content)输出结果:
<think> 这段新闻提到了苹果公司发布新款iPhone、A18芯片、AI功能以及对公司营收的影响。这些关键词如“苹果公司”、“营收增长”、“新机型发布”都指向企业行为和市场影响,虽然涉及技术,但重点在于产品发布对商业的影响。因此更适合归类为商业类新闻。 </think> 答案:C✅ 正确!模型不仅给出了正确答案,还展示了合理的推理路径。
再试一个科技类的例子:
研究人员开发出新型量子计算算法,在特定任务上比经典计算机快百万倍。这一突破有望加速药物研发进程。模型输出:
<think> 新闻提到“量子计算算法”、“比经典计算机快百万倍”、“加速药物研发”,这些都是前沿科技领域的进展,尤其是量子计算属于典型的高科技主题。尽管涉及应用层面,但核心是技术创新。 </think> 答案:D✅ 再次正确识别为“科技”。
4. 上线部署:打造简易Web接口
现在模型能正确分类了,接下来我要把它变成一个可用的服务。目标是:任何人都可以通过网页或API提交新闻,得到分类结果。
4.1 技术选型
- 后端框架:FastAPI(轻量、高性能、自带Swagger)
- 前端页面:HTML + JavaScript(极简交互)
- 部署方式:Docker容器化运行
4.2 核心API代码
from fastapi import FastAPI, Request from fastapi.templating import Jinja2Templates from pydantic import BaseModel import os app = FastAPI() templates = Jinja2Templates(directory="templates") # 复用之前的ChatModel chat_model = ChatOpenAI( model="Qwen-0.6B", temperature=0.3, base_url="https://gpu-pod694e6fd3bffbd265df09695a-8000.web.gpu.csdn.net/v1", api_key="EMPTY", extra_body={"enable_thinking": True}, ) class NewsRequest(BaseModel): content: str @app.get("/") def home(request: Request): return templates.TemplateResponse("index.html", {"request": request}) @app.post("/classify") def classify_news(req: NewsRequest): prompt = f"""请阅读以下新闻内容,并从下列选项中选出最合适的分类: 新闻内容: {req.content} 问题:这篇新闻最可能属于哪个类别? A. 世界 B. 体育 C. 商业 D. 科技 请按如下格式回答: <think> [你的思考过程] </think> 答案:""" response = chat_model.invoke(prompt) full_output = response.content.strip() # 提取答案(最后一行) lines = full_output.split('\n') answer_line = [l for l in lines if l.startswith("答案:")] category_map = {"A": "世界", "B": "体育", "C": "商业", "D": "科技"} if answer_line: raw_answer = answer_line[-1].replace("答案:", "").strip() category = category_map.get(raw_answer.upper(), "未知") else: category = "无法判断" return { "input": req.content, "category": category, "reasoning": full_output }4.3 页面展示(index.html)
<!DOCTYPE html> <html> <head> <title>Qwen3新闻分类器</title> <style> body { font-family: sans-serif; margin: 40px; } textarea { width: 100%; height: 150px; margin: 10px 0; } button { padding: 10px 20px; font-size: 16px; } #result { margin-top: 20px; padding: 15px; background: #f0f0f0; border-radius: 5px; } </style> </head> <body> <h1>📝 Qwen3-0.6B 新闻自动分类器</h1> <p>输入一段新闻内容,看看AI如何分类:</p> <textarea id="newsInput" placeholder="请输入新闻文本..."></textarea><br/> <button onclick="classify()">分类</button> <div id="result"></div> <script> async function classify() { const text = document.getElementById('newsInput').value; const res = await fetch('/classify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: text }) }); const data = await res.json(); document.getElementById('result').innerHTML = ` <strong>预测类别:</strong>${data.category}<br/> <details><summary>点击查看推理过程</summary> <pre>${data.reasoning}</pre></details> `; } </script> </body> </html>4.4 运行与访问
启动命令:
uvicorn app:app --host 0.0.0.0 --port 8000打开浏览器访问http://localhost:8000,就能看到一个简洁的分类界面,输入新闻即可实时获得结果。
5. 性能优化建议
虽然Qwen3-0.6B可以在普通GPU上运行,但在实际部署中仍有一些性能瓶颈需要注意:
| 优化方向 | 建议 |
|---|---|
| 推理速度 | 使用vLLM替代默认HuggingFace推理,吞吐量可提升2倍以上 |
| 并发处理 | 开启streaming=True并配合异步接口,提升用户体验 |
| 缓存机制 | 对高频出现的相似新闻做语义去重+缓存结果,减少重复推理 |
| Prompt精简 | 若对可解释性要求不高,可关闭thinking模式,加快响应 |
例如,使用vLLM部署后的RPS(每秒请求处理数)对比:
| 模型 | 推理引擎 | RPS |
|---|---|---|
| Qwen3-0.6B | HuggingFace | 13.2 |
| Qwen3-0.6B | vLLM | 27.1 |
几乎翻倍!
6. 总结:小模型也能干大事
通过这次实践,我深刻体会到:即使是0.6B这样“小型”的大模型,只要用对方法,也能胜任专业级NLP任务。
关键收获:
- Prompt设计比微调更重要:对于简单分类任务,精心设计的Prompt完全可以替代SFT微调
- 思维链显著提升准确性:让模型“先想后答”,不仅能提高正确率,还能增强可信度
- 端到端落地可行:从模型调用到Web服务,全流程可在一天内完成,适合快速验证想法
- 成本可控:Qwen3-0.6B可在消费级显卡运行,适合中小企业和个人开发者
当然也有局限:
- 对超长文本(>2048 token)支持较弱
- 多轮对话场景下需额外管理上下文
- 极端冷门领域知识可能存在幻觉
但总体来说,这是我用Qwen3做的第一个真正“上线”的AI项目,虽然简单,却让我看到了轻量化大模型在真实业务中的巨大潜力。
如果你也在寻找一个入门级的大模型实战项目,不妨试试用Qwen3-0.6B做个分类器吧,你会惊讶于它的表现。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。