Blocos de código

Ao definir um playbook, você pode fornecer blocos de código, que são códigos Python inline que podem ser usados para controlar melhor o comportamento do agente. Esse código é composto de funções com decoradores especiais e todas as funções de utilitário necessárias.

Ao escrever o código, você pode usar a biblioteca do sistema de blocos de código para controlar o comportamento do agente.

Limitações

Considere as seguintes limitações:

  • Os blocos de código não podem conter objetos que persistam dados. No entanto, é possível usar ferramentas para persistir dados e manter o estado.
  • Os blocos de código não podem fazer chamadas remotas diretamente. Por exemplo, não é possível usar a biblioteca de solicitações do Python. No entanto, você pode usar ferramentas para fazer chamadas remotas indiretamente.
  • Os nomes de recursos convertidos em nomes Python precisam ser nomes Python válidos.
  • Os blocos de código não podem gravar parâmetros de sessão, a menos que ocorra uma transição de fluxo.

Ações inline

As ações inline se comportam de maneira semelhante às ações de ferramentas. Elas têm um esquema de entrada e saída definido, determinado pela assinatura da função Python, incluindo anotações de tipo e docstring. Assim como nas chamadas de ferramentas, o LLM não reconhece o código que implementa a ação.

Exemplo:

@Action
def is_prime(n: int) -> bool:
  """Returns true if n is prime."""
  if not isinstance(n, int) or n < 2:
    return False

  for i in range(2, int(n ** 0.5) + 1):
    if n % i == 0:
      return False

  return True

Para essa função, o LLM vai receber informações sobre a ação, a entrada e a saída.

Para fazer referência a uma ação inline nas instruções do playbook, basta referenciar o nome da ação entre acentos graves e descrever como ela deve ser usada.

Exemplo de uma ação inline place_order:

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

Para criar exemplos que usam ações inline, use o tipo de ferramenta inline-action na seção Entrada e saída.

Para mais informações, consulte a @Action documentação de referência.

Funções de acionamento

As funções de acionamento são usadas para definir ações condicionais no código.

As funções de acionamento são declaradas usando decoradores. É possível usar os seguintes decoradores de função de acionamento:

Decorador Parâmetros do decorador Descrição
@EventTrigger event: str, condition: str, em que a condição é opcional Acionado por um evento
@BeforeModelTrigger condition: str, em que a condição é opcional Acionado sempre antes que o LLM preveja a próxima ação.
@BeforeActionTrigger condition: str, em que a condição é opcional Acionado sempre antes que o LLM execute uma ação.
@BeforePlaybookTrigger condition: str, em que a condição é opcional Acionado na primeira vez que um playbook é iniciado.

Por exemplo, essas funções mostram como usar esses decoradores e parâmetros de decorador, além de como usar a função da biblioteca do sistema de blocos de código de resposta.

# 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 ☕")

Como referenciar fluxos, playbooks e ferramentas

No bloco de código, é possível referenciar fluxos, playbooks e ferramentas específicos usando as variáveis globais flows, playbooks, e tools.

Cada um desses objetos tem membros que correspondem aos nomes dos recursos correspondentes. Esses nomes precisam ser nomes Python válidos.

Exemplo:

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

Ao referenciar fluxos e playbooks em um bloco de código, você também precisa referenciá-los nas instruções do playbook com a seguinte sintaxe:

${RESOURCE_TYPE: my_resource_name}

Por exemplo, se o bloco de código contiver flows.myflow e playbooks.myplaybook, as instruções do playbook deverão incluir:

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

Substituições de ação

É possível usar blocos de código para criar uma fila de ações que ocorrerão antes de outras ações determinadas pelo LLM e, possivelmente, substituí-las. Para criar substituições de ação, use a add_override função global.

Todas as ações de substituição enfileiradas serão executadas sequencialmente, e a saída da ação estará disponível para o LLM. Quando a fila estiver vazia, a operação retornará ao LLM para seleção de ação e entrada, a menos que uma substituição termine a vez com respond ou outra função que conclua a vez.

Argumentos da função:

  • action: a ação a ser realizada. Para uma ação inline, use my_function_name. Para uma ação de ferramenta, use tools.my_tool_name.my_tool_action. Para uma ação de fluxo, use flows.my_flow_name.
  • inputs: entradas opcionais para a ação. Por exemplo: {"location": "Omaha"}.

Exemplos:

# 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)

Substituições de resposta

Semelhante às substituições de ação, mas especificamente para respostas de agentes, é possível usar a função global respond para forçar o agente a responder ao usuário com conteúdo específico.

Exemplo:

respond("Hello")

Chamada de ferramentas

Nas funções de bloco de código, é possível chamar as ferramentas definidas para o agente. Ao contrário de quando você substitui uma ação de ferramenta, quando você chama uma ferramenta diretamente, os resultados da execução da ferramenta não ficam disponíveis para o LLM.

Exemplos:

# 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"]

Intenção de correspondência

Os blocos de código podem corresponder programaticamente a uma intenção para um determinado fluxo usando a Flow.match_intent.

Exemplo:

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?")

Ler parâmetros de sessão

Os blocos de código podem ler parâmetros que estão disponíveis no momento da execução.

Exemplo:

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

Depuração

É possível usar o simulador para depurar as funções de bloco de código. Essas funções serão mostradas como ações no simulador e vão fornecer nossos detalhes conforme necessário.

Controle adicional

Este guia aborda alguns usos comuns da biblioteca do sistema de blocos de código. Para outros tipos de controle, consulte a documentação da biblioteca.