
在大模型落地场景中本地轻量化部署因低延迟、高隐私性、无需依赖云端算力等优势成为开发者与 AI 爱好者的热门需求。本文聚焦 Windows 10/1164 位环境详细拆解 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 mkdir build cd build2.基础编译仅 CPU 支持或者选用GPU 加速编译已安装 CUDA Toolkit如果只使用CPU则执行如下配置 cmake .. -G Visual Studio 18 2026 -A x64 -DLLAMA_CURLOFF cmake --build . --config Release 如果已安装 CUDA Toolkit添加 -DLLAMA_CUDAON 开启 GPU 支持 cmake .. -G Visual Studio 18 2026 -A x64 -DLLAMA_CUDAON cmake --build . --config Release3、下载 GGUF 格式的 Qwen 模型以 7B 为例https://www.modelscope.cn/models pip install modelscope modelscope download --model Xorbits/Qwen-7B-Chat-GGUF下载后的保存位置为 \modelscope\hub\models\Xorbits4、运行模型启动 API 服务支持 HTTP 调用# 命令行启动 chcp 65001 llama-cli.exe -m qwen.gguf -i -c 4096 # CPU 版 llama-server.exe -m qwen.gguf --host 127.0.0.1 --port 11433 -c 4096 # GPU 加速版 llama-server.exe -m qwen-7b-chat.Q4_0.gguf -c 4096 --n-gpu-layers -15、服务启动后默认监听 http://localhost:8080 可通过 curl 测试调用效果。curl http://localhost:8080/completion -H Content-Type: application/json -d { prompt: 你好介绍一下通义千问, temperature: 0.7, max_tokens: 512 }6、工具测试通过代码调用大模型测试效果。基础非流式调用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, headersheaders, datajson.dumps(data), timeout60) response.raise_for_status() result response.json() print(生成结果) print(result[content]) except Exception as e: print(f调用失败{e})多轮对话示例基于 chat/completionsimport 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, headersheaders, datajson.dumps(data), timeout60) 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助手{answer}\n)带有对话记忆功能测试import requests import json import re # 初始化对话历史包含系统提示引导模型记上下文 chat_history [ {role: system, content: 你是一个有帮助的助手必须记住之前的对话内容基于上下文回答用户问题。} ] # 你的服务实际地址保持你原来的 11433 端口和 OpenAI 兼容路径 url http://localhost:11433/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, headersheaders, datajson.dumps(data), timeout60) response.raise_for_status() # 触发 HTTP 错误比如 404、500 result response.json() print(f调试模型原始返回 {json.dumps(result, ensure_asciiFalse)[:500]}) # 可选查看原始返回 # 适配你的 OpenAI 兼容格式从 choices[0].message.content 提取内容 if choices in result and len(result[choices]) 0: choice result[choices][0] if message in choice and content in choice[message]: raw_answer choice[message][content] answer clean_pad_content(raw_answer) # 过滤 PAD 垃圾字符 # 关键将助手回复加入历史下次请求会带上 chat_history.append({role: assistant, content: answer}) return answer else: return f返回格式异常缺少 message/content 字段原始返回{json.dumps(result, ensure_asciiFalse)[:300]} else: return f返回格式异常缺少 choices 字段原始返回{json.dumps(result, ensure_asciiFalse)[:300]} except requests.exceptions.ConnectionError: return 连接失败请检查本地服务是否在 11433 端口运行 except requests.exceptions.Timeout: return 请求超时模型响应过慢 except Exception as e: return f调用失败{str(e)}原始返回{response.text[:300] if response in locals() else 无} # 多轮对话测试重点测试上下文记忆 print(开始多轮对话输入退出结束) print(提示先发送 我的名字是李四再发送 我叫什么名字 测试记忆功能\n) while True: user_input input(你) if user_input.strip() 退出: break if not user_input.strip(): print(助手请输入有效内容\n) continue answer chat_with_model(user_input) print(f助手{answer}\n)函数工具调用测试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: True, description: 加数2} } } } # 2. 初始化对话历史和基础配置 chat_history [ {role: system, content: 你是一个有帮助的助手必须记住之前的对话内容基于上下文回答用户问题。 你可以调用以下工具来辅助回答 1. get_current_time获取当前的本地时间无需参数 2. calculate_add计算两个数字的加法需要参数a和b均为数字 如果需要调用工具请严格按照以下JSON格式返回仅返回JSON不要加其他内容 {name: 工具名, parameters: {参数名: 参数值}} 如果不需要调用工具直接回答用户问题即可不要返回JSON格式。} ] # 本地LLM服务地址 url http://localhost:11433/chat/completions headers {Content-Type: application/json} # 3. 工具调用相关辅助函数 def clean_pad_content(content): 过滤模型返回的 [PAD...] 垃圾字符 return re.sub(r\[PAD\d\], , content).strip() def parse_tool_call(content): 解析模型返回的内容提取工具调用指令JSON格式 try: # 提取JSON部分兼容模型返回时可能带的多余文字 json_match re.search(r\{[\s\S]*\}, content) if not json_match: return None tool_call json.loads(json_match.group()) # 验证必要字段 if name in tool_call and parameters in tool_call: return tool_call return None except (json.JSONDecodeError, Exception): return None def execute_tool(tool_call): 执行工具调用返回执行结果 tool_name tool_call[name] parameters tool_call.get(parameters, {}) # 检查工具是否存在 if tool_name not in tool_registry: return f错误不存在名为 {tool_name} 的工具可用工具{list(tool_registry.keys())} tool_info tool_registry[tool_name] tool_func tool_info[function] tool_params tool_info[parameters] # 验证必填参数 missing_params [] for param_name, param_info in tool_params.items(): if param_info.get(required) and param_name not in parameters: missing_params.append(param_name) if missing_params: return f错误调用 {tool_name} 缺少必填参数{, .join(missing_params)} # 转换参数类型比如字符串转数字 try: for param_name, param_info in tool_params.items(): if param_name in parameters: param_type param_info.get(type, str) if param_type float: parameters[param_name] float(parameters[param_name]) elif param_type int: parameters[param_name] int(parameters[param_name]) except ValueError as e: return f错误参数类型转换失败 - {str(e)} # 执行工具函数 try: result tool_func(**parameters) return f工具调用成功{tool_name}{result} except Exception as e: return f错误执行 {tool_name} 失败 - {str(e)} # 4. 核心对话函数支持工具调用 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] } try: # 第一次调用模型获取是否需要工具调用的响应 response requests.post(url, headersheaders, datajson.dumps(data), timeout60) response.raise_for_status() result response.json() # 解析模型原始返回 if choices in result and len(result[choices]) 0 and message in result[choices][0]: raw_answer result[choices][0][message][content] clean_answer clean_pad_content(raw_answer) else: return f返回格式异常{json.dumps(result, ensure_asciiFalse)[:300]} # 解析是否包含工具调用指令 tool_call parse_tool_call(clean_answer) if tool_call: print(f 检测到工具调用{json.dumps(tool_call, ensure_asciiFalse)}) # 执行工具并获取结果 tool_result execute_tool(tool_call) print(f 工具执行结果{tool_result}) # 将工具执行结果加入对话历史让模型感知结果 chat_history.append({ role: assistant, content: f工具调用结果{tool_result} }) # 第二步基于工具结果再次调用模型生成最终回答 second_response requests.post(url, headersheaders, datajson.dumps(data), timeout60) second_response.raise_for_status() second_result second_response.json() # 解析第二次调用的结果 if choices in second_result and len(second_result[choices]) 0 and message in \ second_result[choices][0]: final_answer clean_pad_content(second_result[choices][0][message][content]) chat_history.append({role: assistant, content: final_answer}) return final_answer else: return f工具调用后二次请求异常{json.dumps(second_result, ensure_asciiFalse)[:300]} else: # 无需调用工具直接返回模型回答 chat_history.append({role: assistant, content: clean_answer}) return clean_answer except requests.exceptions.ConnectionError: return 连接失败请检查本地服务是否在 11433 端口运行 except requests.exceptions.Timeout: return 请求超时模型响应过慢 except Exception as e: return f调用失败{str(e)}原始返回{response.text[:300] if response in locals() else 无} # 5. 多轮对话测试含工具调用 if __name__ __main__: print(开始多轮对话输入退出结束) print( 测试工具调用示例) print( 1. 现在几点了调用获取时间工具) print( 2. 计算123456等于多少调用加法工具) print( 3. 我的名字是李四我叫什么测试上下文记忆\n) while True: user_input input(你) if user_input.strip() 退出: break if not user_input.strip(): print(助手请输入有效内容\n) continue answer chat_with_model(user_input) print(f助手{answer}\n)