在高通 SA8295P(Hexagon V73)上跑 LiteRT-LM + QNN 端侧 NPU

摘要:把 LiteRT-LM 接到 App 进程内走 QNN/HTP 真·出字,理论上在 Snapdragon 8 Gen 2/3 上能跑;但当目标是车机 SoC SA8295P(Hexagon V73)时,会撞上 Google 2026-01 公开承认的"SA8295P not ready yet"。本文把从注册 Qualcomm ID、下载 QAIRT、推库、对接 LiteRT-LM、到 NPU 真·出字判据的全过程按时间线复盘一遍,附原始证据与下一步可破局路径。


0. 目标与背景

目标:在车机 e6142550(Snapdragon SA8295P,Hexagon V73,30 TOPS NPU)上跑通 google-ai-edge/LiteRT-LM + QNN 端侧 NPU,让 1.5B Qwen2.5 文本模型在 HTP 上真·出字(不是静默回退 CPU)。

App 内嵌 LiteRT + QNN + Qwen 拆解 Qwen 是 AI 模型本身;LiteRT 是模型的 “调度总管”;QNN 是高通 NPU 的专属驱动插件;全部打包进你的车载 App 进程内部一起跑,不需要 Ollama、不需要 Linux 容器、不需要 root。

上层:Koog / MCP Agent(你的业务层,处理对话、工具调用)
        ↓ 调用推理接口
LiteRT(调度层)
        ↓ 绑定后端
QNN SDK库(NPU驱动插件)
        ↓ 驱动硬件
SA8295 HTP NPU(芯片硬件)
        ↑
Qwen模型文件:被LiteRT加载,通过QNN在NPU上执行
## 和 A.I chroot+Ollama+Qwen 做对比(方便理解)

### A.I(POC)

用户Query → Koog/MCP Agent → HTTP请求 → Ollama服务(跑在chroot Linux容器)→ Ollama加载Qwen → CPU计算

* Ollama:一站式大模型服务,自带 http 服务、模型管理;
* 缺点:独立服务进程,容器环境,root 依赖,只能 CPU 跑。

### D.II(量产)

用户Query → Koog/MCP Agent → 直接调用本进程内LiteRT接口 → LiteRT转发任务到QNN → NPU硬件跑Qwen

* ​**没有 Ollama,没有独立服务,没有容器**​;
* 推理引擎直接内嵌 App 内部,NPU 硬件加速。

## 关键误区澄清

1. ❌ LiteRT 不是跑模型算力的,它只是调度;算力全部交给 QNN+NPU。
1. ❌ QNN 不能单独直接读取原始 Qwen 模型,必须 LiteRT 做模型加载、数据预处理。
1. ❌ Qwen 模型不能直接在 NPU 上跑,必须提前用 QNN 工具链离线编译,生成适配 HTP 的模型包。

已有条件:

  • App 进程内 + Koog 1.1.1 LLMClient 抽象(com.fawcar.aiosagent.data.llm.LiteRTLLMClient)
  • litertlm-android:0.17.0 aar(Google Maven)
  • 1.6GB Qwen2.5-1.5B .litertlm 模型
  • App 端 Koin DI + NPU 客户端注入 + 路由层(LlmRouter)

一、完整执行步骤

Step 1 — 注册 Qualcomm ID(准备阶段)

入口:https://myaccount.qualcomm.com/profile(注:这是浏览器侧入口,AI 工具不可直接登录,仅作步骤记录)

  • 用公司邮箱注册账号
  • 登录后进入 Qualcomm ID 中心,保存 ID 与密码(后面下载 SDK 用)

这是个一次性账号,免费;预研阶段不会触发付款,也不会触发 Qualcomm AI Stack License 的 redistribution 义务。

Step 2 — 下载 Qualcomm AI Runtime SDK (QAIRT) Community Edition

入口:https://softwarecenter.qualcomm.com/(需登录 Qualcomm ID)

  • 选 "Qualcomm AI Runtime Community"(带 CN-Dev 标,仅供开发/验证;非量产)
  • 本次下载版本:2.51.40.260930(比文档上写的 2.47 更新;实测可用)
  • SDK 大小约 ~2.6GB,包含:
    • lib/aarch64-android/ —— App 进程用的 QNN runtime(libQnnHtp.so 等)
    • lib/hexagon-v73/unsigned/ —— DSP 端 skeleton(libQnnHtpV73Skel.so)
    • 不同 Hexagon 代际的 stub(V66/V68/V69/V73/V75/V79/V81/V85)

