代码块

定义 playbook 时,您可以选择提供代码块,这些代码块是可用于更好地控制代理行为的内嵌 Python 代码。此代码由带有特殊装饰器的函数以及您所需的任何实用函数组成。

编写代码时,您可以使用代码块系统库来控制代理行为。

已知问题

存在以下已知问题:

  • VPC-SC 边界内限制 Artifact Registry 访问权限的项目也会拒绝代码块部署

限制

存在以下限制:

  • 代码块不能包含任何会保留数据的对象。不过,您可以使用工具来保留数据并维护状态。
  • 代码块无法直接进行远程调用。 例如,您无法使用 Python requests 库。不过,您可以利用工具间接进行远程调用。
  • 转换为 Python 名称的资源名称必须是合法的 Python 名称
  • 除非发生流程转换,否则代码块无法写入会话参数。

内嵌操作

内嵌操作的行为与工具操作类似。它们具有由 Python 函数签名(包括类型注释和 docstring)确定的已定义输入和输出架构。与工具调用类似,LLM 不知道实现操作的代码。

示例 :

@Action
def is_prime(n: int): bool
  """Returns true if n is prime."""
  import math
  return (all([False for i in range(2, math.sqrt(n)
               if n % i == 0 ]) and not n < 2)

对于此函数,系统会向 LLM 提供有关操作、输入和输出的信息。

如需在剧本说明中引用内嵌操作,只需在反引号中引用操作名称,并说明应如何使用该操作。

place_order 内嵌操作的示例:

Take the customer's order, then call the `place_order` action when the order is ready.

如需创建使用内嵌操作的示例,请在输入和输出部分中使用 inline-action 工具类型。

如需了解详情,请参阅 @Action 参考文档。

触发函数

触发函数用于在代码中定义条件操作

触发函数使用装饰器进行声明。您可以使用以下触发函数装饰器:

装饰器 装饰器参数 说明
@EventTrigger event: str, condition: str,其中 condition 是可选的 由事件触发
@BeforeModelTrigger condition: str,其中 condition 是可选的 每次在 LLM 预测下一个操作之前触发。
@BeforeActionTrigger condition: str,其中 condition 是可选的 每次在 LLM 执行操作之前触发。
@BeforePlaybookTrigger condition: str,其中 condition 是可选的 首次启动 playbook 时触发。

例如,这些函数展示了如何使用这些装饰器和装饰器参数,以及如何使用 respond 代码块系统库函数。

# No decorator parameter
@PlaybookStartTrigger
def my_playbook_conditional_action():
  respond("How can I help?")

# With a condition decorator parameter
@BeforeActionTrigger('$next-action.name = "search"')
def my_before_action_conditional_action():
  respond("One moment please")

# Event
@EventTrigger(event="welcome")
def my_welcome_event():
  respond("hi")

# Event with a condition:
@EventTrigger(event="welcome",
              condition="$sys.func.NOW().hours < 10")
def my_good_morning_event():
  respond("Good morning ☕")

引用流、playbook 和工具

在代码块中,您可以使用 flowsplaybookstools 全局变量来引用特定的流程、剧本和工具。

这些对象各自都包含与相应资源名称匹配的成员。 这些名称必须是合法的 Python 名称

示例 :

  add_override(playbooks.troubleshooting, {})
  add_override(flows.billing)
  add_override(tools.weather_api.get_weather, {"location": "San Francisco"})

在代码块中引用流和 playbook 时,您还必须在 playbook 说明中引用它们,并使用以下语法:

${RESOURCE_TYPE: my_resource_name}

例如,如果您的代码块包含 flows.myflowplaybooks.myplaybook,则剧本指令应包含:

${FLOW: myflow}
${PLAYBOOK: myplaybook}

操作替换

您可以使用代码块创建一系列将在 LLM 确定的任何后续操作之前执行的操作,并且可能会替换这些后续操作。 您可以使用 add_override 全局函数创建操作替换。

所有排队的替换操作将按顺序执行,并且操作输出将可供 LLM 使用。 队列为空后,操作会返回到 LLM 以进行操作和输入选择,除非替换项通过 respond 或完成回合的其他函数结束回合。

函数实参:

  • action:要执行的操作。 对于内嵌操作,请使用 my_function_name。对于工具操作,请使用 tools.my_tool_name.my_tool_action。 对于流操作,请使用 flows.my_flow_name
  • inputs:操作的可选输入。 例如:{"location": "Omaha"}

样本:

# Assuming remote tool named "dmv" with operationId "search_offices"
# remote tool with only requestBody
add_override(tools.dmv.search_offices,{"address": "95030"})

# remote tool with only parameters
add_override(tools.pets.get_pet, {"id": "123"})

# remote tool with requestBody + parameters:
add_override(tools.pets.create_pet, {"requestBody": {"arg1":"foo"}, "param1": "bar"})

# datastore. Assumes existing datastore tool named "Menu".
add_override(tools.menu.Menu, {"query": "what is the menu"})

# code block action. Assumes another code block @Action my_action.
add_override(my_action)

响应替换

与操作替换类似,但专门针对代理回答,您可以使用 respond 全局函数强制代理使用特定内容回答用户。

示例 :

respond("Hello")

调用工具

在代码块函数中,您可以调用为代理定义的工具。 与替换工具操作不同的是,当您直接调用工具时,LLM 无法获取工具执行结果。

样本:

# Assumes existing tool named "DMV" with operationId "search_offices"
# remote tool with only request body.
offices = tools.dmv.search_offices({"address": "95030"})

# remote tool with parameters and request body
offices = tools.dmv.search_offices({"requestBody": {"address":"95030"}, "param1":"foo"})

# datastore actions. Assumes existing datastore tool named "Menu".
data = tools.menu.Menu({"query": "get the menu"})["snippets"]

匹配意图

代码块可以使用 Flow.match_intent 函数以编程方式匹配给定流程的 intent。

示例 :

matches = flows.flow1.match_intent(history.last_user_utterance).matches
if matches and matches[0].intent == "some_intent":
  to_country = matches[0].parameters.get("to_country")
  if to_country:
    respond(f"To confirm, you're going to {to_country}, right?")

读取会话参数

代码块可以读取执行时可用的参数

示例 :

state["$session.params.my-param"]
state["$request.session-id"]

调试

您可以使用模拟器来调试代码块函数。这些功能将以操作的形式显示在模拟器中,并会根据需要提供我们的详细信息。

其他控制措施

本指南介绍了代码块系统库的一些常见用途。如需了解其他类型的控制,请参阅库文档。