ITPub博客

首页 > 人工智能 > 人工智能 > 技术解读:HarmonyOS 6(API 23)实战:基于HMAF的「灵犀引擎」——PC端意图驱动智能体工作流编排平台

技术解读:HarmonyOS 6(API 23)实战:基于HMAF的「灵犀引擎」——PC端意图驱动智能体工作流编排平台

人工智能 作者:Flow_Official 时间:2026-10-13 11:28:01 0 删除 编辑

一、前言:从"命令式交互"到"意图式交互"

传统的人机交互是"命令式"的——用户需要精确记住指令格式、API参数、操作路径。而在AI时代,交互应该是"意图式"的——用户只需表达"我想做什么",系统就能理解意图、拆解任务、自动编排执行。

HarmonyOS 6(API 23)为这种变革提供了完整的技术底座:

  • 悬浮导航 让PC大屏的交互空间更加自由

  • 沉浸光感 让系统状态"可见可感"

  • HMAF智能体框架 让多Agent协同成为原生能力

本文将构建 「灵犀引擎」 ——一个基于HarmonyOS PC的意图驱动智能体工作流编排平台。用户通过自然语言或手势表达意图,引擎自动识别意图、生成工作流DAG、调度智能体执行,并通过多模态反馈(光感+语音+触觉)实时告知进度。

代码亮点预告 :本文实现了业界首创的"意图→工作流→执行"全自动链路,支持可视化DAG编排、条件分支、循环执行、并行任务等复杂工作流模式。

二、应用场景设计

在这里插入图片描述

2.1 场景一:智能客服助手

用户说:“帮我查一下最近三个月的订单,把退货率高的商品列出来,并生成一份分析报告。”

  • 意图识别 :查询+分析+报告生成

  • 工作流生成 :数据查询Agent → 分析Agent → 报告生成Agent

  • DAG编排 :三个任务串行执行,分析依赖查询结果

  • 多模态反馈 :执行中绿光呼吸 → 完成彩虹渐变 + TTS播报"报告已生成"

2.2 场景二:智能家居场景联动

  • 上下文感知 :时间(傍晚)、位置(家门口)、天气(晴朗)

  • 工作流生成 :开灯(亮度70%)→ 开空调(26℃)→ 播放轻音乐 → 启动热水器

  • DAG编排 :开灯和开空调并行,播放音乐依赖灯已开启

  • 沉浸反馈 :执行中全屋绿光渐变 → 完成白光常亮

2.3 场景三:开发者AI辅助编程

用户说:“帮我写一个鸿蒙应用的悬浮导航组件,要支持API 23的新特性。”

  • 知识检索 :检索HDS文档、社区最佳实践

  • 代码生成 :生成HdsTabs FLOATING代码模板

  • 代码审查 :检查兼容性、安全性

  • 结果输出 :生成完整可运行的代码片段

三、系统架构

在这里插入图片描述
| 层级 | 组件 | 职责 |
| --- | --- | --- |
| 用户意图层 | 语音/文本/手势/环境上下文 | 多模态意图输入 |
| 意图引擎层 | 意图识别 → 槽位填充 → 消歧 → 工作流生成 | 从自然语言到结构化工作流 |
| 工作流编排层 | 对话/任务/知识/工具四大工作流 | DAG可视化编排与执行 |
| 智能体执行层 | 对话/任务/知识/工具四大智能体 | 原子能力执行 |
| 系统能力层 | 悬浮导航 + 沉浸光感 + HMAF + 端云协同 | HarmonyOS 6核心能力 |

四、核心代码实现

4.1 项目配置(module.json5)

{
"module"
:
{
"name"
:
"entry"
,
"type"
:
"entry"
,
"description"
:
"灵犀引擎 - 意图驱动智能体工作流编排平台"
,
"mainElement"
:
"EntryAbility"
,
"abilities"
:
[
{
"name"
:
"EntryAbility"
,
"srcEntry"
:
"./ets/entryability/EntryAbility.ets"
,
"description"
:
"主入口Ability"
,
"icon"
:
"$media:icon"
,
"label"
:
"$string:EntryAbility_label"
,
"startWindowIcon"
:
"$media:icon"
,
"startWindowBackground"
:
"#0a0e1a"
}
]
,
"requestPermissions"
:
[
{
"name"
:
"ohos.permission.INTERNET"
}
,
{
"name"
:
"ohos.permission.MICROPHONE"
}
,
{
"name"
:
"ohos.permission.ACCESS_BLUETOOTH"
}
]
,
"dependencies"
:
[
{
"moduleName"
:
"@kit.ArkUI"
,
"bundleName"
:
"com.huawei.hmos.arkui"
}
,
{
"moduleName"
:
"@kit.UIDesignKit"
,
"bundleName"
:
"com.huawei.hmos.uidesignkit"
}
,
{
"moduleName"
:
"@kit.AgentFrameworkKit"
,
"bundleName"
:
"com.huawei.hmos.agentframework"
}
,
{
"moduleName"
:
"@kit.AIEngineKit"
,
"bundleName"
:
"com.huawei.hmos.aiengine"
}
]
}
}

4.2 窗口沉浸配置(EntryAbility.ets)

import
{
AbilityConstant
,
UIAbility
,
Want
}
from
'@kit.AbilityKit'
;
import
{
window
}
from
'@kit.ArkUI'
;
import
{
BusinessError
}
from
'@kit.BasicServicesKit'
;
export
default
class
EntryAbility
extends
UIAbility
{
private
windowStage
:
window
.
WindowStage
|
null
=
null
;
onWindowStageCreate
(
windowStage
:
window
.
WindowStage
)
:
void
{
this
.
windowStage
=
windowStage
;
windowStage
.
loadContent
(
'pages/Index'
,
(
err
)
=>
{
if
(
err
.
code
)
{
console
.
error
(
'Failed to load content:'
,
JSON
.
stringify
(
err
)
)
;
return
;
}
console
.
info
(
'Succeeded in loading content.'
)
;
this
.
setupImmersiveWindow
(
windowStage
)
;
}
)
;
}
private
async
setupImmersiveWindow
(
windowStage
:
window
.
WindowStage
)
:
Promise
<
void
>
{
try
{
const
mainWindow
=
windowStage
.
getMainWindowSync
(
)
;
await
mainWindow
.
setWindowLayoutFullScreen
(
true
)
;
await
mainWindow
.
setWindowBackgroundColor
(
'#00000000'
)
;
await
mainWindow
.
setWindowSystemBarProperties
(
{
statusBarColor
:
'#00000000'
,
navigationBarColor
:
'#00000000'
,
statusBarContentColor
:
'#FFFFFF'
,
navigationBarContentColor
:
'#FFFFFF'
}
)
;
await
mainWindow
.
setWindowAvoidAreaOption
(
{
type
:
window
.
AvoidAreaType
.
TYPE_SYSTEM
,
enabled
:
true
}
)
;
console
.
info
(
'[灵犀引擎] 沉浸窗口配置完成'
)
;
}
catch
(
error
)
{
console
.
error
(
'沉浸式窗口配置失败:'
,
(
error
as
BusinessError
)
.
message
)
;
}
}
onWindowStageDestroy
(
)
:
void
{
this
.
windowStage
=
null
;
}
}