⚠️ 关键坑:QAIRT 公开 Community 版的 HTP stub 是消费级 Snapdragon 代际,不一定匹配 SA8295P 的 HTP v7。SA8295P 真要量产,匹配 lib 须 OEM/车厂 BSP 固化。

Step 3 — 解压 SDK,定位 App 端 .so 集合

D:\faw\project\aios\qnn\
└── v2.51.40.260930\qairt\2.51.40.260930\lib\
    ├── aarch64-android\           ← App 进程用
    │   ├── libQnnHtp.so
    │   ├── libQnnHtpPrepare.so
    │   ├── libQnnHtpV73Stub.so
    │   ├── libQnnSystem.so
    │   ├── libQnnGenAiTransformer*.so
    │   ├── libQnnModelDlc.so
    │   └── ... (13 个核心 .so)
    └── hexagon-v73\unsigned\      ← DSP 端 skel
        └── libQnnHtpV73Skel.so

Step 4 — 修代码:让 Backend.NPU() 真正拿到正确 lib 路径

坑 1(linker namespace):App 是 adb 装到 /data/app/... 的非系统 App,其 linker namespace 不含 /vendor/lib64,所以 dlopen("/vendor/lib64/libQnnHtp.so") 会失败。 → 把 nativeLibraryDir 从硬编码 /vendor/lib64 改成 applicationInfo.nativeLibraryDir。

坑 2(Koin Scope):androidContext() 是 Scope/KoinApplication 的扩展,只能写在 single { } 内;写 module { } 顶层会编译报 "receiver type mismatch"。

坑 3(EngineConfig 误设):EngineConfig 不要给文本模型设 visionBackend / audioBackend,会 NOT_FOUND: TF_LITE_AUDIO_ENCODER_HW not found。

修改后 AppModule.kt 关键段:

// Koin named single,只在 single { } 内才能用 androidContext()
single<String>(named("npuLibDir")) {
    androidContext().packageManager
        .getApplicationInfo(androidContext().packageName, 0).nativeLibraryDir
}

single<LLMClient>(named("litert")) {
    KoogLlmFactory.createLiteRTClient(
        BuildConfig.LITERT_MODEL_PATH,
        get(named("npuLibDir")),     // ← App 自己的 lib/arm64
        androidContext().cacheDir.absolutePath,
    )
}

single { LlmRouterImpl(
    npuClient = get(named("litert")),
    npuModel  = Models.localNpuQwen,
    npuParams = Models.localChatParams,
    npuAvailable = {
        LiteRTLLMClient.NpuAvailabilityCheck.isAvailable(get(named("npuLibDir")))
    },
    ...
) }

LiteRTLLMClient.kt 关键改动:

EngineConfig(
    modelPath = modelPath,
    backend = Backend.NPU(nativeLibraryDir),  // ← nativeLibraryDir 已指向 App lib
    // 文本模型不要设 visionBackend / audioBackend(设了 NOT_FOUND)
    cacheDir = cacheDir,
)

Step 5 — 把 13 个 QNN lib push 到 App nativeLibraryDir

# 取 App 装包路径(每次重装 hash 变,必须重推)
adb shell pm path com.fawcar.aiosagent
#  → /data/app/~~HASH==/com.fawcar.aiosagent-HASH==/base.apk
# lib dir = 上面的路径换 /base.apk 为 /lib/arm64

DEST=/data/app/~~.../com.fawcar.aiosagent-.../lib/arm64
SRC='D:\faw\project\aios\qnn\v2.51.40.260930\qairt\2.51.40.260930\lib\aarch64-android'

for f in libQnnHtp.so libQnnHtpNetRunExtensions.so libQnnHtpOptraceProfilingReader.so \
         libQnnHtpPrepare.so libQnnHtpProfilingReader.so libQnnHtpV73CalculatorStub.so \
         libQnnHtpV73Stub.so libQnnSystem.so libQnnGenAiTransformer.so \
         libQnnGenAiTransformerModel.so libQnnModelDlc.so libQnnHta.so libQnnHtaNetRunExtensions.so; do
  adb push "$SRC/$f" "$DEST/$f"
done

# DSP 端 skel(OEM 已固化在 /vendor/lib/rfsa/adsp/,无需 push):
# /vendor/lib/rfsa/adsp/libQnnHtpV73Skel.so

