使用 Actions

简介

您已经在 事件生成 & 匹配 章节中了解了如何使用事件。现在我们将介绍 actions,它将使您能够更好地管理事件及其时间依赖性。

重要提示

Action 定义

<ActionName>[(param=<value>[, param=<value>]…)]

示例

# Bot utterance action
UtteranceBotAction(script="Hello", intensity=1.0)

# Bot gesture action
GestureBotAction(gesture="Wave with one hand")

Action 使用 Pascal 命名风格,类似于事件,但以 Action 结尾。

与事件不同,actions 的生命周期取决于底层事件。所有 actions 都包含以下主要事件,其中我们使用 X 作为 action 名称的占位符

StartXAction(**action_arguments) # Start of an action with given action specific arguments
StopXAction(action_uid: str) # Stop of an action with the related uid
XActionStarted(action_uid: str) # Event to signal the action has started
XActionFinished(action_uid: str, is_success: bool, was_stopped: bool, **action_arguments) # Event to signal that the action has ended

在 Colang 中,action 就像 Python 中的对象,事件可以像 action 的对象方法一样被访问。

XAction(**action_arguments).Start()
XAction.Stop(action_uid: str)
XAction.Started(action_uid: str)
XAction.Finished(action_uid: str, is_success: bool, was_stopped: bool, **action_arguments)

以下是 action 的两个常见生命周期,它们取决于事件

XAction.Start() -> Action state: `Starting`
XAction.Started() -> Action state: `Running`
XAction.Finished() -> Action state: `Finished`
XAction.Start() -> Action state: `Starting`
XAction.Started() -> Action state: `Running`
XAction.Stop() -> Action state: `Stopping`
XAction.Finished() -> Action state: `Finished`

UMIM 参考文档中,您将找到许多预定义的 actions,这些 actions 应该涵盖最常见的用例。让我们看看最突出的 action 之一,称为 UtteranceBotAction。此 action 表示与用户通信的主要通道,例如通过语音或文本(取决于特定系统)。此 action 与可以从机器人的角度分组为输出和输入事件的事件相关

输出事件

UtteranceBotAction(script: str).Start()
UtteranceBotAction.Stop(action_uid: str)
UtteranceBotAction.Change(action_uid: str, intensity: float)

输入事件

UtteranceBotAction.Started(action_uid: str, action_started_at: str, ...)
UtteranceBotActionScript.Updated(action_uid: str, interim_transcript: str, ...)
UtteranceBotAction.Finished(action_uid: str, final_transcript: str, ...)

注意

请注意,Colang 不仅限于从机器人的角度工作,还可以用于模拟用户端。在这种情况下,输出和输入分类将翻转。

虽然对于如何使用 sendmatch 关键字处理这些事件没有约束性规则,但在大多数情况下,我们将生成输出事件并匹配输入事件。例如,如果我们希望机器人在做手势之前先说完某些话,我们可以创建以下交互模式

actions/action_events/main.co
flow main
    match StartEvent()
    send UtteranceBotAction(script="Hello").Start() as $event_ref
    match UtteranceBotActionFinished(action_uid=$event_ref.action_uid)
    send GestureBotAction(gesture="Wave").Start()
> /StartEvent

Hello

Gesture: Wave

我们看到,通过使用 Start action 事件引用的 action_uid 属性,我们可以匹配特定 action 的 Finished 事件。这很重要,因为可能在之前有其他 UtteranceBotAction 完成。

启动 Action

Colang 支持基于 action 概念的几个功能,这些功能使设计交互模式更加方便。我们介绍的第一个功能是 start 语句。

重要提示

Start 语句定义

start <Action> [as $<action_ref_name>] [and|or <Action> [as $<action_ref_name>]…)]

示例

start UtteranceBotAction(script="Hello") as $bot_action_ref
actions/start_keyword/main.co
flow main
    start UtteranceBotAction(script="Hello") as $ref_action
    match $ref_action.Finished()
    start GestureBotAction(gesture="Wave")
    match RestartEvent()
Hello

Gesture: Wave

关键字 start 创建一个 action 对象,然后生成一个 action 特定的 Start action 事件。可以使用 as $ref_name 存储对此 action 对象的引用。有了这个 action 引用,我们现在可以方便地匹配 Finished 事件,而不再需要使用 action_uid 参数来标识特定的 action。

现在让我们看一个常见的用户 action UtteranceUserAction 的示例。此 action 表示 UtteranceBotAction 的对应物,并且是用户表达自己的主要通道,例如通过说话、写作或任何其他方式,具体取决于实际系统。用户 action 通常不是由 Colang 启动的,而是由用户(系统)启动的。以下是最重要的 action 事件和参数