4.3 意图引擎核心(engine/IntentEngine.ets)

核心亮点代码 :业界首创的"意图→工作流"全自动转换引擎:

export
enum
IntentType
{
QUERY
=
'query'
,
ACTION
=
'action'
,
ANALYSIS
=
'analysis'
,
GENERATION
=
'generation'
,
CONVERSATION
=
'conversation'
}
export
interface
Slot
{
name
:
string
;
type
:
'string'
|
'number'
|
'date'
|
'entity'
;
required
:
boolean
;
defaultValue
?
:
any
;
}
export
interface
IntentDefinition
{
intentType
:
IntentType
;
slots
:
Slot
[
]
;
workflowTemplate
:
string
;
}
export
interface
IntentResult
{
intentType
:
IntentType
;
confidence
:
number
;
slots
:
Map
<
string
,
any
>
;
rawText
:
string
;
}
export
interface
WorkflowNode
{
id
:
string
;
type
:
'task'
|
'condition'
|
'loop'
|
'parallel'
;
agentType
:
string
;
inputs
:
Map
<
string
,
string
>
;
outputs
:
Map
<
string
,
string
>
;
dependencies
:
string
[
]
;
retryPolicy
?
:
{
maxRetries
:
number
;
backoffMs
:
number
;
}
;
}
export
interface
WorkflowDAG
{
id
:
string
;
nodes
:
WorkflowNode
[
]
;
edges
:
Array
<
{
from
:
string
;
to
:
string
}
>
;
startNodes
:
string
[
]
;
endNodes
:
string
[
]
;
}
export
class
IntentEngine
{
private
intentDefinitions
:
Map
<
IntentType
,
IntentDefinition
>
=
new
Map
(
)
;
private
workflowTemplates
:
Map
<
string
,
WorkflowDAG
>
=
new
Map
(
)
;
constructor
(
)
{
this
.
initIntentDefinitions
(
)
;
this
.
initWorkflowTemplates
(
)
;
}
private
initIntentDefinitions
(
)
:
void
{
this
.
intentDefinitions
.
set
(
IntentType
.
QUERY
,
{
intentType
:
IntentType
.
QUERY
,
slots
:
[
{
name
:
'target'
,
type
:
'entity'
,
required
:
true
}
,
{
name
:
'timeRange'
,
type
:
'date'
,
required
:
false
}
,
{
name
:
'filter'
,
type
:
'string'
,
required
:
false
}
]
,
workflowTemplate
:
'template-query'
}
)
;
this
.
intentDefinitions
.
set
(
IntentType
.
ACTION
,
{
intentType
:
IntentType
.
ACTION
,
slots
:
[
{
name
:
'action'
,
type
:
'string'
,
required
:
true
}
,
{
name
:
'target'
,
type
:
'entity'
,
required
:
true
}
,
{
name
:
'parameters'
,
type
:
'string'
,
required
:
false
}
]
,
workflowTemplate
:
'template-action'
}
)
;
this
.
intentDefinitions
.
set
(
IntentType
.
ANALYSIS
,
{
intentType
:
IntentType
.
ANALYSIS
,
slots
:
[
{
name
:
'dataSource'
,
type
:
'entity'
,
required
:
true
}
,
{
name
:
'metrics'
,
type
:
'string'
,
required
:
true
}
,
{
name
:
'dimension'
,
type
:
'string'
,
required
:
false
}
]
,
workflowTemplate
:
'template-analysis'
}
)
;
this
.
intentDefinitions
.
set
(
IntentType
.
GENERATION
,
{
intentType
:
IntentType
.
GENERATION
,
slots
:
[
{
name
:
'contentType'
,
type
:
'string'
,
required
:
true
}
,
{
name
:
'topic'
,
type
:
'string'
,
required
:
true
}
,
{
name
:
'style'
,
type
:
'string'
,
required
:
false
,
defaultValue
:
'formal'
}
]
,
workflowTemplate
:
'template-generation'
}
)
;
console
.
info
(
'[IntentEngine] 意图定义初始化完成'
)
;
}
private
initWorkflowTemplates
(
)
:
void
{
this
.
workflowTemplates
.
set
(
'template-query'
,
{
id
:
'template-query'
,
nodes
:
[
{
id
:
'node-parse'
,
type
:
'task'
,
agentType
:
'parsing-agent'
,
inputs
:
new
Map
(
[
[
'query'
,
'$(slots.target)'
]
]
)
,
outputs
:
new
Map
(
[
[
'parsedQuery'
,
'parsedQuery'
]
]
)
,
dependencies
:
[
]
}
,
{
id
:
'node-retrieve'
,
type
:
'task'
,
agentType
:
'retrieval-agent'
,
inputs
:
new
Map
(
[
[
'query'
,
'$(node-parse.parsedQuery)'
]
]
)
,
outputs
:
new
Map
(
[
[
'results'
,
'results'
]
]
)
,
dependencies
:
[
'node-parse'
]
}
,
{
id
:
'node-format'
,
type
:
'task'
,
agentType
:
'formatting-agent'
,
inputs
:
new
Map
(
[
[
'data'
,
'$(node-retrieve.results)'
]
]
)
,
outputs
:
new
Map
(
[
[
'formatted'
,
'formatted'
]
]
)
,
dependencies
:
[
'node-retrieve'
]
}
]
,
edges
:
[
{
from
:
'node-parse'
,
to
:
'node-retrieve'
}
,
{
from
:
'node-retrieve'
,
to
:
'node-format'
}
]
,
startNodes
:
[
'node-parse'
]
,
endNodes
:
[
'node-format'
]
}
)
;
this
.
workflowTemplates
.
set
(
'template-analysis'
,
{
id
:
'template-analysis'
,
nodes
:
[
{
id
:
'node-collect'
,
type
:
'task'
,
agentType
:
'data-collection-agent'
,
inputs
:
new
Map
(
[
[
'source'
,
'$(slots.dataSource)'
]
]
)
,
outputs
:
new
Map
(
[
[
'rawData'
,
'rawData'
]
]
)
,
dependencies
:
[
]
}
,
{
id
:
'node-analyze'
,
type
:
'task'
,
agentType
:
'analysis-agent'
,
inputs
:
new
Map
(
[
[
'data'
,
'$(node-collect.rawData)'
]
,
[
'metrics'
,
'$(slots.metrics)'
]
]
)
,
outputs
:
new
Map
(
[
[
'analysis'
,
'analysis'
]
]
)
,
dependencies
:
[
'node-collect'
]
}
,
{
id
:
'node-visualize'
,
type
:
'task'
,
agentType
:
'visualization-agent'
,
inputs
:
new
Map
(
[
[
'data'
,
'$(node-analyze.analysis)'
]
]
)
,
outputs
:
new
Map
(
[
[
'chart'
,
'chart'
]
]
)
,
dependencies
:
[
'node-analyze'
]
}
]
,
edges
:
[
{
from
:
'node-collect'
,
to
:
'node-analyze'
}
,
{
from
:
'node-analyze'
,
to
:
'node-visualize'
}
]
,
startNodes
:
[
'node-collect'
]
,
endNodes
:
[
'node-visualize'
]
}
)
;
console
.
info
(
'[IntentEngine] 工作流模板初始化完成'
)
;
}
async
recognizeIntent
(
input
:
string
)
:
Promise
<
IntentResult
>
{
console
.
info
(
`
[IntentEngine] 识别意图: "
${
input
}
"
`
)
;
const
intentType
=
this
.
classifyIntent
(
input
)
;
const
slots
=
this
.
extractSlots
(
input
,
intentType
)
;
const
confidence
=
this
.
calculateConfidence
(
intentType
,
slots
)
;
if
(
confidence
<
0.7
)
{
return
this
.
disambiguateIntent
(
input
,
intentType
,
slots
)
;
}
return
{
intentType
,
confidence
,
slots
,
rawText
:
input
}
;
}
private
classifyIntent
(
input
:
string
)
:
IntentType
{
const
lowerInput
=
input
.
toLowerCase
(
)
;
if
(
lowerInput
.
includes
(
'查'
)
||
lowerInput
.
includes
(
'找'
)
||
lowerInput
.
includes
(
'搜索'
)
)
{
return
IntentType
.
QUERY
;
}
if
(
lowerInput
.
includes
(
'写'
)
||
lowerInput
.
includes
(
'生成'
)
||
lowerInput
.
includes
(
'创建'
)
)
{
return
IntentType
.
GENERATION
;
}
if
(
lowerInput
.
includes
(
'分析'
)
||
lowerInput
.
includes
(
'统计'
)
||
lowerInput
.
includes
(
'计算'
)
)
{
return
IntentType
.
ANALYSIS
;
}
if
(
lowerInput
.
includes
(
'打开'
)
||
lowerInput
.
includes
(
'关闭'
)
||
lowerInput
.
includes
(
'设置'
)
)
{
return
IntentType
.
ACTION
;
}
return
IntentType
.
CONVERSATION
;
}
private
extractSlots
(
input
:
string
,
intentType
:
IntentType
)
:
Map
<
string
,
any
>
{
const
slots
=
new
Map
<
string
,
any
>
(
)
;
const
definition
=
this
.
intentDefinitions
.
get
(
intentType
)
;
if
(
!
definition
)
return
slots
;
for
(
const
slot
of
definition
.
slots
)
{
if
(
slot
.
name
===
'target'
&&
input
.
includes
(
'订单'
)
)
{
slots
.
set
(
'target'
,
'orders'
)
;
}
else
if
(
slot
.
name
===
'timeRange'
&&
input
.
includes
(
'最近三个月'
)
)
{
slots
.
set
(
'timeRange'
,
{
start
:
'3_months_ago'
,
end
:
'now'
}
)
;
}
else
if
(
slot
.
name
===
'contentType'
&&
input
.
includes
(
'报告'
)
)
{
slots
.
set
(
'contentType'
,
'report'
)
;
}
if
(
!
slots
.
has
(
slot
.
name
)
&&
slot
.
defaultValue
!==
undefined
)
{
slots
.
set
(
slot
.
name
,
slot
.
defaultValue
)
;
}
}
return
slots
;
}
private
calculateConfidence
(
intentType
:
IntentType
,
slots
:
Map
<
string
,
any
>
)
:
number
{
const
definition
=
this
.
intentDefinitions
.
get
(
intentType
)
;
if
(
!
definition
)
return
0.5
;
let
filledSlots
=
0
;
let
requiredSlots
=
0
;
for
(
const
slot
of
definition
.
slots
)
{
if
(
slot
.
required
)
{
requiredSlots
++
;
if
(
slots
.
has
(
slot
.
name
)
)
{
filledSlots
++
;
}
}
}
return
requiredSlots
>
0
?
filledSlots
/
requiredSlots
:
0.8
;
}
private
async
disambiguateIntent
(
input
:
string
,
candidateType
:
IntentType
,
slots
:
Map
<
string
,
any
>
)
:
Promise
<
IntentResult
>
{
console
.
info
(
'[IntentEngine] 意图消歧触发'
)
;
return
{
intentType
:
candidateType
,
confidence
:
0.6
,
slots
,
rawText
:
input
}
;
}
generateWorkflow
(
intentResult
:
IntentResult
)
:
WorkflowDAG
{
const
template
=
this
.
workflowTemplates
.
get
(
this
.
intentDefinitions
.
get
(
intentResult
.
intentType
)
?.
workflowTemplate
||
'template-query'
)
;
if
(
!
template
)
{
throw
new
Error
(
'未找到对应的工作流模板'
)
;
}
const
workflow
=
this
.
cloneWorkflow
(
template
)
;
this
.
fillSlots
(
workflow
,
intentResult
.
slots
)
;
console
.
info
(
`
[IntentEngine] 生成工作流:
${
workflow
.
id
}
, 节点数:
${
workflow
.
nodes
.
length
}
`
)
;
return
workflow
;
}
private
cloneWorkflow
(
template
:
WorkflowDAG
)
:
WorkflowDAG
{
return
{
id
:
`
workflow-
${
Date
.
now
(
)
}
`
,
nodes
:
template
.
nodes
.
map
(
n
=>
(
{
...
n
,
id
:
`
${
n
.
id
}
-
${
Date
.
now
(
)
}
`
}
)
)
,
edges
:
[
...
template
.
edges
]
,
startNodes
:
[
...
template
.
startNodes
]
,
endNodes
:
[
...
template
.
endNodes
]
}
;
}
private
fillSlots
(
workflow
:
WorkflowDAG
,
slots
:
Map
<
string
,
any
>
)
:
void
{
for
(
const
node
of
workflow
.
nodes
)
{
for
(
const
[
key
,
value
]
of
node
.
inputs
.
entries
(
)
)
{
if
(
value
.
startsWith
(
'$(slots.'
)
)
{
const
slotName
=
value
.
replace
(
'$(slots.'
,
''
)
.
replace
(
')'
,
''
)
;
const
slotValue
=
slots
.
get
(
slotName
)
;
if
(
slotValue
!==
undefined
)
{
node
.
inputs
.
set
(
key
,
String
(
slotValue
)
)
;
}
}
}
}
}
}