设备侧验证:

$ adb shell ls -l /data/app/.../com.fawcar.aiosagent-.../lib/arm64/libQnn*.so | wc -l
13
$ adb shell ls /vendor/lib/rfsa/adsp/
# adsp_callback_skel.so  ...  libQnnHtpV73Skel.so  ...

Step 6 — 下载 1.6GB Qwen2.5-1.5B .litertlm 模型

# 台架 + PC 都到不了 huggingface.co(防火墙)
# 用 hf-mirror.com 镜像下载
curl -L -C - --noproxy '*' -o qwen2.5-1.5b-instruct.litertlm \
  https://hf-mirror.com/litert-community/Qwen2.5-1.5B-Instruct/resolve/main/qwen2.5-1.5b-instruct.litertlm
# size = 1,597,922,856 bytes (1.6GB)

# 推到台架
adb push qwen2.5-1.5b-instruct.litertlm /data/local/tmp/
# build.gradle.kts 里 BuildConfig.LITERT_MODEL_PATH 默认指向这个路径

坑 4(后台下载 2 分钟硬杀):用 run_in_background=true 下载会卡在 2m1s 判 failed(数据还在流)。 → 用 curl -C - 断点续传 + for 循环 40 次(每次间隔 3s),前台给大 timeout。

Step 7 — 清 DataStore 强制 LlmMode = LOCAL_ONLY

# LlmMode.DEFAULT = CLOUD_ONLY,且 DataStore 已持久化
# 改代码 default 不生效(永远读存储值)→ 必须 clear
adb shell pm clear com.fawcar.aiosagent

坑 5(DataStore 持久化陷阱):这是最容易忽略的——ChatPrefsRepository 里有存储值时永远读存储值,改 LlmMode.DEFAULT 不会生效。

Step 8 — 构建并安装 debug APK

