metadata
license: other
tags:
- private
- android
- on-device-llm
- llama.cpp
- offline
团智宝(TrainAI)— 离线端侧心理训练方案生成 APP
⚠️ 私有仓库 · 仅供代码备份与同步。 本软件著作权与知识产权归委托方所有;仓库内不含委托方业务资料(知识库/模板/图片/音频)、 不含合同与任何身份信息、不含模型权重。请勿转为公开可见,勿对外分发。
Android(适配鸿蒙 NEXT + 卓易通容器)平板端完全离线运行的训练方案生成工具:
输入训练主题 → 端侧大模型分章节生成完整"指导语"方案 → 自动匹配示意图与背景音乐 → 导出 PDF。
不申请 INTERNET 权限,全部数据留在本机。
仓库内容
| 路径 | 说明 |
|---|---|
app/ |
Android 工程源码(Kotlin + Jetpack Compose + Hilt + Room;JNI/C++ 推理桥) |
docs/ |
使用手册、维护手册、交付说明 |
tools/ |
资源包制作、向量离线预计算、生成质量回归测试(Python) |
fetch_llama_cpp.sh |
拉取并固定第三方推理引擎版本(未随仓库分发) |
不在仓库内(体积或权属原因):llama.cpp 源码(脚本拉取)、GGUF 模型权重、
bge 向量模型、出厂资源包 library.zip、编译产物、APK。
快速开始
./fetch_llama_cpp.sh # 拉取推理引擎(固定 commit)
cd app && echo "sdk.dir=/path/to/Android/sdk" > local.properties
./gradlew assembleDebug # 需要 JDK17 / SDK34 / NDK r26+ / CMake / ninja
架构
UI (Compose) chat 对话生成 / browse 方案库卡片 / knowledge 学习空间 / library 资料库
│
业务层 PromptBuilder(分章节引导生成)· StylePrefs(生成偏好)· Summarizer(AI 总结)
MediaMatcher(示意图/音乐语义匹配)· TemplateExtractor(模板骨架)
│
数据层 Room(文档/切片/媒体/会话)· RagPipeline(切片→bge 向量→余弦检索)
│
推理层 LlamaCpp(Kotlin)──JNI──► llama_jni.cpp ──► llama.cpp(CPU, arm64-v8a)
crash_handler.cpp:native 崩溃黑匣子(信号捕获 + 回溯落盘)
端侧工程要点(踩坑记录,改代码前必读)
- 容器内存上限:鸿蒙 NEXT 的 Android 容器单应用仅约 3–4 GB 可用 → 模型必须 ≤3B(7B 必被 OOM 强杀);代码对 >3GB 的模型直接拒绝加载并给出说明。
- JNI 字符串不能用
NewStringUTF:它要求 Modified UTF-8,模型输出 emoji(4 字节 UTF-8)会让 ARTabort→ 崩溃。token 回调与 prompt 传参一律走byte[]。 - 中文跨 token 边界:一个汉字可能被拆到两个 token,需在 native 侧缓冲不完整的 UTF-8 尾字节,否则显示成
?。 - native 必须 Release 构建:Debug 的 ggml 断言会因 ARM FP16 累加溢出(
isnan/isinf)直接 abort;同时禁用 CPU flash-attention(该路径数值不稳)。 - 生命周期:
Session析构负责释放 model/ctx/sampler;卸载/换模型前先置停止标志并等生成线程退出,否则重复加载泄漏 GB 级内存或 use-after-free。 - 流式背压:
trySend在缓冲满时会静默丢 token(输出缺字),改trySendBlocking;UI 侧节流刷新(每 token 全量刷新是 O(n²) 拷贝)。 - 容器文件沙箱:文件管理器放入的文件应用不可见,大文件必须走 SAF 导入,并分段
fsync防页缓存计入应用内存被强杀。 - 小模型的长文本策略:整篇一次生成会残缺;改为逐章节引导(每章独立 prompt + 结构要求 + few-shot),并对与范例的 n-gram 重合率超阈值的章节自动重写。
许可与合规
第三方组件依其原许可(llama.cpp、ONNX Runtime、PdfBox-Android 等)。 本项目自身代码的著作权归委托方所有,未获书面授权不得公开分发或商用。