基于通义千问 LLM 实现本地简单多轮对话
在本地环境部署通义千问 Qwen1.5-0.5B-Chat 模型并实现多轮对话,需准备 Python 及 PyTorch 环境,通过 ModelScope 加载模型与分词器。利用 apply_chat_template 构建对话历史,设置系统提示语,调用 generate 生成回复并解码输出。完整脚本支持循环交互,可维护上下文记忆。针对显存不足、生成速度及上下文限制提供优化建议,包括量化、设备映射调整及历史记录管理策略。

在本地环境部署通义千问 Qwen1.5-0.5B-Chat 模型并实现多轮对话,需准备 Python 及 PyTorch 环境,通过 ModelScope 加载模型与分词器。利用 apply_chat_template 构建对话历史,设置系统提示语,调用 generate 生成回复并解码输出。完整脚本支持循环交互,可维护上下文记忆。针对显存不足、生成速度及上下文限制提供优化建议,包括量化、设备映射调整及历史记录管理策略。

Qwen(通义千问)是基于 Transformer 架构的纯解码器语言模型系列。其中 Qwen1.5-0.5B-Chat 是该系列中参数量最小的版本之一,非常适合在本地资源受限的环境下进行部署和测试。本文将详细介绍如何在本地环境加载该模型,并实现支持上下文记忆的多轮对话功能。
在开始之前,请确保您的开发环境满足以下要求:
python --version
pip install torch torchvision
pip install transformers
由于模型文件较大,下载速度可能较慢。建议配置国内镜像源以提升效率,例如使用阿里云镜像:
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
pip config set install.trusted-host mirrors.aliyun.com
此外,推荐使用 ModelScope(魔搭社区)作为模型托管平台,它提供了更便捷的模型加载接口:
pip install modelscope
我们需要从 ModelScope 或 HuggingFace 加载预训练模型。为了减少重复下载,可以将模型缓存到本地目录。
from modelscope import AutoTokenizer, AutoModelForCausalLM
import torch
# 设置本地缓存路径
local_model = "./my_local_models/Qwen1.5-0.5B-Chat"
# 初始化分词器
# torch_dtype="auto":自动检测适合的数据类型(如 float16),节省显存
# device_map="auto":自动将模型层分配到可用设备(CPU/GPU)
tokenizer = AutoTokenizer.from_pretrained(
"Qwen/Qwen1.5-0.5B-Chat",
torch_dtype="auto",
device_map="auto",
cache_dir=local_model,
)
# 保存分词器到本地,避免下次重新下载
tokenizer.save_pretrained(local_model)
# 初始化模型
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen1.5-0.5B-Chat",
cache_dir=local_model,
trust_remote_code=True # Qwen 模型通常需要开启此选项以加载自定义代码
)
# 保存模型权重到本地
model.save_pretrained(local_model)
参数说明:
trust_remote_code=True:允许加载包含自定义代码的模型,这对 Qwen 系列至关重要。cache_dir:指定模型文件的存储位置,首次运行后后续启动无需重新下载。大模型通常通过特定的对话格式来区分系统指令、用户输入和助手回复。Qwen 使用 <|im_start|> 和 <|im_end|> 标记来界定角色。
# 构建对话消息列表
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "你好,请介绍一下你自己。"}
]
# 应用聊天模板
# tokenize=False:返回字符串而非张量
# add_generation_prompt=True:添加生成提示符,指示模型开始回答
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
)
print(text)
生成的文本结构如下:
<|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
你好,请介绍一下你自己。<|im_end|>
<|im_start|>assistant
将格式化后的文本转换为模型可处理的输入张量,调用生成接口获取输出 ID,最后解码为人类可读的文本。
# 1. 分词并转为张量
model_inputs = tokenizer([text], return_tensors="pt")
# 2. 生成回复
# max_new_tokens:限制新生成的 token 数量,防止输出过长
generated_ids = model.generate(
model_inputs.input_ids,
max_new_tokens=512,
do_sample=True, # 采样模式,增加多样性
temperature=0.7, # 温度系数,控制随机性
)
# 3. 去除输入部分,仅保留生成内容
# zip 遍历输入 ID 和输出 ID,切片取差值
generated_ids = [
output_ids[len(input_ids):]
for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
# 4. 解码
response = tokenizer.batch_decode(
generated_ids,
skip_special_tokens=True # 移除 <|im_start|> 等标记
)[0]
print(f"模型回答:{response}")
为了实现真正的多轮对话,我们需要维护一个历史消息列表 conversation_history,并在每一轮交互中将新的问答追加到列表中,而不是每次重置。
from modelscope import AutoTokenizer, AutoModelForCausalLM
import torch
# 配置路径
local_model = "./my_local_models/Qwen1.5-0.5B-Chat"
# 加载模型(实际使用时建议封装成类或函数)
tokenizer = AutoTokenizer.from_pretrained(
"Qwen/Qwen1.5-0.5B-Chat",
torch_dtype="auto",
device_map="auto",
cache_dir=local_model,
trust_remote_code=True
)
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen1.5-0.5B-Chat",
cache_dir=local_model,
trust_remote_code=True
)
# 初始化对话历史,包含系统提示
conversation_history = [
{"role": "system", "content": "You are a helpful assistant."}
]
print("=== 本地 Qwen 多轮对话 ===")
print("输入 'q' 退出程序")
while True:
try:
prompt = input("\n用户:")
if prompt.strip().lower() == "q":
break
# 添加用户输入到历史
conversation_history.append({"role": "user", "content": prompt})
# 应用模板
text = tokenizer.apply_chat_template(
conversation_history,
tokenize=False,
add_generation_prompt=True,
)
# 推理
model_inputs = tokenizer([text], return_tensors="pt")
generated_ids = model.generate(
model_inputs.input_ids,
max_new_tokens=512,
do_sample=True,
temperature=,
)
generated_ids = [
output_ids[(input_ids):]
input_ids, output_ids (model_inputs.input_ids, generated_ids)
]
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=)[]
()
conversation_history.append({: , : response})
KeyboardInterrupt:
()
Exception e:
()
如果使用的是 GPU 但显存较小,可以尝试量化模型或使用 CPU 运行。
device_map="auto",改为 device_map="cpu"。bitsandbytes 库加载 4bit 或 8bit 量化模型,大幅降低显存占用。max_new_tokens 为较小的值(如 256)进行测试。do_sample 设为 greedy_search 可略微提升速度,但多样性会降低。小参数模型(如 0.5B)的上下文窗口有限。如果对话轮数过多,可能会超出最大序列长度导致截断。建议定期清理早期对话记录,只保留最近几轮交互。
如果遇到 transformers 版本不兼容问题,建议创建独立的虚拟环境(venv/conda)进行隔离。
本文演示了如何利用 Python 和 ModelScope 在本地快速部署通义千问 Qwen1.5-0.5B-Chat 模型。通过维护对话历史列表,实现了具备上下文理解能力的多轮对话。该方案适用于个人学习、原型验证及轻量级应用场景。对于生产环境,建议考虑模型量化、服务化封装及并发优化等措施。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online