我为 HarmonyOS 做了一个统一大模型 SDK:@hmkit/ai 正式开源
推荐摘要:
@hmkit/ai是一个面向 HarmonyOS NEXT / OpenHarmony 的统一大模型 SDK 与 ArkUI V2 聊天组件,支持多供应商、多模态、Responses API、Agent、RAG、语音和本地会话。目前项目已以 MIT 协议开源。推荐标签:HarmonyOS、ArkTS、人工智能、开源、OpenAI
这两年,大模型能力已经从"聊天接口"逐渐变成应用的基础能力。
但当我尝试在 HarmonyOS 应用中真正接入 AI 时,很快就发现:调用一次 HTTP 接口并不难,难的是把流式响应、多供应商差异、多模态消息、工具调用、会话存储、RAG、语音和 UI 体验组合成一套可以长期维护的工程。
于是我做了 @hmkit/ai。
它是一个面向 HarmonyOS NEXT / OpenHarmony 的统一大模型 SDK,同时提供可直接使用的 ArkUI V2 聊天组件。目前 2.0.0 已经开源:
- GitHub:github.com/lxshwyan/hm...
- Release:github.com/lxshwyan/hm...
- License:MIT
为什么要做统一调用层
不同大模型供应商看起来都提供"OpenAI 兼容接口",但真正接入后仍然有不少差异:
- Endpoint、模型名称和鉴权方式不同;
- 支持的图片、文件、音频能力不同;
- SSE 事件和结束标记可能存在细微差异;
- Chat Completions 与 Responses API 的工具定义并不相同;
- 流式工具参数可能被拆成多个不完整 JSON 片段;
- 客户端还要处理取消、超时、错误归一化和生命周期清理。
如果业务页面直接依赖某一家供应商的请求结构,后面切换模型或增加 Provider 时,UI、会话和业务逻辑往往都要跟着修改。
@hmkit/ai 的思路是把这些问题拆成几个相互独立的层:
text
ArkUI Chat View
↓
Conversation / Agent Runtime
↓
Unified Message & Tool Types
↓
Chat Completions / Responses / Voice
↓
Provider Configuration
↓
HarmonyOS HTTP / WebSocket / Audio
页面只处理消息、状态和用户操作;协议层负责请求映射和流式解析;Provider 层描述服务地址、模型与能力;平台层负责 HarmonyOS 网络、文件和音频能力。
从最基础的流式聊天开始
库中统一使用 HmAIMessage 表示消息,通过 HmAIConversationController 管理多轮对话、流式状态、取消和错误。
以 DeepSeek 为例:
ets
import {
HmAIConversationController,
HmAIMessage,
HmAIProviders
} from '@hmkit/ai';
const provider = HmAIProviders.deepSeek('deepseek-chat');
const client = provider.createChatClient(temporaryApiKey);
const controller = new HmAIConversationController(client);
await controller.sendMessage(
HmAIMessage.user('请帮我整理今天的工作重点')
);
当前内置了以下 Provider 预设:
- OpenAI
- DeepSeek
- 通义千问
- 豆包
- 智谱
- 自定义 OpenAI-compatible 服务
Provider 不只是保存一个 URL,还会声明图片、文件、音频、工具调用和 structured output 等能力。应用可以在发送前检查能力,避免把不支持的内容交给模型。
多模态不是给消息加一个图片地址
多模态消息需要同时面对远程 URL、本地文件、Data URL、MIME 类型、大小限制和供应商序列化差异。
@hmkit/ai 使用 HmAIContentPart 统一描述文本、图片、文件和音频:
ets
const message = HmAIMessage.userParts([
HmAIContentPart.text('请分析这张图片'),
HmAIContentPart.imageUrl('https://example.com/chart.png')
]);
对于本地附件,库提供需要显式传入 UIAbilityContext 的选择器和读取工具。这样做是为了避免 HAR 在内部偷偷持有全局 Context,也让宿主应用能够决定权限、大小限制和文件生命周期。
同时支持 Chat Completions 与 Responses API
OpenAI 新一代 Responses API 将输入、输出、工具和响应状态组合成了新的数据模型,它并不是简单换一个请求路径。
例如 function tool 在 Responses API 中采用更扁平的结构,流式响应也会出现具名事件:
text
response.output_text.delta
response.function_call_arguments.delta
response.output_item.done
response.completed
因此项目为两个协议保留了各自的编码器和流式解码器,同时共享消息、工具和错误类型。
ets
const options = new OpenAIResponsesClientOptions(
'https://api.openai.com/v1',
'gpt-5'
);
options.apiKey = temporaryApiKey;
const client = new OpenAIResponsesClient(options);
const request = new HmAIResponsesRequest([
HmAIMessage.user('总结这份附件')
]);
request.previousResponseId = previousId;
const result = await client.createResponseStream(request).start();
目前支持文本、图片、文件输入,function tools、tool results、JSON Schema、previous_response_id、引用来源和 usage。
Agent 最重要的能力不是"自动",而是可控制
让模型调用工具很容易,但如果工具涉及文件、网络、支付或系统能力,"模型想调用就执行"并不是一个适合生产环境的默认值。
项目中的 Agent Runtime 默认要求人工审批,并记录每一步的状态:
ets
const agentOptions = new HmAIAgentRuntimeOptions();
agentOptions.approvalPolicy = new HmAIAlwaysAskPolicy();
const repository = new HmAIFileAgentRepository(
filesDir + '/agent-tasks'
);
const runtime = new HmAIAgentRuntime(
client,
registry,
repository,
observer,
agentOptions
);
const task = await runtime.start('查询天气并整理结果');
Agent 只允许调用 HmAIToolRegistry 中明确注册的工具。运行中的任务可以:
- 等待批准或拒绝;
- 展示当前步骤状态;
- 主动中断;
- 从持久化任务恢复;
- 通过最大轮次限制阻止无限循环。
这套设计更适合需要审计和用户确认的真实应用,而不仅是一个自动调用工具的演示。
本地会话和轻量 RAG
除了模型调用,项目也提供了本地会话存储:
- 历史记录;
- 搜索;
- 导入和导出;
- 删除与恢复;
- 内存或应用沙箱文件存储。
RAG 部分包含文档分块、Embedding 抽象、本地向量索引、相似度检索和引用来源。
ets
const rag = new HmAIRAGEngine();
await rag.ingest(new HmAIRAGDocument(
'doc-1',
'产品手册',
documentText,
sourceUrl
));
const sources = await rag.retrieve('如何取消流式响应?', 4);
const context = await rag.context('如何取消流式响应?', 4);
内置的 HmAIHashEmbeddingModel 完全离线,适合 Demo、测试和轻量检索。正式语义检索可以实现 HmAIEmbeddingModel,替换为自己的 Embedding 服务。
不只做 SDK,也提供可商用的 ArkUI 组件
最初的 Demo 更像一个开发者调试页面:模型配置占据首屏,历史记录和聊天区域缺少产品层级。
后来我重新设计了整个界面:
- 使用克制的靛蓝色作为品牌色;
- 技术配置默认收起;
- 增加品牌化欢迎页和建议问题;
- 助手内容采用编辑式排版,减少沉重气泡;
- 输入区改成悬浮圆角 Composer;
- 附件、错误、停止和重新生成都有独立状态;
- 支持 light/dark 主题和 phone/tablet 布局。
配图建议:此处插入 Pura 90 模拟器首屏截图。
组件的使用方式保持简单:
ets
HmAIChatView({
messages: this.messages,
state: this.state,
emptyText: '今天想一起完成什么?',
suggestions: [
'整理工作重点',
'分析一份文档',
'制定执行计划'
],
pendingAttachments: this.attachments.map(
(item): string => item.name
),
showAttachmentButton: true,
onSend: (content: string): void => {
this.send(content);
},
onSuggestion: (content: string): void => {
this.send(content);
},
onAttachmentRequested: (): void => {
this.pickFiles();
},
onCancel: (): void => {
this.controller.cancel();
}
})
Markdown 渲染支持标题、引用、列表、表格、链接、行内代码、公式和轻量语法高亮。长会话使用 ArkUI List 与可配置的消息窗口,并通过流式批处理降低高频刷新开销。
语音和实时对话
语音部分拆分为三个层次:
OpenAIVoiceClient:语音转写和流式 TTS;HmAIMicrophoneCapture、HmAIPCMStreamPlayer:HarmonyOS 音频采集和播放;OpenAIRealtimeSession:WebSocket 实时文本、音频和增量事件。
库不会替宿主静默申请麦克风权限。权限说明、动态授权、前后台生命周期、音频格式和临时令牌仍由应用负责。
如何保证它不只是"能跑"
流式协议最容易出现的问题,是网络分片并不会按照 JSON 或 UTF-8 字符边界到达。
测试中特别覆盖了:
- SSE 的任意分片、CRLF 和
[DONE]; - 多字节 UTF-8 被拆分;
- 工具调用 ID、函数名和参数分片累积;
- Chat Completions、Responses 和 Audio Mock 协议;
- Agent 审批、拒绝、中断和恢复;
- 多模态序列化;
- Markdown、会话存储和 RAG;
- 模拟器输入、发送、流式渲染和附件入口。
当前发布门禁包括:
- 33 项 Hypium 单元测试全部通过;
- 123 个公开 API 符号契约检查;
- Chat、Responses、Audio Mock 服务测试;
- HAR 版本、元数据和凭据扫描;
- Pura 90 模拟器 UI 自动化;
- GitHub Actions CI。
项目提供统一验证命令:
shell
ohpm install --all
./scripts/verify.sh
连接模拟器或真机后可以运行:
shell
./scripts/test-ui.sh
客户端 API Key 的安全边界
这一点非常重要:不要把生产环境的大模型 API Key 写进 HarmonyOS 客户端。
无论做多少混淆,随 App 分发的长期静态密钥都无法得到可靠保护。正式应用应该通过自己的服务端代理保存供应商密钥,再向客户端签发短期、最小权限的会话凭据。
Demo 中提供的 API Key 输入只用于本机调试:
- 不持久化;
- 不写日志;
- 页面退出时清空;
- 不进入开源仓库和构建产物。
会话、附件、Agent 任务和 RAG 向量也可能包含敏感信息,宿主需要自行决定沙箱存储、加密、备份和数据保留策略。
开源之后准备做什么
@hmkit/ai 当前以 MIT 协议开源。接下来会继续关注:
- 更多供应商和模型的兼容性反馈;
- 更完整的真实设备语音测试;
- RAG 文档 Loader 与 Embedding 适配;
- Agent 工具生态和审批 UI;
- ArkUI 组件的主题与扩展能力;
- OHPM 发布和版本维护。
如果你正在做 HarmonyOS AI 应用,欢迎试用、提交 Issue 或参与贡献。
项目地址:
如果这个项目对你有帮助,也欢迎点一个 Star。
发布前可选优化
以下内容用于发布准备,可在复制到掘金时删除:
- 在"ArkUI 组件"章节插入 Pura 90 商用首屏截图。
- 封面标题建议使用:
HarmonyOS 也有统一 AI SDK 了。 - 封面副标题建议使用:
多模型 / Agent / RAG / 语音 / ArkUI。 - 掘金标题备选:
我开源了一个 HarmonyOS 统一大模型 SDK:支持 Agent、RAG 与多模态从 SSE 到 Agent:如何为 HarmonyOS 设计一套 AI SDK@hmkit/ai 2.0 开源:让 HarmonyOS 应用快速接入大模型