跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • 浅色
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • 深色
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(LCZ-Blue)
  • 不使用皮肤
  • LCZ-Green
  • LCZ-Blue
  • LCZ-Black
折叠
品牌标识

抡锤者

首页 版块 标签 硬件 AI 广场
  1. 主页
  2. 版块
  3. AI硬件
  4. Deepseek-Harness 单卡(7900XTX)运行Qwen3.8-27B 完整文档-1

Deepseek-Harness 单卡(7900XTX)运行Qwen3.8-27B 完整文档-1

已定时 已固定 已锁定 已移动 AI硬件
7900xtxdsharnessqwen-27b
1 帖子 1 发布者 91 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
回复
  • 在新帖中回复
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • lybhb8L
    lybhb8L
    lybhb8
    编写于 最后由 编辑
    #1

    将本地 llama.cpp 推理服务接入 DeepSeek Harness (DSH) 的全过程:环境准备、服务部署、shim 开发、DSH 配置、性能测试、日常运维与根因诊断。

    本文档合并自《DSH 接入本地模型完整教程》与《本地模型接入 DSH —— 诊断与解决方案》。

    实测环境:Ubuntu 22.04 · Intel CPU · 62GB RAM · AMD 7900 XTX (Vulkan, 25.75GB VRAM) · llama.cpp b11223 (Vulkan + MTP + ngram-k4v) · Node.js 24 · Qwen3.8-27B / Qwen3.6-27B (Q4_K_M)

    实测日期:2026-09-29(含同日 shim A/B 复核与 k4v 投机解码实测)


    目录

    1. 架构概览
    2. 环境准备
    3. 部署 llama.cpp 推理服务
    4. 开发工具调用 Shim
    5. 配置 DSH 接入
    6. 性能测试
    7. 日常运维
    8. 故障排查
    9. 诊断与实战记录
    10. 附录:文件清单

    本次更新(2026-09-30)

    • §9.8(重写)— CTX 从 256K 降到 128K 的根因:vkAllocateMemory 装不下 DEVICE_LOCAL,
      Vulkan 把权重退回 GTT,decode 掉到 0.49 tok/s。llama.sh 加 -cram -1。
      下界 64K(Hermes Agent 硬性要求 context >= 64000),上界 128K(实测 ~21.2GB/25.75GB 留余量)。
    • §1.1 / §3.1 / §3.2 / §5.1 / §9.4 — 3.8 的 ctx 全面改为 131072;overlay 的
      contextWindow: 131072 / maxTokens: 32768(原先声明 262144,是超限的直接来源)。
    • §3.1 内嵌代码块与 ~/llama-bin/llama.sh 逐行同步(含 systemd 自动检测、_USER_OVERRIDES 机制);
      §5.1 与 ~/llama-bin/dsh-shim-overlay.yml 同步。
    • 修正 §9.7 的锚点死链(#97-补充复核shim-ab-与多轮稳定性)。

    上次更新(2026-09-29)

    • §1.2 / §9.1 / §9.7 — shim 必要性复核:直连 :8080 现可正常完成工具调用,
      原「直连 0/10」复现不出来;coerce() 在 18 次强制采样中零次触发。结论改为
      「shim 仍默认启用,但不应再被当作不可替代的必需品」。
    • §6.3(新增)— 投机解码 k4v 实测:code_refactor +30.7%、合成重复 +42.3%,
      其余负载零退步。已默认启用,size-n 必须 32。
    • §3.1 / §5.1 — 内嵌代码块已与 ~/llama-bin/ 下真实文件重新同步。
    • §5.1 / §9.2 — overlay 默认模型由 3.6 改为 3.8。

    1. 架构概览

    1.1 三层架构

    
    DSH (Agent 框架)
      │  OpenAI 兼容请求 (含 tools 定义)
      ▼
    dsh-llm-shim (:8090, Node.js)
      │  tool_choice 改为 none,转发纯文本流
      ▼
    llama.cpp llama-server (Vulkan + MTP)
      :8080  Qwen3.8-27B  (ctx=131072)
      :8081  Qwen3.6-27B  (ctx=196608)  ← 两实例互斥
    

    1.2 为什么需要 Shim

    llama.cpp b11223 早期实测中自带的 tool-call 解析器(peg-native)解析不了 Qwen3.x 的 XML 工具调用:第二个参数起的整段被吞进第一个参数,并诱发模型无限重复 tool_call 标签直到 max_tokens(实测 32768 token / 7.7 分钟,零可用输出)。

    shim 的策略:

    1. 把 tool_choice 强制改为 none,llama.cpp 不做工具语法约束
    2. 模型原始 XML 完整出现在 message.content 里
    3. shim 自行把 XML 解析成标准 OpenAI tool_calls
    4. 检测到重复 tool_call 时立即掐断上游流
    方案 成功率 单次耗时
    直连 llama.cpp(2026-09-29 首次) 0/10 ~30s(跑飞)
    经 shim(同期) 10/10 ~1s

    ⚠ 2026-09-29 复核:直连已可用,shim 的必要性需重新评估

    同日按当前配置重新做 A/B,「直连 0/10」复现不出来:

    场景 结果
    简单工具直连 :8080 10/10,无跑飞
    DSH 真实复杂 schema(多工具)直连 2/2
    上述 + thinking 开启 2/2
    dsh headless 端到端(仅换 baseURL 端口) 66 文件 / ubuntu-ai,与经 shim 完全一致
    参数类型强制压测(7 字段全 required,含 number/boolean/array/object) 直连 12/12 类型全对、0 次字符串化;经 shim 6/6

    原结论只有三种可能:① build 或依赖已变;② 模型行为随采样/上下文漂移;③ 原基准本身有问题。
    本轮未能定位到确切原因。因此 shim 仍默认启用,但不应再被当作不可替代的必需品。

    另见 §9.7 对 coerce() 类型强转分支的专项测试。
    下线前的判断标准:切直连后连续跑真实 dsh 会话,观察是否出现工具参数校验失败。


    2. 环境准备

    2.1 硬件要求

    组件 最低要求 实测配置
    CPU 8 核 x86_64 Intel 多核
    RAM 32 GB 62 GB
    GPU Vulkan 1.3 AMD 25.75 GB VRAM
    磁盘 30 GB 可用 NVMe SSD

    显存估算:Qwen3.8-27B Q4_K_M 文本约 23.72 GB,加视觉 mmproj 约 24.9 GB。两个 27B 模型不能同时运行。

    2.2 软件依赖

    依赖 版本 用途
    Node.js >= 18 运行 shim(无第三方依赖)
    llama.cpp b11223 Vulkan 推理引擎
    Python >= 3.8 基准测试
    Vulkan 驱动 AMDGPU-Pro / Mesa GPU 加速

    2.3 模型文件

    
    ls ~/models/
    # Qwen3.8-27B-UD-Q4_K_M.gguf    (16.4GB)
    # Qwen3.6-27B-Q4_K_M-mtp.gguf
    # mmproj-model-bf16.gguf         (视觉投影,可选)
    

    3. 部署 llama.cpp 推理服务

    3.1 管理脚本 llama.sh

    存放到 ~/llama-bin/llama.sh:

    
    #!/bin/bash
    # 本地 LLM 服务统一入口 — llama.cpp Vulkan + MTP
    #
    #   ./llama.sh 38            启动 Qwen3.8-27B (:8080)(默认走 setsid 手动;systemd 托管时请用 systemctl --user start qwen38)
    #   ./llama.sh 36            启动 Qwen3.6-27B (:8081)(顺带拉起 :8090 shim)
    #   ./llama.sh stop          停止全部(38 自动走 systemctl --user stop qwen38,不会被自动拉回)
    #   ./llama.sh status        查看状态
    #   ./llama.sh 36 --use      停掉当前,换成 3.6
    #   ./llama.sh 38 --vision   带视觉启动(加载期开关,需重启)
    #   ./llama.sh 38 --fg       前台运行(给 systemd 用)
    #
    # 覆盖: CTX=196608 NMAX=2 UB=512 K4V=0 K4V_N=32 API_KEY=xxx MMPROJ=path LOG=path ./llama.sh 38
    # 注意: 下面初始化 CTX/NMAX 前必须先抓取环境值,否则 CTX="" 会让 ${CTX:-默认} 失效
    ENV_CTX="${CTX:-}"; ENV_NMAX="${NMAX:-}"; ENV_MMPROJ="${MMPROJ:-}"; ENV_EXTRA="${EXTRA:-}"
    set -uo pipefail
    
    BIN_DIR="${BIN_DIR:-$HOME/llama-bin/vulkan/llama-b11223}"
    BIN="$BIN_DIR/llama-server"
    SHIM="${SHIM:-$HOME/llama-bin/shim.sh}"   # 工具调用中间层(DSH 本地模型用)
    VRAM_DEV=/sys/class/drm/card0/device
    
    # 密钥:独立文件,不进脚本、不进 shell 环境
    ENV_FILE="${ENV_FILE:-$HOME/.config/qwen38/api.env}"
    [ -r "$ENV_FILE" ] && { set -a; . "$ENV_FILE"; set +a; }
    
    # profile: 别名|模型文件|ctx|nmax
    # 均为 qwen35 混合架构: 65 层但 full_attention_interval=4 → 仅 16 层真注意力,
    # 其余为 SSM 状态(常数大小, 与 ctx 无关). 训练上限均为 262144.
    #
    # 2026-09-30: CTX 从 262144 降到 131072。原注释说"多分配的 KV 不花钱"是错的——
    # 24GB 卡上 256K 会把模型+KV 顶到 ~26.3GB/24.5GB,vkAllocateMemory 装不下
    # DEVICE_LOCAL,Vulkan 后端把全部权重退回 GTT(系统内存)映射:实测
    # vis_vram_used=567MiB / gtt_used=23490MiB,decode 掉到 0.49 tok/s、prefill 30 t/s。
    # 「只有实际填满多少影响 decode」也不成立——溢出到 GTT 后每个 token 都要走 PCIe。
    #
    # 下界 64K:Hermes Agent 硬性要求 context >= 64000,低于此直接拒绝连接。
    # 上界实测:32K→17.4GB,128K→~21.2GB,256K→~26.3GB(爆)。128K 是留余量的最大值。
    # 需要更大窗口用 ENV_CTX 覆盖,但别超 ~160K。
    P38_ALIAS="qwen3.8-27b"; P38_MODEL="Qwen3.8-27B-UD-Q4_K_M.gguf";   P38_CTX=131072; P38_NMAX=3
    P36_ALIAS="qwen3.6-27b"; P36_MODEL="Qwen3.6-27B-Q4_K_M-mtp.gguf"; P36_CTX=196608; P36_NMAX=3
    P38_PORT="${P38_PORT:-8080}"
    P36_PORT="${P36_PORT:-8081}"
    MMPROJ_FULL="$HOME/models/mmproj-model-bf16.gguf"   # 仅 3.8 有效
    
    # 记下「用户自己设的」调优变量。必须在这里取:下面第 45 行起会把 CTX/NMAX 清空
    # 并给 UB/HOST/LOG/K4V 赋默认值,等到启动路径上再判断就分不清是用户设的还是默认了。
    _TUNABLE="CTX ENV_CTX UB B NMAX ENV_NMAX K4V K4V_N K4V_M K4V_HITS CRAM EXTRA ENV_EXTRA TEMP TOPK CKV CV LOG HOST MMPROJ"
    _USER_OVERRIDES=""
    for _v in $_TUNABLE; do [ -n "${!_v-}" ] && _USER_OVERRIDES="$_USER_OVERRIDES $_v"; done
    
    KEY=""; ALIAS=""; MODEL=""; CTX=""; NMAX=""; PORT=""; NAME=""
    case "${1:-}" in
        38|qwen38) KEY=38; NAME="Qwen3.8-27B"; ALIAS=$P38_ALIAS; MODEL=$P38_MODEL; CTX="${ENV_CTX:-$P38_CTX}"; NMAX="${ENV_NMAX:-$P38_NMAX}"; PORT=$P38_PORT ;;
        36|qwen36) KEY=36; NAME="Qwen3.6-27B"; ALIAS=$P36_ALIAS; MODEL=$P36_MODEL; CTX="${ENV_CTX:-$P36_CTX}"; NMAX="${ENV_NMAX:-$P36_NMAX}"; PORT=$P36_PORT ;;
    esac
    
    MODEL_PATH=""; [ -n "$MODEL" ] && MODEL_PATH="$HOME/models/$MODEL"
    API_KEY="${API_KEY:-${QWEN_API_KEY:-}}"
    HOST="${HOST:-0.0.0.0}"
    
    # 只匹配本模型的进程;用 alias 定位,避免 pkill -f "llama-server -m"
    # 连带杀掉另一个模型的实例
    _running() { pgrep -f -- "--alias $1" 2>/dev/null; }
    # 有 systemd 用户服务托管的模型(38 → qwen38.service),stop 必须走 systemctl:
    # 否则 pkill 造成的"非正常退出"会被 Restart=on-failure 在 20s 后拉回来
    _svc_of() { case "$1" in "$P38_ALIAS") echo qwen38.service ;; esac; }
    # 注意 kind 必须是 shell 变量;写成 awk 的 -v 变量时 shell 展开不到
    _vram() { local kind="$1"; awk '{printf "%.2f", $1/1e9}' "$VRAM_DEV/mem_info_vram_$kind" 2>/dev/null; }
    
    stop() {
        local n=0 a svc
        for a in "$P38_ALIAS" "$P36_ALIAS"; do
            if _running "$a" >/dev/null; then
                svc=$(_svc_of "$a")
                if [ -n "$svc" ] && systemctl --user is-active --quiet "$svc" 2>/dev/null; then
                    # systemd 接管中:受控停止,避免被 Restart 拉回;等进程真正退出
                    systemctl --user stop "$svc" 2>/dev/null
                    for _ in $(seq 1 45); do _running "$a" >/dev/null || break; sleep 1; done
                else
                    pkill -f -- "--alias $a" 2>/dev/null
                    for _ in $(seq 1 45); do _running "$a" >/dev/null || break; sleep 1; done
                    pkill -9 -f -- "--alias $a" 2>/dev/null
                fi
                n=$((n+1))
            fi
        done
        [ "$n" -gt 0 ] && echo "已停止 $n 个实例" || echo "未在运行"
        # 模型都停了,工具调用中间层留着也没用;交给 shim.sh 用 PID 精确停,
        # 避免裸 pgrep/pkill 文件名误杀其它提到该文件的进程。
        if [ -x "$SHIM" ]; then
            _out=$("$SHIM" stop 2>&1)
            case "$_out" in *已停止*) echo "$_out" ;; esac
        fi
    }
    
    status() {
        printf '%-10s %-7s %-6s %-11s %s\n' 模型 端口 状态 显存 模型文件
        for spec in "Qwen3.8-27B|$P38_ALIAS|$P38_PORT|$P38_MODEL" "Qwen3.6-27B|$P36_ALIAS|$P36_PORT|$P36_MODEL"; do
            IFS='|' read -r name a p m <<<"$spec"
            if _running "$a" >/dev/null; then
                printf '%-10s %-7s %-6s %-11s %s\n' "$name" ":$p" "运行" "$(_vram used) GB" "$m"
            elif curl -fsS --max-time 2 "http://127.0.0.1:$p/health" >/dev/null 2>&1; then
                # 进程看不见但端口在服务(例如从别的命名空间/终端起来的)也算运行
                printf '%-10s %-7s %-6s %-11s %s\n' "$name" ":$p" "运行" "-" "$m"
            else
                printf '%-10s %-7s %-6s %-11s %s\n' "$name" ":$p" "停止" "-" "$m"
            fi
        done
        # 以端口健康为准:shim 可能由别的终端/会话拉起,进程看不到但确实在服务
        if curl -fsS --max-time 2 "http://127.0.0.1:8090/health" >/dev/null 2>&1; then
            _shim_state=运行; else _shim_state=停止; fi
        printf '%-10s %-7s %-6s %-11s %s\n' "shim" ":8090" "$_shim_state" "-" "dsh-llm-shim.mjs"
        echo "总显存: $(_vram used) / $(_vram total) GB"
    }
    
    if [ -z "$KEY" ]; then
        # 裸命令(函数已定义,可安全调用):stop/status,其余按 status 兜底
        case "${1:-}" in
            stop) stop; exit 0 ;;
            status) status; exit 0 ;;
            *) status; exit 0 ;;
        esac
    fi
    
    MMPROJ=""
    for a in "$@"; do
        case "$a" in
            --vision) MMPROJ="$MMPROJ_FULL" ;;
            --stop) stop; exit 0 ;;
            --status) status; exit 0 ;;
            --restart|--use)
                for a2 in "$@"; do
                    case "$a2" in 36|qwen36) NEXT=36 ;; esac
                done
                stop; sleep 2
                case "${NEXT:-}" in 36) exec "$0" 36 --vision ;; *) exec "$0" 38 ;; esac ;;
        esac
    done
    
    [ -f "$MODEL_PATH" ] || { echo "模型缺失: $MODEL_PATH" >&2; exit 1; }
    [ -x "$BIN" ] || { echo "二进制缺失: $BIN" >&2; exit 1; }
    
    if _running "$ALIAS" >/dev/null; then
        echo "$NAME 已在 :$PORT 运行。要重启先 stop,或用 ./llama.sh $KEY --use" >&2
        exit 1
    fi
    # 另一个模型占着显存就停掉,否则必然 OOM
    if _running "$P38_ALIAS" >/dev/null || _running "$P36_ALIAS" >/dev/null; then
        echo "提示: 另一模型正在运行,将先停止(两者不能共存于 25.75GB 显存)"
        stop; sleep 2
    fi
    [ -n "$MMPROJ" ] && [ ! -f "$MMPROJ" ] && { echo "mmproj 缺失,关闭视觉: $MMPROJ" >&2; MMPROJ=""; }
    # UB 默认 512:llama-bench 上 pp32768 有 399→414 t/s(+3.7%) 的提升,
    # 但服务端实测 decode 63.7→59.3 t/s(−7%)、显存 23.64→24.83 GB(96%),
    # 且触发 "failed to fit params to free device memory"(-ngl 999 写死无法自动收缩)。
    # prefill 的收益抵不上 decode 的损失,故保持 512。保留变量以便复测。
    UB="${UB:-512}"; B="${B:-$((UB * 4))}"
    # 实测: ub2048 纯文本 @256K 投影 22924 MiB, 视觉 mmproj 再 +1.19GB → 约 24.6GB / 25.75GB 极限
    if [ -n "$MMPROJ" ] && [ "$CTX" -gt 196608 ] && [ "$UB" -gt 512 ]; then
        echo "⚠ ctx=$CTX + 视觉 + ub=$UB 会逼近 25.75GB 上限;建议 CTX=196608 或 UB=512" >&2
    fi
    
    # 投机解码: MTP 自投机 + n-gram 查表叠加(k4v)。
    # 3.8 实测(temp=0, 每项 2 轮取中位数, n_gen 两配置完全一致故无输出长度混淆):
    #   工作负载              draft-mtp   +k4v(n=32)     变化
    #   code_refactor             86.1        112.6     +30.7%  ← dsh 改文件典型负载
    #   repeat_synth              86.0        122.4     +42.3%
    #   template_batch            47.2         46.7      -1.1%  (噪音内)
    #   reasoning                 72.9         72.1      -1.1%  (噪音内)
    #   prose                     47.2         46.7      -1.1%  (噪音内)
    # 零 VRAM 成本, 零重编。n=32 是关键: n=12 在「格式重复但内容要换」的任务上倒扣
    # 5~10%(n-gram 一直开火猜错时间轴), n=32 把所有负项收进 ±1.3% 噪音内。
    # 原理: k4v 从已生成上下文做 n-gram 查表, 命中一次吐最多 48 token; 没命中退回 MTP。
    # 来源: https://lcz.me/topic/1398 §二/§三(该文在 7900XTX Vulkan 上交叉验证过)
    K4V="${K4V:-1}"
    SPEC_TYPE="draft-mtp"; K4V_ARGS=()
    if [ "$K4V" = "1" ]; then
        SPEC_TYPE="ngram-map-k4v,draft-mtp"
        K4V_ARGS=( --spec-ngram-map-k4v-size-n "${K4V_N:-32}"
                   --spec-ngram-map-k4v-size-m "${K4V_M:-48}"
                   --spec-ngram-map-k4v-min-hits "${K4V_HITS:-1}" )
    fi
    
    ARGS=( -m "$MODEL_PATH" -c "$CTX" -ngl 999 -fa 1
           -ub "$UB" -b "$B" --reasoning off --parallel 1
           -cram "${CRAM:--1}"
           --host "$HOST" --port "$PORT" --alias "$ALIAS"
           --spec-type "$SPEC_TYPE" --spec-draft-n-max "$NMAX" "${K4V_ARGS[@]}" )
    # KV 精度与采样:草稿与目标共享 context,V cache 量化误差会压低接受率。
    # 3.6 实测(reps=3, ctx196608, n-max4): 0.7/20 → 67.33 tok/s 接受0.544
    #                                      0.3/5  → 68.70 tok/s 接受0.560
    # 3.6 最佳: n-max3 + 0.3/5 → 69.54 tok/s 接受0.657 (V=q4_0 最优; q8_0/f16 反而更差更慢)
    # 3.8 保持 0.7/20 —— 其 83.30 tok/s 是在该采样下实测的
    if [ "$KEY" = "36" ]; then
        ARGS+=( -ctk "${CKV:-q8_0}" -ctv "${CV:-q4_0}"
                --temp "${TEMP:-0.3}" --top-k "${TOPK:-5}" )
    else
        ARGS+=( -ctk "${CKV:-q4_0}" -ctv "${CV:-q4_0}"
                --temp "${TEMP:-0.7}" --top-k "${TOPK:-20}" )
    fi
    # EXTRA 透传调优参数,例如 EXTRA="--spec-draft-p-min 0.2"
    [ -n "$ENV_EXTRA" ] && ARGS+=( $ENV_EXTRA )
    [ -n "$MMPROJ" ] && ARGS+=(--mmproj "$MMPROJ")
    # 关闭服务端认证: 配合 opencode 里 apiKey="" 使用,不传 --api-key
    LOG="${LOG:-/tmp/qwen${KEY}-vulkan.log}"
    
    echo "model  : $NAME  ($MODEL)"
    echo "config : ctx=$CTX  n-max=$NMAX  ub=$UB/b=$B  视觉=$([ -n "$MMPROJ" ] && echo 开 || echo 关)  认证=无"
    echo "listen : $HOST:$PORT   log: $LOG"
    
    for a in "$@"; do
        if [ "$a" = "--fg" ]; then
            # systemd 用的就是 --fg:exec 之后脚本就结束了,所以 shim 必须在这里起,
            # 否则「起模型就自动带 shim」在 --fg 下不成立。start 是幂等的。
            [ -x "$SHIM" ] && "$SHIM" start
            exec "$BIN" "${ARGS[@]}"
        fi
    done
    
    # 有 systemd 单元托管时一律交给 systemctl:手动 setsid 起的进程不受
    # Restart=on-failure 保护,还会占住端口让单元以 exit-code 1 反复 crash-loop
    # (2026-09-30 22:10 就是这么把 qwen38 顶掉的)。
    # systemctl 不继承当前 shell 的环境,所以存在调优变量或 --vision 时退回直起,
    # 否则 `CTX=163840 ./llama.sh 38` 会被静默吞掉。
    VIA=direct
    _SVC=$(_svc_of "$ALIAS")
    if [ -n "$_SVC" ] && systemctl --user cat "$_SVC" >/dev/null 2>&1; then
        if [ -n "$_USER_OVERRIDES" ] || [ -n "$MMPROJ" ]; then
            echo "⚠ 有覆盖[${_USER_OVERRIDES:- --vision}] systemd 不继承 → 直起(无 Restart 保护)" >&2
        else
            VIA=systemd
        fi
    fi
    
    PROBE=127.0.0.1; [ "$HOST" = "0.0.0.0" ] || PROBE="$HOST"
    _fail_hint() { [ "$VIA" = systemd ] && echo "journalctl --user -u $_SVC -n 50" || echo "$LOG"; }
    
    if [ "$VIA" = systemd ]; then
        echo "→ systemctl --user start $_SVC"
        systemctl --user start "$_SVC"
    else
        setsid nohup "$BIN" "${ARGS[@]}" </dev/null >"$LOG" 2>&1 & disown
    fi
    
    printf 'loading'
    for _ in $(seq 1 90); do
        sleep 4
        curl -fsS --max-time 3 "http://$PROBE:$PORT/health" 2>/dev/null | grep -q '"ok"' && break
        _running "$ALIAS" >/dev/null || { echo; echo "启动失败,看: $(_fail_hint)" >&2; exit 1; }
        printf '.'
    done
    
    if curl -fsS --max-time 3 "http://$PROBE:$PORT/health" 2>/dev/null | grep -q '"ok"'; then
        echo; echo "就绪"
        awk -v u="$(_vram used)" -v t="$(_vram total)" \
            'BEGIN{printf "显存  : %s / %s GB (%.0f%%)\n", u, t, t?100*u/t:0}'
        LAN=$(ip route get 1.1.1.1 2>/dev/null | grep -oE 'src [0-9.]+' | cut -d' ' -f2)
        [ -n "$LAN" ] && echo "局域网: http://$LAN:$PORT/v1   (模型名 $ALIAS)"
        [ "$VIA" = direct ] && { grep -q "nextn.*ignoring" "$LOG" 2>/dev/null && \
            echo "⚠ 日志显示 MTP 头被忽略,检查 --spec-type 是否生效" >&2; }
        # 工具调用中间层:llama.cpp b11223 自带的 tool-call 解析器解析不了 Qwen3.x 的 XML
        # 工具调用(参数被吞 + 诱发无限重复),改由 shim 代为解析。详见
        # ~/桌面/本地模型接入DSH-诊断.md。shim 已在跑时 start 是幂等的。
        if [ -x "$SHIM" ]; then
            "$SHIM" start
        else
            echo "⚠ 缺少 $SHIM,DSH 本地模型会拿不到工具调用" >&2
        fi
    else
        echo; echo "超时,看 $(_fail_hint)" >&2; exit 1
    fi
    

    3.2 使用说明

    cd ~/llama-bin
    
    ./llama.sh 38          # 启动 Qwen3.8-27B (:8080)
    ./llama.sh 36          # 启动 Qwen3.6-27B (:8081)
    ./llama.sh status      # 查看状态
    ./llama.sh stop        # 停止所有
    ./llama.sh 36 --use   # 切换到 3.6(先停当前再起 3.6)
    ./llama.sh 38 --vision # 带视觉启动
    ./llama.sh 38 --fg     # 前台运行(systemd 用)
    

    关键参数说明:

    • -ngl 999 -fa 1:全部层 offload 到 GPU
    • -c 131072:默认 ctx 128K,不是训练上限 262144。256K 会把模型+KV 顶到 ~26.3GB/25.75GB,
      Vulkan 装不下 DEVICE_LOCAL 而把权重退回 GTT(系统内存)映射,decode 掉到 0.49 tok/s。
      下界 64K(Hermes Agent 硬性要求 context >= 64000)。
      需要更大窗口用 CTX=65536 ./llama.sh 38 覆盖,但每次加大都要重新核对显存(详见 §9.8)
    • -cram -1:KV cache 放内存而非显存。25.75GB 卡上省下的正是权重能留在 DEVICE_LOCAL 的那点余量
    • --spec-type ngram-map-k4v,draft-mtp --spec-draft-n-max 3:投机解码。ngram-map-k4v 不可省略,详见 §6.3
    • --spec-ngram-map-k4v-size-n 32:n-gram 查表长度,必须 32。取 12 会在「格式重复但内容要换」的任务上倒扣 5~10%
    • -ctk q4_0 -ctv q4_0:KV cache 量化(只换容量不换速度)
    • --parallel 1:单并发(本地推理推荐)
    • --reasoning off:关闭推理模式(Qwen3.x)
    • systemd 自动检测:有 qwen38.service 单元时,无覆盖变量的启动自动走 systemctl --user start;
      有 CTX/UB/K4V 等覆盖或 --vision 时退回直起(systemd 不继承 shell 环境),并打印警告

    常见误用:./llama.sh use 36 不是有效命令。切换模型用 ./llama.sh 36 --use,
    或直接 ./llama.sh stop && ./llama.sh 36。在 32GB 以外的显存预算下两个 27B 无法共存,
    脚本会自动先停另一个。


    1 条回复 最后回复
    0

    你好!看起来您对这段对话很感兴趣,但您还没有一个账号。

    厌倦了每次访问都刷到同样的帖子?您注册账号后,您下次访问时都将自动回到上次浏览的位置,并可选择接收新回复的通知(通过电子邮件或推送通知)。您还可以收藏帖子、为帖子点赞,以此向其他社区成员表达您的感谢。

    有了你的建议,这篇帖子会更精彩哦 💗

    注册 登录
    回复
    • 在新帖中回复
    登录后回复
    • 从旧到新
    • 从新到旧
    • 最多赞同


    • 登录

    • 登录或注册以进行搜索。
    • 第一个帖子
      最后一个帖子
    0
    • 版块
    • 最新
    • 标签
    • 热门
    • 用户
    • 群组