第五章 性能基线与 GPU 卸载实验Qwen2.5-7B-Instruct · Q4_K_M · llama.cpp · V100本章承接第三、四章。实验基于已下载的官方量化 GGUF不属于“自行完成量化”。所有数值均来自本次实测日志。5.1 实验目标前面已通过llama-cli成功运行 Qwen2.5-7B-Instruct Q4_K_M。现在建立能够复用的性能基线并观察 GPU 卸载层数对推理速度和显存占用的影响。要回答三个问题输入处理Prompt Processing与逐 Token 生成Token Generation的速度分别是多少同一模型使用单卡或多卡运行时成绩有什么差异减少 GPU 卸载层数节省了多少显存又付出了多少生成速度代价5.2 测试环境与模型项目配置系统Ubuntu 22.04.1 LTSGPUTesla V100-PCIE-32GB单卡实验指定 CUDA1CUDA 编译环境cuda/12.4 模块llama.cppcommit0ee9435CUDA 构建build-v100模型Qwen2.5-7B-Instruct模型参数量bench 输出7.62 BGGUF 格式/量化类型GGUF / Q4_K_M输出名称Q4_K - Medium模型文件大小bench 输出4.36 GiBCPU 线程4模型文件是一个被拆成两片的 GGUF-m指向00001-of-00002.gguf程序会加载其余分片。概念区别GGUF 是模型文件格式Q4_K_M 是其中的量化表示类型llama.cpp是负责加载权重和执行推理的软件。下载官方 Q4_K_M GGUF 并运行不等于从 FP16 权重亲自完成量化。5.3 正式性能测试pp512 与 tg128pp512测模型处理 512 个输入 Token 的速度tg128测生成 128 个 Token 的速度。两者应分别记录不能混为一个“推理速度”。-r 3表示每种测试重复三次输出平均值及标准差。conda activate llmexportPYTHONNOUSERSITE1module load cuda/12.4cd/slurm/home/zhengjie/xss_llmMODEL/slurm/home/zhengjie/xss_llm/models/Qwen2.5-7B-Instruct-GGUF/qwen2.5-7b-instruct-q4_k_m-00001-of-00002.ggufBENCH./llama.cpp/build-v100/bin/llama-benchmkdir-plogs/benchmarks$BENCH\-m$MODEL\-devCUDA1-smnone-ngl99\-t4-p512-n128-r3-omd\21|teelogs/benchmarks/qwen2.5-7b-q4km-v100-single.md单卡完整卸载实测模式pp512tokens/stg128tokens/sCUDA1-sm none-ngl 993118.45 ± 144.84116.00 ± 0.27此前在未显式限定设备的 CUDA 配置下-ngl 99的一组结果为pp512 2896.42 ± 9.56、tg128 112.98 ± 0.11tokens/s。这两组仅能作为不同配置下的实测记录不能由此证明“单卡必然比多卡更快”因为运行时的共享节点负载、时间等条件不完全相同。5.4 三个容易混淆的参数参数意义-ngl 99允许尽可能多的模型层卸载到 GPU不表示有 99 层也不表示使用 99 张卡-dev CUDA1限定允许使用的设备为 CUDA1-sm none不把模型拆分到多张 GPUllama-bench的输出出现backend CUDA只能说明使用 CUDA 后端如果同时有ngl 0不能把它理解成模型层已经全部在 GPU 上计算。5.5 单卡 GPU 卸载层数对照实验保持模型、单卡设备、线程数、输入/输出 Token 数量和重复次数一致比较不同的-ngl。$BENCH\-m$MODEL\-devCUDA1-smnone-ngl20\-t4-p512-n128-r3-omd\21|teelogs/benchmarks/qwen2.5-7b-q4km-v100-single-ngl20.md单卡设置pp512tokens/stg128tokens/s-ngl 993118.45 ± 144.84116.00 ± 0.27-ngl 201152.13 ± 22.5715.92 ± 0.03降低卸载层数后CPU 需要承担更多模型层的计算CPU/GPU 之间还可能存在数据传输成本。单路生成必须依次经过各层因此即使部分层在 GPU 上CPU 侧也可能拖慢整体生成速度。这里观察到的是卸载方式变化的影响不是对 FP16 与 Q4_K_M 量化效果的比较。5.6 显存观察只统计当前 llama-cli 进程本次使用单卡 CUDA1在两组交互式llama-cli测试中保持-c 2048、-t 4、-n 256、--temp 0和相同中文提问。等模型回答完并停留在下一轮输入提示时使用nvidia-smi-i1nvidia-smi-i1\--query-compute-appspid,process_name,used_gpu_memory\--formatcsv单卡设置llama-cli 进程显存实际聊天 Generation-ngl 994772 MiB109.8 tokens/s-ngl 203570 MiB12.1 tokens/s在两次截图中CUDA1 上另有一个约 306 MiB 的 Python 进程。因此不能拿nvidia-smi的整卡总占用当成模型进程的占用。从-ngl 99改为-ngl 20本次静态快照记录的模型进程显存减少1202 MiB但实际聊天生成也明显变慢。-ngl是“卸载层数”不是显存百分比运行时仍有 GPU 计算缓冲区、KV Cache 等资源。显存节省不代表这些权重消失部分模型权重仍需占用主机内存。测量边界进程在等待下一轮输入时的nvidia-smi数值是模型已加载后的显存快照不是生成过程的峰值显存。此外基准测试与聊天测试的工作负载不同两类速度不要混入同一列进行严格比较。5.7 实验结论与下一步Qwen2.5-7B Q4_K_M 的 GGUF 文件大小约4.36 GiB本次在 CUDA1 上、-ngl 99、-c 2048的llama-cli显存快照为4772 MiB。文件大小不等于运行显存也不等于峰值显存。在同一单卡正式 Benchmark 条件下tg128从-ngl 99的116.00降至-ngl 20的15.92 tokens/s。本次交互测试记录中少卸载模型层可减少 GPU 显存占用但需要接受更低生成速度。这反映了端侧部署中的显存—速度取舍。目前使用的是官方已经量化好的 Q4_K_M GGUF。后续可以从 Qwen2.5-7B-Instruct 原始模型出发自行转换为高精度 GGUF再使用llama-quantize生成并比较不同精度版本这才是“自行量化”阶段。日志位于logs/benchmarks/保存实验记录时应保留模型版本、llama.cpp commit、指定设备、-ngl、上下文长度、重复次数和测试时间等条件。第六章 从原始权重到自制量化模型F16、Q8_0 与 Q4_K_M本章使用Qwen2.5-7B-Instruct和已编译的llama.cpp完成“下载原始权重 → 转换 F16 GGUF → 自行量化 Q4_K_M 与 Q8_0 → 单卡推理及性能对照”的完整流程。此前使用的官方 Q4_K_M 文件作为参照本章的 F16 GGUF、Q4_K_M 和 Q8_0 均由本实验转换或量化产生。6.1 实验目标与文件规划三个模型文件各有用途不能混淆文件存放位置用途原始 Safetensors约 15Gmodels/Qwen2.5-7B-Instruct/原始高精度权重自制 F16 GGUF约 15Gmodels/converted/Qwen2.5-7B-Instruct-F16.gguf后续量化的输入自制 Q4_K_M GGUF约 4.4Gmodels/quantized/Qwen2.5-7B-Instruct-Q4_K_M.gguf低比特量化成果自制 Q8_0 GGUF约 7.6Gmodels/quantized/Qwen2.5-7B-Instruct-Q8_0.gguf较高精度量化对照之前下载的官方量化模型仍保存在models/Qwen2.5-7B-Instruct-GGUF/供后续对照使用。本章的操作不会覆盖它。6.2 下载并检查原始模型在学校服务器的项目目录中使用原有llm环境conda activate llmexportPYTHONNOUSERSITE1cd/slurm/home/zhengjie/xss_llmmkdir-pmodels/Qwen2.5-7B-InstructexportHF_ENDPOINThttps://hf-mirror.comexportHF_HUB_DISABLE_XET1hf download Qwen/Qwen2.5-7B-Instruct\--local-dir /slurm/home/zhengjie/xss_llm/models/Qwen2.5-7B-Instruct下载完成后检查ls-lhmodels/Qwen2.5-7B-Instruct/*.safetensorsdu-shmodels/Qwen2.5-7B-Instructlsmodels/Qwen2.5-7B-Instruct/config.json\models/Qwen2.5-7B-Instruct/tokenizer.json\models/Qwen2.5-7B-Instruct/model.safetensors.index.json**实际结果**四个 Safetensors 权重分片均存在目录约15G模型配置、分词器和权重索引文件齐全。6.3 将原始模型转换为 F16 GGUF转换格式不等于 Q4_K_M 量化。本次源文件中的主要权重为 BF16指定--outtype f16后主要张量转成 F16一些较小的归一化权重和偏置保留为 F32。GGUF 同时保存模型结构、分词器等推理所需元数据。先确认转换脚本支持相关参数python-sllama.cpp/convert_hf_to_gguf.py--help再执行mkdir-pmodels/converted logs/conversionset-opipefail python-sllama.cpp/convert_hf_to_gguf.py\models/Qwen2.5-7B-Instruct\--outfilemodels/converted/Qwen2.5-7B-Instruct-F16.gguf\--outtypef16\21|teelogs/conversion/qwen2.5-7b-f16.log转换日志记录了339 个张量、总大小约 15.2G最终提示Model successfully exported to models/converted/Qwen2.5-7B-Instruct-F16.gguf实际文件检查Qwen2.5-7B-Instruct-F16.gguf 15G6.4 使用 llama-quantize 自主量化llama-quantize的输入是上一节产生的高精度 GGUF输出是指定类型的量化 GGUF。本实验使用Q4_K_M它是混合精度量化配置不能理解为“模型中的每个张量都严格使用 4 bit”。mkdir-pmodels/quantized logs/quantizationset-opipefail ./llama.cpp/build-v100/bin/llama-quantize\models/converted/Qwen2.5-7B-Instruct-F16.gguf\models/quantized/Qwen2.5-7B-Instruct-Q4_K_M.gguf\Q4_K_M\21|teelogs/quantization/qwen2.5-7b-q4km.log实际量化结果指标实测值处理张量数量339量化前模型权重数据大小14526.27 MiB量化前平均精度16.00 BPW量化后模型权重数据大小4460.45 MiB量化后平均精度4.91 BPW量化耗时109929.16 ms约 110 秒输出文件的ls -lh大小4.4GBPW是Bits Per Weight即平均每个权重占用的 bit 数。量化后权重数据约为量化前的30.7%约减少69.3%这不是对整份 GGUF 文件逐字节测得的压缩率。为什么 Q4_K_M 实测是 4.91 BPW因为日志显示不同张量采用了不同精度。例如blk.26.attn_q.weight f16 → q4_K blk.26.attn_v.weight f16 → q6_K blk.26.ffn_down.weight f16 → q6_K blk.26.ffn_gate.weight f16 → q4_K blk.26.attn_q.bias f32保留部分张量以 Q6_K 保存部分以 Q4_K 保存少量小张量仍为 F32。因此Q4_K_M 是目标量化方案名并不代表整模型平均恰好 4.00 BPW。本次使用的是 llama.cpp 的量化工具不是 GPTQ 校准量化实验。6.5 在单张 V100 上运行自制模型量化文件生成后还需要实际加载和推理才能确认整个流程可用。实验沿用之前确定的CUDA1 单卡配置conda activate llmexportPYTHONNOUSERSITE1module load cuda/12.4cd/slurm/home/zhengjie/xss_llmMODEL/slurm/home/zhengjie/xss_llm/models/quantized/Qwen2.5-7B-Instruct-Q4_K_M.ggufmkdir-plogs/inference ./llama.cpp/build-v100/bin/llama-cli\-m$MODEL\-devCUDA1\-smnone\-ngl99\-c2048\-t4\-n128\--temp0\--single-turn\-p请用通俗易懂的语言解释什么是大语言模型控制在100字以内。\21|teelogs/inference/qwen2.5-7b-self-q4km-first-run.log实际日志确认模型路径为models/quantized/Qwen2.5-7B-Instruct-Q4_K_M.gguf加载类型为Q4_K - Medium并能生成中文回答[ Prompt: 602.0 t/s | Generation: 84.3 t/s ]回答中出现“人类-like的文本”这一不自然措辞。它是值得记录的观察但单次问答不足以判断该措辞是否由量化引起需要高精度和量化模型在一致条件下、面对更多输入时才能评估输出差异。6.6 官方与自制 Q4_K_M 的正式性能对照首次问答通过后为避免把交互式聊天的速度和基准测试混在一起使用统一的llama-bench工作负载测试自制 Q4_K_M单张 V100CUDA1、-sm none、-ngl 99、-t 4、-p 512、-n 128、每项重复 3 次。MODEL/slurm/home/zhengjie/xss_llm/models/quantized/Qwen2.5-7B-Instruct-Q4_K_M.ggufBENCH./llama.cpp/build-v100/bin/llama-benchmkdir-plogs/benchmarksset-opipefail$BENCH\-m$MODEL-devCUDA1-smnone-ngl99\-t4-p512-n128-r3-omd\21|teelogs/benchmarks/qwen2.5-7b-self-q4km-v100-single.md指标官方 Q4_K_M自制 Q4_K_MBenchmark 报告的模型大小4.36 GiB4.36 GiBpp512输入处理速度3118.45 ± 144.84 t/s3050.62 ± 262.79 t/stg128逐 Token 生成速度116.00 ± 0.27 t/s115.77 ± 0.33 t/s两份模型的体积和本次单卡吞吐量接近。结果只能说明本次测试条件下的表现不等于证明两份文件逐字节一致或所有回答相同。±为基准程序在重复测量中报告的波动量不应把本次微小差距直接归因为量化效果差异。6.7 从同一份 F16 GGUF 自主量化 Q8_0为比较不同量化类型继续使用原始的F16 GGUF作为输入而不是将 Q4_K_M 再转为 Q8_0提高已经量化过的权重存储位数不能恢复此前丢失的信息。mkdir-pmodels/quantized logs/quantizationset-opipefail ./llama.cpp/build-v100/bin/llama-quantize\models/converted/Qwen2.5-7B-Instruct-F16.gguf\models/quantized/Qwen2.5-7B-Instruct-Q8_0.gguf\Q8_0\21|teelogs/quantization/qwen2.5-7b-q8_0.log实际量化日志model size 14526.27 MiB (16.00 BPW) quant size 7717.68 MiB ( 8.50 BPW) quantize time 87003.46 msls -lh显示输出文件约7.6G。Q8_0 的平均8.50 BPW并非错误量化块还需保存缩放参数且并非模型所有张量都按同一种低比特形式存储。量化约耗时87 秒这是一次性的模型准备时间不是推理延迟。6.8 验证自制 Q8_0 并完成 Benchmark使用和 Q4_K_M 相同的中文提问、单卡与推理参数验证 Q8_0conda activate llmexportPYTHONNOUSERSITE1module load cuda/12.4cd/slurm/home/zhengjie/xss_llmMODEL/slurm/home/zhengjie/xss_llm/models/quantized/Qwen2.5-7B-Instruct-Q8_0.gguf./llama.cpp/build-v100/bin/llama-cli\-m$MODEL-devCUDA1-smnone-ngl99\-c2048-t4-n128--temp0--single-turn\-p请用通俗易懂的语言解释什么是大语言模型控制在100字以内。\21|teelogs/inference/qwen2.5-7b-self-q8_0-first-run.log实际加载类型为Q8_0中文问答正常。本次交互输出速度[ Prompt: 354.3 t/s | Generation: 66.9 t/s ]然后按统一的单卡 Benchmark 条件测量BENCH./llama.cpp/build-v100/bin/llama-benchset-opipefail$BENCH\-m$MODEL-devCUDA1-smnone-ngl99\-t4-p512-n128-r3-omd\21|teelogs/benchmarks/qwen2.5-7b-self-q8_0-v100-single.md实际测得pp512 3698.46 ± 172.25 t/stg128 86.29 ± 0.14 t/sBenchmark 报告模型大小7.54 GiB。6.9 测量 F16 基线并汇总三模型数据最后使用同一份自行转换的 F16 GGUF 和相同的llama-bench参数补齐高精度基线。执行前应确认指定 GPU 有足够可用显存。MODEL/slurm/home/zhengjie/xss_llm/models/converted/Qwen2.5-7B-Instruct-F16.ggufBENCH./llama.cpp/build-v100/bin/llama-benchset-opipefail$BENCH\-m$MODEL-devCUDA1-smnone-ngl99\-t4-p512-n128-r3-omd\21|teelogs/benchmarks/qwen2.5-7b-f16-v100-single.md本次正式对照表均为 Qwen2.5-7B-Instructbuild0ee9435指标F16自制转换Q8_0自制Q4_K_M自制Benchmark 模型大小14.19 GiB7.54 GiB4.36 GiBls -lh约数15G7.6G4.4G量化日志平均 BPW16.008.504.91pp512t/s4357.11 ± 341.993698.46 ± 172.253050.62 ± 262.79tg128t/s51.90 ± 0.0586.29 ± 0.14115.77 ± 0.33测试条件Tesla V100-PCIE-32GB-dev CUDA1 -sm none -ngl 99 -t 4 -p 512 -n 128 -r 3 -o md。四张卡被程序发现并不表示该次工作负载使用四张卡本实验显式选择 CUDA1 单卡且禁用模型切分。结果解读本次测试中F16 的批量 Prompt 处理速度较高Q4_K_M 的逐 Token 生成速度较高Q8_0 介于两者之间。以 F16 为参照Q8_0 和 Q4_K_M 的tg128分别约为1.66 倍和2.23 倍这不是说它们在所有任务中都按相同比例加速也不能单凭此表判定回答质量。pp512测量一次性处理 512 个输入 Token 的吞吐量tg128测量逐 Token 生成 128 个 Token 的吞吐量。llama-cli的实际问答速度与这两个固定负载不同不应直接混用另外文件大小也不等于显存峰值。6.10 本章成果与下一阶段至此已完整完成原始 Safetensors → F16 GGUF → 分别制作 Q8_0、Q4_K_M → 中文推理验证 → 同条件单卡 Benchmark。两种量化模型均可加载并生成中文回答但单道中文问答只能作为功能检查尚不能证明量化对回答质量的影响大小。下一阶段进入llama-server部署与本地 API 调用让模型以服务形式运行再通过 HTTP 请求调用。部署演示可沿用已验证的自制 Q4_K_M如需对照精度或资源消耗也保留 F16 与 Q8_0 文件不必再次下载或量化。第七章 使用 llama-server 部署本地大模型7.1 为什么已经有 llama-cli还需要 llama-server前面的llama-cli主要用于在终端中直接与模型交互适合验证模型是否能够正常加载和生成文本。而llama-server可以把本地 GGUF 模型部署成一个 HTTP 服务使 Python 程序、网页或其他应用能够通过 API 调用模型。整体调用流程可以理解为Python / 网页 / 其他客户端 ↓ HTTP 请求 ↓ llama-server ↓ 本地 GGUF 模型 ↓ 返回回答本章继续使用前面已经自主量化完成的 Qwen2.5-7B-Instruct Q4_K_M 模型。7.2 启动 llama-server模型路径/slurm/home/zhengjie/xss_llm/models/quantized/Qwen2.5-7B-Instruct-Q4_K_M.gguf启动命令conda activate llmexportPYTHONNOUSERSITE1module load cuda/12.4cd/slurm/home/zhengjie/xss_llmMODEL/slurm/home/zhengjie/xss_llm/models/quantized/Qwen2.5-7B-Instruct-Q4_K_M.ggufmkdir-plogs/server ./llama.cpp/build-v100/bin/llama-server\-m$MODEL\-devCUDA1\-smnone\-ngl99\-c2048\-t4\--host127.0.0.1\--port18080\21|teelogs/server/qwen2.5-7b-self-q4km-server.log服务端实际输出中出现llama_server: model loaded llama_server: listening on http://127.0.0.1:18080说明模型已经成功加载服务开始监听本机18080端口。这里使用127.0.0.1表示服务只监听服务器本机不直接暴露到外部网络。7.3 使用 health 接口检查服务状态在另一个终端执行curlhttp://127.0.0.1:18080/health实际返回{status:ok}这说明llama-server已经处于可用状态可以继续接收 API 请求。7.4 使用 curl 调用聊天 APIllama-server启动后可以通过/v1/chat/completions接口发送聊天请求。curlhttp://127.0.0.1:18080/v1/chat/completions\-HContent-Type: application/json\-d{ model: Qwen2.5-7B-Instruct-Q4_K_M.gguf, messages: [ { role: user, content: 请用通俗易懂的语言解释什么是大语言模型控制在100字以内。 } ], temperature: 0, max_tokens: 128 }实际请求成功返回 JSON其中模型回答为大语言模型是一种强大的计算机程序能理解和生成人类-like的文本涵盖广泛话题。它通过大量数据学习能回答问题、写文章甚至创作诗歌和故事。本次请求记录指标结果Prompt Tokens49Completion Tokens40Total Tokens89生成速度约 81.90 tokens/s这一步说明模型已经不再只能通过llama-cli使用而是可以通过标准 HTTP 请求被其他程序调用。7.5 使用 Python 调用本地模型 API创建 Python 脚本catscripts/chat_local.pyPY import json from urllib.request import Request, urlopen url http://127.0.0.1:18080/v1/chat/completions payload { model: Qwen2.5-7B-Instruct-Q4_K_M.gguf, messages: [ { role: user, content: 请用通俗易懂的语言解释什么是大语言模型控制在100字以内。 } ], temperature: 0, max_tokens: 128, } request Request( url, datajson.dumps(payload, ensure_asciiFalse).encode(utf-8), headers{Content-Type: application/json}, methodPOST, ) with urlopen(request, timeout120) as response: result json.load(response) print(模型回答) print(result[choices][0][message][content]) print(\nToken 用量) print(result.get(usage, {})) PY执行python-sscripts/chat_local.py实际输出模型回答 大语言模型是一种强大的计算机程序能理解和生成人类-like的文本就像和一个知识渊博的朋友聊天一样它可以写文章、回答问题、创作诗歌等。 Token 用量 {completion_tokens: 38, prompt_tokens: 49, total_tokens: 87, prompt_tokens_details: {cached_tokens: 48}}这说明 Python 程序已经能够通过 HTTP API 获取本地模型回答。其中cached_tokens: 48表示服务端报告部分输入 Token 使用了提示词缓存它不是额外增加的 Token 消耗。7.6 实现简单的多轮对话为了让 Python 程序支持上下文需要在客户端保存messages并在每次请求时把历史消息一起发送给模型。创建交互脚本importjsonfromurllib.requestimportRequest,urlopen URLhttp://127.0.0.1:18080/v1/chat/completionsmessages[{role:system,content:你是一个中文助手请清楚、简洁地回答问题。}]print(本地大模型聊天已启动输入 /exit 退出。)whileTrue:questioninput(\n你).strip()ifquestion/exit:breakifnotquestion:continuemessages.append({role:user,content:question})payload{model:Qwen2.5-7B-Instruct-Q4_K_M.gguf,messages:messages,temperature:0,max_tokens:256}requestRequest(URL,datajson.dumps(payload,ensure_asciiFalse).encode(utf-8),headers{Content-Type:application/json},methodPOST)try:withurlopen(request,timeout120)asresponse:resultjson.load(response)answerresult[choices][0][message][content]print(\n模型answer)messages.append({role:assistant,content:answer})messagesmessages[:1]messages[-12:]exceptExceptionasexc:print(f\n请求失败{exc})messages.pop()实际测试中程序已经可以连续进行多轮对话说明客户端能够通过messages保存并传递上下文。需要注意HTTP API 本身不会自动替 Python 程序保存全部聊天历史多轮对话依赖客户端主动维护上下文。7.7 多轮对话中的幻觉现象在多轮对话测试中输入张一帆是谁模型给出了一个具体人物身份并声称与电视剧《甄嬛传》有关。在用户继续质疑后模型仍然重复这一说法。这个实验说明大语言模型有可能生成语句流畅、细节具体但没有可靠依据的内容这类现象通常称为“幻觉”。因此模型能够正常部署和生成文本并不代表它输出的所有事实都可信。量化主要解决的是模型存储空间、显存占用和推理效率问题并不会自动解决事实准确性问题。7.8 使用 System Prompt 降低随意编造为了观察提示词约束的作用重新开启独立请求并增加更严格的 System Promptcurlhttp://127.0.0.1:18080/v1/chat/completions\-HContent-Type: application/json\-d{ model: Qwen2.5-7B-Instruct-Q4_K_M.gguf, messages: [ { role: system, content: 你是严谨的中文助手。对于无法确认的人物身份不要猜测不要编造作品、演员或经历。请明确说明无法确认并询问必要的背景信息。 }, { role: user, content: 张一帆是谁 } ], temperature: 0, max_tokens: 128 }这次模型回答关于“张一帆”的身份我没有找到足够的信息来确认具体是指哪个人物。这可能是一个普通的名字也可能是某个特定人物的名称但没有足够的上下文信息让我确定。您能提供更多的背景信息吗与前一次相比模型不再直接编造具体人物身份而是表达不确定性并请求更多背景信息。这说明明确的 System Prompt 可以改善模型在某些不确定问题上的回答方式但不能证明提示词能够彻底消除幻觉。另外模型回答中的“没有找到足够的信息”并不代表它进行了联网搜索。本实验中的llama-server只加载本地 GGUF 模型没有接入搜索工具或外部数据库。7.9 检查 Python 多轮对话脚本执行python-mpy_compile scripts/chat_interactive.py终端没有报错说明脚本通过 Python 语法检查。需要区分py_compile只能验证语法是否正确不能证明全部业务逻辑都正确。前面的实际多轮对话成功运行才是功能能够工作的直接验证。7.10 本章实践结果本章已经完成从本地模型到可调用服务的完整链路自主量化 Q4_K_M GGUF ↓ llama-server 加载模型 ↓ HTTP 服务启动 ↓ curl 调用聊天 API ↓ Python 调用 API ↓ Python 多轮对话 ↓ 观察模型幻觉与提示词约束至此自主量化得到的 GGUF 模型已经从“可以在终端中运行”进一步发展为“可以被程序通过 HTTP API 调用”的本地大模型服务。