"我之所以想要实现零成本使用,是因为我认为开发的意义是让普通人使用科技产品的成本降低,而不是让普通人使用科技产品的门槛变高。"
大家好,我是一名大一学生。最近,华为鸿蒙生态(HarmonyOS NEXT)正在向"原生智能"全面演进。在这个节点上,我决定启动一个硬核的个人项目:独立开发一个服务于鸿蒙系统的原生 AI Agent(智能体)。
市面上的 AI 套壳应用已经很多了,但我并不想只做一个调用云端大模型 API 的"聊天框"。我的终极目标,是构建一套"端云协同"的 Agent 架构------不仅能在联网时解决复杂问题,更能在手机本地跑通小模型。
也就是说,我想打造一个能够在断网状态下也能够正常使用,同时还能完美保护用户隐私信息的智能体。
这篇文章,是我项目的第一天记录,包含架构思考与真实的踩坑日记。
🏗️ 架构愿景:为什么必须是"端云协同"?
目前的 AI 应用在走向大众时,存在三大门槛:
1. 成本门槛:API 调用按 Token 计费,普通人长期使用依然是一笔开销。
2. 隐私门槛:所有对话和本地文件都上传云端,存在数据泄露风险。
3. 网络门槛:在山区,荒野,信号屏蔽区等弱网或无网环境下,纯云端 AI 直接瘫痪。
因此,我的鸿蒙 Agent 项目设计了如下的双核架构:
· 云端大脑(聪明但需付费):接入 DeepSeek 等大模型,处理需要复杂逻辑、长文本推理的高级任务。 · 端侧大脑(免费且安全):利用鸿蒙的端侧推理能力,在手机 NPU 上运行 Qwen2.5-0.5B 级别的量化小模型。实现日常对话零延迟、完全离线、隐私绝对安全。 · 抽象接口层:在 ArkTS 代码中定义一个 IModelProvider 接口,让 UI 层对底层无感知,实现"一键切换"。
我希望这个项目证明:最好的技术,是让人感觉不到技术的存在,且普惠每一个人。
🛠️ 实战踩坑:鸿蒙原生开发的"四大天堑"
作为一个在鸿蒙 PC 和真机(HUAWEI Pura 90 Pro Max)之间反复横跳的新手,第一天我就被鸿蒙的工程化要求狠狠教育了。
1. 环境冲突与玄学报错:hdc 服务卡死
一开始,我将手机连接电脑,终端执行 hdc list targets 始终返回 Empty,甚至报错 Connect server failed。后来发现,鸿蒙电脑终端默认调用了系统底层的 hdc,与 DevEco Studio 自带的开发版 hdc 版本产生冲突,抢占了 8710 端口。 解决:强杀残留进程,彻底抛弃终端指令,全权交由 DevEco Studio 的图形化界面接管,并在 Project Structure 中重新生成自动签名,最终成功在真机上跑通 Hello World。
2. ArkTS 的"毒打":严格类型检查
相比于传统的 JavaScript/TypeScript,鸿蒙的 ArkTS 极其严苛,禁用了大量动态特性。在编写网络请求时,我遇到了报错:arkts-no-untyped-obj-literals。 解决:ArkTS 不允许使用无类型的对象字面量。我必须手动定义 interface,强制约束请求体和返回值的结构,这极大地提升了代码的健壮性。
3. 废弃 API 的背刺
在处理网络流式数据时,官方文档中的部分教程仍在使用 TextDecoder.decodeWithStream,但在最新的鸿蒙 SDK 中,该 API 已被标记为废弃(Deprecated),直接导致编译失败。 解决:弃用旧版解码器,改用鸿蒙推荐的 buffer 模块,通过 buffer.from(chunk).toString('utf-8') 完成二进制到字符串的转换。
4. SSE 流式解析:让文字逐个蹦出来
为了让体验像 ChatGPT 一样丝滑,必须处理 Server-Sent Events (SSE)。网络回调传回的 ArrayBuffer 边界是随机的,一个中文字符甚至可能被切成两半。 解决:我必须维护一个全局的 textBuffer,每次收到数据先追加,再按 \n 拆分。只处理以 data: 开头的完整行,残缺的 JSON 块留在缓冲区等待下一次拼接。这彻底解决了中文乱码和 JSON 解析崩溃的问题。
💻 阶段成果与核心代码
目前,我已经成功在真机上跑通了基于 http.requestInStream 的流式对话。
typescript
// 核心流式解析逻辑 (ChatService.ets)
httpRequest.on('dataReceive', (chunk: ArrayBuffer) => {
// 使用最新的 buffer API 替代废弃的解码器
const text = buffer.from(chunk).toString('utf-8');
this.textBuffer += text;
const lines = this.textBuffer.split('\n');
// 将可能不完整的最后一行留在缓冲区
this.textBuffer = lines.pop() || '';
for (const rawLine of lines) {
const line = rawLine.replace(/\r$/, '').trim();
if (!line.startsWith('data: ')) continue;
const payload = line.substring(6).trim();
if (payload === '[DONE]') {
onDone();
httpRequest.destroy();
return;
}
try {
const json = JSON.parse(payload) as StreamResponse;
const delta = json.choices?.[0]?.delta?.content;
if (delta) {
onDelta(delta); // 驱动 UI 更新
}
} catch (e) {
// 忽略解析异常,等待补齐
}
}
});
🚀 下一步计划:从 Chat 到真正的 Agent
跑通流式对话只是第一步,接下来的路依然充满挑战:
· Day 2-3:赋予记忆。利用数组维护多轮上下文(messages),让 AI 不再是"金鱼记忆"。 · Day 4-5:工具体系与 Agent Loop。在沙箱中搭建显式的 Map<string, ToolHandler>,实现第一个本地工具(如读取文件),跑通 ReAct 循环(推理 -> 调用 -> 观察 -> 总结)。 · Day 6 以后:端侧模型集成。调研开源项目,尝试在手机上运行 Qwen2.5-0.5B 模型,替换现有的云端 API,真正实现"零成本、断网可用"。
🌟 写在最后
在 AI 狂飙突进的时代,开发者很容易沉迷于堆砌算力和参数量。但我始终认为,技术终究是为人服务的。
我希望几个月后,当这个鸿蒙 Agent 完成时,它不仅能在联网状态下,满足普通用户的基本需求;还能在野外断网的极端环境下,成为用户的生存向导;同时,还能凭借其极强的隐私性,对军警职业及涉密部门人员提供安全的服务。
这条路还很长,我会在 GitHub 上持续更新我的开发进度和踩坑日记。如果你也对鸿蒙开发、端侧 AI 感兴趣,欢迎关注我,我们评论区交流。
(Gitee 仓库地址:gitee.com/Whmagent/w-...