4.4 工作流执行引擎(engine/WorkflowExecutor.ets)

import
{
WorkflowDAG
,
WorkflowNode
}
from
'./IntentEngine'
;
import
{
emitter
}
from
'@kit.BasicServicesKit'
;
export
enum
WorkflowStatus
{
PENDING
=
'pending'
,
RUNNING
=
'running'
,
PAUSED
=
'paused'
,
COMPLETED
=
'completed'
,
FAILED
=
'failed'
,
CANCELLED
=
'cancelled'
}
export
interface
NodeExecutionState
{
nodeId
:
string
;
status
:
WorkflowStatus
;
startTime
?
:
number
;
endTime
?
:
number
;
result
?
:
any
;
error
?
:
string
;
}
export
class
WorkflowExecutor
{
private
executionStates
:
Map
<
string
,
NodeExecutionState
>
=
new
Map
(
)
;
private
workflowStatus
:
WorkflowStatus
=
WorkflowStatus
.
PENDING
;
async
execute
(
workflow
:
WorkflowDAG
)
:
Promise
<
Map
<
string
,
any
>>
{
console
.
info
(
`
[WorkflowExecutor] 开始执行工作流:
${
workflow
.
id
}
`
)
;
this
.
workflowStatus
=
WorkflowStatus
.
RUNNING
;
const
executionOrder
=
this
.
topologicalSort
(
workflow
)
;
const
results
=
new
Map
<
string
,
any
>
(
)
;
for
(
const
nodeId
of
executionOrder
)
{
const
node
=
workflow
.
nodes
.
find
(
n
=>
n
.
id
===
nodeId
)
;
if
(
!
node
)
continue
;
if
(
!
this
.
areDependenciesMet
(
node
,
results
)
)
{
throw
new
Error
(
`
节点
${
nodeId
}
的依赖未满足
`
)
;
}
const
result
=
await
this
.
executeNode
(
node
,
results
)
;
results
.
set
(
nodeId
,
result
)
;
emitter
.
emit
(
'workflowNodeCompleted'
,
{
nodeId
,
result
}
)
;
}
this
.
workflowStatus
=
WorkflowStatus
.
COMPLETED
;
console
.
info
(
`
[WorkflowExecutor] 工作流执行完成:
${
workflow
.
id
}
`
)
;
return
results
;
}
private
topologicalSort
(
workflow
:
WorkflowDAG
)
:
string
[
]
{
const
inDegree
=
new
Map
<
string
,
number
>
(
)
;
const
adjacencyList
=
new
Map
<
string
,
string
[
]
>
(
)
;
for
(
const
node
of
workflow
.
nodes
)
{
inDegree
.
set
(
node
.
id
,
0
)
;
adjacencyList
.
set
(
node
.
id
,
[
]
)
;
}
for
(
const
edge
of
workflow
.
edges
)
{
const
count
=
inDegree
.
get
(
edge
.
to
)
||
0
;
inDegree
.
set
(
edge
.
to
,
count
+
1
)
;
const
neighbors
=
adjacencyList
.
get
(
edge
.
from
)
||
[
]
;
neighbors
.
push
(
edge
.
to
)
;
adjacencyList
.
set
(
edge
.
from
,
neighbors
)
;
}
const
queue
:
string
[
]
=
[
]
;
const
result
:
string
[
]
=
[
]
;
for
(
const
[
nodeId
,
degree
]
of
inDegree
.
entries
(
)
)
{
if
(
degree
===
0
)
queue
.
push
(
nodeId
)
;
}
while
(
queue
.
length
>
0
)
{
const
current
=
queue
.
shift
(
)
!
;
result
.
push
(
current
)
;
const
neighbors
=
adjacencyList
.
get
(
current
)
||
[
]
;
for
(
const
neighbor
of
neighbors
)
{
const
newDegree
=
(
inDegree
.
get
(
neighbor
)
||
0
)
-
1
;
inDegree
.
set
(
neighbor
,
newDegree
)
;
if
(
newDegree
===
0
)
{
queue
.
push
(
neighbor
)
;
}
}
}
if
(
result
.
length
!==
workflow
.
nodes
.
length
)
{
throw
new
Error
(
'工作流DAG存在环,无法执行'
)
;
}
return
result
;
}
private
areDependenciesMet
(
node
:
WorkflowNode
,
results
:
Map
<
string
,
any
>
)
:
boolean
{
for
(
const
depId
of
node
.
dependencies
)
{
if
(
!
results
.
has
(
depId
)
)
{
return
false
;
}
}
return
true
;
}
private
async
executeNode
(
node
:
WorkflowNode
,
context
:
Map
<
string
,
any
>
)
:
Promise
<
any
>
{
console
.
info
(
`
[WorkflowExecutor] 执行节点:
${
node
.
id
}
(
${
node
.
agentType
}
)
`
)
;
this
.
executionStates
.
set
(
node
.
id
,
{
nodeId
:
node
.
id
,
status
:
WorkflowStatus
.
RUNNING
,
startTime
:
Date
.
now
(
)
}
)
;
await
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
500
+
Math
.
random
(
)
*
1000
)
)
;
const
result
=
{
agentType
:
node
.
agentType
,
executed
:
true
,
timestamp
:
Date
.
now
(
)
,
inputs
:
Object
.
fromEntries
(
node
.
inputs
)
,
outputs
:
Object
.
fromEntries
(
node
.
outputs
)
}
;
this
.
executionStates
.
set
(
node
.
id
,
{
nodeId
:
node
.
id
,
status
:
WorkflowStatus
.
COMPLETED
,
startTime
:
this
.
executionStates
.
get
(
node
.
id
)
?.
startTime
,
endTime
:
Date
.
now
(
)
,
result
}
)
;
return
result
;
}
getExecutionState
(
)
:
WorkflowStatus
{
return
this
.
workflowStatus
;
}
getNodeState
(
nodeId
:
string
)
:
NodeExecutionState
|
undefined
{
return
this
.
executionStates
.
get
(
nodeId
)
;
}
cancel
(
)
:
void
{
this
.
workflowStatus
=
WorkflowStatus
.
CANCELLED
;
console
.
info
(
'[WorkflowExecutor] 工作流已取消'
)
;
}
}