$env:GRADLE_USER_HOME = "D:\faw\project\aios\.gradle_uh"
& "D:\faw\project\aios\.gradle_uh\wrapper\dists\gradle-8.8-all\...\gradle-8.8\bin\gradle.bat" `
   -p D:\faw\project\aios\AiosAgent :app:assembleDebug --no-daemon --max-workers=1

adb -s e6142550 install -r -d -t app/build/outputs/apk/debug/app-debug.apk

Step 9 — 写探针 Activity,跑"与真实聊天链路同源"的 NPU 推理

坑 6(UI 自动化不可靠):软键盘弹出会重排布局(EditText bounds 在 y=208/288 两档跳变),且输入框右侧图标是麦克风不是发送。改用 am start 启动专用探针 Activity(100% 可靠)。

// NpuProbeActivity.kt(探针,临时)
class NpuProbeActivity : Activity(), KoinComponent {
    private val outFile get() = File(filesDir, "npu_probe.txt")  // 必须写 App 私有 filesDir
    // 探针结果写文件(写 /data/local/tmp 不行,SELinux 不让 App 写)
    ...
    val client = LiteRTLLMClient(modelPath, libDir, cacheDir.absolutePath, backend = Backend.NPU(libDir))
    val reply = withContext(Dispatchers.IO) { client.execute(prompt, model).textContent() }
    outFile.appendText("REPLY_OK elapsed=${elapsed}ms len=${text.length}\n")
    outFile.appendText("REPLY_TEXT=$text\n")
}
adb shell am start -n com.fawcar.aiosagent/.data.llm.NpuProbeActivity
sleep 60
adb shell cat /data/data/com.fawcar.aiosagent/files/npu_probe.txt

Step 10 — NPU 真·出字判据(重要!)

"REPLY_OK 出现 = NPU 生效"是错的,会被静默回退 CPU 骗。

唯一判据(logcat):

  • Replacing ... with delegate (DispatchDelegate) → NPU ✅
  • Replacing ... with delegate (TfLiteXNNPackDelegate) → CPU ❌(静默回退)

辅助判据:

  • 进程 /proc/<pid>/maps 里没有任何 libQnn*.so → 一定没上 NPU
  • 进程 /proc/<pid>/maps 里没有任何来自 App lib/arm64 的 .so → 加速器都没加载
adb shell logcat -c
adb shell am start -n com.fawcar.aiosagent/.data.llm.NpuProbeActivity
# 必须在 20s 内抓,否则被 com.fawcar.ai.assistant 崩溃循环 + wpa_supplicant 刷屏冲掉
sleep 20 && adb shell logcat -d | grep -E 'DispatchDelegate|XNNPackDelegate|litert_dispatch|npu_registry'

二、执行过程的关键发现(按时间线)

2.1 第一次跑:路由未选 NPU,走云端

探针输出:

mode=CLOUD_ONLY
ROUTE client=DashscopeLLMClient

根因:LlmMode 默认 CLOUD_ONLY,且 DataStore 已持久化该值(见 Step 7)。 → pm clear 后变 mode=LOCAL_ONLY / client=LiteRTLLMClient。

2.2 第二次跑:NPU 客户端被选中,但 Engine.initialize() 加载 QNN lib 失败

logcat:

E AndroidRuntime: java.lang.UnsatisfiedLinkError:
  dlopen failed: library "/vendor/lib64/libQnnHtp.so" not found

根因:见 Step 4 坑 1(linker namespace),App 拿不到 /vendor/lib64。 → 改 nativeLibraryDir = applicationInfo.nativeLibraryDir,把 13 个 QNN lib 推到 App 自己的 lib/arm64/(见 Step 5)。 → 加完后 /proc/<pid>/maps 能看到 libQnnHtp.so / libQnnSystem.so 等被 dlopen,libQnnHtp.so 加载成功。

2.3 第三次跑:createConversation 报 TF_LITE_AUDIO_ENCODER_HW not found

探针输出:

PROBE_FAILED: LiteRtLmJniException: Failed to create conversation:
  NOT_FOUND: TF_LITE_AUDIO_ENCODER_HW not found in the model.

根因:EngineConfig 给文本模型误设了 visionBackend / audioBackend = Backend.NPU(...),而 qwen2.5-1.5b 文本模型里没有这两个编码器。 → 移除 visionBackend / audioBackend 字段(见 Step 4 坑 3)。

2.4 第四次跑:能出字了,但被判为"出字 = NPU 生效"是误判

探针输出(看起来成功):

REPLY_OK elapsed=29495ms len=263
REPLY_TEXT=I apologize, but you've written "I didn't think much about it." ...

真因(logcat 抓出来):

I tflite : Replacing 1291 out of 1409 node(s) with delegate (TfLiteXNNPackDelegate) ...   ← CPU!

/proc/<pid>/maps 里没有任何 libQnn*.so、没有任何 App lib/arm64 下的 .so。 → **实际上跑的是 CPU(XNNPack)**,NPU 路径在 dispatch 加载这一步就静默回退了。 → Backend.NPU` 同样静默回退**,照样出字,只留一行 W/E 日志。

这次教训:写"出字了"三个字时必须先在 logcat 里 grep delegate (...),否则在写博客的同时已经把"假成功"记下来了。

2.5 第五次跑:补齐 libLiteRtDispatch_Qualcomm.so(LiteRT→QNN 桥接)

Backend.NPU() 内部要 dlopen 一份叫 libLiteRtDispatch_Qualcomm.so 的桥接库(在 nativeLibraryDir 里找), 该库不在 litertlm-android:0.17.0 aar 里(aar 只有一个 liblitertlm_jni.so,TFLite+XNNPack 全静态打进去), 也不在 QAIRT SDK 里(QAIRT 只有一个老 TFLite 用的 libQnnTFLiteDelegate.so)。

唯一来源:google-ai-edge/LiteRT GitHub Releaseslitert_npu_runtime_libraries_jit.zip(v2.2.0):

DEST=/data/app/.../com.fawcar.aiosagent-.../lib/arm64
curl -L -C - --noproxy '*' -O \
  https://github.com/google-ai-edge/LiteRT/releases/download/v2.2.0/litert_npu_runtime_libraries_jit.zip
unzip -j -d extracted/ litert_npu_runtime_libraries_jit.zip \
  '*qualcomm_runtime_v73/*libLiteRtDispatch*.so' \
  '*qualcomm_runtime_v73/*libLiteRtCompilerPlugin*.so'
# 提取出:
#   libLiteRtDispatch_Qualcomm.so       445,576 bytes (导出 LiteRtDispatchGetApi)
#   libLiteRtCompilerPlugin_Qualcomm.so 724,016 bytes (导出 LiteRtCreateCompilerPlugin)
# 都是 aarch64-elf64,对应 Hexagon V73(SA8295P 这一代)
adb push extracted/libLiteRtDispatch_Qualcomm.so $DEST/
adb push extracted/libLiteRtCompilerPlugin_Qualcomm.so $DEST/

