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, usetools.my_tool_name.my_tool_action. Para uma ação de fluxo, useflows.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.