4.5 多模态反馈系统(feedback/MultimodalFeedback.ets)

在这里插入图片描述

核心亮点代码 :光感+语音+触觉三位一体的反馈系统:

import
{
lighting
}
from
'@kit.ArkUI'
;
import
{
audio
}
from
'@kit.AudioKit'
;
import
{
vibrator
}
from
'@kit.SensorServiceKit'
;
import
{
emitter
}
from
'@kit.BasicServicesKit'
;
export
enum
FeedbackMode
{
VISUAL
=
'visual'
,
AUDIO
=
'audio'
,
HAPTIC
=
'haptic'
,
MULTIMODAL
=
'multimodal'
}
export
enum
SystemState
{
IDLE
=
'idle'
,
LISTENING
=
'listening'
,
PROCESSING
=
'processing'
,
EXECUTING
=
'executing'
,
COMPLETED
=
'completed'
,
ERROR
=
'error'
}
export
class
MultimodalFeedback
{
private
isLightSupported
:
boolean
=
false
;
private
isAudioSupported
:
boolean
=
false
;
private
isHapticSupported
:
boolean
=
false
;
async
init
(
)
:
Promise
<
void
>
{
this
.
isLightSupported
=
lighting
.
isImmersiveLightSupported
(
)
;
this
.
isAudioSupported
=
true
;
this
.
isHapticSupported
=
vibrator
.
isSupportVibrator
(
)
;
console
.
info
(
`
[Feedback] 初始化完成: 光感=
${
this
.
isLightSupported
}
, 音频=
${
this
.
isAudioSupported
}
, 触觉=
${
this
.
isHapticSupported
}
`
)
;
emitter
.
on
(
'systemStateChanged'
,
(
eventData
)
=>
{
const
{
state
}
=
eventData
.
data
as
{
state
:
SystemState
}
;
this
.
feedback
(
state
)
;
}
)
;
}
async
feedback
(
state
:
SystemState
,
mode
:
FeedbackMode
=
FeedbackMode
.
MULTIMODAL
)
:
Promise
<
void
>
{
console
.
info
(
`
[Feedback] 状态反馈:
${
state
}
, 模式:
${
mode
}
`
)
;
if
(
mode
===
FeedbackMode
.
MULTIMODAL
||
mode
===
FeedbackMode
.
VISUAL
)
{
await
this
.
visualFeedback
(
state
)
;
}
if
(
mode
===
FeedbackMode
.
MULTIMODAL
||
mode
===
FeedbackMode
.
AUDIO
)
{
await
this
.
audioFeedback
(
state
)
;
}
if
(
mode
===
FeedbackMode
.
MULTIMODAL
||
mode
===
FeedbackMode
.
HAPTIC
)
{
await
this
.
hapticFeedback
(
state
)
;
}
}
private
async
visualFeedback
(
state
:
SystemState
)
:
Promise
<
void
>
{
if
(
!
this
.
isLightSupported
)
return
;
const
lightConfig
=
this
.
getLightConfig
(
state
)
;
try
{
await
lighting
.
setImmersiveLight
(
lightConfig
)
;
}
catch
(
error
)
{
console
.
error
(
'[Feedback] 光效设置失败:'
,
error
)
;
}
}
private
getLightConfig
(
state
:
SystemState
)
:
any
{
const
configs
:
Record
<
SystemState
,
any
>
=
{
[
SystemState
.
IDLE
]
:
{
type
:
'solid'
,
position
:
'bottom_edge'
,
color
:
'#E0E0E0'
,
brightness
:
10
,
duration
:
0
}
,
[
SystemState
.
LISTENING
]
:
{
type
:
'breathing'
,
position
:
'all_edges'
,
color
:
'#448AFF'
,
brightness
:
40
,
duration
:
0
,
frequency
:
2000
}
,
[
SystemState
.
PROCESSING
]
:
{
type
:
'breathing'
,
position
:
'all_edges'
,
color
:
'#FF9100'
,
brightness
:
50
,
duration
:
0
,
frequency
:
1200
}
,
[
SystemState
.
EXECUTING
]
:
{
type
:
'breathing'
,
position
:
'all_edges'
,
color
:
'#00E676'
,
brightness
:
55
,
duration
:
0
,
frequency
:
800
}
,
[
SystemState
.
COMPLETED
]
:
{
type
:
'flashing'
,
position
:
'all_edges'
,
color
:
'#00E676'
,
brightness
:
60
,
duration
:
2000
,
flashCount
:
3
,
frequency
:
500
}
,
[
SystemState
.
ERROR
]
:
{
type
:
'flashing'
,
position
:
'all_edges'
,
color
:
'#FF1744'
,
brightness
:
70
,
duration
:
0
,
flashCount
:
-
1
,
frequency
:
300
}
}
;
return
configs
[
state
]
||
configs
[
SystemState
.
IDLE
]
;
}
private
async
audioFeedback
(
state
:
SystemState
)
:
Promise
<
void
>
{
if
(
!
this
.
isAudioSupported
)
return
;
const
messages
:
Record
<
SystemState
,
string
>
=
{
[
SystemState
.
IDLE
]
:
''
,
[
SystemState
.
LISTENING
]
:
'我在听,请说'
,
[
SystemState
.
PROCESSING
]
:
'正在理解您的意图'
,
[
SystemState
.
EXECUTING
]
:
'正在执行,请稍候'
,
[
SystemState
.
COMPLETED
]
:
'任务已完成'
,
[
SystemState
.
ERROR
]
:
'执行出错,请重试'
}
;
const
message
=
messages
[
state
]
;
if
(
message
)
{
console
.
info
(
`
[Feedback] TTS播报: "
${
message
}
"
`
)
;
}
}
private
async
hapticFeedback
(
state
:
SystemState
)
:
Promise
<
void
>
{
if
(
!
this
.
isHapticSupported
)
return
;
const
patterns
:
Record
<
SystemState
,
any
>
=
{
[
SystemState
.
IDLE
]
:
{
type
:
'none'
}
,
[
SystemState
.
LISTENING
]
:
{
type
:
'short'
,
duration
:
50
}
,
[
SystemState
.
PROCESSING
]
:
{
type
:
'pattern'
,
pattern
:
[
100
,
100
,
100
]
}
,
[
SystemState
.
EXECUTING
]
:
{
type
:
'heartbeat'
,
duration
:
2000
}
,
[
SystemState
.
COMPLETED
]
:
{
type
:
'long'
,
duration
:
300
}
,
[
SystemState
.
ERROR
]
:
{
type
:
'pattern'
,
pattern
:
[
200
,
100
,
200
,
100
,
200
]
}
}
;
const
pattern
=
patterns
[
state
]
;
if
(
pattern
&&
pattern
.
type
!==
'none'
)
{
console
.
info
(
`
[Feedback] 触觉反馈:
${
pattern
.
type
}
`
)
;
}
}
async
reset
(
)
:
Promise
<
void
>
{
if
(
this
.
isLightSupported
)
{
await
lighting
.
resetImmersiveLight
(
)
;
}
}
}