ABI / 版本互校全过:

  • QNN system 1.15.0 ≥ 要求的 1.11.0 ✅
  • dispatch lib 的 LiteRtDispatchApi 56 字节布局(含 abi_header)与 aar 嵌入的 LiteRT 兼容 ✅

2.6 第六次跑(critical):dispatch 加载成功,但 QNN 后端初始化失败

logcat 关键证据:

I litert : [litert_dispatch.cc:160] Loading shared library:
  .../lib/arm64/libLiteRtDispatch_Qualcomm.so
I litert : [qnn_manager.cc:175] Loading qnn system shared library from ".../libQnnSystem.so"
W litert : [qnn_manager.cc:360] Qnn System library version 1.15.0 is used.
  The version LiteRT using is 1.11.0.                                  ← 版本 OK
W litert : [qnn_manager.cc:262] Qnn library version 2.40.0 is used.
  The version LiteRT using is 2.36.0.                                  ← 版本 OK
W litert : [qnn_manager.cc:302] Qnn backend library version 5.51.0 is used.
  The version LiteRT using is 5.47.0.                                  ← 版本 OK
I lrt-qc  : INFO: [Qnn] Initializing QNN backend for SoC model: 39     ← SA8295P 的 soc_id
W qnn     : QnnDsp <W> Failed in loading stub: dlopen failed:
  library "libQnnHtpV68Stub.so" not found                              ← 找 v68 stub
E qnn     : QnnDsp <E> Failed to load skel, error: 4000
E qnn     : QnnDsp <E> Transport layer setup failed: 14001
E qnn     : QnnDsp <E> Failed to create transport for device, error: 4000
E litert  : [dispatch_api.cc:145] Failed to initialize QNN backend
E litert  : [dispatch_delegate.cc:131] Failed to initialize Dispatch API

翻译:

  • dispatch lib 加载 ✅
  • QNN system 加载 ✅、版本满足要求 ✅
  • 但 dispatch 把 SoC 39(SA8295P)映射到了 v68(/vendor/lib/rfsa/adsp/ 实际只有 v73 件)
  • 找 libQnnHtpV68Stub.so 失败 → skel 加载失败 → QNN backend 初始化失败 → 静默回退 CPU

旁证:Specified config SOC, ignoring on real target —— dispatch 内部硬编码 SoC 表里没 39,走兜底 v68。

2.7 跨后端对照(cross-check 排除"模型本身"因素)

把探针扩展支持 Backend.GPU(),三后端同 APK 同模型跑一遍:

后端关键日志结果
CPU (XNNPack)delegate (TfLiteXNNPackDelegate) + REPLY_OK 13.8s✅ 出字 263 字符
GPU (Vulkan)Failed to modify graph with delegate❌ 启动失败
NPU (dispatch + QNN 2.51.40)QnnDsp Failed to load skel, error: 4000❌ DSP skel 加载失败

→ CPU 走通 + GPU/NPU 都失败,证明:模型本身 OK、LiteRT-LM 集成 OK、Koog 接线 OK、路由层 OK。卡点在 SoC 适配层。


三、最终结论:SA8295P 上 NPU 短期不可用 —— Google 官方公开承认

3.1 决定性证据:Google 2026-01 在 Hugging Face 公开承认

HF litert-community/Gemma3-1B-IT discussion #20(原文链接):

"Unfortunately, SA8295P is not ready at the moment. Due to hardware differences from the existing supported SOCs, it will require a different quantization scheme to run. This SOC is on the team's radar and we will post the model here when SA8295P is supported." —— @marissaw, LiteRT Community (FKA TFLite) org, 2026-01-06

原始链接:https://huggingface.co/litert-community/Gemma3-1B-IT/discussions/20

含义:

  • SA8295P 不在 LiteRT 公开支持的 SoC 列表里
  • 即使 GPU/NPU 加速器装上,模型本身还需要"different quantization scheme"——意味着不能拿现成的 1.5B fp16 模型直接当 NPU context,需要重新做量化
  • Google 团队把这个 SoC 放在"on the team's radar",但没有时间表

3.2 与"Google 公开 dispatch 库" 的关系

