跳到主要内容

Unsloth快速上手指南

课程说明:

  体验课时间有限,若想深度学习大模型技术,欢迎大家报名由我主讲的《2025大模型Agent智能体开发实战》(秋招冲刺班)

b3a518f1a9821408a79363cf694f5172

《2025大模型Agent智能体开发实战》(秋招冲刺班) 为【100+小时】体系大课,总共20大模块精讲精析,零基础直达大模型企业级应用!

a55d48e952ed59f8d93e050594843bc

部分项目成果演示

from IPython.display import Video
  • MateGen项目演示
Video("https://ml2022.oss-cn-hangzhou.aliyuncs.com/MG%E6%BC%94%E7%A4%BA%E8%A7%86%E9%A2%91.mp4", width=800, height=400)
  • 智能客服项目演示
Video("https://ml2022.oss-cn-hangzhou.aliyuncs.com/%E6%99%BA%E8%83%BD%E5%AE%A2%E6%9C%8D%E6%A1%88%E4%BE%8B%E8%A7%86%E9%A2%91.mp4", width=800, height=400)
  • Dify项目演示
Video("https://ml2022.oss-cn-hangzhou.aliyuncs.com/2f1b47f42c65fd59e8d3a83e6cb9f13b_raw.mp4", width=800, height=400)
  • LangChain&LangGraph搭建Multi-Agnet
Video("https://ml2022.oss-cn-hangzhou.aliyuncs.com/%E5%8F%AF%E8%A7%86%E5%8C%96%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90Multi-Agent%E6%95%88%E6%9E%9C%E6%BC%94%E7%A4%BA%E6%95%88%E6%9E%9C.mp4", width=800, height=400)

此外,若是对大模型底层原理感兴趣,也欢迎报名由我和菜菜老师共同主讲的《2025大模型原理与实战课程》(秋招冲刺班)

aaf3bafd8ff8120d5fb079f092268961

两门大模型课程秋招冲刺班预售进行中,直播间可享超值特价+全套学习福利,合购还有更多优惠哦~详细信息扫码添加助教,回复“大模型”,即可领取课程大纲&查看课程详情👇

image-20250819203708000 bff56b8959b8a17d9d0a6d1e72f5d9b8 c287fe1e94de372b44f3031ff8b86bd8

GPT-OSS高效微调实战

Part 3.Unsloth快速上手指南

  在进行了充足的准备工作后,接下来正式开始进行微调。

七、Unsloth基本使用方法介绍

  Unsloth是一个集模型调用和高效微调为一体的框架,在开始进行模型微调前,我们可以先尝试借助Unsloth进行模型调用。需要注意的是,Unsloth的使用难度远比一般的微调框架简单,在Jupyter中即可完成模型微调,且微调结束后还可以直接进行模型调用,并支持在Jupyter中进行模型权重合并与导出,非常便捷。

import os
os.environ["CUDA_VISIBLE_DEVICES"] = "1"

由于当前实验环境是多卡环境,而动态量化模型只支持单卡运行,因此这里先设置接下来运行的GPU编号。

1.模型导入与调用流程

  首先进行模型导入:

from unsloth import FastLanguageModel
import torch
max_seq_length = 8192
dtype = None
load_in_4bit = False
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "./gpt-oss-20b",
max_seq_length = max_seq_length,
dtype = dtype,
load_in_4bit = load_in_4bit,
)

导入完成后即可查看模型基本情况,包括模型结构和分词器信息等:

model

需要注意,此时模型还没有LoRA层。

tokenizer
  • 显存占用

此时模型约占用显存16G:

gpu_stats = torch.cuda.get_device_properties(0)
start_gpu_memory = round(torch.cuda.max_memory_reserved() / 1024 / 1024 / 1024, 3)
max_memory = round(gpu_stats.total_memory / 1024 / 1024 / 1024, 3)
print(f"GPU = {gpu_stats.name}. Max memory = {max_memory} GB.")
print(f"{start_gpu_memory} GB of memory reserved.")
  • 开启对话

  然后即可尝试进行对话。借助Unsloth进行模型调用总共需要两个步骤,其一是借助apply_chat_template进行分词同时输入对话相关参数,其二则是借助generate进行文本创建。一次基本对话流程如下所示:

messages = [
{"role" : "user", "content" : "你好,好久不见!"}
]
text = tokenizer.apply_chat_template(
messages,
tokenize = False,
add_generation_prompt = True,
return_tensors = "pt",
reasoning_effort = "low",
)

此时text就是加载了gpt-oss内置提示词模板之后的字符串。据此也能看出gpt-oss内置提示词模板的特殊字符:

text

然后进行分词:

inputs = tokenizer(text, return_tensors="pt").to("cuda")
inputs

并进行推理:

outputs = model.generate(
input_ids=inputs.input_ids,
attention_mask=inputs.attention_mask,
max_new_tokens=max_seq_length,
use_cache=True,
)

最终获得模型输出结果:

outputs
response = tokenizer.batch_decode(outputs)
response
response[0]

需要注意的是,这其实是一种非常底层的打印模型输入和输出信息的方法,这种字符格式(同时包含模型输入和输出)也是Unsloth在进行高效微调过程中需要用到的数据集基本格式。

  此外也可通过如下方式生成带有长思考过程的结果:

text = tokenizer.apply_chat_template(
messages,
tokenize = False,
add_generation_prompt = True,
return_tensors = "pt",
reasoning_effort = "high",
)

inputs = tokenizer(text, return_tensors="pt").to("cuda")

outputs = model.generate(
input_ids=inputs.input_ids,
attention_mask=inputs.attention_mask,
max_new_tokens=max_seq_length,
use_cache=True,
)

response = tokenizer.batch_decode(outputs)
response
response[0]

同时如果存在系统提示词,则实际对话效果如下:

messages = [
{"role" : "system", "content" : "你是一名助人为乐的助手,名叫小明。"},
{"role" : "user", "content" : "你好,好久不见!请问你叫什么名字?"}
]
text = tokenizer.apply_chat_template(
messages,
tokenize = False,
add_generation_prompt = True,
reasoning_effort = "high",
)

inputs = tokenizer(text, return_tensors="pt").to("cuda")

outputs = model.generate(
input_ids=inputs.input_ids,
attention_mask=inputs.attention_mask,
max_new_tokens=max_seq_length,
use_cache=True,
)

response = tokenizer.batch_decode(outputs)
response[0]

能够看到,此时问答数据中就包含了系统消息。同样该格式的数据也可以直接用于Unsloth的指令微调。也就是说,如果我们希望提高模型多轮对话或者指令跟随能力,就可以创建大量类似这种数据集进行微调。在实际微调过程中,模型会主动学习最后一个assistant之后的内容,从而学会指令跟随和多轮对话能力。

  最后,我们尝试让模型调用外部函数,即创建一条function call message。

import requests, json
def get_weather(loc):
"""
查询即时天气函数
:param loc: 必要参数,字符串类型,用于表示查询天气的具体城市名称,\
注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则loc参数需要输入'Beijing';
:return:OpenWeather API查询即时天气的结果,具体URL请求地址为:https://api.openweathermap.org/data/2.5/weather\
返回结果对象类型为解析之后的JSON格式对象,并用字符串形式进行表示,其中包含了全部重要的天气信息
"""
# Step 1.构建请求
url = "https://api.openweathermap.org/data/2.5/weather"

# Step 2.设置查询参数
params = {
"q": loc,
"appid": "YOUR_API_KEY", # 输入API key
"units": "metric", # 使用摄氏度而不是华氏度
"lang":"zh_cn" # 输出语言为简体中文
}

# Step 3.发送GET请求
response = requests.get(url, params=params)

# Step 4.解析响应
data = response.json()
return json.dumps(data)
tools = [
{
"type": "function",
"function":{
'name': 'get_weather',
'description': '查询即时天气函数,根据输入的城市名称,查询对应城市的实时天气,一次只能输入一个城市名称',
'parameters': {
'type': 'object',
'properties': {
'loc': {
'description': "城市名称,注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则loc参数需要输入'Beijing'",
'type': 'string'
}
},
'required': ['loc']
}
}
}
]
messages = [
{"role" : "system", "content" : "你是一名助人为乐的天气查询助手,当用户询问天气信息时,请调用get_weather函数进行天气查询。"},
{"role" : "user", "content" : "你好,请帮我查询下北京今天天气如何?"}
]
text = tokenizer.apply_chat_template(
messages,
tools = tools,
tokenize = False,
add_generation_prompt = True,
reasoning_effort = "high",
)

