Transformer(LLM)+ 提示词(Prompt)实战:用 Deep Seek 做新闻归类
不训练模型,只调用大模型 API + 构建提示词,就能完成一个文本归类任务。
配套项目为”今日头条新闻 10 归类”(finance / realty / stocks / education / science / society / politics / sports / game / entertainment)。
一、和传统机器学习/深度学习的本质差异
| 传统方法(随机森林/fast Text/BERT) | 本教程(LLM) |
|---|---|
| 自己训练模型,保存 .pt / .bin / .pkl | 不训练,直接调用 Deep Seek API |
| 本地跑,吃 CPU/GPU | 调云端 API,要有 API Key |
| 自己构建特征、模型结构 | 设计提示词(Prompt),让大模型干活 |
一句话:以前是”教模型学会分类”,这一章是”写一份好指令,让已经无所不知的大模型直接分类“——这就是 零样本分类(Zero-shot) 的实战。
二、Transformer(LLM)是什么
LLM = Large Language Model(大语言模型),如 GPT、Deep Seek、文心一言。
- 在海量文本上预训练过,具有宽泛的”知识”和”理解能力”
- 你给它一段输入(提示词 Prompt),它产出回答(Completion)
- 不需要面向你的任务重新训练——靠提示词就能”指挥”它干各类活
为什么能直接归类?
它早已知道”皇马””转会”属于体育。模型在训练时见过无数”新闻+类别”的语料,你只需要告诉它作业规范,它就能套用既有知识完成归类。
三、提示词(Prompt)是什么
Prompt = 你写给大模型的”任务说明书”。
消息结构(Chat 格式)
Transformer 的对话 API 一般接收消息列表,每条消息有角色:
| 角色 | 含义 | 示例 |
| — | — | — |
| system | 系统设定(给模型立规矩) | “你是一名新闻归类审核员…” |
| user | 用户提问/作业 | “新闻标题:‘金证顾问:过山车行情说明什么’,请归类” |
| assistant | 模型的回答(对话历史) | 之前的回答 |
prompt
=
[
{
"role"
:
"system"
,
"content"
:
"你是一名新闻分类审核员,任务是将新闻标题分类到以下类别之一:..."
}
,
{
"role"
:
"user"
,
"content"
:
"新闻标题:'金证顾问:过山车行情意味着什么',请分类并说明原因。"
}
]
四、提示词工程(Prompt Engineering)核心技巧
不改代码,只靠”把话说清楚”让大模型分得更准,这是本章的精髓。
技巧 1:明确角色
你是一名新闻分类审核员
→ 给模型”人设”,它会更专业地进入状态。
技巧 2:给全类别(限制输出空间)
请将标题分类到以下类别之一:finance, realty, stocks, education, science, society, politics, sports, game, entertainment
→ 明确告诉它能选哪些答案,避免模型自创类别。
技巧 3:给关键词(每类的典型词)
- finance: 银行、信用卡、贷款、利率
- sports: 比赛、运动员、奥运
- realty: 房产、地价、楼盘
→ 提供”线索”,降低误判。
技巧 4:给示例(Few-shot)
- finance: (例: "各银行信用卡挂失费迥异")
- sports: (例: "卡佩罗:德国脚生猛的原因")
→ 示例是”基准答案样板”,模型照葫芦画瓢。
技巧 5:要求结构化输出(JSON)
返回 JSON 格式:{"category": "类别", "reason": "分类原因"}
→ 让输出可解析,程序才能处理结果。
技巧 6:处理边界情况
如果标题涉及教育机构但核心是社会贡献,优先归为 society
→ 提前给”模糊样本”的仲裁规范。
五、环境准备
5.1 安装依赖
pip
install
langchain-openai python-dotenv tenacity pandas scikit-learn
5.2 创建 .env(存密钥,不写死在代码)
DEEPSEEK_API_KEY=sk-你的密钥
base_url=
class_file=D:/你的路径/01-data/class.txt
⚠️ 为什么用 .env? API Key 是敏感信息,硬编码在 py 里上传 Git 会泄露。用 .env 加载 + 读取。
5.3 准备 Deep Seek API Key
- 去 Deep Seek 开放平台注册、充值、创建 API Key
- 或使用支持 Open AI 兼容 API 的平台(智谱 AI、阿里百炼等,改 base_url 即可)
六、完整代码 + 逐段讲解
代码总览(deepseek_classifier LLM.py)
import
os
import
json
import
pandas
as
pd
from
langchain_openai
import
ChatOpenAI
from
dotenv
import
load_dotenv
from
sklearn
.
metrics
import
classification_report
from
tenacity
import
retry
,
stop_after_attempt
,
wait_fixed
load_dotenv
(
)
class_file
=
os
.
getenv
(
"class_file"
)
id2name
=
{
i
:
line
.
strip
(
)
for
i
,
line
in
enumerate
(
open
(
class_file
,
encoding
=
"utf-8"
)
)
}
name2id
=
{
line
.
strip
(
)
:
i
for
i
,
line
in
enumerate
(
open
(
class_file
,
encoding
=
"utf-8"
)
)
}
llm
=
ChatOpenAI
(
model
=
"deepseek-chat"
,
base_url
=
os
.
getenv
(
"base_url"
)
,
api_key
=
os
.
getenv
(
"DEEPSEEK_API_KEY"
)
,
model_kwargs
=
{
"response_format"
:
{
"type"
:
"json_object"
}
}
)
@retry
(
stop
=
stop_after_attempt
(
3
)
,
wait
=
wait_fixed
(
2
)
)
def
invoke_llm
(
prompt
)
:
"""调用 LLM,失败自动重试 3 次,每次间隔 2 秒"""
return
llm
.
invoke
(
prompt
)
def
read_data
(
file_path
)
:
"""读取 tab 分隔的新闻标题和标签"""
df
=
pd
.
read_csv
(
file_path
,
sep
=
'\t'
,
header
=
None
,
names
=
[
'title'
,
'label'
]
,
encoding
=
'utf-8'
)
return
df
[
'title'
]
.
tolist
(
)
,
df
[
'label'
]
.
tolist
(
)
def
classify_news
(
title
:
str
)
-
>
dict
:
"""将新闻标题分类到指定类别,返回 {category, reason}"""
prompt
=
[
{
"role"
:
"system"
,
"content"
:
"""
你是一名新闻分类审核员,任务是将新闻标题分类到以下类别之一:
finance, realty, stocks, education, science, society, politics, sports, game, entertainment。
请根据标题内容和以下关键词与示例,匹配最相关的类别。如果标题涉及教育机构但核心是社会贡献,优先归为 society。
返回 JSON 格式:{"category": "类别", "reason": "分类原因"}
类别关键词与示例:
- finance: 银行、信用卡、贷款、利率 (例: "各银行信用卡挂失费迥异")
- realty: 房产、地价、楼盘 (例: "东5环海棠公社230平准现房")
- stocks: 股市、股指、期货 (例: "金证顾问:过山车行情意味着什么")
- education: 学校、考试、招生 (例: "中华女子学院仅1专业招男生")
- science: 技术、网站、宇航 (例: "“手机钱包”亮相科博会")
- society: 社会事件、犯罪、公益 (例: "82岁老太为学生做饭扫地44年")
- politics: 政策、国际关系 (例: "查韦斯称愿为俄罗斯提供空军基地")
- sports: 比赛、运动员、奥运 (例: "卡佩罗:德国脚生猛的原因")
- game: 电子游戏、网游、电竞 (例: "《赤壁OL》攻城战硝烟又起")
- entertainment: 明星、影视、综艺 (例: "冯德伦徐若瑄隔空传情")
"""
}
,
{
"role"
:
"user"
,
"content"
:
f"新闻标题:'
{
title
}
',请分类并说明原因。"
}
]
response
=
invoke_llm
(
prompt
)
result
=
json
.
loads
(
response
.
content
)
return
{
"category"
:
result
.
get
(
"category"
,
"society"
)
,
"reason"
:
result
.
get
(
"reason"
,
"未明确分类,归为社会类别"
)
}
if
__name__
==
'__main__'
:
file_path
=
"D:/你的路径/01-data/dev2.txt"
titles
,
true_labels
=
read_data
(
file_path
)
pred_labels
=
[
]
results
=
[
]
for
title
in
titles
:
result
=
classify_news
(
title
)
category
=
result
[
"category"
]
pred_label
=
name2id
.
get
(
category
,
5
)
pred_labels
.
append
(
pred_label
)
results
.
append
(
{
"title"
:
title
,
"category"
:
category
,
"reason"
:
result
[
"reason"
]
}
)
for
r
in
results
:
print
(
r
)
print
(
"评估指标:"
)
report
=
classification_report
(
true_labels
,
pred_labels
)
print
(
report
)
七、代码逐段深度解析
① 强制 JSON 输出
强制大模型返回 JSON。否则它会输出一大段”……因为……”,程序没法解析。加了这行,它只会返回 {"category": "...", "reason": "..."}。
② 失败自动重试
失败自动重试。API 调用可能因网络/限流失败,重试 3 次、每次等 2 秒,提升稳定性。
③ messages 列表 = 消息对话
- system:给模型立规矩(你是谁 + 作业 + 规范 + 输出格式)
- user:具体要分类的标题
④ 解析 JSON
Transformer 返回的是 JSON 字符串,用 json 库解析成 Python 字典,才能取 category / reason。
⑤ 类别转数字标签
Transformer 返回的是类别英文名(如 “sports”),要转成数字标签(如 7)才能和真实标签对比。映射的第二个参数是默认值(找不到就给 5=society)。
八、运行链路
1. 配置 .env(Key + base_url + class_file)
2. python deepseek_classifierLLM.py
3. 程序逐条调用 DeepSeek API 分类
4. 输出每条结果 + 整体评估报告
九、常见问题(FAQ)
Q 1:模块找不到
→ 检查依赖是否装全。
Q 2:API 报 401 / Invalid API Key
→ .env 里的 Key 失效了,去 Deep Seek 平台重新创建,注意 .env 文件要放在运行目录下。
Q 3:返回结果解析失败(json.loads 报错)
→ Transformer 没按 JSON 返回。检查 response_format 是否设定,或提示词里是否明确”返回 JSON 格式”。
Q 4:归类很慢
→ LLM 是逐条调用,每条要走网络往返。小数据(如 dev 2.txt 5条)验证,大数据建议并发或只测子集。
Q 5:依赖版本冲突
→ langchain-openai 迭代问题,升级即可。
Q 6:要不要 API Key 才能跑?
→ 必须。没有 Key 无法调用云端 Transformer。可用 Deep Seek 或智谱/百炼等兼容平台。
十、效果与对比
| 模型 | 精准率 | 特点 |
|---|---|---|
| 随机森林 | ~81% | 传统机器学习,便宜 |
| fast Text | ~92% | 轻量快速 |
| BERT | 95%+ | 深度学习,要 GPU |
| LLM + 提示词 | 看
ID:1216 |