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

从小项目到大型鸿蒙 App 的架构变化

从小项目到大型鸿蒙 App 的架构变化

子玥酱(掘金 / 知乎 / ZEEKLOG / 简书 同名) 大家好,我是子玥酱,一名长期深耕在一线的前端程序媛 👩‍💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。 我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括前端工程化、小程序、React / RN、Flutter、跨端方案, 在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。 技术方向:前端 / 跨端 / 小程序 / 移动端工程化 内容平台:掘金、知乎、ZEEKLOG、简书 创作特点:实战导向、源码拆解、少空谈多落地 文章状态:长期稳定更新,大量原创输出 我的内容主要围绕 前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读 展开。文章不会停留在“API 怎么用”,而是更关注为什么这么设计、在什么场景下容易踩坑、

By Ne0inhk
前端营销(AIGC II)

前端营销(AIGC II)

营销并非传统意义上的“前端创意投放”,而是深度内嵌于供应链、流量、用户、商品、场域的中台化运营体系。京东上下游链路极长,从采销、仓储、履约到流量分发、转化成交、用户复购,营销的核心价值是整合——找准人、选好货、用对场。前端在这里不再只是“做页面”,而是承接中台能力、串联全链路、支撑多品类快节奏运营的关键枢纽。 本文从业务理解与技术实现两大维度,系统拆解京东营销前端的真实角色、能力边界与工程实践。 一、业务理解:先懂营销,再写代码 京东营销前端的起点,是对齐业务本质:营销偏中台、本质是运营。前端必须把业务逻辑吃透,才能用技术支撑“整合”核心目标。 1.1 京东营销的核心定位:整合型运营中台 * 核心价值:人-货-场全域整合 * 人:搜推用户、PLUS会员、校园人群、CPS渠道人群、品牌定向人群 * 货:

By Ne0inhk

【AI大模型学习日志4:深度拆解Meta Llama系列——全球开源大模型的事实标准与AI普惠化的奠基者】

在上一篇AI大模型学习日志中,我们深度拆解了Anthropic的Claude系列,它以“安全对齐+长上下文对话”为核心差异化,成为企业级对话场景的标杆,凭借严谨的内容输出与隐私保护优势,在政企、法律等强合规领域站稳脚跟。而在大模型赛道,有一款产品彻底打破了“闭源模型垄断高端能力”的格局——它没有高调的发布会,没有复杂的商业化噱头,仅通过开源免费的模式,就推动了AI技术的普惠化普及,成为全球数千万开发者的首选开源底座,定义了开源大模型的事实标准,它就是Meta(原Facebook)研发的Llama(Large Language Model Meta AI)系列。 在Llama出现之前,开源大模型普遍存在“性能弱、场景适配差、商用受限”的痛点,而闭源大模型的API调用成本高昂,让中小企业与独立开发者望而却步,AI技术的普惠化陷入瓶颈。Llama的横空出世,不仅填补了“高性能开源大模型”的空白,更以宽松的开源许可、轻量化的部署优势,让全球开发者都能零成本获取旗舰级AI能力,推动了开源大模型生态的爆发式增长。本文所有核心信息均以Meta官方技术白皮书、Llama版本更新公告、开源协议文档及权

By Ne0inhk

高校计算机课程改革:增加AIGC实际操作环节

高校计算机课程改革:增加AIGC实际操作环节 如今,走进一间高校的计算机实验室,你可能会看到这样一幕:学生们不再只是盯着代码编辑器写算法作业,而是围在电脑前,输入一段古诗,点击“生成”按钮后,屏幕上立刻播放出一段宛如真人朗读的语音——语调自然、情感丰富,甚至还能切换成儿童声线或女性播音员风格。这不再是科幻场景,而是越来越多高校正在开展的AIGC(人工智能生成内容)教学实践。 随着大模型技术从科研走向落地,传统的编程训练和理论讲授已难以满足学生对真实AI系统运作机制的理解需求。特别是在语音合成领域,像VoxCPM-1.5-TTS这类基于跨模态预训练的大规模模型,已经具备了高质量、低延迟的推理能力,为教学提供了前所未有的实操平台。将这些前沿工具以Web UI镜像的形式引入课堂,不仅降低了使用门槛,更让学生从“看懂模型”迈向“跑通流程”,真正实现从理论到工程的跨越。 为什么是TTS?它为何适合作为AIGC入门载体? 在众多AIGC应用中,文本转语音(Text-to-Speech, TTS)之所以成为教学改革的理想切入点,关键在于它的反馈直观、链条完整、技术闭环清晰。 想象一下,一

By Ne0inhk