inputs = tokenizer(text, return_tensors="pt").to("cuda")

outputs = model.generate(
input_ids=inputs.input_ids,
attention_mask=inputs.attention_mask,
max_new_tokens=max_seq_length,
use_cache=True,
)

response = tokenizer.batch_decode(outputs)
response[0]

能够看到,此时模型就会创建一条同时带有指令、思考、外部函数的function call message。

而更进一步的,我们也可以测试模型的多个外部函数并联调用效果:

messages = [
{"role" : "system", "content" : "你是一名助人为乐的天气查询助手,当用户询问天气信息时,请调用get_weather函数进行天气查询。查询多个地点时,需要单独创建调用工具的消息。"},
{"role" : "user", "content" : "你好,请帮我查询下南昌和天津今天天气如何?"}
]
text = tokenizer.apply_chat_template(
messages,
tools = tools,
tokenize = False,
add_generation_prompt = True,
reasoning_effort = "high",
)

inputs = tokenizer(text, return_tensors="pt").to("cuda")

outputs = model.generate(
input_ids=inputs.input_ids,
attention_mask=inputs.attention_mask,
max_new_tokens=max_seq_length,
use_cache=True,
)

response = tokenizer.batch_decode(outputs)
response[0]

能发现,此时模型同时发起了两条Function call message。不过同时模型也返回了正在调用信息过程中的给用户返回的信息。

然后继续测试当模型接收到外部函数返回消息时候,模型返回内容。

messages
messages.append({
"role": "assistant",
"content": "<think>\n我将调用 get_weather 函数来查询天气。\n</think>\n",
"tool_calls": [
{
"name": "get_weather",
"arguments": {
"location": "北京"
}
},
{
"name": "get_weather",
"arguments": {
"location": "杭州"
}
}
]
})
messages.append({
"role": "tool",
"content": json.dumps({
"location": "北京",
"weather": "晴,最高气温26℃"
})
})
messages.append({
"role": "tool",
"content": json.dumps({
"location": "杭州",
"weather": "多云转小雨,最高气温23℃"
})
})
messages
text = tokenizer.apply_chat_template(
messages,
tools = tools,
tokenize = False,
add_generation_prompt = True,
reasoning_effort = "high",
)

inputs = tokenizer(text, return_tensors="pt").to("cuda")

outputs = model.generate(
input_ids=inputs.input_ids,
attention_mask=inputs.attention_mask,
max_new_tokens=max_seq_length,
use_cache=True,
)

response = tokenizer.batch_decode(outputs)
response[0]

而这就是一条能够进行工具并联微调训练的数据集。

  • 多工具串联调用
tools = [
{
"type": "function",
"function":{
'name': 'get_weather',
'description': '查询即时天气函数,根据输入的城市名称,查询对应城市的实时天气,一次只能输入一个城市名称',
'parameters': {
'type': 'object',
'properties': {
'loc': {
'description': "城市名称,注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则loc参数需要输入'Beijing'",
'type': 'string'
}
},
'required': ['loc']
}
}
},
{
"type": "function",
"function":{
'name': 'write_file',
'description': '将指定内容写入本地文件。',
'parameters': {
'type': 'object',
'properties': {
'content': {
'description': "用于表示需要写入文档的具体内容。",
'type': 'string'
}
},
'required': ['content']
}
}
}
]
messages = [
{"role" : "system", "content" : "你是一名助人为乐的天气查询助手,当用户询问天气信息时,请调用get_weather函数进行天气查询。当用户需要将内容写入本地文档时,请调用write_file函数进行操作。注意需要等待工具返回结果才能确认是否调用成功。"},
{"role" : "user", "content" : "你好,请帮我查询下北京和杭州两地今天天气,并将其写入本地文档。"}
]
messages.append({
"role": "assistant",
"content": "<think>\n我将调用 get_weather 函数来查询天气。\n</think>\n",
"tool_calls": [
{
"name": "get_weather",
"arguments": {
"location": "北京"
}
},
{
"name": "get_weather",
"arguments": {
"location": "杭州"
}
}
]
})
messages.append({
"role": "tool",
"content": json.dumps({
"location": "北京",
"weather": "晴,最高气温26℃"
})
})
messages.append({
"role": "tool",
"content": json.dumps({
"location": "杭州",
"weather": "多云转小雨,最高气温23℃"
})
})
text = tokenizer.apply_chat_template(
messages,
tools = tools,
tokenize = False,
add_generation_prompt = True,
reasoning_effort = "low",
)

