Windows 环境下 llama.cpp 编译 + Qwen 模型本地部署全指南

在大模型落地场景中,本地轻量化部署因低延迟、高隐私性、无需依赖云端算力等优势,成为开发者与 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 mkdir build cd build 

2.基础编译(仅 CPU 支持)或者选用GPU 加速编译(已安装 CUDA Toolkit)

如果只使用CPU则执行如下配置 cmake ..-G"Visual Studio 18 2026"-A x64 -DLLAMA_CURL=OFF cmake --build.--config Release 如果已安装 CUDA Toolkit,添加 -DLLAMA_CUDA=ON 开启 GPU 支持 cmake ..-G"Visual Studio 18 2026"-A x64 -DLLAMA_CUDA=ON cmake --build.--config Release 

3、下载 GGUF 格式的 Qwen 模型(以 7B 为例)

https://www.modelscope.cn/models pip install modelscope modelscope download --model Xorbits/Qwen-7B-Chat-GGUF 

下载后的保存位置为 \modelscope\hub\models\Xorbits

4、运行模型启动 API 服务(支持 HTTP 调用)

# 命令行启动 chcp 65001 llama-cli.exe -m qwen.gguf -i-c4096# CPU 版 llama-server.exe -m qwen.gguf --host127.0.0.1 --port11433-c4096# GPU 加速版 llama-server.exe -m qwen-7b-chat.Q4_0.gguf -c4096 --n-gpu-layers -1

