大模型最新面试题系列:模型部署(二)
一、如何通过unsloth的批处理(Batching)功能提升推理效率?
Unsloth的批处理(Batching)功能通过整合硬件加速、内存优化和动态调度技术,显著提升大模型推理效率。以下是具体实现方法和实际应用场景的深度解析:
动态批处理与硬件协同优化
Unsloth的核心机制是将多个推理请求合并为一个批次,利用GPU的并行计算能力提升吞吐量。例如,当处理多个用户的实时查询时,系统会自动将请求打包成批次(如16个请求/批次),通过矩阵运算的批量处理减少单次计算的延迟。这种方式尤其适用于Transformer架构的模型,因为其自注意力机制在大批次下的计算效率更高。
硬件加速策略
- 混合精度计算:默认启用BF16/FP16混合精度,在保持精度的同时减少显存带宽占用。例如,Llama-3.1(8B)在A100 40GB GPU上使用BF16时,吞吐量提升2倍,显存占用降低50%。
- CUDA内核优化:通过Triton语言重写关键算子(如注意力模块),将计算密集型操作的执行效率提升30%-50%。例如,Mistral-7B模型在RTX 4090上的推理速度可达每秒4000 tokens。
动态批次调整
- 自适应批次大小:根据输入请求的到达率自动调整批次大小。例如,在高并发时将批次大小从8增加到32,提升吞吐量;在低并发时降至4,减少延迟。
- 长上下文处理:通过RoPE扩展技术支持超长上下文(如Llama-3.3 70B支持89K上下文),在处理长文本生成任务时保持批次效率。
内存优化与显存管理
Unsloth通过量化技术和显存复用策略,解决大模型推理时的内存瓶颈问题,为批处理提供更大空间。
量化技术
- 动态4位量化:将模型参数从FP32压缩为4位整数,显存占用减少70%。例如,Llama-3.1(8B)在4位量化后仅需7GB显存即可运行,允许在消费级显卡(如RTX 4090)上处理更大批次。
- 混合量化:对部分关键层(如注意力层)保持16位精度,其余层使用4位量化,在精度和效率间取得平衡。例如,Qwen2.5(7B)在混合量化后,BLEU评分仅下降1.2%,但吞吐量提升1.8倍。
显存复用
- KV缓存优化:动态管理键值缓存(Key-Value Cache),避免重复计算。例如,处理连续对话时,缓存历史token的中间结果,批次内请求共享缓存数据,减少显存占用30%。
- 梯度检查点:选择性存储中间激活值,需要时重新计算,进一步节省显存。例如,在微调Llama-3.3 70B时,显存占用从80GB降至48GB,允许更大批次的推理。
与vLLM集成的端到端优化
Unsloth与vLLM推理框架深度集成,实现动态批处理与实时推理的协同优化。
动态请求合并
- Continuous Batching:将不同长度的请求动态合并为批次,减少填充(Padding)带来的计算浪费。例如,处理长度为100和200的请求时,自动填充到200,批次内总token数提升40%。
- 流式输出:支持边生成边输出,在批次处理过程中逐步返回结果,降低延迟。例如,生成1000 tokens的响应时,每生成50 tokens即可返回部分结果,用户等待时间缩短50%。
性能监控与调优
- 吞吐量-延迟平衡:通过参数配置(如
max_batch_size=32
、max_queue_len=100
)动态调整批次大小和队列长度。例如,在A100 80GB GPU上,将批次大小从16调整为32,吞吐量提升25%,但延迟增加15%。 - 硬件感知优化:自动检测GPU架构(如Ampere、Hopper),选择最优的计算内核和内存分配策略。例如,在H100上启用Tensor Core加速,吞吐量提升3倍。
实际应用案例与效果
案例1:客服对话系统
- 场景:处理数万用户的实时咨询请求。
- 配置:使用Llama-3.1(8B),4位量化,批次大小16,vLLM动态调度。
- 效果:吞吐量达每秒3000 tokens,响应延迟低于500ms,显存占用仅15GB。
案例2:代码生成
- 场景:处理长代码片段的补全请求。
- 配置:使用CodeLlama(7B),混合精度,批次大小8,梯度检查点启用。
- 效果:生成1000行代码的时间从12秒降至4秒,显存占用减少60%。
案例3:医疗影像报告生成
- 场景:处理高分辨率医学影像的分析请求。
- 配置:使用Mistral-7B,动态4位量化,批次大小4,长上下文支持。
- 效果:处理512x512影像的报告生成时间从8秒降至3秒,显存占用从20GB降至7GB。
参数调优与最佳实践
关键参数说明
参数名称 | 描述 | 推荐值范围 |
---|---|---|
batch_size | 单次处理的请求数 | 8-64(根据显存调整) |
max_seq_length | 最大上下文长度 | 2048-32768(根据模型支持) |
quantization | 量化精度(4bit/8bit/FP16) | 4bit(默认) |
gradient_checkpointing | 是否启用梯度检查点(节省显存) | True/False |
stream_output | 是否启用流式输出 | True |
调优步骤
- 显存压力测试:逐步增加批次大小,观察显存占用和吞吐量的变化,找到临界点。
- 延迟敏感型场景:优先降低批次大小(如4-8),启用流式输出。
- 吞吐量优先场景:增大批次大小(如32-64),启用混合量化。
- 长上下文场景:启用RoPE扩展,调整
max_seq_length
至模型支持上限。
常见问题与解决方案
问题现象 | 可能原因 | 解决方案 |
---|---|---|
显存不足 | 批次过大或未启用量化 | 降低批次大小,启用4位量化 |
延迟过高 | 批次合并等待时间过长 | 减小max_queue_len 参数 |
吞吐量低 | 硬件未充分利用 | 启用混合精度,优化内核参数 |
模型输出异常 | 量化精度不足或缓存策略错误 | 关闭量化,调整KV缓存参数 |
二、对比模型并行与流水线并行在分布式推理中的部署难度。
以下是模型并行与流水线并行在分布式推理中部署难度的对比分析,结合硬件依赖、通信开销、负载均衡等核心维度,通过表格形式呈现关键差异:
分布式推理并行策略部署难度对比表
维度 | 模型并行(Model Parallelism) | 流水线并行(Pipeline Parallelism) |
---|---|---|
硬件要求 | 必须依赖高速GPU互联(如NVLink),否则通信延迟显著影响性能。 例:70B模型需4张40GB GPU通过NVLink互联。 | 对通信带宽要求较低,普通PCIe即可支持。 例:3阶段流水线可部署在3台普通服务器(PCIe 4.0)。 |
通信开销 | 每层计算后需同步中间结果(如AllReduce),通信频率极高。 在无NVLink场景下,通信时间占比可达总耗时的50%以上。 | 仅在阶段间传递激活值,通信量较小。 例如:7B模型的层间激活值传输量约为权重参数的1/10。 |
负载均衡 | 层计算量差异可能导致设备利用率不均(如注意力层 vs 全连接层)。 需手动调整层分配策略,优化难度高。 | 阶段计算时间需严格平衡,否则产生“流水线气泡”。 例如:若阶段1耗时10ms,阶段2耗时5ms,整体吞吐量受限为20ms/批次。 |
编程复杂度 | 需手动分割模型层或使用特定框架(如vLLM张量并行)。 例:Llama-3.3 70B需按层分配到8个GPU,配置参数超过50个。 | 需设计阶段划分和微批次调度,动态管理数据流。 例:GPT-4的120层需划分为8个阶段,每个阶段处理15层。 |
调试难度 | 层间通信错误难以定位(如参数同步失败)。 需结合nvidia-smi和NCCL调试工具分析GPU利用率。 | 阶段间数据流异常难以排查(如激活值格式不匹配)。 需使用分布式跟踪工具(如Dask)监控流水线状态。 |
扩展性 | 增加GPU数量可能受限于通信带宽,线性扩展能力差。 例:从4卡扩展到8卡时,吞吐量仅提升30%。 | 可通过增加阶段或复制阶段扩展,理论扩展性更高。 例:8阶段流水线扩展到16阶段时,吞吐量提升约70%。 |
容错性 | 单GPU故障可能导致整个模型推理中断,需重新计算。 恢复时间与模型大小成正比(如70B模型恢复需5-10分钟)。 | 单阶段故障仅影响当前批次,可通过重试或切换备用阶段恢复。 例:阶段3故障时,系统自动将该批次路由至备用阶段3。 |
内存管理 | 显存占用分散,但需处理参数分片冲突。 例:Llama-3.3 70B在4卡张量并行时,每卡显存占用约35GB。 | 需存储中间激活值,总内存需求可能更高。 例:GPT-4的120层流水线在8卡部署时,激活值缓存占用约200GB。 |
训练/推理兼容性 | 训练与推理部署差异较小,参数同步逻辑可复用。 例:vLLM的张量并行可直接用于训练和推理。 | 训练需处理反向传播和梯度同步,推理需简化调度逻辑。 例:DeepSpeed的流水线并行在训练时需额外配置梯度检查点。 |
框架支持 | 主流框架(PyTorch/TensorFlow)原生支持较好。 例:PyTorch的DistributedDataParallel支持张量并行。 | 依赖特定库或自定义实现(如Megatron-LM、DeepSpeed)。 例:DeepSpeed的流水线并行需手动配置阶段划分。 |
典型场景选择建议
场景需求 | 推荐策略 | 原因 |
---|---|---|
超大模型(如70B以上)显存不足 | 模型并行 | 显存扩展能力强,支持单卡无法容纳的模型。 |
实时推理(如客服对话) | 流水线并行 | 微批次处理减少延迟,支持边生成边输出。 |
多节点集群(跨机部署) | 流水线并行 | 减少跨机通信次数,适合长距离网络。 |
硬件资源有限(如普通PCIe) | 流水线并行 | 对通信带宽要求低,可在普通硬件上运行。 |
高容错性要求(如金融风控) | 流水线并行 | 单阶段故障不影响全局,恢复机制更灵活。 |
性能调优关键参数
策略 | 参数 | 作用 |
---|---|---|
模型并行 | tensor_parallel_size | 控制GPU数量,需与硬件互联能力匹配。 |
allreduce_alg | 选择通信算法(如NCCL、MPI),优化同步效率。 | |
流水线并行 | microbatch_size | 平衡计算与通信,推荐值为8-32。 |
num_stages | 阶段数量,需与模型层数匹配(如120层划分为8阶段)。 |
通过上述对比可见,模型并行在显存扩展和框架支持上更具优势,但对硬件要求苛刻;流水线并行在延迟优化和容错性上表现更好,但需要更复杂的调度逻辑。实际部署时需根据模型规模、硬件条件和业务需求综合选择,必要时可采用混合并行策略(如模型并行+流水线并行)。
三、如何通过llama - factory的推理脚本实现流式输出(Stream Output)
核心实现原理
llama - factory 的流式输出基于 vLLM 推理引擎 和 OpenAI 风格 API 实现。vLLM 支持高效的流式生成,通过 stream=True
参数触发逐 token 输出。其核心机制包括:
- 动态 batch 管理:vLLM 会将多个请求合并为一个 batch 处理,但流式输出时会优先处理单个请求,确保实时性。
- KV cache 优化:vLLM 复用历史 token 的键值缓存,避免重复计算,提升生成速度。
- HTTP 长连接:API 接口通过 HTTP chunked 传输协议实现增量输出,客户端可实时接收数据。
具体操作步骤
1. 启动推理服务
在 llama - factory 中,流式输出依赖于 vLLM 的推理服务。通过以下命令启动:
llamafactory-cli serve --model-name-or-path your_model_path --streaming True
--streaming True
开启流式输出支持- 服务默认监听端口 8000,可通过
--port
参数修改
2. API 调用示例
使用 OpenAI 风格的接口进行流式请求:
import openai
openai.api_base = "http://localhost:8000/v1"
response = openai.ChatCompletion.create(
model="your_model_name",
messages=[
{"role": "user", "content": "写一个 Python 冒泡排序函数"}
],
stream=True # 关键参数,启用流式输出
)
for chunk in response:
delta = chunk['choices'][0]['delta']
if 'content' in delta:
print(delta['content'], end='', flush=True)
- 输出结果会以
{"role":"assistant","content":"..."
的 JSON 块形式逐字符返回 - 客户端需处理断包和连接保持问题
3. 命令行工具使用
llama - factory 提供了 llamafactory-cli
工具支持流式输出:
llamafactory-cli chat --prompt "写一个 Python 冒泡排序函数" --stream
--stream
参数启用流式输出- 输出格式为纯文本,自动拼接各 token
关键参数配置
1. 模型相关参数
参数名称 | 描述 | 推荐值 |
---|---|---|
max_new_tokens | 生成的最大 token 数 | 512-2048 |
temperature | 采样温度,控制输出多样性(0.0-1.0) | 0.7 |
top_p | 核采样参数,控制输出随机性(0.0-1.0) | 0.95 |
2. 流式输出优化参数
参数名称 | 描述 | 推荐值 |
---|---|---|
stream_interval | 输出间隔时间(秒) | 0.01-0.1 |
timeout | 连接超时时间(秒) | 300 |
chunk_size | 每次传输的 token 数 | 16-64 |
高级功能扩展
1. 自定义输出格式
通过修改 src/llamafactory/api/vllm_server.py
中的 generate
函数,可自定义输出格式:
async def generate(request: Request):
# 原有代码
...
# 添加自定义处理逻辑
for chunk in response:
custom_output = process_chunk(chunk) # 自定义处理函数
yield json.dumps(custom_output)
2. 多语言支持
在 llamafactory/data/template.py
中配置多语言模板:
TEMPLATE_MAPPING = {
"zh": {
"prompt": "请用中文回答:{query}",
"stream_prefix": "回答:"
},
"en": {
"prompt": "Please answer in English: {query}",
"stream_prefix": "Answer: "
}
}
3. 性能优化
- 模型量化:使用
--quantization-bit 4
进行 4 位量化,减少显存占用 - 模型并行:通过
--num-gpus
参数启用多卡并行推理 - 缓存策略:设置
--max-batch-size
调整 batch 大小,平衡吞吐量和延迟
四、解释vllm的--trust_remote_code
参数在加载自定义模型时的作用和风险。
1. 支持自定义代码执行
在加载模型时,某些模型可能会依赖于一些自定义的代码逻辑。例如,一些模型使用了特殊的架构或者自定义的前向传播方法,这些代码并不是 transformers
库中默认支持的。当你使用 --trust_remote_code
参数时,vLLM 会允许从远程源加载并执行这些自定义代码。这样就能让 vLLM 顺利加载和运行那些需要特殊代码实现的模型。比如,某个研究团队发布了一个新的语言模型,该模型采用了全新的注意力机制,并且提供了实现该机制的自定义代码。在加载这个模型时,使用 --trust_remote_code
就可以让 vLLM 执行这些代码,从而正确地加载和使用该模型。
2. 灵活性和扩展性
这个参数为模型的使用提供了更大的灵活性和扩展性。研究人员和开发者可以自由地探索和使用最新的模型架构和技术。即使这些模型的实现不在标准库的支持范围内,也能够借助 --trust_remote_code
来加载和运行它们。这有助于推动自然语言处理领域的创新,因为它允许社区更快地采用新的研究成果。
使用 --trust_remote_code
参数的风险
虽然 --trust_remote_code
带来了很多便利,但也伴随着一些不可忽视的风险。
1. 安全风险
加载和执行远程代码是一项具有潜在危险的操作。因为你无法完全确定远程代码的来源和安全性。恶意代码可能会利用这个机会进行攻击,例如窃取系统中的敏感信息(如用户数据、系统配置等)、修改系统文件、在后台运行恶意程序等。如果攻击者将恶意代码嵌入到自定义模型的代码中,当你使用 --trust_remote_code
参数加载该模型时,就可能会遭受攻击。
2. 兼容性问题
远程代码可能与你本地的环境存在兼容性问题。这些代码可能依赖于特定版本的库或者操作系统,而你的本地环境可能并不满足这些要求。这可能会导致模型加载失败、运行时出错或者产生不可预期的结果。例如,远程代码可能使用了某个库的最新版本的特定功能,而你本地安装的是旧版本的库,就会出现兼容性问题。
3. 维护成本增加
使用自定义代码会增加模型的维护成本。因为你不仅要关注模型本身的更新,还要关注自定义代码的更新和维护。如果自定义代码的开发者停止维护或者更新代码,可能会导致模型在未来无法正常使用。此外,当出现问题时,排查和解决问题的难度也会增加,因为你需要同时考虑模型和自定义代码的因素。
在使用 --trust_remote_code
参数时,要谨慎权衡其带来的好处和风险。如果可能的话,尽量从可信任的来源获取自定义代码,并且在使用之前对代码进行仔细的审查和测试。
五、如何通过DeepSpeed的--bf16
参数启用BF16精度训练?
要通过 DeepSpeed 的 --bf16
参数启用 BF16(Brain Floating Point 16)精度训练,可按以下步骤进行:
1. 环境准备
首先,要保证你的环境已经正确安装了 DeepSpeed 以及相关的深度学习框架(如 PyTorch)。可以使用如下命令安装 DeepSpeed:
pip install deepspeed
2. 配置 DeepSpeed 配置文件
DeepSpeed 通常需要一个配置文件来指定训练过程中的各种参数。创建一个 JSON 格式的配置文件,例如 deepspeed_config.json
,在其中设置启用 BF16 精度训练。示例配置文件内容如下:
{
"train_batch_size": 64,
"optimizer": {
"type": "Adam",
"params": {
"lr": 0.0001
}
},
"fp16": {
"enabled": false
},
"bf16": {
"enabled": true
}
}
在上述配置文件中:
train_batch_size
是训练时的批次大小。optimizer
部分定义了优化器的类型和参数,这里使用的是 Adam 优化器,学习率为 0.0001。fp16
的enabled
设为false
,表明不启用 FP16 精度训练。bf16
的enabled
设为true
,以此来启用 BF16 精度训练。
3. 修改训练脚本
要确保你的训练脚本与 DeepSpeed 兼容。下面是一个简单的 PyTorch 训练脚本示例,展示了如何集成 DeepSpeed 并启用 BF16 精度训练:
import torch
import deepspeed
# 初始化模型
model = ... # 这里需要替换为你的模型定义
parameters = filter(lambda p: p.requires_grad, model.parameters())
# 初始化 DeepSpeed
model, optimizer, _, _ = deepspeed.initialize(
model=model,
model_parameters=parameters,
config='deepspeed_config.json'
)
# 训练循环
for epoch in range(num_epochs):
for inputs, labels in dataloader:
outputs = model(inputs)
loss = ... # 这里需要替换为你的损失函数计算
model.backward(loss)
model.step()
在这个脚本中:
- 首先定义了模型和可训练的参数。
- 然后使用
deepspeed.initialize
函数来初始化 DeepSpeed,传入模型、参数和之前创建的 DeepSpeed 配置文件路径。 - 最后在训练循环中进行前向传播、损失计算、反向传播和参数更新。
4. 启动训练
使用 deepspeed
命令来启动训练脚本,并通过 --bf16
参数启用 BF16 精度训练。示例命令如下:
deepspeed --bf16 train.py
这里的 train.py
是你的训练脚本文件名。
注意事项
- 硬件支持:要确保你的 GPU 支持 BF16 数据类型。像 NVIDIA A100、H100 等 GPU 都支持 BF16 运算,使用支持 BF16 的 GPU 才能发挥出 BF16 精度训练的优势。
- 数值稳定性:BF16 的动态范围比 FP16 大,但在某些情况下,仍然可能会遇到数值稳定性问题。如果在训练过程中发现损失值出现异常或者模型不收敛,可能需要调整超参数或者采用其他技术来提高数值稳定性。
- 兼容性:要确保你的深度学习框架版本与 DeepSpeed 兼容,避免因为版本不兼容而导致训练失败。
六、对比不同推理引擎(TensorRT vs ONNX Runtime)在vllm中的集成效果
对比维度 | TensorRT 在 vLLM 中的集成效果 | ONNX Runtime 在 vLLM 中的集成效果 |
---|---|---|
性能表现 | - 高度优化的推理引擎,专为 NVIDIA GPU 设计。在 vLLM 中集成后,可利用 TensorRT 的张量核心进行高效计算,对于大规模语言模型推理,能显著提升推理速度,尤其是在批量推理场景下,可实现极低的延迟和高吞吐量。 - 支持 INT8、FP16 等低精度推理,能进一步降低计算量和内存占用,提升性能。 | - 跨平台支持良好,可在多种硬件上运行,包括 CPU、GPU 等。在 vLLM 中使用 ONNX Runtime 时,可根据硬件资源灵活选择计算后端。 - 推理性能在不同硬件上较为稳定,但相比 TensorRT 在 NVIDIA GPU 上的优化程度,其在 NVIDIA GPU 上的性能提升可能相对有限。不过在 CPU 上的推理表现有一定优势。 |
模型兼容性 | - 对模型结构有一定要求,需要将模型转换为 TensorRT 引擎格式。某些复杂模型结构可能需要额外的处理才能与 TensorRT 兼容。 - 对于一些特定的算子和层,可能需要进行自定义实现或适配。 | - 支持 ONNX 格式的模型,具有良好的模型兼容性。大部分深度学习框架训练的模型都可以转换为 ONNX 格式,然后使用 ONNX Runtime 进行推理,在 vLLM 中集成时,模型转换过程相对简单。 |
开发难度 | - 集成过程相对复杂,需要对 TensorRT 的 API 有深入了解。包括模型转换、引擎构建、推理流程等步骤,都需要进行详细的配置和优化。 - 对于开发者的技术要求较高,需要具备一定的 GPU 编程和优化经验。 | - 集成相对简单,ONNX Runtime 提供了简洁的 API 接口,便于开发者使用。只需要将模型转换为 ONNX 格式,然后调用相应的 API 进行推理即可。 - 开发文档丰富,社区支持良好,降低了开发难度。 |
灵活性 | - 灵活性相对较低,主要针对 NVIDIA GPU 进行优化,对于其他硬件平台的支持有限。一旦选择了 TensorRT,就需要依赖 NVIDIA 的硬件生态。 | - 具有较高的灵活性,可根据不同的硬件资源选择合适的计算后端,如 CPU、NVIDIA GPU、AMD GPU 等。可以在不同的环境中快速部署和运行模型。 |
成本 | - 需要 NVIDIA GPU 硬件支持,硬件成本较高。同时,对于大规模推理场景,可能需要多 GPU 配置,进一步增加了成本。 | - 硬件选择较为灵活,可根据实际需求选择不同的硬件平台,成本相对较低。例如,对于一些对性能要求不高的场景,可以选择使用 CPU 进行推理。 |
七、解释在llama - factory中如何通过--lora
参数加载预训练的LoRA权重
1. 确保环境准备就绪
在安装 peft
库时,最好指定具体版本,因为不同版本的 peft
可能对某些功能支持不同。同时,强调 peft
库与 transformers
库版本的兼容性也很重要,因为它们之间可能存在版本不兼容问题。以下是更完善的环境准备步骤:
# 建议指定 peft 库版本,这里以 0.4.0 为例,可根据实际情况调整
pip install peft==0.4.0
2. 准备预训练的 LoRA 权重
在实际操作中,预训练的 LoRA 权重可能有不同的存储格式和文件结构。可以补充一些检查和验证步骤,确保权重文件的完整性和正确性。例如:
# 检查 LoRA 权重目录是否存在
if [ ! -d "./lora_weights" ]; then
echo "LoRA 权重目录不存在,请检查路径。"
exit 1
fi
# 检查 LoRA 权重目录中是否包含必要的文件,如 adapter_config.json 和 adapter_model.bin
if [ ! -f "./lora_weights/adapter_config.json" ] || [ ! -f "./lora_weights/adapter_model.bin" ]; then
echo "LoRA 权重文件不完整,请检查。"
exit 1
fi
3. 启动服务时加载 LoRA 权重
在启动 llamafactory-cli serve
命令时,可能会遇到一些常见错误,比如模型路径错误、权限问题等。可以补充一些错误处理和提示信息:
# 启动服务并加载 LoRA 权重
llamafactory-cli serve --model-name-or-path your_base_model_path --lora ./lora_weights
# 检查服务启动是否成功,可根据实际的错误输出进行更详细的判断
if [ $? -ne 0 ]; then
echo "服务启动失败,请检查模型路径和 LoRA 权重路径是否正确,以及是否有足够的权限。"
fi
4. 代码调用示例
在代码调用示例中,可以添加一些异常处理,增强代码的健壮性。同时,对于 GPU 设备的使用可以进行明确指定:
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
try:
# 加载基础模型和分词器
base_model_path = "your_base_model_path"
model = AutoModelForCausalLM.from_pretrained(base_model_path)
tokenizer = AutoTokenizer.from_pretrained(base_model_path)
# 加载 LoRA 权重
lora_path = "./lora_weights"
model = PeftModel.from_pretrained(model, lora_path)
# 将模型移动到 GPU 上(如果有可用的 GPU)
device = "cuda" if torch.cuda.is_available() else "cpu"
model = model.to(device)
# 进行推理
input_text = "请介绍一下人工智能"
input_ids = tokenizer(input_text, return_tensors="pt").input_ids.to(device)
output = model.generate(input_ids)
output_text = tokenizer.decode(output[0], skip_special_tokens=True)
print(output_text)
except Exception as e:
print(f"推理过程中出现错误: {e}")