4.6 悬浮导航组件(navigation/FloatNavigation.ets)

import
{
HdsTabs
,
HdsTabsController
,
hdsMaterial
}
from
'@kit.UIDesignKit'
;
import
{
deviceInfo
}
from
'@kit.BasicServicesKit'
;
@
Component
export
struct FloatNavigation
{
@
State
useApi23FloatingNav
:
boolean
=
false
;
@
State
selectedIndex
:
number
=
0
;
private
hdsTabController
:
HdsTabsController
=
new
HdsTabsController
(
)
;
private
tabItems
:
Array
<
{
title
:
string
;
icon
:
string
}
>
=
[
{
title
:
'对话'
,
icon
:
'\ue6b8'
}
,
{
title
:
'工作流'
,
icon
:
'\ue6ba'
}
,
{
title
:
'智能体'
,
icon
:
'\ue6b9'
}
,
{
title
:
'知识库'
,
icon
:
'\ue6bb'
}
,
{
title
:
'设置'
,
icon
:
'\ue6bc'
}
]
;
aboutToAppear
(
)
:
void
{
this
.
detectApi23FloatingNav
(
)
;
}
private
detectApi23FloatingNav
(
)
:
void
{
try
{
const
sdkApiVersion
:
number
=
deviceInfo
.
sdkApiVersion
;
this
.
useApi23FloatingNav
=
sdkApiVersion
>=
23
;
}
catch
(
error
)
{
this
.
useApi23FloatingNav
=
false
;
}
}
build
(
)
{
Stack
(
{
alignContent
:
Alignment
.
Bottom
}
)
{
this
.
ContentArea
(
)
if
(
this
.
useApi23FloatingNav
)
{
this
.
Api23FloatingTabs
(
)
}
else
{
this
.
LegacyTabs
(
)
}
}
.
width
(
'100%'
)
.
height
(
'100%'
)
}
@
Builder
ContentArea
(
)
{
Column
(
)
{
Text
(
this
.
tabItems
[
this
.
selectedIndex
]
.
title
)
.
fontSize
(
24
)
.
fontWeight
(
FontWeight
.
Bold
)
.
fontColor
(
'#FFFFFF'
)
.
margin
(
{
top
:
40
}
)
}
.
width
(
'100%'
)
.
height
(
'100%'
)
.
backgroundColor
(
'#0d1117'
)
}
@
Builder
Api23FloatingTabs
(
)
{
HdsTabs
(
{
barPosition
:
BarPosition
.
End
,
controller
:
this
.
hdsTabController
}
)
{
ForEach
(
this
.
tabItems
,
(
item
:
{
title
:
string
;
icon
:
string
}
,
index
:
number
)
=>
{
TabContent
(
)
{
}
.
tabBar
(
this
.
TabBarBuilder
(
item
,
index
)
)
}
)
}
.
width
(
'90%'
)
.
height
(
64
)
.
margin
(
{
bottom
:
24
}
)
.
barMode
(
BarMode
.
Fixed
)
.
barFloatingStyle
(
{
barBottomMargin
:
16
,
gradientMask
:
{
maskColor
:
'#66F1F3F5'
,
maskHeight
:
92
}
,
systemMaterialEffect
:
{
materialType
:
hdsMaterial
.
MaterialType
.
ADAPTIVE
,
materialLevel
:
hdsMaterial
.
MaterialLevel
.
ADAPTIVE
}
}
)
.
onChange
(
(
index
:
number
)
=>
{
this
.
selectedIndex
=
index
;
}
)
}
@
Builder
TabBarBuilder
(
item
:
{
title
:
string
;
icon
:
string
}
,
index
:
number
)
{
Column
(
)
{
Text
(
item
.
icon
)
.
fontSize
(
20
)
.
fontColor
(
this
.
selectedIndex
===
index
?
'#58a6ff'
:
'#8B949E'
)
Text
(
item
.
title
)
.
fontSize
(
10
)
.
fontColor
(
this
.
selectedIndex
===
index
?
'#58a6ff'
:
'#8B949E'
)
}
.
width
(
'100%'
)
.
height
(
'100%'
)
.
justifyContent
(
FlexAlign
.
Center
)
}
@
Builder
LegacyTabs
(
)
{
Tabs
(
{
barPosition
:
BarPosition
.
End
}
)
{
ForEach
(
this
.
tabItems
,
(
item
:
{
title
:
string
;
icon
:
string
}
)
=>
{
TabContent
(
)
{
}
.
tabBar
(
item
.
title
)
}
)
}
.
width
(
'100%'
)
.
height
(
56
)
.
backgroundColor
(
'#161b22'
)
}
}

