学习日期:2026-09-19
实践内容:本地部署开源大语言模型、单轮问答、多轮循环问答
使用模型:
Qwen/Qwen1.5-0.5B-Chat参考资料:Datawhale Hello-Agents 第三章《大语言模型基础》1
本章主要介绍了语言模型的发展、Transformer 架构、提示工程、文本分词以及开源大语言模型的本地调用。本文重点记录我在第三章中的动手实践过程:在本地运行一个轻量级 Qwen 对话模型,并在教程代码基础上增加循环问答功能。
一、实践目标
本次实践主要完成以下任务:
- 在本地加载开源对话模型;
- 使用分词器将自然语言转换为 Token ID;
- 调用模型的
generate()方法生成回答; - 将模型输出的 Token ID 解码为文本;
- 在原有单轮问答基础上,增加循环问答和上下文记忆功能;
- 记录实践过程中遇到的网络和依赖问题。
二、实践环境
本次实践使用的是本地 Jupyter Notebook 环境:
- 操作系统:Windows
- Python 环境:Anaconda
asr - 运行设备:CPU
- 模型来源:ModelScope
- 模型名称:
Qwen/Qwen1.5-0.5B-Chat
由于直接访问 Hugging Face 时出现了连接超时问题,本次实践改用 ModelScope 下载模型。ModelScope 可以提供相同的 Qwen 模型,并且在国内网络环境下更加稳定。
三、相关知识点回顾
1. 大语言模型的生成方式
本次使用的 Qwen 模型属于 Decoder-Only 架构。它的基本工作方式是自回归生成:
- 输入已有文本;
- 模型预测下一个最可能出现的 Token;
- 将新 Token 加入输入;
- 重复这个过程,直到生成完整回答。
因此,大语言模型并不是一次性生成完整句子,而是一个 Token 一个 Token 地逐步生成。
2. 分词器的作用
计算机不能直接处理自然语言文本,需要使用分词器将文本转换为 Token ID。例如,本次实践中的输入:
text
你好,请介绍你自己。
经过分词器编码后,会变成类似下面的张量:
text
{'input_ids': tensor([[151644, 8948, 198, 2610, 525, 264, ...]]),
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, ...]])}
模型实际处理的是这些数字,而不是原始汉字。
3. 对话模板
对话模型通常需要按照固定格式组织输入。Qwen 提供了 apply_chat_template() 方法,可以把 system、user、assistant 等角色转换成模型能够理解的对话格式。
四、加载本地模型
首先导入 PyTorch 和 ModelScope 中的模型加载类:
python
import torch
from modelscope import AutoModelForCausalLM, AutoTokenizer
model_id = "Qwen/Qwen1.5-0.5B-Chat"
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using device: {device}")
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id,
torch_dtype="auto"
).to(device)
print("模型和分词器加载完成!")
我的电脑没有使用 GPU,因此输出为:
text
Using device: cpu
模型和分词器加载完成!
第一次运行时会自动下载模型文件。下载完成后,后续运行会直接使用本地缓存,不需要重新下载完整模型。
五、实现单轮问答
教程中的基础代码是构造一个 messages 列表,然后使用对话模板进行编码:
python
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "你好,请介绍你自己。"}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
model_inputs = tokenizer([text], return_tensors="pt").to(device)
接着调用 generate() 生成回答:
python
generated_ids = model.generate(
model_inputs.input_ids,
max_new_tokens=512
)
generated_ids = [
output_ids[len(input_ids):]
for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
response = tokenizer.batch_decode(
generated_ids,
skip_special_tokens=True
)[0]
print("模型的回答:")
print(response)
运行结果为:
text
模型的回答:
我是来自阿里云的大规模语言模型,我叫通义千问。
这一步让我完整看到了大语言模型从文本输入到文本输出的过程:
text
用户文本
↓
对话模板
↓
Token ID
↓
模型生成新的 Token ID
↓
分词器解码
↓
自然语言回答
六、改进:增加循环问答功能
教程中的代码只能完成一次问答。为了更接近真实聊天场景,我在原代码基础上增加了循环问答功能。
1. 改进内容
主要增加了以下功能:
- 使用
while True持续接收用户输入; - 使用
messages保存对话历史; - 最多保留最近 6 轮问答,避免上下文过长;
- 支持
quit、exit、bye、退出、再见等退出命令; - 支持
/clear清空对话历史; - 使用
attention_mask参与生成; - 只解码模型新生成的 Token;
- 增加空输入和异常处理。
2. 关键代码
python
messages = [
{"role": "system", "content": "你是一个有帮助的中文助手,回答请简洁、准确。"}
]
MAX_HISTORY_TURNS = 6
EXIT_COMMANDS = {"quit", "exit", "bye", "退出", "再见"}
CLEAR_COMMANDS = {"/clear", "clear", "清空", "清空历史"}
while True:
try:
user_input = input("用户:").strip()
except (EOFError, KeyboardInterrupt):
print("\n助手:对话已结束。")
break
if not user_input:
print("助手:请输入内容后再发送。")
continue
if user_input.lower() in EXIT_COMMANDS:
print("助手:再见!")
break
if user_input.lower() in CLEAR_COMMANDS:
messages = [
{"role": "system", "content": "你是一个有帮助的中文助手,回答请简洁、准确。"}
]
print("助手:对话历史已清空。")
continue
messages.append({"role": "user", "content": user_input})
# 只保留 system 和最近几轮问答
if len(messages) > 1 + MAX_HISTORY_TURNS * 2:
messages = [messages[0]] + messages[-MAX_HISTORY_TURNS * 2:]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
model_inputs = tokenizer([text], return_tensors="pt").to(device)
with torch.no_grad():
generated_ids = model.generate(
**model_inputs,
max_new_tokens=256,
do_sample=True,
temperature=0.7,
top_p=0.8,
repetition_penalty=1.05,
pad_token_id=tokenizer.eos_token_id
)
new_token_ids = generated_ids[0][model_inputs.input_ids.shape[-1]:]
response = tokenizer.decode(
new_token_ids,
skip_special_tokens=True
).strip()
messages.append({"role": "assistant", "content": response})
print(f"助手:{response}\n")
3. 循环问答运行结果
程序启动后显示:
text
已进入循环问答模式
输入 quit / exit / bye / 退出 / 再见 可以结束对话
输入 /clear 可以清空对话历史
我进行了两轮关于 AI 经济的测试:
text
用户:你觉得AI经济存在泡沫吗?
助手:AI经济的发展确实存在一定的泡沫现象,因为AI技术的快速发展导致了大量的人才失业和就业机会减少,这给社会带来了不确定性。另外,AI技术的广泛应用也可能会带来一些不可预见的风险,比如数据安全问题等。因此,我们需要在推动AI经济发展的同时,也要关注其可能带来的风险,采取相应的措施来防范和应对这些风险。
用户:AI经济泡沫会在几年内破裂呢?
助手:AI经济泡沫破裂的时间取决于许多因素,包括AI技术的成熟度、市场环境的变化、政策法规的调整等。目前来看,AI经济泡沫还没有完全破裂,但随着技术的不断进步和政策法规的不断完善,未来几年内AI经济泡沫的可能性可能会进一步降低。
从结果可以看到,第二个问题使用了第一个问题的上下文,说明 messages 中保存的对话历史已经生效。
不过也能看出,小模型的回答比较笼统,缺少数据和明确依据。这正好对应了本章提到的模型幻觉和可靠性问题:模型可以生成看似合理的回答,但回答内容不一定经过事实验证。
七、实践中遇到的问题及解决方法
1. Hugging Face 连接超时
最开始使用 Hugging Face 下载模型时,出现了连接超时:
text
WinError 10060
由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。
原因是当前网络无法稳定访问 Hugging Face。解决方法是改用 ModelScope:
python
from modelscope import AutoModelForCausalLM, AutoTokenizer
并将模型来源改为:
python
model_id = "Qwen/Qwen1.5-0.5B-Chat"
2. ModelScope 依赖版本不兼容
使用 ModelScope 时,还遇到过下面的错误:
text
ImportError: cannot import name 'DEFAULT_CREDENTIALS_PATH'
from 'modelscope_hub.compat.constants'
这个错误说明 modelscope 和 modelscope-hub 版本不匹配。解决方法是卸载后安装兼容版本:
bash
D:\anaconda3\envs\asr\python.exe -m pip uninstall -y modelscope modelscope-hub
D:\anaconda3\envs\asr\python.exe -m pip install --no-cache-dir "modelscope==1.40.1" "modelscope-hub==0.4.3" -i https://pypi.tuna.tsinghua.edu.cn/simple
安装后重启 Jupyter Kernel,再运行下面的代码检查:
python
import modelscope_hub.compat.constants as constants
print(constants.DEFAULT_CREDENTIALS_PATH)
print("modelscope-hub 检查通过")
检查通过后,模型就可以正常加载。
3. TqdmWarning
运行过程中还出现了:
text
TqdmWarning: IProgress not found
这个提示只是 Jupyter 进度条组件的警告,不影响模型下载和运行,可以暂时忽略。
八、学习心得
通过本次实践,我对第三章的内容有了更直观的理解。
首先,我认识到大语言模型并不是直接"理解文字",而是通过分词器将文本转换为 Token ID,再由模型基于上下文逐步生成新的 Token。apply_chat_template()、generate() 和 decode() 分别对应输入格式化、模型生成和输出解码三个关键步骤。
其次,我在原有代码基础上增加了循环问答功能。这让我理解了对话历史中 system、user 和 assistant 三种角色的作用,也认识到上下文窗口不能无限增长,因此需要限制保留的历史轮数。
最后,这次实践也让我看到了小模型的局限。它可以完成基本对话,但在回答开放性问题时可能会给出比较笼统、缺少依据的内容。因此,在实际构建智能体时,还需要结合检索、工具调用和人工校验,不能完全相信模型生成的结果。
九、参考资料
1 Datawhale. Hello-Agents:第三章 大语言模型基础EB/OL. https://github.com/datawhalechina/hello-agents
2 ModelScope. Qwen1.5-0.5B-Chat 模型页EB/OL. https://modelscope.cn/models/Qwen/Qwen1.5-0.5B-Chat