
一、端侧大模型的机遇与约束
1.1 为什么把大模型搬上板子
前六讲我们把"视觉"这条线从融合系统、推理引擎、模型供给、图像处理一直打到了视频流水线,板子已经能"看懂"世界。但"看懂"只是智能的一半,另一半是"理解和表达"——能用自然语言对话、能总结、能问答、能做决策辅助。这些正是大语言模型(LLM)的强项。
把 LLM 搬到端侧,价值非常直接:数据不出本机,隐私和合规天然友好;没有云端 API 的网络依赖与按量计费,本地推理一次投入长期免费;断网环境(车载、野外、产线)里依然能对话。当视觉负责"感知"、语言模型负责"理解",端侧设备才真正从"摄像头"升级为"会思考的助手"。这也是阿加犀在具身智能、机器人方向重点押注的能力组合。
1.2 端侧 LLM 的三道硬约束
但 LLM 不是想搬就能搬,它和前面那些检测模型完全不是一个量级。三道硬约束必须心里有数:
- 算力约束:LLM 的推理是海量矩阵乘,对 NPU/CPU 算力要求远高于检测模型。一个 0.5B 的小模型和高通 NPU 还能过得去,7B 往上就非旗舰端侧能轻易扛。
- 内存约束:模型权重 + 推理时的 KV Cache(注意力键值缓存)都要占内存,上下文越长、KV Cache 越大,内存越吃紧。这往往是端侧 LLM 最先撞到的墙。
- 功耗约束:持续跑 LLM 的算力开销,对电池供电设备是实打实的负担,需权衡"多久生成一次"。
理解这三条,你就不会拿"云端能跑 7B"的直觉去要求板子,而是老老实实从 0.5B、1.5B 这类小模型起步,把体验做顺再做规模。这也是为什么本讲把主力板选在算力更高的犀牛派 X1。
1.3 AidGen 的定位:基于 AidLite 的生成式推理加速
AidGen 是阿加犀的生成式 Transformer 推理框架,它构建在 AidLite 之上——也就是说,前面第 02~04 讲你熟悉的 AidLite 调度能力,被 AidGen 复用并扩展到了生成式模型上。AidGen 负责把 LLM/多模态模型的推理,调度到端侧的 CPU、GPU、NPU 上加速,让你不必从零搭一套大模型推理运行时。
它的价值在于"复用":你不用自己处理 KV Cache、不用自己写算子调度、不用自己管权重加载,这些 AidGen 在 AidLite 的底座上替你做掉。你面对的是"加载模型 → 多轮对话 → 拿输出"这种高层接口。这一脉相承的设计,正是 AidLux 工具链"底座复用"哲学的又一次体现。
1.4 本讲目标与硬件准备
读完本讲,你应该能:第一,理解 AidGen 在工具链中的位置与 AidLLM/AidMLM 的能力划分;第二,从 Model Farm 取一个适配的大模型(如 Qwen2.5-0.5B-Instruct)并在犀牛派 X1 上部署;第三,跑通多轮对话并理解上下文长度(cl)对资源的影响。
硬件准备:本讲以**犀牛派 X1(QCS8550)**为主力,因为它的 NPU 算力与内存水位更适合 LLM;更轻的小模型(0.5B 量级)也可在犀牛派 A1 上尝试,但体验与并发受限。这里要说明一个事实:AidGen 当前在 Linux 上以 C++ 形态提供完整支持,Python 绑定在规划中,所以本讲的实战代码以 C++ 为主——这与本系列"Python 为主"的通用约定不同,是 AidGen 这个组件当前的真实能力边界,后面 2.4 节会专门讲清,避免你拿 Python 去硬套一个尚未稳定支持的路径。
1.5 端侧 LLM 的真实落地点
讲了机遇和约束,落到"到底用在哪"更具体。端侧 LLM 的几个典型落地点:一是本地语音助手(结合第 10 讲的 AidVoice,麦克风进来 → ASR → LLM 总结/问答 → TTS 出去),断网也能用;二是智能摄像头解说(结合第 05、06 讲的视觉,摄像头看到画面 → 检测 → LLM 生成中文描述,第 11 讲综合实战会做);三是工业 / 产线的本地知识问答(设备手册、故障排查,数据不出厂);四是机器人交互(具身智能里,让机器人用自然语言理解和回应指令)。这些场景的共同点是"数据敏感或网络不稳",恰好是端侧 LLM 的主场,也是阿加犀在机器人与边缘 AI 方向重点发力的组合。
二、AidGen 在工具链中的位置
2.1 它站在 AidLite 肩上
AidGen 与 AidLite 不是并列关系,而是上下关系。架构上可以这样看:
AidGen 在 AidLite 之上做了生成式特有的事:自回归逐 token 生成、KV Cache 管理、对话模板拼装;而底层的"模型加载、算子调度、NPU 加速"仍由 AidLite 承担。所以你之前建立的 AidLite 认知(模型属性、后端、NPU 调度)在 AidGen 里依然成立,只是被包进了更高层的接口。
2.2 AidLLM 与 AidMLM 能力矩阵
AidGen 在组件层面划分为两类能力:
- AidLLM(语言大模型):纯文本的大语言模型推理,负责对话、总结、问答、翻译等。这是本讲的主力。
- AidMLM(多模态大模型):支持图文等多模态输入的大模型推理,能让板子"看图说话"——结合第 05、06 讲的视觉能力,做到"摄像头看到 → 大模型理解并描述"。
两者的关系可以理解为:AidLLM 是"读文字、写文字",AidMLM 是"读图+文字、写文字"。随着端侧算力提升,多模态是更让人兴奋的方向,但落地门槛也更高,建议先把 AidLLM 这条线跑顺,再图多模态。
2.3 调度 CPU / GPU / NPU
和 AidLite 一致,AidGen 也能调度端侧的多种计算单元。对 LLM 而言,不同算子的特性不同:部分算子适合 NPU 加速,部分在 CPU/GPU 上更稳。AidGen 在 AidLite 底座上做了这类调度决策,你的代码通常不必手动选每个算子的后端——这和第 02 讲"一次开发、跨单元调度"的思想相同。理解这一点,能让你在遇到性能问题时,知道该去查 AidGen 的调度配置、而不是自己重写底层。
2.4 当前支持情况:为什么本讲示例用 C++
这里要把话说透,免得你走弯路。根据 AidLux 官方说明,AidGen 目前在 Linux 上以 C++ 提供完整支持,而 Python、Android 侧在规划推进中。这意味着:现在想实打实把大模型跑起来,主路径是 C++。
所以本讲没有强行用 Python 去演示一个 AidGen 尚不稳定支持的接口,而是如实以 C++ 给出可运行骨架——这既是尊重"信息准确"的底线,也是帮你省掉"照着 Python 示例却跑不通"的无效劳动。如果你和本系列多数读者一样是 Python 背景,也别慌:C++ 部分只负责"起引擎、跑对话"这薄薄一层,真正的业务逻辑(怎么组织 prompt、怎么用模型输出)仍然可以用你熟悉的方式思考,甚至把 AidGen 的 C++ 程序包成一个本地服务(第 08 讲 AidGenSE 会进一步把这个服务做成 OpenAI 兼容接口,那时 Python 调用就完全顺了)。换句话说,C++ 是当下的"启动器",不是你的"主战场"。
2.5 端侧 LLM 与云端 LLM 的本质区别
很多人拿端侧 LLM 和云端 API 直接比能力,这是不公平的。两者本质区别在三处:一是数据位置,端侧数据不出本机,云端要把数据传出去;二是依赖,端侧断网可用,云端一旦断网即失效;三是成本结构,端侧是一次性硬件投入后本地推理边际成本趋零,云端按调用量持续计费。所以端侧 LLM 不是"云端替代"而是"云端补充"——能用云端的场景继续用云端,那些对隐私、离线、成本敏感的场景,才交给端侧。选型时问自己一句"这数据敢不敢出本机、这网络靠不靠得住",答案就清楚了。
2.6 组件版本与模型的对应关系
和第 03、04 讲反复强调的"版本纪律"一样,AidGen 也有自己的版本对应关系:AidGen SDK 的版本、底层 AidLite / QNN 的版本、以及你下载的大模型所适配的版本,三者要互相对齐。比如某版大模型标注"需 AidGen X 及以上 + QNN Y",你板子上的 AidGen 和 QNN 就得满足。搞混了,轻则加载失败,重则生成乱码。建议把"模型 → AidGen 版本 → QNN 版本"记进项目文档,和前面所有版本表合并成一份总表。版本对齐看似枯燥,却是端侧从"能跑"到"稳定跑"的护城河。
三、模型供给:从 Model Farm 取大模型
3.1 大模型分区与 Qwen2.5 系列
模型从哪来?和检测模型一样,两条路:自己转(用第 04 讲的 AIMO,如果平台支持大模型转换)或从 Model Farm 取现成。对 LLM,Model Farm 通常有专门的"大模型分区",聚集了适配高通平台的模型,例如 Qwen2.5 系列的多个尺寸(0.5B、1.5B、3B 等)。这些模型多已做好端侧适配,下载即用概率高。
取模型时同样要看"适配平台与版本"字段,确认和你的板子(X1 是 QCS8550)匹配。大模型对算力敏感,平台往往会标注推荐运行的最低硬件,照着选最稳。
3.2 选多大的模型:0.5B / 1.5B / 3B 的取舍
端侧 LLM 选尺寸,是"体验"和"资源"的直接博弈:
- 0.5B(如 Qwen2.5-0.5B-Instruct):最轻,X1 上能跑得比较顺,首 token 延迟低,适合做轻量对话、简单问答、指令执行;能力上限有限,复杂推理较弱。
- 1.5B:能力和流畅度的平衡点,X1 上可用,但上下文和并发要克制。
- 3B 及以上:能力更强,但对 X1 的内存与算力都是考验,需谨慎评估上下文长度与并发需求。
我的建议:先用 0.5B 把整条链路(部署→对话→服务化)跑顺、建立体感,再按需升尺寸。别一上来就追大,大模型在端侧的"能跑"和"跑得舒服"之间,差距比小模型大得多。
3.3 下载与文件结构
从 Model Farm 下载大模型后,通常会得到一个目录,里面含模型权重、配置文件、以及关键的对话模板文件 aidgen_chat_template.txt。解压到板子的固定目录(建议 /home/aidlux/models/...),后续配置都指向这里。把模型目录和"所用版本、尺寸、适配平台"一起记进项目文档,和前面"模型→QNN 版本"那张表合并管理。
3.4 对话模板 aidgen_chat_template.txt
LLM 不是"你输一句、它答一句"那么简单,它需要一套对话模板来规定角色设定、轮次格式、特殊 token。AidGen 通过 aidgen_chat_template.txt 描述这套格式。不同模型的模板约定不同(ChatML、Llama 风格等),必须用模型对应的那份,否则生成会乱。
模板的本质,是把"系统提示 + 用户轮 + 助手轮"按模型训练时的格式拼起来,并在合适位置插入特殊标记。你改模板,本质是改"怎么和模型说话"。这部分虽然不起眼,却是端侧 LLM 正确性的命门——模板错一格,输出就可能变成乱码或忽略指令。
3.5 量化:端侧 LLM 为什么常做权重压缩
端侧 LLM 的权重体积和内存占用,是它能不能跑起来的关键。一个 7B 模型即便 FP16 也要十几 GB,端侧根本放不下;所以端侧 LLM 几乎都要做权重量化——把 FP16 压到 INT8 甚至 INT4。量化对 LLM 的重要性比检测模型更甚:检测模型量化掉点还能用,LLM 量化过度会明显"变傻"(逻辑错乱、胡说八道)。因此端侧 LLM 的量化是门精细活,要在"放得下"和"说得清"之间找平衡,往往 INT8 起步、INT4 谨慎。这也解释了为什么 Model Farm 上的端侧 LLM 会标注不同精度版本——你下载时选的就是"压到什么程度"。具体量化方案由平台与模型决定,你只需理解"精度越低越省资源、但越可能变笨"这个权衡。
3.6 下载后的完整性校验
大模型文件体积大、分片多(权重常被拆成多个分片),下载或拷贝过程中损坏的概率比小模型高。落地前做个完整性校验是好习惯:一是核对文件大小、分片数量是否与 Model Farm 说明一致;二是若平台提供校验和(hash),比对一下;三是先跑一次最小对话验证能加载、能出 token,再投入正式使用。这和第 01 讲"升级前备份"、第 04 讲"转换日志归档"是同一套"交付前先验证"的工程纪律——大模型一旦带病上线,排查成本极高。
四、环境调研:安装与编译链
4.1 aid-pkg -i aidgen-sdk
在犀牛派上安装 AidGen 的 SDK(具体包名与参数以 AidLux 当前 aid-pkg 文档为准,常用形态如 aid-pkg -i aidgen-sdk 或类似):
sudo aid-pkg update
sudo aid-pkg install aidgen-sdk # 或 aid-pkg -i aidgen-sdk,以文档为准
装完后,AidGen 的头文件与库会出现在系统路径,供 C++ 编译链接。和第 01 讲一致,装完用 aid-pkg installed 确认 AidGen 在列、版本正确。
4.2 编译链:cmake 与本地编译
AidGen 的 C++ 示例通常用 CMake 构建。犀牛派 X1 本身是 ARM 平台,可以直接在板上用 cmake + make 本地编译(省去交叉编译的环境搭建);若追求效率,也可在 x86 配交叉编译工具链。本讲以"板上本地编译"最省事,适合验证与学习。
准备好 CMakeLists.txt(声明对 AidGen 库的链接)和你的源文件,即可构建。注意把 AidGen 的头文件路径、库路径在 CMake 里指对,否则会卡在找不到头文件或链接失败。
4.3 预装验证
验证方式是先跑 AidGen 自带的 LLM 示例(如一个最小对话程序),确认能加载模型、能出 token。如果官方示例都跑不通,多半是模型路径、模板或 SDK 版本问题,先解决环境再上自己的代码。这和第 02 讲"先跑官方示例验环境"一脉相承——端侧 LLM 的环境坑(路径、模板、内存)比小模型多,更该先用成功路径验证。
4.4 内存预算:X1 上到底能开多大模型
动手前算一笔内存账,能少走弯路。端侧 LLM 运行时的内存 ≈ 权重占用 + KV Cache + 运行时开销。权重随精度(INT4 < INT8 < FP16)和参数量线性变化;KV Cache 随上下文长度 cl 和层数线性增长。以犀牛派 X1 的内存水位为基准,0.5B~1.5B 的 INT8/INT4 模型通常能舒服放下并留出余量,3B 就要精打细算 cl,更大尺寸则超出舒适区。这笔账不用算到字节,但"先估算、再选尺寸"的习惯,能让你避开"下载了一个跑不起来的大模型"的尴尬。具体可用内存以板型规格与真机为准。
五、操作步骤:X1 上部署 Qwen2.5 对话
下面以"在犀牛派 X1 上部署 Qwen2.5-0.5B-Instruct 并跑多轮对话"为例,讲清步骤。具体 SDK 包名、API 类名与方法以 AidGen 当前版本文档为准,这里讲不变的流程逻辑。
5.1 解压模型到固定目录
把从 Model Farm 下的大模型解压到 /home/aidlux/models/qwen2.5-0.5b-instruct/,确认目录内含权重、配置文件、对话模板。路径后续要在代码/配置里引用——再次强调,大模型相关路径强烈建议用绝对路径(见坑点 7.1)。
5.2 改配置文件与对话模板
根据你的模型,确认(必要时修改)两处:一是代码里引用的模型/配置/模板路径;二是对话模板 aidgen_chat_template.txt 是否和模型匹配(通常 Model Farm 已带对的,别手贱乱改)。如果模板内容和你的模型训练格式不符,生成会出错——模板这块"能不动就不动"。
5.3 cmake 编译
在示例或你的工程目录里构建:
mkdir -p build && cd build
cmake .. # 指向含 CMakeLists.txt 的上层目录
make -j$(nproc) # 板上多核并行编译
编译期常见问题是头文件/库找不到(CMake 路径没指对)或 SDK 版本不匹配。报错信息通常很直白,对着改即可。
5.4 运行与多轮对话
运行生成的可执行文件,进入对话循环:输入一句话,模型流式返回回答;继续输入,模型带着历史上下文接着答。第一跑通时建议先用极短输入,确认能出 token、不崩,再放开长对话。
5.5 对比不同上下文长度 cl
上下文长度(cl,context length)是端侧 LLM 的关键旋钮:它决定模型能"记住"多少历史 token。调大 cl,能聊更久、参考更长前文,但 KV Cache 内存随之线性增长,容易撞内存墙;调小 cl,省内存但忘性大。
建议你分别用 cl=512 / 1024 / 2048 跑同一段长对话,观察:内存占用、首 token 延迟、长对话是否开始"遗忘前文"。这组对比能让你直观理解 cl 的代价,为产品定义"该支持多长对话"提供依据。具体上限以你的真机实测与模型支持为准。
5.6 首次运行的启动开销与预热
端侧 LLM 第一次启动,往往会比后续慢——引擎要加载权重、构建 KV Cache 结构、可能还有模型图编译。所以首跑的"加载时间"别当成常态,跑通后看稳定态的响应更准。如果首跑就崩,多半是内存不足(cl 太大或模型太重)或路径/模板问题,回到 7.1~7.4 逐条排查。把"首跑慢"和"运行慢"分开看,能避免误判。
六、关键代码:C++ 推理骨架 + prompt_template
6.1 C++ 推理骨架(构建 / 对话循环)
下面给一个 C++ 部署 Qwen2.5 对话的示意骨架。注意类名、方法名以 AidGen SDK 头文件为准,这里是结构示意,重点看流程:建引擎 → 拼模板 prompt → 流式生成 → 维护历史。
// AidGen 部署 Qwen2.5-0.5B-Instruct 示意骨架(类名以 SDK 为准)
#include <aidgen/aidgen_llm.h> // 具体头文件路径以 AidGen SDK 为准
#include <iostream>
#include <string>
int main() {
// 1) 配置引擎(路径一律用绝对路径!)
aidgen::LLMConfig cfg;
cfg.model_dir = "/home/aidlux/models/qwen2.5-0.5b-instruct";
cfg.template_file = "/home/aidlux/models/qwen2.5-0.5b-instruct/aidgen_chat_template.txt";
cfg.context_length = 2048; // cl:上下文长度,按需调整
auto engine = aidgen::LLMEngine::Create(cfg);
if (!engine) { std::cerr << "引擎创建失败,检查路径与 SDK 版本\n"; return -1; }
// 2) 多轮对话循环
std::string history;
std::string line;
while (std::getline(std::cin, line)) {
if (line == "exit") break;
// 3) 用模板拼装带角色/轮次的 prompt
std::string prompt = engine->ApplyTemplate(history, line);
// 4) 流式生成:每出一个 token 就输出,体验更顺
std::string answer;
engine->Generate(prompt, [&](const std::string& tok) {
std::cout << tok << std::flush;
answer += tok;
});
std::cout << std::endl;
// 5) 把本轮并入历史,供下一轮参考
history = engine->AppendTurn(history, line, answer);
}
return 0;
}
这段骨架只有"建引擎、拼 prompt、流式生成、维护历史"四件事,其余(权重加载、KV Cache、算子调度)都被 AidGen 包了。看清这点,你会发现端侧 LLM 的"应用层"其实不比前面检测模型复杂多少——复杂的是下面那些底座,而 AidGen 替你扛了。
6.2 prompt_template 配置片段
对话模板决定"怎么和模型说话"。一个示意性的模板(具体格式随模型而定):
# aidgen_chat_template.txt(示意,按模型实际模板为准)
{{system}}
你是一个有帮助的本地助手,回答简洁准确。
{{user}}
{input}
{{assistant}}
{output}
模板里的特殊标记(系统提示、用户轮、助手轮)必须和模型训练时一致。你改模板,本质是改"模型眼里的对话长什么样"。务实建议:直接用 Model Farm 随模型附带的模板,验证能跑通后再微调系统提示(如改角色设定),别重写整个格式。
6.3 多轮对话的会话管理
端侧多轮对话的难点不在"生成",而在"历史怎么攒"。两个常见做法:一是像 6.1 那样把历史文本拼接后整体重新喂给模型(简单,但 cl 有限时老历史会被截断);二是更精细的会话管理,对历史做摘要或滑动窗口,保证不超过 cl。产品里通常要后者——否则聊到一定长度,模型要么报错(超 cl),要么悄悄遗忘开头。这部分逻辑虽不在 AidGen 接口内,却直接影响体验,值得你专门设计。
6.4 与 AidLite 调用的对比(复用思维)
虽然 AidGen 用 C++ 且面向生成式,但底层的"资源复用"思维和 AidLite 一致:引擎(engine)对应 interpreter,应在循环外创建、循环内只调用生成;不要每轮重建引擎,否则开销会把体验拖垮。这条纪律和第 02、05、06 讲"重资源复用、循环内只做轻量调用"是完全相同的——工具换了,工程常识不变。
6.5 Python 用户怎么用:先服务化,再调用
如果你主语言是 Python,不必纠结本节的 C++ 细节——把 6.1 的 C++ 程序包成一个本地可执行服务(监听端口、接收文本、返回生成结果),你的 Python 业务就能通过 HTTP/本地 socket 调用它。更进一步,第 08 讲 AidGenSE 会把这件事做成"本地 OpenAI 兼容服务",届时你用 Python 的 requests 甚至标准 OpenAI SDK 就能直接对话,C++ 彻底退居幕后。所以本节的 C++ 是"当下把模型跑起来的启动器",而你真正的业务逻辑,依然可以待在 Python 世界里。
6.6 流式生成的底层逻辑:token 是怎么一个个出来的
LLM 的"流式输出"不是把结果切块显示,而是它本来就是逐 token 自回归生成的——每生成一个 token,就以它为条件预测下一个,直到遇到结束标记。所谓"流式",只是每产出一个 token 就通过回调/事件推给前端,而不是等整句结束。理解这点有两个好处:一是你能在 6.1 的回调里做"边出边显示",体验远好于干等;二是你能分清"首 token 延迟"(出第一个字多快)和"生成吞吐"(之后出字多快)是两个不同指标——前者看反应、后者看语速,调优时各有侧重。
6.7 独立程序 vs 可嵌入库:LLM 怎么接进你的产品
6.1 给的是"独立可执行程序"形态,适合验证与命令行交互。但产品里你往往希望 LLM 是"被调用的一部分",而非一个独立进程。两种集成思路:一是进程内嵌入,把 6.1 的引擎初始化放进主程序启动阶段,对话函数作为内部接口直接调,延迟最低、最顺;二是独立服务,把 LLM 包成常驻进程 / 服务,主程序通过本地接口调用,解耦更干净、便于多语言(如 Python 主程序调 C++ 服务)。前者简单直接,后者灵活可扩展。第 08 讲 AidGenSE 走的就是"服务化"这条路,并进一步做成 OpenAI 兼容——届时集成成本最低。
七、坑点
7.1 配置文件路径须用绝对路径
大模型相关的模型目录、配置、模板路径,强烈建议一律用绝对路径。相对路径在 C++ 服务以不同工作目录启动时极易解析错,表现为"文件找不到、引擎创建失败"。这是 AidGen 部署最高频的坑,一句"改成绝对路径"能省下大把调试时间。
7.2 对话模板与模型不匹配
用了错误的 aidgen_chat_template.txt(比如把 A 模型的模板套到 B 模型),生成会乱码、忽略指令或输出异常格式。对策:用模型自带的模板,验证能跑通再微调;改模板前先备份。
7.3 cl 显存 / 内存溢出
上下文长度(cl)调太大,KV Cache 撑爆内存,表现为启动失败、生成中途崩或系统变卡。对策:先用小 cl 跑通,再按需上调;长对话做历史摘要/滑动窗口(6.3)。端侧内存是 LLM 最先撞的墙,cl 是墙上的门。
7.4 模型未注册 / 路径错
模型目录结构不对、权重文件名与配置不符,或路径指错,都会让引擎加载失败。对策:对照 Model Farm 的说明核对目录结构,用绝对路径,先跑官方示例确认模型本身可加载。
7.5 性能调优的先后:先尺寸,再 cl,再系统
端侧 LLM 慢或崩时,调优顺序有讲究,别一上来就调系统参数。第一优先是模型尺寸:换成更小的模型(如从 1.5B 降到 0.5B),往往立竿见影;第二是 cl:调小上下文长度,立刻省下 KV Cache 内存与计算;第三才是系统层面的调度/线程配置。这个"由粗到细"的顺序,和第 12 讲性能调优的方法论一致——先动影响最大的旋钮。很多人卡在"小模型跑得动却非要上大模型",其实退一步尺寸就全解决了。
八、验证:终端多轮对话
8.1 输出正确性
跑通后,用几类问题验证:简单问答是否答对、是否遵循系统提示的角色设定、多轮对话是否记得前文(在 cl 范围内)。如果答非所问或忽略指令,先查模板与系统提示,再查模型是否下对。正确性是 LLM 验收的第一关。
8.2 首 token 延迟与吞吐
端侧 LLM 体验的两项关键指标:首 token 延迟(从输入到出第一个字的时间,决定"反应快不快")和生成吞吐(每秒生成多少 token,决定"说得快不快")。用 6.1 的流式输出计时即可粗略测:记录首 token 时刻与结束时刻。这两项以你的真机实测为准,且和模型尺寸、cl、板子算力强相关。
8.3 X1 与 A1 差异
| 指标 | 犀牛派 A1(QCS6490) | 犀牛派 X1(QCS8550) |
|---|---|---|
| 可流畅运行的 LLM 尺寸 | 仅最小(0.5B 量级,受限) | 0.5B~3B 更从容(以实测为准) |
| 首 token 延迟 | 偏高 | 更低(以实测为准) |
| 多轮/长上下文 | 受内存制约明显 | 余量更大(以实测为准) |
对端侧 LLM,"高低搭配"的含义更尖锐:A1 可小试 0.5B 但体验受限,X1 才能真正把大模型用舒服。选型时别拿 A1 硬扛大模型,那会牺牲掉整个体验。具体尺寸与延迟以真机实测为准。
8.4 端侧 LLM 能力怎么评测:别只看"能聊"
验收端侧 LLM,不能止步于"它说话了"。建议用三类标尺:一是正确性,用几道固定问答看是否答对、是否遵循系统提示的角色;二是长上下文可靠性,在 cl 范围内塞长对话,看它是否记得前文、是否超长就崩;三是鲁棒性,给它模糊、违规或诱导性问题,看是否稳定不崩、不输出异常格式。把这几条做成固定测试用例,每次换模型/换 cl 都跑一遍,你就有了属于自己项目的"LLM 验收基线"——这和检测模型用固定测试图做精度比对是同一思路,只是对象从"框"变成了"话"。
8.5 常见异常现象对照表
端侧 LLM 出问题时的现象,往往能反推病因。一张速查表:“引擎创建失败” → 路径错 / 模型结构不符 / SDK 版本不对(7.1、7.4);“首跑就崩、后续也崩” → 内存不足,cl 太大或模型太重(7.3、4.4);“答非所问 / 忽略指令” → 对话模板错或系统提示不对(7.2、6.2);“长对话中途遗忘或报错” → 超 cl 或历史管理缺失(6.3、5.5);“生成极慢” → 模型过大、A1 硬扛、或 cl 过高(7.5、8.3)。先把现象对号入座,再去看对应章节,能比盲目改代码快得多。这张表和检测模型的"一致性比对"一样,都是把"玄学调试"变成"有依据排查"的工具。
九、FAQ
Q1:为什么本讲用 C++ 而不是 Python?
因为 AidGen 当前在 Linux 上以 C++ 提供完整支持,Python 在规划中。如实用 C++ 给出可运行骨架,避免你照着未稳定支持的 Python 接口白费功夫;第 08 讲 AidGenSE 服务化后,Python 即可顺畅调用。
Q2:A1 能跑大模型吗?
可以跑最小尺寸(0.5B 量级)做轻量体验,但内存与算力受限,体验与并发不如 X1。认真做端侧 LLM 建议直接上 X1。
Q3:cl 设多大合适?
取决于内存与对话长度需求。先用小 cl(如 1024)跑通,再按需上调;长对话务必做历史管理(6.3),否则超 cl 会出错或遗忘。
Q4:对话模板可以自己写吗?
可以,但必须和模型训练格式一致。建议先用模型自带的,验证通再微调系统提示,别重写整个格式。
Q5:流式输出怎么实现?
如 6.1,生成接口通常支持回调,每产出一个 token 就调用回调实时输出,体验远好于"等全部生成完再显示"。
Q6:多轮对话历史会无限增长吗?
不会,受 cl 限制。你需要在应用层做历史截断、摘要或滑动窗口(6.3),否则超出部分会被丢弃或导致错误。
Q7:AidGen 和直接用 llama.cpp 之类有什么区别?
AidGen 构建在 AidLite 之上,复用其 NPU/CPU/GPU 调度与端侧优化;裸用其他运行时则更底层,需自己处理调度与适配。选 AidGen 是为复用工具链一致性。
Q8:模型可以从 AIMO 自己转 LLM 吗?
大模型转换请参考 AidLux 官方对 AIMO 的支持范围与 Model Farm 的大模型分区;若平台支持则可用 AIMO,否则优先取 Model Farm 现成适配模型。
Q9:生成很慢正常吗?
端侧 LLM 比云端慢是常态,重点是看首 token 延迟与吞吐是否可接受。过小模型、过大 cl、或 A1 硬扛大模型都会更慢。
Q10:后面怎么把 LLM 接进我的 Python 应用?
两种方式:把本节 C++ 程序包成本地服务用 HTTP 调用,或直接等第 08 讲 AidGenSE 的 OpenAI 兼容服务,用标准方式对接。
十、结论
本讲我们跨过了工具链从"感知"到"认知"的门槛:用 AidGen 把大语言模型(Qwen2.5)搬上了犀牛派 X1,跑通了多轮对话,并厘清了上下文长度、对话模板、内存约束这些端侧 LLM 的关键旋钮。你也理解了 AidGen"站在 AidLite 肩上"的架构——前面建立的底座认知,在这里继续生效。
更关键的是,你看到工具链的另一面:不是每个组件都"Python 优先"。AidGen 当下以 C++ 提供完整能力,我们如实接受了这个边界,并把 C++ 定位成"启动器"而非"主战场"——真正的业务逻辑,会在第 08 讲服务化后用你熟悉的 Python 无缝接入。这种"先认清工具的真实能力、再决定怎么用"的态度,比死守某种语言更重要。
下一讲,我们把本讲的本地大模型进一步服务化:用 AidGenSE 把它封装成"本地版 OpenAI",对外提供标准 HTTP 接口,让你的任意 Python 应用、Web 前端零改造就能调用端侧大模型。那才是大模型真正"融入产品"的一步。
本文 AidGen 的定位、AidLLM/AidMLM 划分、支持情况(Linux C++ 已支持、Python 规划中)、对话模板与模型供给等来自 AidLux 官方文档;端侧 LLM 的尺寸/延迟/内存约束参考高通公开资料,精确值以真机实测为准。C++ 类名与方法为结构示意,具体以 AidGen SDK 头文件与当前版本文档为准。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/HuiMinHuang2001/article/details/167129876