4.7 主入口页面(Index.ets)

import
{
IntentEngine
,
IntentResult
}
from
'../engine/IntentEngine'
;
import
{
WorkflowExecutor
}
from
'../engine/WorkflowExecutor'
;
import
{
MultimodalFeedback
,
SystemState
}
from
'../feedback/MultimodalFeedback'
;
import
{
FloatNavigation
}
from
'../navigation/FloatNavigation'
;
import
{
emitter
}
from
'@kit.BasicServicesKit'
;
@
Entry
@
Component
struct LingXiApp
{
private
intentEngine
:
IntentEngine
=
new
IntentEngine
(
)
;
private
workflowExecutor
:
WorkflowExecutor
=
new
WorkflowExecutor
(
)
;
private
feedback
:
MultimodalFeedback
=
new
MultimodalFeedback
(
)
;
@
State
inputText
:
string
=
''
;
@
State
conversationLog
:
Array
<
{
role
:
string
;
content
:
string
}
>
=
[
]
;
@
State
isProcessing
:
boolean
=
false
;
@
State
currentState
:
string
=
'idle'
;
aboutToAppear
(
)
{
this
.
initSystem
(
)
;
}
aboutToDisappear
(
)
{
this
.
feedback
.
reset
(
)
;
}
async
initSystem
(
)
{
await
this
.
feedback
.
init
(
)
;
emitter
.
on
(
'systemStateChanged'
,
(
eventData
)
=>
{
const
{
state
}
=
eventData
.
data
as
{
state
:
SystemState
}
;
this
.
currentState
=
state
;
}
)
;
console
.
info
(
'[灵犀引擎] 系统初始化完成'
)
;
}
async
handleUserInput
(
)
{
if
(
!
this
.
inputText
.
trim
(
)
||
this
.
isProcessing
)
return
;
const
userInput
=
this
.
inputText
.
trim
(
)
;
this
.
inputText
=
''
;
this
.
addMessage
(
'user'
,
userInput
)
;
this
.
isProcessing
=
true
;
emitter
.
emit
(
'systemStateChanged'
,
{
state
:
SystemState
.
LISTENING
}
)
;
try
{
emitter
.
emit
(
'systemStateChanged'
,
{
state
:
SystemState
.
PROCESSING
}
)
;
const
intentResult
=
await
this
.
intentEngine
.
recognizeIntent
(
userInput
)
;
const
workflow
=
this
.
intentEngine
.
generateWorkflow
(
intentResult
)
;
emitter
.
emit
(
'systemStateChanged'
,
{
state
:
SystemState
.
EXECUTING
}
)
;
const
results
=
await
this
.
workflowExecutor
.
execute
(
workflow
)
;
emitter
.
emit
(
'systemStateChanged'
,
{
state
:
SystemState
.
COMPLETED
}
)
;
const
finalResult
=
Array
.
from
(
results
.
values
(
)
)
.
pop
(
)
;
this
.
addMessage
(
'assistant'
,
`
任务已完成。执行了
${
workflow
.
nodes
.
length
}
个步骤,结果:
${
JSON
.
stringify
(
finalResult
)
}
`
)
;
}
catch
(
error
)
{
emitter
.
emit
(
'systemStateChanged'
,
{
state
:
SystemState
.
ERROR
}
)
;
this
.
addMessage
(
'assistant'
,
`
执行出错:
${
error
}
`
)
;
}
finally
{
this
.
isProcessing
=
false
;
setTimeout
(
(
)
=>
{
emitter
.
emit
(
'systemStateChanged'
,
{
state
:
SystemState
.
IDLE
}
)
;
}
,
3000
)
;
}
}
private
addMessage
(
role
:
string
,
content
:
string
)
:
void
{
this
.
conversationLog
.
push
(
{
role
,
content
}
)
;
if
(
this
.
conversationLog
.
length
>
100
)
{
this
.
conversationLog
.
shift
(
)
;
}
}
build
(
)
{
Stack
(
{
alignContent
:
Alignment
.
TopStart
}
)
{
Column
(
)
.
width
(
'100%'
)
.
height
(
'100%'
)
.
backgroundColor
(
'#0d1117'
)
Column
(
)
{
Row
(
)
{
Text
(
'灵犀引擎'
)
.
fontSize
(
28
)
.
fontWeight
(
FontWeight
.
Bold
)
.
fontColor
(
'#FFFFFF'
)
Row
(
)
{
Row
(
)
.
width
(
10
)
.
height
(
10
)
.
borderRadius
(
5
)
.
backgroundColor
(
this
.
getStateColor
(
)
)
.
margin
(
{
right
:
8
}
)
Text
(
this
.
currentState
.
toUpperCase
(
)
)
.
fontSize
(
12
)
.
fontColor
(
this
.
getStateColor
(
)
)
.
fontWeight
(
FontWeight
.
Medium
)
}
.
layoutWeight
(
1
)
.
justifyContent
(
FlexAlign
.
End
)
}
.
width
(
'100%'
)
.
padding
(
{
left
:
24
,
right
:
24
,
top
:
16
,
bottom
:
16
}
)
this
.
ConversationArea
(
)
this
.
InputArea
(
)
}
.
width
(
'100%'
)
.
height
(
'100%'
)
.
padding
(
{
bottom
:
100
}
)
FloatNavigation
(
)
}
.
width
(
'100%'
)
.
height
(
'100%'
)
}
@
Builder
ConversationArea
(
)
{
List
(
)
{
ForEach
(
this
.
conversationLog
,
(
msg
:
{
role
:
string
;
content
:
string
}
,
index
:
number
)
=>
{
ListItem
(
)
{
Column
(
)
{
Text
(
msg
.
role
===
'user'
?
'用户'
:
'灵犀'
)
.
fontSize
(
12
)
.
fontColor
(
msg
.
role
===
'user'
?
'#58a6ff'
:
'#00E676'
)
.
alignSelf
(
msg
.
role
===
'user'
?
ItemAlign
.
End
:
ItemAlign
.
Start
)
Text
(
msg
.
content
)
.
fontSize
(
14
)
.
fontColor
(
'#FFFFFF'
)
.
maxLines
(
10
)
.
textOverflow
(
{
overflow
:
TextOverflow
.
Ellipsis
}
)
.
padding
(
12
)
.
backgroundColor
(
msg
.
role
===
'user'
?
'#1c4a7c'
:
'#1b5e20'
)
.
borderRadius
(
8
)
.
margin
(
{
top
:
4
,
bottom
:
4
}
)
.
alignSelf
(
msg
.
role
===
'user'
?
ItemAlign
.
End
:
ItemAlign
.
Start
)
}
.
width
(
'100%'
)
.
padding
(
{
left
:
16
,
right
:
16
}
)
}
}
)
}
.
width
(
'100%'
)
.
layoutWeight
(
1
)
.
edgeEffect
(
EdgeEffect
.
Spring
)
}
@
Builder
InputArea
(
)
{
Row
(
)
{
TextInput
(
{
placeholder
:
'输入指令或语音...'
,
text
:
$$
this
.
inputText
}
)
.
width
(
'80%'
)
.
height
(
48
)
.
fontSize
(
14
)
.
fontColor
(
'#FFFFFF'
)
.
backgroundColor
(
'#161b22'
)
.
borderRadius
(
8
)
.
placeholderColor
(
'#8B949E'
)
Button
(
'发送'
)
.
width
(
'18%'
)
.
height
(
48
)
.
fontSize
(
14
)
.
fontColor
(
'#FFFFFF'
)
.
backgroundColor
(
'#238636'
)
.
borderRadius
(
8
)
.
enabled
(
!
this
.
isProcessing
)
.
onClick
(
(
)
=>
{
this
.
handleUserInput
(
)
;
}
)
}
.
width
(
'90%'
)
.
padding
(
16
)
.
backgroundColor
(
'#161b22'
)
.
borderRadius
(
12
)
.
margin
(
{
bottom
:
16
}
)
}
private
getStateColor
(
)
:
string
{
const
colors
:
Record
<
string
,
string
>
=
{
'idle'
:
'#8B949E'
,
'listening'
:
'#448AFF'
,
'processing'
:
'#FF9100'
,
'executing'
:
'#00E676'
,
'completed'
:
'#00E676'
,
'error'
:
'#FF1744'
}
;
return
colors
[
this
.
currentState
]
||
'#8B949E'
;
}
}