5、服务启动后默认监听 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, 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"}defchat_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:returnf"调用失败:{e}"# 多轮对话示例print("开始多轮对话(输入'退出'结束):")whileTrue: 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"}defclean_pad_content(content):"""过滤模型返回的 [PAD...] 垃圾字符"""return re.sub(r'\[PAD\d+\]','', content).strip()defchat_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()# 触发 HTTP 错误(比如 404、500) result = response.json()print(f"调试:模型原始返回 = {json.dumps(result, ensure_ascii=False)[:500]}")# 可选:查看原始返回# 适配你的 OpenAI 兼容格式:从 choices[0].message.content 提取内容if"choices"in result andlen(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:returnf"返回格式异常:缺少 message/content 字段,原始返回:{json.dumps(result, ensure_ascii=False)[:300]}"else:returnf"返回格式异常:缺少 choices 字段,原始返回:{json.dumps(result, ensure_ascii=False)[:300]}"except requests.exceptions.ConnectionError:return"连接失败:请检查本地服务是否在 11433 端口运行"except requests.exceptions.Timeout:return"请求超时:模型响应过慢"except Exception as e:returnf"调用失败:{str(e)},原始返回:{response.text[:300]if'response'inlocals()else'无'}"# 多轮对话测试(重点测试上下文记忆)print("开始多轮对话(输入'退出'结束):")print("提示:先发送 '我的名字是李四',再发送 '我叫什么名字' 测试记忆功能\n")whileTrue: user_input =input("你:")if user_input.strip()=="退出":breakifnot 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:获取当前时间defget_current_time():"""获取当前的本地时间,格式为 年-月-日 时:分:秒""" current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")returnf"当前时间为:{current_time}"# 工具2:加法计算defcalculate_add(a:float, b:float):"""计算两个数的加法结果"""returnf"{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. 工具调用相关辅助函数 ======================defclean_pad_content(content):"""过滤模型返回的 [PAD...] 垃圾字符"""return re.sub(r'\[PAD\d+\]','', content).strip()defparse_tool_call(content):"""解析模型返回的内容,提取工具调用指令(JSON格式)"""try:# 提取JSON部分(兼容模型返回时可能带的多余文字) json_match = re.search(r'\{[\s\S]*\}', content)ifnot json_match:returnNone tool_call = json.loads(json_match.group())# 验证必要字段if"name"in tool_call and"parameters"in tool_call:return tool_call returnNoneexcept(json.JSONDecodeError, Exception):returnNonedefexecute_tool(tool_call):"""执行工具调用,返回执行结果""" tool_name = tool_call["name"] parameters = tool_call.get("parameters",{})# 检查工具是否存在if tool_name notin tool_registry:returnf"错误:不存在名为 {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 notin parameters: missing_params.append(param_name)if missing_params:returnf"错误:调用 {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:returnf"错误:参数类型转换失败 - {str(e)}"# 执行工具函数try: result = tool_func(**parameters)returnf"工具调用成功({tool_name}):{result}"except Exception as e:returnf"错误:执行 {tool_name} 失败 - {str(e)}"# ====================== 4. 核心对话函数(支持工具调用) ======================defchat_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, headers=headers, data=json.dumps(data), timeout=60) response.raise_for_status() result = response.json()# 解析模型原始返回if"choices"in result andlen(result["choices"])>0and"message"in result["choices"][0]: raw_answer = result["choices"][0]["message"]["content"] clean_answer = clean_pad_content(raw_answer)else:returnf"返回格式异常:{json.dumps(result, ensure_ascii=False)[:300]}"# 解析是否包含工具调用指令 tool_call = parse_tool_call(clean_answer)if tool_call:print(f"📢 检测到工具调用:{json.dumps(tool_call, ensure_ascii=False)}")# 执行工具并获取结果 tool_result = execute_tool(tool_call)print(f"🔧 工具执行结果:{tool_result}")# 将工具执行结果加入对话历史(让模型感知结果) chat_history.append({"role":"assistant","content":f"工具调用结果:{tool_result}"})# 第二步:基于工具结果,再次调用模型生成最终回答 second_response = requests.post(url, headers=headers, data=json.dumps(data), timeout=60) second_response.raise_for_status() second_result = second_response.json()# 解析第二次调用的结果if"choices"in second_result andlen(second_result["choices"])>0and"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:returnf"工具调用后二次请求异常:{json.dumps(second_result, ensure_ascii=False)[: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:returnf"调用失败:{str(e)},原始返回:{response.text[:300]if'response'inlocals()else'无'}"# ====================== 5. 多轮对话测试(含工具调用) ======================if __name__ =="__main__":print("开始多轮对话(输入'退出'结束):")print("📌 测试工具调用示例:")print(" 1. 现在几点了?(调用获取时间工具)")print(" 2. 计算123+456等于多少?(调用加法工具)")print(" 3. 我的名字是李四,我叫什么?(测试上下文记忆)\n")whileTrue: user_input =input("你:")if user_input.strip()=="退出":breakifnot user_input.strip():print("助手:请输入有效内容!\n")continue answer = chat_with_model(user_input)print(f"助手:{answer}\n")

Read more

【顶尖无人机企业都在用的避障方案】:TOP 5算法对比及选型指南

第一章:无人机避障技术的发展现状与挑战 近年来,随着无人机在物流、农业、测绘和安防等领域的广泛应用,避障技术作为保障其安全飞行的核心能力,得到了快速演进。现代无人机避障系统普遍融合了多种传感器与智能算法,以实现对复杂环境的实时感知与响应。 主流避障传感器对比 不同类型的传感器在精度、成本和适用场景上各有优劣,常见的组合包括: 传感器类型探测距离优点局限性超声波0.1–5 m成本低,测距稳定易受温度和表面材质影响红外0.1–3 m响应快,体积小易受强光干扰激光雷达(LiDAR)1–100 m高精度,远距离成本高,体积较大立体视觉(Stereo Vision)0.5–20 m可识别纹理与形状依赖光照,计算量大 基于深度学习的动态避障策略 当前前沿研究倾向于将卷积神经网络(CNN)与强化学习结合,实现动态路径规划。例如,使用YOLOv8进行实时障碍物检测,并通过决策网络输出避障指令。 # 示例:使用OpenCV与YOLO进行障碍物检测 import cv2 net = cv2.

By Ne0inhk
写给技术管理者的低代码手册系列文章(6)——第二部分:低代码的概念、价值与发展现状(第二章)

