Files
test2/05-LLM/03_api_deepseek_v3.py

113 lines
4.4 KiB
Python
Raw Permalink Normal View History

2026-02-26 16:49:19 +08:00
# 先安装: pip install openai
import os
import dotenv
from sklearn.metrics import accuracy_score
from tenacity import retry, stop_after_attempt, wait_fixed
import pandas as pd
import json
from langchain_openai import ChatOpenAI
dotenv.load_dotenv()
# 获取环境变量
BASE_URL = os.getenv("BASE_URL")
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEV2FILE = os.getenv("DEV2FILE")
CLASS_FILE = os.getenv("CLASS_FILE")
# 提前定义提示词
SYSTEM_PROMPT = """
你是一个专门用于中文新闻标题分类的助手能够将给定的新闻标题准确地分类到以下十个预定义的类别之一
finance财经realty房产stocks股市education教育science科技society社会politics政治sports体育game游戏和entertainment娱乐
请根据标题内容和以下关键词与示例匹配最相关的类别如果标题涉及教育机构但核心是社会贡献优先归为 society
返回 JSON 格式{"category": "类别", "reason": "分类原因"}
例如
- 输入同步A股首秀港股缩量回调应返回{"category": "stocks", "reason": "股市"}
- 输入布拉特放球员一条生路吧 FIFA能消化俱乐部的攻击应返回sports{"category": "sports", "reason": "体育"}
请注意只从上述提供的十个类别中选择一个最合适的进行返回如果标题与多个类别相关请选择最相关的一个请直接返回类别名称无需额外解释!!!
"""
# 加载配置和类别映射
id2name = {i: line.strip() for i, line in enumerate(open(CLASS_FILE, encoding="utf-8"))}
# name2id{标签:索引}
name2id = {v: k for k, v in id2name.items()}
# 创建 LLM 对象
llm = ChatOpenAI(
base_url=BASE_URL,
api_key=DEEPSEEK_API_KEY,
model="deepseek-chat",
model_kwargs={"response_format": {"type": "json_object"}}
)
# 定义带重试机制的 LLM 调用函数
@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
def invoke_llm(prompt):
"""调用 LLM
# stop_after_attempt若失败则重试最多3次
# wait_fixed每次间隔2秒"""
return llm.invoke(prompt)
# 调用模型进行新闻标题分类获取响应
def get_deepseek_res(title: str) -> dict:
"""将新闻标题分类到指定类别,返回分类结果"""
# 定义提示词,包含类别说明和示例
prompt = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": f"新闻标题:'{title}',请分类并说明原因。"}
]
# print(prompt) # [{"role":'system',"content":提示词},{"role":'user',"content":''体验2D巅峰 倚天屠龙记十大创新概览''}]
# 调用 LLM 获取分类结果
response = invoke_llm(prompt)
result = json.loads(response.content)
# 返回分类结果,包含类别和原因
return {
"category": result.get("category", "society"), # 默认 社会society
"reason": result.get("reason", "未明确分类,归为社会类别")
}
# 分类并进行评估
def evaluate_classification():
"""对新闻标题分类进行评估"""
# 读取 tab 分隔的新闻标题和标签数据
df = pd.read_csv(DEV2FILE, sep='\t', header=None, names=['title', 'label'], encoding='utf-8')
# 拆包
titles = df['title'].tolist()
labels = df['label'].tolist()
print("titles-->", titles)
print("labels-->", labels)
# 如果多的话,只测试前 2 个
# titles = titles[:2]
# labels = labels[:2]
# 定义列表用于存储预测结果
pred_labels = []
# 遍历所有的标题,依次调用get_deepseek_res
for title in titles:
# 调用大模型获取结果
category_dict = get_deepseek_res(title)
print('category_dict-->', category_dict) # {'category': 'game', 'reason': '游戏'}...{'category': 'society', 'reason': '社会'}
# 获取预测类别,如果没有默认设置,则默认为 society社会
pred_category = category_dict.get("category", "society")
print('pred_category-->', pred_category) # game...society
# 添加到预测结果列表中 注意: name2id格式{标签:索引}
pred_labels.append(name2id[pred_category])
# 最终打印或者返回预测结果
print('pred_labels-->', pred_labels) # [8,5]
# 准确率
print('accuracy_score-->', accuracy_score(pred_labels, labels))
# 测试
if __name__ == '__main__':
# 测试评估
evaluate_classification()