UtteranceUserActionStarted(action_uid: str)
UtteranceUserActionTranscriptUpdated(action_uid: str, interim_transcript: str)
UtteranceUserActionIntensityUpdated(action_uid: str, intensity: float)
UtteranceUserActionFinished(action_uid: str, final_transcript: str)

有了这些,现在让我们构建一个小对话模式

actions/dialog_pattern/main.co
flow main
    match UtteranceUserAction.Finished(final_transcript="Hi")
    start UtteranceBotAction(script="Hi there! How are you?") as $ref_action_1
    match $ref_action_1.Finished()
    match UtteranceUserAction.Finished(final_transcript="Good and you?")
    start UtteranceBotAction(script="Great! Thanks") as $ref_action_2
    start GestureBotAction(gesture="Thumbs up") as $ref_action_3
    match $ref_action_2.Finished() and $ref_action_3.Finished()
> Hi

Hi there! How are you?

> Good and you?

Great! Thanks

Gesture: Thumbs up

您可能已经注意到,这与我们在介绍示例 introduction/interaction_sequence/main.co 中看到的示例非常相似。不同之处在于我们有更多的时间控制,并且只有在机器人完成话语后才开始匹配用户输入。另请注意,只有在第二个机器人话语 action 和机器人手势 action 都完成后,交互模式才完成。

等待 Action

让我们介绍 await 语句,以进一步简化之前的示例

actions/await_keyword/main.co
flow main
    match UtteranceUserAction.Finished(final_transcript="Hi")
    await UtteranceBotAction(script="Hi there! How are you?")
    match UtteranceUserAction.Finished(final_transcript="Good and you?")
    # ...

await 是启动 action 并等待 action 完成(即匹配 .Finished() 事件)的快捷方式表示法。

重要提示

Await 语句定义

await <Action> [as $<action_ref_name>] [and|or <Action> [as $<action_ref_name>]…)]

示例

await UtteranceBotAction(script="Hello") as $bot_action_ref

不幸的是,我们无法使用这个来简化示例的第二部分……或者我们可以吗?实际上,是的!我们可以使用 action 分组,使用 and 关键字来像这样简化它

actions/action_grouping/main.co
flow main
    match UtteranceUserAction.Finished(final_transcript="Hi")
    await UtteranceBotAction(script="Hi there! How are you?")
    match UtteranceUserAction.Finished(final_transcript="Good and you?")
    await UtteranceBotAction(script="Great! Thanks") and GestureBotAction(gesture="Thumbs up")

Action 分组与事件分组相同,只是使用关键字 startawait 代替 sendmatch

重要提示

注意,这个

await Action1() or Action2()

将随机启动 actions 中的一个(而不是两个!)并等待它完成

为了进一步简化,实际上我们可以完全省略所有 await 关键字,因为它是默认的语句关键字。

actions/omit_wait_keyword/main.co
flow main
    match UtteranceUserAction.Finished(final_transcript="Hi")
    UtteranceBotAction(script="Hi there! How are you?")
    match UtteranceUserAction.Finished(final_transcript="Good and you?")
    UtteranceBotAction(script="Great! Thanks") and GestureBotAction(gesture="Thumbs up")

重要提示

await 是默认的语句关键字,可以省略。

如果我们想启动两个 actions,并且只等待其中一个完成,我们可以像这样实现

actions/wait_for_first_action_only/main.co
flow main
    match StartEvent()
    start UtteranceBotAction(script="Great! Thanks") as $ref_action_1
        and GestureBotAction(gesture="Thumbs up") as $ref_action_2
    match $ref_action_1.Finished() or $ref_action_2.Finished()

更多关于 Actions

如果需要,我们还可以使用其引用停止 action,如下所示

actions/stop_action/main.co
flow main
    match StartEvent()
    start UtteranceBotAction(script="Great! Thanks") as $ref_action
    send $ref_action.Stop()

不幸的是,使用简单的聊天 CLI,我们将看不到 Stop 事件的任何效果,因为话语是立即完成的。但在任何实际系统中,话语都需要一些时间才能完成,如果需要,可以像这样停止。

另一个需要指出的细节是通过 action 引用访问的 action 事件与直接通过 action 匹配之间的区别

# Case 1) Wait for Finished event of the specific action
start UtteranceBotAction(script="hi") as $action_ref
match $action_ref.Finished()

# Case 2) Wait for the Finished event of any UtteranceBotAction
match UtteranceBotAction.Finished()

在第一种情况下,匹配是针对特定的 action 引用(相同的 action_uid 参数),并且不会匹配来自另一个 UtteranceBotAction 的任何其他 Finished 事件。第二种情况更通用,将匹配来自任何 UtteranceBotAction 的任何 Finished 事件。

有了这些,我们现在准备好在下一章 定义 Flows 中了解更多关于 flows 概念的信息。