写给技术管理者的低代码手册系列文章(6)——第二部分:低代码的概念、价值与发展现状(第二章)

在明确了低代码的商业定位后,我们需要关注的是另一个所有商业产品都需要回答的首要问题,企业为什么愿意为低代码买单?要回答这个问题,不能只从开发效率提升、少写代码这样的技术视角出发,而必须回到企业软件的总体投入与产出结构,也就是企业在软件上的“总账”。 2.1 从“买一个系统”到“养一个系统” 在大多数企业的决策语境中,软件首先被当作一种“可以购买或交付的对象”。 无论是立项一个定制开发项目,还是采购一套成品软件,讨论的重心通常集中在几个明确的问题上:多少钱、多久交付、功能是否覆盖需求。在这一阶段,软件的成本看起来是清晰的、可控的,甚至是可以精确比较的。但当系统真正投入使用后,企业很快会发现,最初讨论的那笔钱,只是整个账目中最小、也最容易理解的一部分,属于冰山的一角,那么该如何看清隐藏在水面下的冰山呢? 图:企业软件成本构成以不可见的隐形成本为主 2.1.1 从“项目成本”到“生命周期成本”的视角转换 一个典型的企业系统,很少只服务于某一个短期目标。它往往伴随着业务一起运行多年,并不断被调整、扩展和修补。

By Ne0inhk
【STM32项目开源】基于STM32的智能家居环境监测系统

【STM32项目开源】基于STM32的智能家居环境监测系统

目录 一、设计背景和意义 1.1设计背景 1.2设计意义 二、实物效果展示 2.1实物图片 2.2实物演示视频 三、硬件功能简介 3.1项目功能详解 3.2元器件清单 四、主框图与软件流程图 五、硬件PCB展示 六、软件程序设计 七、项目资料包内容          资料获取:查看主页介绍“充哥单片机设计” 一、设计背景和意义 1.1设计背景         随着物联网(IoT)、嵌入式系统和云计算等技术的飞速发展,智能家居系统正在逐渐改变人们的生活方式。智能家居不仅仅是简单的远程开关控制,而是向着环境感知、自主判断、智能决策的方向不断演进。特别是在城市化进程加快、生活节奏加快的背景下,用户对生活便捷性、家庭安全性和环境舒适度的要求不断提高,这对智能家居系统的综合感知、智能响应能力提出了更高的要求。         当前市面上的智能家居产品多以分立模块存在,系统功能较为单一,

By Ne0inhk
宇树G1机器人强化学习训练完整实战教程

宇树G1机器人强化学习训练完整实战教程

0. 前言 人形机器人的运动控制一直是机器人领域的重要挑战,而强化学习为解决这一问题提供了强有力的工具。本教程将基于宇树G1人形机器人,从基础的强化学习环境搭建开始,逐步深入到高自由度模型的训练配置、奖励函数设计与优化,最终实现复杂动作的训练控制。作者看到一个很棒的系列,所以针对性的对文章内容进行了整理和二次理解,方便大家更好的阅读《不同自由度的宇树G1机器人强化学习训练配置及运行实战 + RSL-RL代码库问题修复》、《宇树G1机器人强化学习训练奖励函数代码架构 + 创建新的奖励函数(1)》、《RL指标分析与看板应用 — 宇树G1机器人高自由度模型强化学习训练实战(3)》、《调参解析 — 宇树G1机器人高自由度模型强化学习训练实战(4)》、《舞蹈训练?手撕奖励函数 — 宇树G1机器人高自由度模型强化学习训练实战(5)》。 1. 强化学习训练环境配置 1.1 基础环境搭建 宇树机器人的强化学习训练基于Isaac Gym物理仿真环境和RSL-RL强化学习框架。首先需要确保这两个核心组件正确安装和配置。 在开始训练之前,我们通过简单的命令来启动12自由度G1机器人的基础训练:

By Ne0inhk