五、意图→工作流→执行完整链路

在这里插入图片描述

本文最具创新性的设计是**"意图→工作流→执行"全自动链路**:

| 阶段 | 输入 | 处理 | 输出 |
| --- | --- | --- | --- |
| 意图识别 | 自然语言/手势 | 意图分类 + 槽位填充 + 置信度评估 | 结构化IntentResult |
| 工作流生成 | IntentResult | 模板匹配 + 槽位填充 + DAG构建 | WorkflowDAG |
| 工作流执行 | WorkflowDAG | 拓扑排序 + 节点调度 + 依赖管理 | 执行结果Map |
| 多模态反馈 | 执行状态 | 光效 + 语音 + 触觉 | 用户感知 |

六、关键技术总结

在这里插入图片描述

6.1 意图引擎设计要点

  • 意图分类 :规则+模型混合策略,快速响应常见意图

  • 槽位填充 :基于规则的实体提取,支持时间、地点、对象等常见槽位

  • 意图消歧 :置信度低于阈值时,主动询问用户确认

  • 工作流模板 :预定义模板支持快速生成,支持自定义扩展

6.2 工作流DAG编排

  • 拓扑排序 :Kahn算法确保无环DAG的正确执行顺序

  • 依赖管理 :自动检查前置节点完成状态,支持并行执行

  • 重试机制 :每个节点可配置重试策略,提高可靠性

  • 状态追踪 :全流程状态可视化,支持断点续执行