inputs = tokenizer(text, return_tensors="pt").to("cuda")

outputs = model.generate(
input_ids=inputs.input_ids,
attention_mask=inputs.attention_mask,
max_new_tokens=max_seq_length,
use_cache=True,
)

response = tokenizer.batch_decode(outputs)
response[0]

至此,我们就完整查看了个模型各种调用外部工具的形式。

2. Unsloth高层对话API

  当然,除了使用上述底层API进行对话外,Unsloth还提供了更加便捷的流式输出模型对话信息的函数,基本对话效果如下:

from transformers import TextStreamer
messages = [
{"role" : "user", "content" : "你好,好久不见!"}
]
text = tokenizer.apply_chat_template(
messages,
tokenize = False,
add_generation_prompt = True,
reasoning_effort = "low",
)

_ = model.generate(
**tokenizer(text, return_tensors = "pt").to("cuda"),
max_new_tokens = 256,
streamer = TextStreamer(tokenizer, skip_prompt = True),
)
text = tokenizer.apply_chat_template(
messages,
tokenize = False,
add_generation_prompt = True,
reasoning_effort = "high",
)

from transformers import TextStreamer
_ = model.generate(
**tokenizer(text, return_tensors = "pt").to("cuda"),
max_new_tokens = 256,
streamer = TextStreamer(tokenizer, skip_prompt = True),
)

在基本掌握Unsloth的模型导入和对话方法后,接下来正式进入到gpt-oss大模型高效微调流程中。

八、高效微调数据集创建

1. HuggingFace与ModelScope平台数据集介绍

  若要选择公开数据集进行高效微调,则首先可以考虑HuggingFace和ModelScope平台上的数据集。其中HuggingFace上不仅保管了最大规模数量的数据集,而且HuggingFace的dataset工具,也是目前主流微调核心库如trl库默认支持的数据集格式。此外,ModelScope则是国内版的“HuggingFace”,拥有最大规模的中文数据集。

image-20250508183656931

其中右侧都是目前最流行的数据集,目前排名第一的是英伟达的Nemotron-CrossThink数据集,该数据集用于训练英伟达最新开源的号称最强开源推理模型的Llama-Nemotron,涵盖物理、法律、社会科学、经济学等多个领域的问答对,采用多项选择题和开放式问答格式,旨在提升模型的通用推理能力。

image-20250508184133390

其中关于中文满血DeepSeek-R1模型蒸馏数据集,是非常高质量的可以用于训练模型中文推理能力或者模型蒸馏的数据集。

image-20250508184258142

2. 数据集下载流程

我们使用 Open Math Reasoning 数据集,该数据集曾被用于赢得 AIMO(AI 数学奥林匹克 - 第二届进步奖)挑战!我们从中抽取了 10% 可验证的推理轨迹,这些轨迹是基于 DeepSeek R1 模型生成的,并且准确率超过 95%。数据集地址:https://huggingface.co/datasets/unsloth/OpenMathReasoning-mini

image-20250506192017620

在实际微调过程中,大多都会使用huggingface的datasets库进行数据集下载和管理,实际下载流程如下:

!pip install --upgrade datasets huggingface_hub
# 设置 HTTP 和 HTTPS 代理
import os
os.environ["HTTP_PROXY"] = "http://127.0.0.1:10080"
os.environ["HTTPS_PROXY"] = "http://127.0.0.1:10080"

此外如果是使用AutoDL服务器,也可开启学术加速功能以更加稳定的连接huggingface。

  datasets 是 Hugging Face 提供的一个高效数据处理库,专为机器学习和大语言模型(LLM)训练而设计。它支持加载、处理、转换和保存各种格式的数据(如 JSON、CSV、Parquet 等),并能与 transformers 模型无缝集成。通过 datasets,开发者可以快速完成数据清洗、切分、tokenization 等常见任务,大大提升训练效率,特别适合用于指令微调、对话生成、Function Calling 等任务的数据预处理。

from datasets import load_dataset

然后分别下载并导入这两个库:

reasoning_dataset = load_dataset("unsloth/OpenMathReasoning-mini", split = "cot")

只下载包含cot的数据集

然后输入数据集名称,即可查看数据集基本信息:

reasoning_dataset

加上索引则可以直接查看对应数据集信息:

reasoning_dataset[0]

能够看出这是一个基于DeepSeek R1回答的数学数据集,其中problem是问题,generated_solution是数学推导过程(即思考过程),而expected_answer则是最终的答案。该数据集总共接近2万条数据:

len(reasoning_dataset)

2. 微调数据集清洗

  接下来尝试对上述两个格式各异的数据集进行数据清洗,主要是围绕数据集进行数据格式的调整,便于后续带入gpt-oss提示词模板。对于dataset格式的数据对象来说,可以先创建满足格式调整的函数,然后使用map方法对数据集格式进行调整。这里先创建generate_conversation函数,用于对reasoning_dataset中的每一条数据进行格式调整,即通过新创建一个新的特征conversations,来以对话形式保存历史问答数据:

def generate_conversation(examples):
problems = examples["problem"]
solutions = examples["generated_solution"]
conversations = []
for problem, solution in zip(problems, solutions):
conversations.append([
{"role" : "user", "content" : problem},
{"role" : "assistant", "content" : solution},
])
return { "conversations": conversations, }
reasoning_dataset[0]
reasoning_data = reasoning_dataset.map(generate_conversation, batched = True)

此时历史问答数据如下:

reasoning_data["conversations"]
reasoning_data["conversations"][0]

接下来将其带入gpt-oss的提示词模板中进行转化:

reasoning_conversations = tokenizer.apply_chat_template(
reasoning_data["conversations"],
tokenize = False,
)

最后创建的数据就是一个包含多个对话信息的list:

reasoning_conversations[0]
len(reasoning_conversations)

之后即可带入这些数据进行微调。能看出每条数据的格式都和Unsloth底层对话API创建的数据格式类似,之后我们或许可以借助Unsloth底层对话API来创建微调数据集。

九、gpt-oss推理能力高效微调流程

  准备完数据之后,即可开始进行微调。这里我们先进行少量数据微调测试,程序能够基本跑通后,我们再进行大规模数据集微调。

1. Unsloth微调流程实践

Step 1. 进行LoRA参数注入

model = FastLanguageModel.get_peft_model(
model,
r = 32, # Choose any number > 0! Suggested 8, 16, 32, 64, 128
target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",],
lora_alpha = 32, # Best to choose alpha = rank or rank*2
lora_dropout = 0, # Supports any, but = 0 is optimized
bias = "none", # Supports any, but = "none" is optimized
# [NEW] "unsloth" uses 30% less VRAM, fits 2x larger batch sizes!
use_gradient_checkpointing = "unsloth", # True or "unsloth" for very long context
random_state = 3407,
use_rslora = False, # We support rank stabilized LoRA
loftq_config = None, # And LoftQ
)

Step 2. 设置微调参数

from trl import SFTTrainer, SFTConfig
trainer = SFTTrainer(
model = model,
tokenizer = tokenizer,
train_dataset = combined_dataset,
eval_dataset = None, # Can set up evaluation!
args = SFTConfig(
dataset_text_field = "text",
per_device_train_batch_size = 2,
gradient_accumulation_steps = 4, # Use GA to mimic batch size!
warmup_steps = 5,
# num_train_epochs = 1, # Set this for 1 full training run.
max_steps = 30,
learning_rate = 2e-4, # Reduce to 2e-5 for long training runs
logging_steps = 1,
optim = "adamw_8bit",
weight_decay = 0.01,
lr_scheduler_type = "linear",
seed = 3407,
report_to = "wandb", # Use this for WandB etc
),
)

其中SFTTrainer:一个专门为指令微调设计的训练器,封装了 Hugging Face 的 Trainer,而SFTConfig:配置训练参数的专用类,功能类似 TrainingArguments。而SFTConfig核心参数解释如下:

参数名含义
dataset_text_field="text"数据集中用于训练的字段名称,如 textprompt
per_device_train_batch_size=2每张 GPU 上的 batch size 是 2
gradient_accumulation_steps=4梯度累计 4 次后才进行一次反向传播(等效于总 batch size = 2 × 4 = 8)
warmup_steps=5前 5 步进行 warmup(缓慢提升学习率)
max_steps=30最多训练 30 步(适合调试或快速实验)
learning_rate=2e-4初始学习率(短训练可用较高值)
logging_steps=1每训练 1 步就打印一次日志
optim="adamw_8bit"使用 8-bit AdamW 优化器(节省内存,Unsloth 支持)
weight_decay=0.01权重衰减,用于防止过拟合
lr_scheduler_type="linear"线性学习率调度器(从高到低线性下降)
seed=3407固定随机种子,确保结果可复现
report_to="none"不使用 WandB 或 TensorBoard 等日志平台(可改为 "wandb"

此时基本训练过程为:

  1. combined_dataset 中取出一批样本(2 条)
  2. 重复上面过程 4 次(gradient_accumulation_steps=4
  3. 将累计的梯度用于更新模型一次参数(等效于一次大 batch 更新)
  4. 重复上述过程,直到 max_steps=30 停止

此时显存占用如下:

# @title Show current memory stats
gpu_stats = torch.cuda.get_device_properties(0)
start_gpu_memory = round(torch.cuda.max_memory_reserved() / 1024 / 1024 / 1024, 3)
max_memory = round(gpu_stats.total_memory / 1024 / 1024 / 1024, 3)
print(f"GPU = {gpu_stats.name}. Max memory = {max_memory} GB.")
print(f"{start_gpu_memory} GB of memory reserved.")

Step 3. 【可选】设置wandb

  接下来可继续设置wandb用于进行模型训练过程关键信息记录。

import wandb
wandb.login(key="4b62572b8426ff59ce46fec93a00eb1feecc026a")

Step 4. 微调执行流程

  一切准备就绪后,接下来即可开始进行微调。由于本次微调总共只运行30个step,整个过程并不会很长,实际执行过程如下:

trainer_stats = trainer.train()
  • 微调期间显存占用检测
# @title Show final memory and time stats
used_memory = round(torch.cuda.max_memory_reserved() / 1024 / 1024 / 1024, 3)
used_memory_for_lora = round(used_memory - start_gpu_memory, 3)
used_percentage = round(used_memory / max_memory * 100, 3)
lora_percentage = round(used_memory_for_lora / max_memory * 100, 3)
print(f"{trainer_stats.metrics['train_runtime']} seconds used for training.")
print(
f"{round(trainer_stats.metrics['train_runtime']/60, 2)} minutes used for training."
)
print(f"Peak reserved memory = {used_memory} GB.")
print(f"Peak reserved memory for training = {used_memory_for_lora} GB.")
print(f"Peak reserved memory % of max memory = {used_percentage} %.")
print(f"Peak reserved memory for training % of max memory = {lora_percentage} %.")
  • 查看wandb记录结果

  同时,如果开启了wandb,则可以在对应的网页看到模型训练记录结果:

image-20250507222022165

能够看到loss波动下降,整个训练过程属于正常情况。

Step 5. 模型对话测试

而当我们完成训练后,即可尝试进行模型对话:

messages = [
{"role" : "user", "content" : "Solve (x + 2)^2 = 0."}
]
text = tokenizer.apply_chat_template(
messages,
tokenize = False,
add_generation_prompt = True, # Must add for generation
enable_thinking = False, # Disable thinking
)

from transformers import TextStreamer
_ = model.generate(
**tokenizer(text, return_tensors = "pt").to("cuda"),
max_new_tokens = 256, # Increase for longer outputs!
temperature = 0.7, top_p = 0.8, top_k = 20, # For non thinking
streamer = TextStreamer(tokenizer, skip_prompt = True),
)
messages = [
{"role" : "user", "content" : "Solve (x + 2)^2 = 0."}
]
text = tokenizer.apply_chat_template(
messages,
tokenize = False,
add_generation_prompt = True, # Must add for generation
enable_thinking = True, # Disable thinking
)

from transformers import TextStreamer
_ = model.generate(
**tokenizer(text, return_tensors = "pt").to("cuda"),
max_new_tokens = 20488, # Increase for longer outputs!
temperature = 0.6, top_p = 0.95, top_k = 20, # For thinking
streamer = TextStreamer(tokenizer, skip_prompt = True),
)

能够看出问答语气风格有明显优化,表述更加完整,答案也更加专业。