在大模型落地场景中,本地轻量化部署因低延迟、高隐私性、无需依赖云端算力等优势,成为开发者与 AI 爱好者的热门需求。本文聚焦 Windows 10/11(64 位)环境,详细拆解 llama.cpp 工具的编译流程(支持 CPU/GPU 双模式,GPU 加速需依赖 NVIDIA CUDA),并指导如何通过 modelscope 下载 GGUF 格式的 Qwen-7B-Chat 模型,最终实现模型本地启动与 API 服务搭建。
1. 克隆代码
打开管理员权限的 PowerShell/CMD,执行以下命令克隆代码:
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp
mkdir build
cd build
2. 编译项目
基础编译(仅 CPU 支持)或者选用 GPU 加速编译(已安装 CUDA Toolkit)。
# 如果只使用 CPU 则执行如下配置
cmake .. -G "Visual Studio 17 2022" -A x64 -DLLAMA_CURL=OFF
cmake --build . --config Release
# 如果已安装 CUDA Toolkit,添加 -DLLAMA_CUDA=ON 开启 GPU 支持
cmake .. -G "Visual Studio 17 2022" -A x64 -DLLAMA_CUDA=ON
cmake --build . --config Release
3. 下载模型
下载 GGUF 格式的 Qwen 模型(以 7B 为例)。
pip install modelscope
modelscope download --model Xorbits/Qwen-7B-Chat-GGUF
下载后的保存位置通常为 \modelscope\hub\models\Xorbits。
4. 启动服务
运行模型启动 API 服务(支持 HTTP 调用)。
# CPU 版
cp 65001
llama-cli.exe -m qwen.gguf -i -c 4096
# GPU 加速版
llama-server.exe -m qwen-7b-chat.Q4_0.gguf -c 4096 --n-gpu-layers -1 --port 8080
5. 测试调用
服务启动后默认监听 http://localhost:8080,可通过 curl 测试调用效果。
curl http://localhost:8080/completion -H "Content-Type: application/json" -d '{ "prompt": "你好,介绍一下通义千问", "temperature": 0.7, "max_tokens": 512 }'
6. 代码调用示例
通过 Python 代码调用大模型测试效果。
基础非流式调用(completion 端点)
import requests
import json
url = "http://localhost:8080/completion"
headers = {"Content-Type": "application/json"}
data = {
"model": "qwen.gguf",
"prompt": "你好,请用 100 字介绍一下通义千问",
"temperature": 0.7, # 回答随机性(越低越保守)
"max_tokens": 512, # 最大生成 token 数
"ctx_size": 4096, # 上下文窗口(与服务启动时一致)
"stop": ["<|im_end|>"] # 停止符(适配 Qwen 的对话格式)
}
try:
response = requests.post(url, headers=headers, data=json.dumps(data), timeout=60)
response.raise_for_status()
result = response.json()
print("生成结果:")
print(result["content"])
except Exception as e:
print(f"调用失败:{e}")
多轮对话示例(基于 chat/completions)
import requests
import json
chat_history = []
url = "http://localhost:8080/chat/completions"
headers = {"Content-Type": "application/json"}
def chat_with_model(prompt):
# 添加当前用户消息到历史
chat_history.append({"role": "user", "content": prompt})
data = {
"model": "qwen.gguf",
"messages": chat_history,
"temperature": 0.7,
"max_tokens": 512
}
try:
response = requests.post(url, headers=headers, data=json.dumps(data), timeout=60)
response.raise_for_status()
result = response.json()
answer = result["choices"][0]["message"]["content"]
# 添加助手回答到历史
chat_history.append({"role": "assistant", "content": answer})
return answer
except Exception as e:
return f"调用失败:{e}"
# 多轮对话示例
print("开始多轮对话(输入'退出'结束):")
while True:
user_input = input("你:")
if user_input == "退出":
break
answer = chat_with_model(user_input)
print(f"助手:\n")
带有对话记忆功能测试
import requests
import json
import re
# 初始化对话历史(包含系统提示,引导模型记上下文)
chat_history = [{"role": "system", "content": "你是一个有帮助的助手,必须记住之前的对话内容,基于上下文回答用户问题。"}]
# 你的服务实际地址(保持你原来的 8080 端口和 OpenAI 兼容路径)
url = "http://localhost:8080/chat/completions"
headers = {"Content-Type": "application/json"}
def clean_pad_content(content):
"""过滤模型返回的 [PAD...] 垃圾字符"""
return re.sub(r'\[PAD\d+\]', '', content).strip()
def chat_with_model(prompt):
global chat_history
# 添加当前用户消息到历史(关键:上下文靠这个列表传递)
chat_history.append({"role": "user", "content": prompt})
data = {
"model": "qwen.gguf", # 保持你原来的模型名(你的服务识别这个名字)
"messages": chat_history, # 传递完整对话历史
"temperature": 0.7,
"max_tokens": 512,
"stream": False, # 关闭流式输出,适配你的返回格式
"stop": ["[PAD"] # 提前终止 PAD 字符的输出
}
try:
response = requests.post(url, headers=headers, data=json.dumps(data), timeout=60)
response.raise_for_status()
result = response.json()
print(f"调试:模型原始返回 = ")
result (result[]) > :
choice = result[][]
choice choice[]:
raw_answer = choice[][]
answer = clean_pad_content(raw_answer)
chat_history.append({: , : answer})
answer
:
:
requests.exceptions.ConnectionError:
requests.exceptions.Timeout:
Exception e:
()
()
:
user_input = ()
user_input.strip() == :
user_input.strip():
()
answer = chat_with_model(user_input)
()
函数工具调用测试
import requests
import json
import re
from datetime import datetime
# ====================== 1. 定义可用工具集 ======================
# 工具 1:获取当前时间
def get_current_time():
"""获取当前的本地时间,格式为 年 - 月 - 日 时:分:秒"""
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return f"当前时间为:{current_time}"
# 工具 2:加法计算
def calculate_add(a: float, b: float):
"""计算两个数的加法结果"""
return f"{a} + {b} = {a + b}"
# 工具注册表(核心:映射工具名到函数和描述,供模型识别)
tool_registry = {
"get_current_time": {
"function": get_current_time,
"description": "获取当前的本地时间,无需参数",
"parameters": {} # 无参数
},
"calculate_add": {
"function": calculate_add,
"description": "计算两个数字的加法,需要两个参数:a(数字)、b(数字)",
"parameters": {
"a": {"type": "float", "required": True, "description": "加数 1"},
"b": {"type": "float", "required": , : }
}
}
}
chat_history = [{: , : }]
url =
headers = {: }
():
re.sub(, , content).strip()
():
:
json_match = re.search(, content)
json_match:
tool_call = json.loads(json_match.group())
tool_call tool_call:
tool_call
(json.JSONDecodeError, Exception):
():
tool_name = tool_call[]
parameters = tool_call.get(, {})
tool_name tool_registry:
tool_info = tool_registry[tool_name]
tool_func = tool_info[]
tool_params = tool_info[]
missing_params = []
param_name, param_info tool_params.items():
param_info.get() param_name parameters:
missing_params.append(param_name)
missing_params:
:
param_name, param_info tool_params.items():
param_name parameters:
param_type = param_info.get(, )
param_type == :
parameters[param_name] = (parameters[param_name])
param_type == :
parameters[param_name] = (parameters[param_name])
ValueError e:
:
result = tool_func(**parameters)
Exception e:
():
chat_history
chat_history.append({: , : prompt})
data = {
: ,
: chat_history,
: ,
: ,
: ,
: []
}
:
response = requests.post(url, headers=headers, data=json.dumps(data), timeout=)
response.raise_for_status()
result = response.json()
result (result[]) > result[][]:
raw_answer = result[][][][]
clean_answer = clean_pad_content(raw_answer)
:
tool_call = parse_tool_call(clean_answer)
tool_call:
()
tool_result = execute_tool(tool_call)
()
chat_history.append({: , : })
second_response = requests.post(url, headers=headers, data=json.dumps(data), timeout=)
second_response.raise_for_status()
second_result = second_response.json()
second_result (second_result[]) > second_result[][]:
final_answer = clean_pad_content(second_result[][][][])
chat_history.append({: , : final_answer})
final_answer
:
:
chat_history.append({: , : clean_answer})
clean_answer
requests.exceptions.ConnectionError:
requests.exceptions.Timeout:
Exception e:
__name__ == :
()
()
()
()
()
:
user_input = ()
user_input.strip() == :
user_input.strip():
()
answer = chat_with_model(user_input)
()