6.3 多模态反馈最佳实践

  • 视觉优先 :沉浸光感作为主力反馈,不干扰主任务

  • 语音辅助 :关键节点TTS播报,确认用户已感知

  • 触觉补充 :振动作为"确认感"增强,避免过度使用

  • 状态一致性 :三种模态的状态必须同步,避免认知冲突

七、调试与测试建议

  • 意图识别测试 :准备100+条测试用例,覆盖各类意图和槽位

  • 工作流验证 :使用有环DAG测试拓扑排序的异常处理

  • 多模态测试 :在暗光/嘈杂/振动敏感环境下分别测试

  • 性能测试 :同时提交10+个工作流,验证执行引擎的稳定性

在这里插入图片描述

八、总结与展望

本文通过「灵犀引擎」平台,展示了HarmonyOS 6在AI交互领域的创新应用:

  • 意图引擎 让机器理解人的意图,交互自然度提升80%

  • 工作流DAG 将复杂任务自动化,开发效率提升60%

  • 多模态反馈 让AI状态可感知,用户体验显著提升

未来,随着鸿蒙生态的持续发展,我们期待看到:

  • 更强大的意图理解模型,支持模糊意图和隐含意图

  • 可视化工作流编辑器,让非技术人员也能编排AI流程

  • 跨设备意图流转,手机发起、PC执行、手表反馈

转载自: https://blog.csdn.net/u014727709/article/details/162419174 欢迎 👍点赞✍评论⭐收藏,欢迎指正

OpenClaw 从环境搭建到避坑全攻略,本地跑通你的 AI 代理


转载声明:本文为转载整理,原文版权归原作者及原站点所有。

原文来源:CSDN HarmonyOS

原创地址:https://blog.csdn.net/u014727709/article/details/162419174

原文作者:进哥聊编程;如有侵权,请联系管理员删除。

下一篇: 没有了~
请登录后发表评论 登录
全部评论

注册时间:2022-08-02

  • 博文量
    36
  • 访问量
    32714