v2.2.0 / v2.1.5 / v2.1.6 / v2.0.3 等所有公开 release 的 dispatch lib 内置的 SoC→代际表都把 SA8295P (soc_id=39) 强制走 v68。我们 push v73 库没用,是 dispatch 内部用 v68(兜底逻辑)。这条对所有想要在 SA8295P 上跑 NPU 的人都成立。

3.3 写在最后的"为什么我花了两天才到这一步"

中间踩了 6 个独立坑(每个都能独立让 NPU 路径静默回退或崩):

  1. LlmMode 默认 CLOUD_ONLY + DataStore 持久化 —— 改 default 不生效,必须 pm clear
  2. /vendor/lib64 对普通 App 不可 dlopen(linker namespace) —— 改推 App 自己的 lib dir
  3. androidContext() 写在 module { } 顶层编译失败 —— 必须是 Koin single { } 内
  4. EngineConfig 误设 visionBackend/audioBackend —— 文本模型没有,NOT_FOUND
  5. 缺 libLiteRtDispatch_Qualcomm.so —— aar 不带、QAIRT 不带,要去 LiteRT GitHub Release 拿
  6. SA8295P 暂不支持(Google 官方承认) —— dispatch 强走 v68,找不到 stub

每个坑都"看似出字 = 成功",但只有 delegate 类型是 NPU 判据。这条最容易被写"成功"博客时漏掉。

3.4 当前可破局的两条路(按 ROI 排序)

方案 1:本地 bazel 编 dispatch + 覆盖 target_htp_arch=73(中等成本,最有可能跑通)

  • 命令:bazel build --config=android_arm64 @litert//litert/vendors/qualcomm/dispatch:dispatch_api_so
  • 同时打 patch:把 source 里写死的 SoC→代际表中 39 改为 v73,或传 --copt=-DQUALCOMM_TARGET_HTP_ARCH=73
  • 需要:NDK r28b+、bazel 环境、源码(外网)
  • 风险:可能仍然撞上"different quantization scheme"——模型层还要重做

方案 2:OEM/车厂 BSP 提供 SA8295P 配套 QNN 运行时(高成本,走流程)

  • 公开 QAIRT Community 不含 SA8295P BSP 件;车厂通常已购平台 license,可以走"内部技术对接"渠道
  • 时间:数周到数月

方案 3:等 Google 官方适配(无时间表)

3.5 业务影响

  • D.II(NPU 路径)在 SA8295P 上短期不可达
  • D(Ollama CPU 1.5B @ 22s)仍然兜底可用(已 §7 验证过)
  • 云端 DashScope 当前 403 不可用 → "端云双栈"实际只剩"端(CPU 1.5B) + 等云端"
  • D.II 的代码改动(Koin 单例、EngineConfig、NPU lib 准备、SoC 探针)作为架构能力沉淀有价值,下次遇到 SM8550/8650/8750 这类在表里的 SoC 可直接复用

四、证据汇总(按出现顺序)

阶段证据关键一行
Step 5adb shell ls libQnn*.so | wc -l13
Step 7mode=LOCAL_ONLYpm clear 前后对照
Step 9探针文件 npu_probe.txtREPLY_OK elapsed=29495ms len=263
Step 9/proc//maps 无 libQnn*.so"出字"=CPU,不是 NPU
Step 10logcat delegate 类型(TfLiteXNNPackDelegate) = CPU
2.5dispatch lib 导出LiteRtDispatchGetApi / LiteRtCreateCompilerPlugin
2.6QNN 互校Qnn System library version 1.15.0 ≥ 要求的 1.11.0
2.6SoC 映射错位SoC model: 39 + dlopen failed: library "libQnnHtpV68Stub.so" not found
2.6QNN DSP 错误QnnDsp Failed to load skel, error: 4000
2.7三后端对照CPU ✅ / GPU ❌ / NPU ❌
3.1Google 官方确认HF discussion #20, 2026-01-06

五、引用


结论一句话:在 SA8295P 上跑 NPU 端侧 LLM,代码 + 库 + 桥接 dispatch 全部到位,仍然跑不出来——因为 Google 公开 dispatch 库把 SoC 39 强走 v68,而本机只有 v73。这不在我们控制范围内。业务上短期用 CPU 兜底,长期要么等 Google 适配、要么拿 OEM BSP、要么自己 bazel 编 dispatch 并覆盖 hex arch。

首页