【HarmonyOS学习笔记】2026-07-24 | textProcessing 实体识别与踩坑实录
date: 2026-07-24
tags: HarmonyOS, textProcessing, 实体识别, NaturalLanguageKit, ArkTS, 触摸事件, 异步回调
type: 技术参考+踩坑实录
Part 1:textProcessing 实体识别技术参考
HarmonyOS NaturalLanguageKit
textProcessing.getEntity()的 10 种实体类型完整技术参考since 5.0.0(12)
API 概览
arkts
import { textProcessing, EntityType } from '@kit.NaturalLanguageKit'
const entities = await textProcessing.getEntity(text: string, entityConfig?: EntityConfig)
interface Entity {
text: string // 实体原文本
charOffset: number // 实体在原文本中的字符偏移
type: EntityType // 实体类别
jsonObject: string // 结构化信息(JSON字符串,需JSON.parse解析)
}
interface EntityConfig {
entityTypes?: EntityType[] // 指定只识别哪些类型,默认全选
}
关键特性:
- since 5.0.0(12),API 24 完全可用
- 无权限要求
- init() 非必须,调用可减少首次延迟
- jsonObject 是 JSON 字符串,需
JSON.parse()解析 - 文本长度不超过 1000 字符
- 支持语言:简体中文、英文、繁体中文
- 不支持模拟器
10 种实体一览
| # | 枚举名 | 枚举值 | 中文名 | 说明 |
|---|---|---|---|---|
| 1 | EntityType.DATETIME |
'datetime' |
时间 | 识别日期、时间、周期、节日,返回 startTimestamp/endTimestamp 时间戳和 repeat 周期 |
| 2 | EntityType.EMAIL |
'email' |
邮箱 | 识别电子邮件地址,jsonObject 为空,原文即邮箱 |
| 3 | EntityType.EXPRESS_NO |
'expressNo' |
快递单号 | 识别快递单号,返回 isTailNum 判断是否仅尾号 |
| 4 | EntityType.FLIGHT_NO |
'flightNo' |
航班号 | 识别航班号(如 CA1234),jsonObject 为空,原文即航班号 |
| 5 | EntityType.LOCATION |
'location' |
地点 | 识别地点,返回结构化地址(省/市/区/道路),含 isAbstract 判断是否抽象地点 |
| 6 | EntityType.NAME |
'name' |
姓名 | 识别人名,返回 type 区分正式姓名(nr)/昵称(nrn)/称谓(nrt)/其他(nrx) |
| 7 | EntityType.PHONE_NO |
'phoneNo' |
手机号 | 识别手机号和固话,返回 type 区分手机(1)/固话(0),含分机号 extNumber |
| 8 | EntityType.URL |
'url' |
URL | 识别网址链接,jsonObject 为空,原文即 URL |
| 9 | EntityType.VERIFICATION_CODE |
'verificationCode' |
验证码 | 识别验证码,返回 type(验证码内容) 和 supplier(提供商) |
| 10 | EntityType.ID_NO |
'idNo' |
身份证号 | 识别证件号,返回 type 区分身份证(0)/护照(1),含 isComplete 判断是否完整 |
1. DATETIME --- 时间实体
测试输入:
"明天要交报告"
"下周一去北京出差"
"下午3点开会"
"8月15号前完成"
"每天早上跑步"
"这周末"
"国庆节"
"今天跑了5公里"
"后天"
"明天下午5点到7点"
jsonObject 结构 :键名 "time",值为 JSONArray:
json
{
"time": [{
"repeat": "每天",
"rrule": "",
"start": "2026-07-23T08:00:00",
"suggestStart": "2026-07-23T08:00:00",
"startTimestamp": 1784736000000,
"end": "2026-07-23T12:00:00",
"suggestEnd": "2026-07-23T12:00:00",
"endTimestamp": 1784750400000,
"maxSection": "P",
"minSection": "P",
"isContainFuzzyTime": false,
"containFuzzySection": "",
"inferType": "",
"rangeDecoration": "",
"rangeText": "",
"isFestival": false,
"normalFestival": "",
"isLunarTime": false,
"startLunarTime": "",
"isSolarTerm": false,
"isIllegal": false,
"isChangedIllegal": false,
"isPlusTwelveHour": false,
"sequence": 1,
"oriFestival": "",
"timestampZone": "",
"originTimestamp": 1784736000000
}]
}
字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
| repeat | string | 周期文本("每天"、"每周一"等) |
| start | string | 开始时间 ISO 格式 |
| suggestStart | string | 具体开始时间 |
| startTimestamp | number | 开始时间戳(毫秒) |
| end | string | 结束时间 ISO 格式 |
| suggestEnd | string | 具体结束时间 |
| endTimestamp | number | 结束时间戳(毫秒) |
| maxSection | string | 最大时间粒度(P=精确, M=早晨, F=上午, N=中午, A=下午, L=傍晚, E=晚上, W=凌晨) |
| minSection | string | 最小时间粒度 |
| isContainFuzzyTime | boolean | 是否包含模糊时间 |
| containFuzzySection | string | 模糊时间粒度 |
| inferType | string | 时间推理类型 |
| rangeDecoration | string | 范围描述 |
| rangeText | string | 带范围描述的文本 |
| isFestival | boolean | 是否节日 |
| normalFestival | string | 节日归一化值 |
| isLunarTime | boolean | 是否农历 |
| startLunarTime | string | 农历时间 |
| isSolarTerm | boolean | 是否节气 |
| isIllegal | boolean | 是否非法时间 |
| isChangedIllegal | boolean | 是否自动修正 |
| isPlusTwelveHour | boolean | 是否包含天以内模糊时间 |
| sequence | number | 实体出现频率 |
| oriFestival | string | 包含的节日文本 |
| timestampZone | string | 时区 |
| originTimestamp | number | 入参文本时间戳 |
2. EMAIL --- 邮箱实体
测试输入 :"发邮件到test@example.com"
jsonObject 结构 :键名 "email",值为空字符串。jsonObject 无额外结构化信息,实体原文即邮箱地址。
3. EXPRESS_NO --- 快递单号实体
测试输入 :"快递单号SF1234567890"
jsonObject 结构 :键名 "expressNo",值为 JSONArray:
json
{
"expressNo": [{
"isTailNum": 0
}]
}
| 字段 | 类型 | 说明 |
|---|---|---|
| isTailNum | number | 0=完整单号, 1=仅尾号 |
4. FLIGHT_NO --- 航班号实体
测试输入 :"我坐CA1234的航班"
jsonObject 结构 :键名 "flightNo",值为空字符串。jsonObject 无额外结构化信息,实体原文即航班号。
5. LOCATION --- 地点实体
测试输入:
"下午去国贸开会"
"北京朝阳区万达广场"
"我在上海"
"去趟南京路"
"公司楼下星巴克"
jsonObject 结构 :键名 "location",值为 JSONArray:
json
{
"location": [{
"type": "",
"coreLocation": {
"oriText": "国贸",
"value": "国贸",
"province": "北京市",
"city": "北京市",
"county": "朝阳区",
"district": "",
"subDistrict": "",
"town": "",
"village": "",
"subVillage": "",
"region": "",
"road": "",
"default": "国贸",
"location": ""
},
"adornLocation": {},
"isAbstract": 0
}]
}
外层字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| type | string | 地点类型 |
| coreLocation | object | 核心地点信息 |
| adornLocation | object | 修饰核心地点的信息 |
| isAbstract | number | 0=非抽象地点, 1=抽象地点 |
coreLocation 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| oriText | string | 原文 |
| value | string | 归一化值 |
| province | string | 省 |
| city | string | 市 |
| county | string | 区/县 |
| district | string | 区域 |
| subDistrict | string | 子区域 |
| town | string | 镇 |
| village | string | 村 |
| subVillage | string | 子村 |
| region | string | 地区 |
| road | string | 道路 |
| default | string | 默认显示名称 |
| location | string | 定位信息 |
6. NAME --- 姓名实体
测试输入 :"老王电话13812345678" / "张三说明天开会" / "李医生说要注意休息"
jsonObject 结构 :键名 "name",值为 JSONArray:
json
{
"name": [{
"type": "nr"
}]
}
| 字段 | 类型 | 说明 |
|---|---|---|
| type | string | nr=正式姓名, nrn=昵称, nrt=称谓, nrx=其他 |
7. PHONE_NO --- 手机号实体
测试输入 :"老王电话13812345678" / "打给010-88888888" / "联系电话13812345678分机1234"
jsonObject 结构 :键名 "phoneNum",值为 JSONArray:
json
{
"phoneNum": [{
"type": 1,
"number": "13812345678",
"extNumber": ""
}]
}
| 字段 | 类型 | 说明 |
|---|---|---|
| type | number | 0=固话, 1=手机 |
| number | string | 号码(去除分机号) |
| extNumber | string | 分机号 |
8. URL --- URL 实体
测试输入 :"访问https://example.com查看详情"
jsonObject 结构 :键名 "url",值为空字符串。jsonObject 无额外结构化信息,实体原文即 URL。
9. VERIFICATION_CODE --- 验证码实体
测试输入 :"验证码123456" / "你的验证码是888999"
jsonObject 结构 :键名 "verificationCode",值为 JSONArray:
json
{
"verificationCode": [{
"type": "123456",
"supplier": "某平台"
}]
}
| 字段 | 类型 | 说明 |
|---|---|---|
| type | string | 验证码内容 |
| supplier | string | 验证码提供商(可选) |
10. ID_NO --- 身份证号实体
测试输入 :"身份证号110101199001011234" / "护照号12345678"
jsonObject 结构 :键名 "idNo",值为 JSONArray:
json
{
"idNo": [{
"number": "110101199001011234",
"sequence": 1,
"type": 0,
"isComplete": 1
}]
}
| 字段 | 类型 | 说明 |
|---|---|---|
| number | string | 证件号码 |
| sequence | number | 出现频率 |
| type | number | 0=身份证, 1=护照 |
| isComplete | number | 1=完整证件号, 0=含*等字符 |
错误码参考
| 错误码 | 说明 |
|---|---|
| 200 | 运行超时,请稍后重试 |
| 401 | 参数检查失败 |
| 1011200001 | 运行失败,请重试 |
| 1011200002 | 服务异常 |
init/release 生命周期
| 方法 | 说明 |
|---|---|
| init() | 预热引擎,减少首次调用延迟。非必须,不调则首次 getEntity 自动初始化 |
| release() | 释放引擎资源 |
两者共享同一个引擎,对 getEntity 和 getWordSegment 都生效。
推荐方案:onForeground → init(),onBackground → release()。前台时引擎常驻内存,提取无延迟;切后台释放资源给其他应用;回前台重新预热(100-300ms)。
输出格式示例
输入:"明天下午3点去国贸找老王,他电话13812345678"
📅 时间:明天下午3点
→ {"time":[{"start":"2026-07-24T15:00:00","startTimestamp":1784828400000,...}]}
📍 地点:国贸
→ {"location":[{"type":"","coreLocation":{"oriText":"国贸","default":"国贸",...},"isAbstract":0}]}
👤 姓名:老王
→ {"name":[{"type":"nrn"}]}
📞 手机:13812345678
→ {"phoneNum":[{"type":1,"number":"13812345678","extNumber":""}]}
Part 2:踩坑实录
Bug 1:划走松开仍发送消息
现象:按住按钮说话,手指划出按钮区域后松开,消息仍然被发送。期望划走松开应丢弃。
根因:HarmonyOS TouchEvent 机制:
| 用户操作 | 系统触发 | 开发者预期 |
|---|---|---|
| 原地松开 | TouchType.Up |
发送消息 ✅ |
| 手指划出区域松开 | TouchType.Up ❌ |
以为是 Cancel |
| 系统拦截(弹窗遮盖等) | TouchType.Cancel |
丢弃消息 ✅ |
Cancel 是系统级事件,不是用户级事件。 手指划出组件区域后松开,系统仍然触发 Up 而非 Cancel。只有系统拦截(权限弹窗、手势冲突等)才会触发 Cancel。
修复:记录 Down 坐标,Up 时算位移距离,>50vp 走 cancel(),≤50vp 走 stop():
arkts
@Local touchStartX: number = 0
@Local touchStartY: number = 0
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Down) {
this.touchStartX = event.touches[0].x
this.touchStartY = event.touches[0].y
this.inputService.start()
} else if (event.type === TouchType.Up) {
const dx = event.touches[0].x - this.touchStartX
const dy = event.touches[0].y - this.touchStartY
const distance = Math.sqrt(dx * dx + dy * dy)
if (distance > 50) {
this.inputService.cancel()
} else {
this.inputService.stop()
}
} else if (event.type === TouchType.Cancel) {
this.inputService.cancel()
}
})
教训 :不要假设 Cancel = 手指划出。Cancel 是系统级事件不是用户级事件。需要用坐标位移来判断用户意图。
Bug 2:权限弹窗后按钮保持红色
现象:首次按住按钮 → 弹出权限对话框 → 授权后关闭 → 按钮仍然红色 → 直到点击任意位置才恢复。
根因:时序分析:
1. Down → start() → _holding=true → 按钮变红
2. await PermissionHelper.request() → 弹出权限对话框
3. 用户在对话框上操作 → 手指离开按钮 → 但 touch 事件被对话框拦截
4. Up/Cancel 事件没发到按钮 → stop()/cancel() 没被调用
5. _holding 仍然是 true → 按钮保持红色 ❌
6. 权限授权成功 → startRecording() → 引擎开始录音 → 但用户不知道
7. 直到用户点击任意位置 → 触发新的 touch → 按钮才恢复
核心问题:权限弹窗期间 touch 事件被系统对话框拦截,按钮收不到 Up/Cancel,_holding 无法恢复。
修复 :start() 中先同步检查权限(getSelfPermissionStatus),已授权直接录音;未授权才弹窗,弹窗后 _holding=false 恢复 UI,本次录音作废:
arkts
async start(): Promise<void> {
const atManager = abilityAccessCtrl.createAtManager()
const permStatus = atManager.getSelfPermissionStatus('ohos.permission.MICROPHONE')
const alreadyGranted = permStatus === abilityAccessCtrl.PermissionStatus.GRANTED
this._holding = true
this.onHoldingChange?.(true)
if (alreadyGranted) {
await this.startRecording()
return
}
const granted = await PermissionHelper.request(context, 'ohos.permission.MICROPHONE')
this._holding = false
this.onHoldingChange?.(false)
if (!granted) { return }
// 授权成功但手指已不在按钮上,用户重新按住即可(第二次不弹权限)
}
教训 :await 弹窗类操作会打断 touch 事件流。弹窗期间组件收不到 touch 事件,需要在弹窗返回后主动恢复 UI 状态。区分"同步检查已授权"和"需要弹窗授权"两种路径。
Bug 3:cancel() 后 onComplete 仍发送消息
现象 :调用 cancel() 取消后,onComplete 回调仍然触发了发送,导致消息被发出。
根因 :engine.cancel() 是异步触发回调的,时序不确定:
cancel() → _holding=false
↓ (异步)
onResult(isFinal=true) → 追加 _accumulatedText ← cancel还没清空文本
↓ (异步)
onComplete → sendAccumulated() → 发送了!
cancel() → _accumulatedText='', _currentPartial='' ← 清空太晚了
engine.cancel() 的回调可能在 cancel() 方法体执行完之前触发,也可能在之后。时序不可预测。
修复 :新增 _cancelled 标志位,cancel() 时设 true,sendAccumulated() 检查到就不发送:
arkts
private _cancelled: boolean = false
cancel(): void {
this._cancelled = true
this._holding = false
this.onHoldingChange?.(false)
if (this.engine !== undefined) {
this.engine.cancel(this.currentSessionId)
this.engine.shutdown()
this.engine = undefined
}
this._accumulatedText = ''
this._currentPartial = ''
}
start(): void {
this._cancelled = false
...
}
private sendAccumulated(): void {
if (this._cancelled) {
this._accumulatedText = ''
this._currentPartial = ''
return
}
...
}
教训:引擎回调是异步的,不能假设调了 cancel()/shutdown() 后回调就不会执行。需要用标志位防御,在回调入口检查当前状态是否仍然合法。
Bug 4:Entity 不是 Kit 顶级导出
现象:
arkts
import { textProcessing, EntityType, Entity } from '@kit.NaturalLanguageKit'
编译报错:Module '"@kit.NaturalLanguageKit"' has no exported member 'Entity'
根因 :Entity 是 textProcessing 命名空间下的子类型,不是 Kit 的顶级导出。EntityType 是枚举,作为顶级导出;Entity 是接口,挂在命名空间下。
修复:
arkts
// 报错
import { textProcessing, EntityType, Entity } from '@kit.NaturalLanguageKit'
const entities: Entity[] = await textProcessing.getEntity(text)
// 正确
import { textProcessing, EntityType } from '@kit.NaturalLanguageKit'
const entities: textProcessing.Entity[] = await textProcessing.getEntity(text)
教训:Kit 的顶级导出和命名空间子类型是不同的。枚举通常顶级导出,接口/类可能在命名空间下。不确定时先看 .d.ts 或搜索文档。
Bug 5:Map 构造函数 + 对象字面量 = arkts-no-untyped-obj-literals
现象:
arkts
private formatMap: Map<string, EntityFormatItem> = new Map([
['datetime', { emoji: '📅', label: '时间' }],
['phoneNo', { emoji: '📞', label: '手机' }],
])
编译报错:Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)
根因 :ArkTS 要求所有对象字面量必须有显式类型声明,包括 Map 构造函数参数中的嵌套对象。即使 Map 的泛型已经声明了 EntityFormatItem,构造函数参数中的 { emoji, label } 仍然被视为 untyped object literal。
修复:放弃 Map,改用数组 + Record 索引:
arkts
interface EntityFormatItem {
emoji: string
label: string
}
private formatItems: EntityFormatItem[] = [
{ emoji: '📅', label: '时间' },
{ emoji: '📞', label: '手机' },
]
private typeIndexMap: Record<string, number> = {
'datetime': 0,
'phoneNo': 1,
} as Record<string, number>
教训 :ArkTS 中 Map 的构造函数参数不属于类型推断上下文。需要对象字面量时,优先用有类型声明的数组,或用 Record + as 断言。
Bug 6:Map 不能 as Record 转换
现象:
arkts
return new Map<string, Object>() as Record<string, Object>
编译报错:Conversion of type 'Map<string, Object>' to type 'Record<string, Object>' may be a mistake because neither type sufficiently overlaps with the other
根因 :Map 和 Record 是不同的数据结构。Map 没有索引签名,不能直接转换为 Record。ArkTS 的 as 断言要求两边有足够的类型重叠。
修复:用空对象字面量替代:
arkts
const EMPTY_RECORD: Record<string, Object> = {} as Record<string, Object>
private safeParse(json: string): Record<string, Object> {
if (json === '' || json === '{}') {
return EMPTY_RECORD
}
...
}
教训 :Map ≠ Record,不能互相转换。需要键值对结构时统一用 Record,不要混用 Map。
Bug 7:JSON.parse() 返回 any 被禁止
现象:
arkts
const parsed = JSON.parse(json)
if (typeof parsed === 'object') {
return parsed as Record<string, Object>
}
编译报错:Use explicit types instead of "any", "unknown" (arkts-no-any-unknown)
根因 :JSON.parse() 的 TypeScript 签名返回 any,ArkTS 禁止 any 类型。不能直接使用 JSON.parse() 的返回值,也不能对 any 做 as 断言。
修复 :两步 as 转换------先 as Object(合法,Object 是所有引用类型的基类),再 as Record<string, Object>:
arkts
const parsed: Object = JSON.parse(json) as Object
if (parsed !== null && typeof parsed === 'object') {
return parsed as Record<string, Object>
}
教训 :ArkTS 中 JSON.parse() 必须先 as Object 再 as 具体类型。不能直接使用返回值或一步到位。这是 ArkTS 对 any 类型的硬限制。
设计变更 1:筛选字段 → 返回完整数据
最初对每种实体只提取"最有价值"的字段(PHONE_NO → 只返回 number,LOCATION → 只返回 default 等),对应的 extractDetail() + 4 个 extractXxx() + safeParse() 约 100 行代码。
后来发现用户要的是完整 jsonObject 数据,不要代码帮他筛选。删除所有提取方法,formatEntity() 改为直接输出完整 jsonObject,代码从约 200 行降到约 130 行。
教训:不要替用户做选择。数据筛选是业务逻辑,不属于提取层。提取层应返回完整数据,让上层决定怎么用。
设计变更 2:init/release 生命周期
最初没有调用 textProcessing.init() 和 textProcessing.release(),每次 getEntity() 自动初始化引擎。
后来发现:init() 首次调用可减少 100-300ms 延迟;不 release 会一直占几十 MB 内存。改为 EntityExtractor 暴露 init()/release() 方法,EntryAbility 在 onForeground/onBackground 中调用。
教训:引擎类 API 的 init/release 要主动管理,不要依赖自动初始化。自动初始化只是兜底,主动 init 能优化首次体验,主动 release 能避免内存浪费。生命周期选择:onForeground/onBackground > aboutToAppear/aboutToDisappear > onCreate/onDestroy。
设计变更 3:maxLines 限制与动态内容
消息气泡有 maxLines(20) + textOverflow(Ellipsis) 限制。当显示实体识别的完整 jsonObject 数据时,DATETIME 实体 20+ 个字段一行就超长,20 行限制导致数据被截断。删除 maxLines 和 textOverflow,文本完整显示。
教训:显示限制要和内容匹配。之前硬编码固定文本时 20 行足够,现在显示动态数据就要重新评估限制。
通用教训
异步代码的三类陷阱
| 陷阱类型 | 表现 | 防御方法 |
|---|---|---|
| 回调时序不确定 | cancel/shutdown 后回调仍触发 | 标志位防御(_cancelled、_sessionGeneration) |
| 系统弹窗打断事件流 | await 弹窗期间 touch 事件丢失 | 弹窗返回后主动恢复 UI 状态 |
| 系统事件语义≠用户认知 | Cancel ≠ 手指划出 | 用坐标位移判断用户真实意图 |
ArkTS 编译的三类陷阱
| 陷阱类型 | 表现 | 防御方法 |
|---|---|---|
| Kit 命名空间 | Entity 不在顶级导出 | 用 textProcessing.Entity,不确定就查 .d.ts |
| 对象字面量无类型 | Map 构造函数参数报错 | 用有类型上下文的数组,或 Record + as |
| JSON.parse 返回 any | 禁止直接使用返回值 | 先 as Object 再 as Record,两步转换 |
设计层面的三类陷阱
| 陷阱类型 | 表现 | 防御方法 |
|---|---|---|
| 替用户做选择 | 筛选字段 vs 完整数据 | 提取层返回完整数据,业务层决定怎么用 |
| 忽略生命周期 | init/release 不管理 | 引擎类 API 主动管理,onForeground/onBackground |
| 显示限制与内容不匹配 | maxLines 截断动态数据 | 显示限制随内容变化重新评估 |
7 条经验法则
- 遇到
await--- 想一想:这期间外部状态会变吗?事件会丢失吗? - 遇到回调 --- 想一想:回调触发时,我预设的状态还成立吗?需要标志位吗?
- 遇到系统弹窗 --- 想一想:弹窗期间 UI 状态需要手动恢复吗?
- 遇到系统事件 --- 想一想:事件语义和用户认知一致吗?不一致就自己判断
- 遇到 Kit 导入 --- 先确认类型在命名空间下还是顶级导出,不要猜
- 遇到对象字面量 --- 确保有类型上下文,没有就声明 interface
- 遇到 JSON.parse --- 记住两步 as:
as Object→as Record<string, Object>
先画时序图再写代码,先查 .d.ts 再写 import,能省很多调试时间。
能看到这里的应该算是至爱亲朋,手足兄弟了。既然来都来了,下面准备了点薄礼,拿走不谢:
HarmonyOS 端侧 AI 能力全景
所有端侧 AI Kit 及其核心能力,全部离线可用,无需联网
CoreSpeechKit --- 语音能力
| 能力 | 模块 | 说明 | since |
|---|---|---|---|
| 语音识别(ASR) | speechRecognizer |
语音→文字,支持 long/short 模式,recognitionMode=0 引擎自己录音 | 5.0.0(12) |
| 语音合成(TTS) | textToSpeech |
文字→语音,支持多音色/语速/音调/音量,≤10000字 | 5.0.0(12) |
| AI字幕 | AICaption |
实时语音转字幕 | 5.0.0(12) |
| 文本朗读 | textReader |
无障碍场景文本朗读 | 5.0.0(12) |
arkts
import { speechRecognizer, textToSpeech } from '@kit.CoreSpeechKit'
NaturalLanguageKit --- 自然语言能力
| 能力 | 模块 | 说明 | since |
|---|---|---|---|
| 实体抽取 | textProcessing.getEntity |
10种实体识别(时间/地点/人名/手机号等) | 5.0.0(12) |
| 分词+词性标注 | textProcessing.getWordSegment |
中文分词,返回词语+词性(名词/动词/形容词等) | 5.0.0(12) |
arkts
import { textProcessing, EntityType } from '@kit.NaturalLanguageKit'
DataAugmentationKit --- 端侧大模型能力
| 能力 | 模块 | 说明 | since |
|---|---|---|---|
| 端侧LLM对话 | localChatModel |
端侧大语言模型,支持流式/非流式问答,问题≤4500字节 | 6.0.0(20) |
| 检索增强生成 | rag |
RAG 检索增强生成 | 6.0.0(20) |
| 知识检索 | retrieval |
知识库检索 | 6.0.0(20) |
| 向量化 | knowledgeProcessor |
文本向量化处理(仅PC可用) | 6.0.0(20) |
arkts
import { localChatModel } from '@kit.DataAugmentationKit'
CoreVisionKit --- 视觉能力
| 能力 | 模块 | 说明 | since |
|---|---|---|---|
| 文字识别(OCR) | textRecognition |
图片中识别文字,支持中/英/日/韩/繁体中文 | 4.0.0(10) |
| 人脸检测 | faceDetector |
检测人脸2D/3D轮廓、表情、年龄、性别 | 5.0.0(12) |
| 人脸比对 | faceComparator |
人脸特征比对,输出相似度 | 5.0.0(12) |
| 主体分割 | subjectSegmentation |
前景/背景分割,抠图 | 5.0.0(12) |
| 多目标识别 | objectDetection |
通用物体检测与位置识别 | 5.0.0(12) |
| 骨骼点检测 | skeletonDetection |
人体骨架关键点检测 | 5.0.0(12) |
| 图像超分 | imageSuperResolution |
1x去噪/3x放大增强 | 5.0.0(12) |
| 文本搜图 | textSearchImage |
通过文本描述搜索图片 | 5.0.0(12) |
arkts
import { textRecognition, faceDetector, subjectSegmentation } from '@kit.CoreVisionKit'
VisionKit --- 场景化视觉服务
| 能力 | 模块 | 说明 | since |
|---|---|---|---|
| 活体检测 | interactiveLiveness |
动作活体检测(点头/张嘴/眨眼),抵御照片/视频攻击 | 5.0.0(12) |
arkts
import { interactiveLiveness } from '@kit.VisionKit'
MindSporeLiteKit --- 自定义模型
| 能力 | 模块 | 说明 | since |
|---|---|---|---|
| 端侧推理 | mindSporeLite |
加载 .ms 模型文件执行推理,支持 CPU/GPU/NPU | 5.0.0(12) |
| 端侧训练 | mindSporeLite |
端侧迁移学习微调模型 | 5.0.0(12) |
arkts
import { mindSporeLite } from '@kit.MindSporeLiteKit'
AgentFrameworkKit --- 意图框架
| 能力 | 模块 | 说明 | since |
|---|---|---|---|
| 意图执行 | insightIntent |
系统反向调度App(小艺语音→App执行意图) | 5.0.0(12) |
| 意图实体定义 | InsightIntentEntity |
定义App可被系统调度的意图和数据结构 | 5.0.0(12) |
arkts
import { insightIntent } from '@kit.AbilityKit'
能力全景速查
| 输入→输出 | Kit | 能力 |
|---|---|---|
| 语音→文字 | CoreSpeechKit | speechRecognizer |
| 文字→语音 | CoreSpeechKit | textToSpeech |
| 文字→实体 | NaturalLanguageKit | textProcessing.getEntity |
| 文字→分词 | NaturalLanguageKit | textProcessing.getWordSegment |
| 文字→智能回答 | DataAugmentationKit | localChatModel |
| 图片→文字 | CoreVisionKit | textRecognition (OCR) |
| 图片→人脸 | CoreVisionKit | faceDetector / faceComparator |
| 图片→抠图 | CoreVisionKit | subjectSegmentation |
| 图片→物体 | CoreVisionKit | objectDetection |
| 图片→骨架 | CoreVisionKit | skeletonDetection |
| 图片→超分 | CoreVisionKit | imageSuperResolution |
| 自定义模型 | MindSporeLiteKit | mindSporeLite 推理/训练 |
| 系统→App | AgentFrameworkKit | insightIntent 反向调度 |
学习小结:textProcessing.getEntity() 提供 10 种实体识别,无需权限无需联网,是端侧 NLP 的核心能力。踩坑集中在三个方面------异步回调时序不确定(需要标志位防御)、ArkTS 编译规则(命名空间导出、对象字面量、JSON.parse 两步 as)、设计选择(完整数据优于筛选、生命周期要主动管理)。7 条经验法则的核心是:先画时序图再写代码,先查 .d.ts 再写 import。
懿路向前 · AI辅助整理
2026-07-24