【AI学习-2.1】部署自己的本地大模型 -本地推理

在我之前的文章已经对 AI 相关的一些核心概念做了系统性的介绍。相信读者在阅读完之后,已经对人工智能有了一个初步而整体的认知。

在正式进入 AI 底层算法与数学原理之前,我个人更建议大家先在本地部署并运行一个大模型 。通过实际操作获得直观体验,可以显著降低后续学习过程中的理解成本,也有助于把抽象概念与真实行为建立联系。本文所使用的系统环境为 Windows ,并且完全基于 CPU 进行计算 。需要特别说明的是,作者本人使用的是 AMD 显卡(A 卡)。然而,就目前的实际情况来看,AMD 在 Windows 平台上对大模型推理与训练的支持仍然不够成熟。为了充分利用硬件,我曾尝试过多种方案,包括 WSL2、DirectML 等,但在实际使用过程中,由于兼容性、稳定性以及环境配置等问题,最终都未能顺利运行模型,反而消耗了大量时间成本。

权衡之后,我最终选择直接使用 CPU 运行模型。虽然性能上有所牺牲,但在稳定性、可控性以及排错成本方面都要友好得多,也几乎不会遇到各种"非预期问题"。回过头来看,我个人非常后悔没有在一开始就选择 CPU 方案------对于学习阶段而言,稳定性远比性能更重要。

如果把 AI 技术本身类比为羽毛球技术 ,那么用于实现 AI 的各种编程语言(如 Python、C++)以及相关框架和库(如 PyTorch、TensorFlow)更像是羽毛球拍的选择 。在学习羽毛球技术的初期,最快的提升方式并不是一味追求最专业、最昂贵的球拍,而是选择当下最容易获取、最顺手、最稳定的工具 。同理,在 AI 学习的早期阶段,更重要的是理解原理、动手实践和建立整体认知 ,而不是纠结于某种特定语言或框架。随着经验的积累,更换编程语言或底层库所需的成本,远远低于从零学习 AI 技术本身的成本。因此,我个人非常建议初学者在入门阶段减少技术选型上的执念 ,优先关注理论理解与实践过程。具体工具会不断演进,某些技术甚至会被淘汰,但解决问题的思维方式与方法论是长期有效的

本地模型推理

为了让大家能看到自己运行的模型来源于哪里,我会先显式地把模型的代码,参数拉取到本地,然后再读取他完成推理。避免使用过于高层级的API。推理得不明不白。模型上,我选用阿里千问开源模型Qwen3-4B

这个模型比较新,不算大,但也绝对不小,而且支持推理模式,CPU也完全跑得动(虽然略慢了点),所以很适合用于学习

huggingface地址:https://huggingface.co/Qwen/Qwen3-4B

第一步 通过git命令把代码拉取到本地

git lfs install

git clone https://huggingface.co/Qwen/Qwen3-4B

这一步可能需要科学上网,也需要等挺长的一段时间,需要有耐心

第二步 拉下来的查看代码

拉下来后目录结构应该是这样的

目录重要文件解释

config.json:描述模型结构与超参数。比如字段有 model_type(模型类型)、hidden_size(隐藏层维度)、num_hidden_layers(层数)、num_attention_heads(注意力头数)、vocab_size、max_position_embeddings、torch_dtype、bos_token_id、eos_token_id 等,用于恢复网络结构与推理/训练时的数值类型和位置编码长度。

safetensors文件:大模型参数(weights)的分片文件(sharded weights),它们合在一起,就是完整的模型权重

tokenizer.json:保存分词器的完整可复现状态,通常包含 BPE 模型(vocab 与 merges)、normalizer、pre_tokenizer、post_processor、decoder 以及特殊符号的处理规则。你仓库中同时存在 vocab.json 与 merges.txt,说明分词器是 BPE;tokenizer.json 是它们的合并序列化版本,AutoTokenizer.from_pretrained 会优先读它。

tokenizer_config.json:为 Transformers 提供分词器的高层默认行为与元信息,尤其是特殊符号、最大长度、类名等

generation_config.json:为 model.generate 提供默认的采样与终止参数,未在调用时显式覆盖则使用这里的值,比如do_sample:true,启用随机采样。temperature:0.6,控制分布平滑度;top_k:20、top_p:0.95,限制采样空间,影响多样性与稳定性

第三步 编码加载和运行模型

我使用PyCharm新开一个新python项目。

首先通过pip下载pytorch

pip install torch transformers peft sentencepiece safetensors

导入必要的包

复制代码
import time

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

写个简单的计时方法,打印每个步骤的时间

复制代码
def tic():
    return time.perf_counter()

def toc(t0, msg):
    print(f"⏱ {msg}: {time.perf_counter() - t0:.3f} s")

开始计时,并且设置torch 12线程并发计算

复制代码
t0 = tic()

# ===== 基础设置 =====
torch.set_num_threads(12)

加载刚才拉下来的模型并记录时间

复制代码
model_path = r"E:\你刚才拉下来的项目地址\Qwen3-4B"
# ===== tokenizer =====
tokenizer = AutoTokenizer.from_pretrained(
    model_path,
    trust_remote_code=True
)

# ===== 加载 基础模型 模型 =====
base_model = AutoModelForCausalLM.from_pretrained(
    model_path,
    device_map="cpu",
    dtype=torch.float32,
    trust_remote_code=True,
    # 启用分块加载 + 就地绑定, 在加载模型权重时,避免“权重在内存里被复制一遍”,把“加载峰值内存”降到最低。
    low_cpu_mem_usage=True
)


toc(t0, "加载模型")
t0 = tic()

设置模型进行推理模式

base_model.eval()

这行代码相当于告诉模型:"现在是推理,不是训练,关闭训练专用行为,让模型进入确定性、稳定的推理模式,本质上是设置了model.training = False

构建给大模型的输入并且使用tokenizer编码

复制代码
messages = [
    {
        "role": "system",
        "content": "你是一个简洁的助手。"
    },
    {"role": "user",
     "content": "到底什么是光"}
]

input_ids = tokenizer.apply_chat_template(
    messages,
    return_tensors="pt",
    add_generation_prompt=True
)

# 构造 attention_mask
attention_mask = torch.ones_like(input_ids)

inputs = {
    "input_ids": input_ids.to(base_model.device),
    "attention_mask": attention_mask.to(base_model.device)
}

开始推理,这里限制最多输出96个token,不然等太久了

复制代码
with torch.no_grad():
    outputs = base_model.generate(
        # **inputs,
        **inputs,
        max_new_tokens=96,
        temperature=0.7,
        top_p=0.9,
        do_sample=True,
        use_cache=True
    )


toc(t0, "模型推理")

print("模型回答: \n")

print(tokenizer.decode(outputs[0], skip_special_tokens=True))

自此我们的代码就写好了,总代码如下

python 复制代码
import time

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM


# ================= 计时工具 =================
def tic():
    return time.perf_counter()

def toc(t0, msg):
    print(f"⏱ {msg}: {time.perf_counter() - t0:.3f} s")


# ================= 基础设置 =================

t0 = tic()

# ===== 基础设置 =====
torch.set_num_threads(12)

model_path = r"E:\it\project\pycharm\Qwen3-4B"
# ===== tokenizer =====
tokenizer = AutoTokenizer.from_pretrained(
    model_path,
    trust_remote_code=True
)

# ===== 加载 基础模型 模型 =====
base_model = AutoModelForCausalLM.from_pretrained(
    model_path,
    device_map="cpu",
    dtype=torch.float32,
    trust_remote_code=True,
    # 启用分块加载 + 就地绑定, 在加载模型权重时,避免"权重在内存里被复制一遍",把"加载峰值内存"降到最低。
    low_cpu_mem_usage=True
)



toc(t0, "加载模型")
t0 = tic()

# 告诉模型:"现在是推理,不是训练,关闭训练专用行为,让模型进入确定性、稳定的推理模式,本质上是设置了model.training = False
base_model.eval()



messages = [
    {
        "role": "system",
        "content": "你是一个简洁的助手。"
    },
    {"role": "user",
     "content": "到底什么是光"}
]

input_ids = tokenizer.apply_chat_template(
    messages,
    return_tensors="pt",
    add_generation_prompt=True
)

# 构造 attention_mask
attention_mask = torch.ones_like(input_ids)

inputs = {
    "input_ids": input_ids.to(base_model.device),
    "attention_mask": attention_mask.to(base_model.device)
}


#接下来的代码只做推理,不需要梯度,不要构建计算图
with torch.no_grad():
    outputs = base_model.generate(
        # **inputs,
        **inputs,
        max_new_tokens=96,
        temperature=0.7,
        top_p=0.9,
        do_sample=True,
        use_cache=True
    )


toc(t0, "模型推理")

print("模型回答: \n")

print(tokenizer.decode(outputs[0], skip_special_tokens=True))

推理过程

可以看见cpu消耗突然到了百分之60

推理结果

可以看见推理完成了,但是因为我设置max_new_tokens=96,输出不太完整,有条件的可以设置大一点。根据这个代码我们完全可以自己改装一下,变成一个web应用,给其他人提供chat gpt的功能,但是因为这部分和文章核心内容无关,就不做了。

相关推荐
西岸行者3 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意3 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码3 天前
嵌入式学习路线
学习
毛小茛3 天前
计算机系统概论——校验码
学习
babe小鑫3 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms3 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下3 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。3 天前
2026.2.25监控学习
学习
im_AMBER3 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J3 天前
从“Hello World“ 开始 C++
c语言·c++·学习