Quando definisci un playbook, puoi fornire facoltativamente blocchi di codice, ovvero codice Python incorporato che può essere utilizzato per controllare meglio il comportamento dell'agente. Questo codice è composto da funzioni con decoratori speciali e da tutte le funzioni di utilità necessarie.
Quando scrivi il codice, puoi utilizzare la libreria di sistema dei blocchi di codice per controllare il comportamento dell'agente.
Problemi noti
Si applicano i seguenti problemi noti:
- I progetti nei perimetri VPC-SC che limitano l'accesso ad Artifact Registry rifiuteranno anche i deployment di Code Block.
Limitazioni
Si applicano le seguenti limitazioni:
- I blocchi di codice non possono contenere oggetti che persistono i dati. Tuttavia, puoi utilizzare strumenti per rendere persistenti i dati e mantenere lo stato.
- I blocchi di codice non possono effettuare chiamate remote direttamente. Ad esempio, non puoi utilizzare la libreria requests di Python. Tuttavia, puoi utilizzare strumenti per effettuare chiamate da remoto indirettamente.
- I nomi delle risorse convertiti in nomi Python devono essere nomi Python legali.
- I blocchi di codice non possono leggere o scrivere i parametri di sessione, a meno che non avvenga una transizione del flusso.
Azioni in linea
Le azioni in linea si comportano in modo simile alle azioni dei tool. Hanno uno schema di input e output definito, che è determinato dalla firma della funzione Python, incluse le annotazioni di tipo e la docstring. Analogamente alle chiamate di strumenti, l'LLM non è a conoscenza del codice che implementa l'azione.
Esempio:
@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)
Per questa funzione, al LLM verranno fornite informazioni sull'azione, sul suo input e sul suo output.
Per fare riferimento a un'azione in linea nelle istruzioni del playbook, basta fare riferimento al nome dell'azione tra apici inversi e descrivere come deve essere utilizzata.
Esempio per un'azione in linea place_order
:
Take the customer's order, then call the `place_order` action when the order is ready.
Per creare esempi che utilizzano azioni in linea, utilizza il tipo di strumento inline-action nella sezione Input e output.
Per saperne di più, consulta la documentazione di riferimento di@Action.
Funzioni di attivazione
Le funzioni di attivazione vengono utilizzate per definire azioni condizionali nel codice.
Le funzioni di trigger vengono dichiarate utilizzando i decoratori. Puoi utilizzare i seguenti decoratori di funzioni di trigger:
Decoratore | Parametri del decoratore | Descrizione |
---|---|---|
@EventTrigger | event: str, condition: str , dove la condizione è facoltativa |
Attivato da un evento |
@BeforeModelTrigger | condition: str , dove la condizione è facoltativa |
Attivato ogni volta prima che l'LLM preveda l'azione successiva. |
@BeforeActionTrigger | condition: str , dove la condizione è facoltativa |
Attivato ogni volta prima che l'LLM esegua un'azione. |
@BeforePlaybookTrigger | condition: str , dove la condizione è facoltativa |
Attivato al primo avvio di un playbook. |
Ad esempio, queste funzioni mostrano come utilizzare questi decoratori e i parametri dei decoratori, nonché come utilizzare la funzione di libreria di sistema del blocco di codice 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 ☕")
Riferimenti a flussi, playbook e strumenti
Nel blocco di codice, puoi fare riferimento a flussi, playbook e strumenti specifici utilizzando le variabili globali flows, playbooks e tools.
Ognuno di questi oggetti ha membri che corrispondono ai nomi delle risorse corrispondenti. Questi nomi devono essere nomi Python legali.
Esempio:
add_override(playbooks.troubleshooting, {})
add_override(flows.billing)
add_override(tools.weather_api.get_weather, {"location": "San Francisco"})
Quando fai riferimento a flussi e playbook in un blocco di codice, devi farvi riferimento anche nelle istruzioni del playbook con la seguente sintassi:
${RESOURCE_TYPE: my_resource_name}
Ad esempio,
se il blocco di codice contiene flows.myflow
e playbooks.myplaybook
,
le istruzioni del playbook devono includere:
${FLOW: myflow}
${PLAYBOOK: myplaybook}
Override delle azioni
Puoi utilizzare i blocchi di codice per creare una coda di azioni che verranno eseguite prima di qualsiasi altra azione determinata dal LLM e potenzialmente sostituirle. Crea override delle azioni utilizzando la funzione globale add_override.
Tutte le azioni di override in coda verranno eseguite in sequenza e l'output dell'azione sarà disponibile per il LLM. Una volta vuota, la coda torna all'LLM per l'azione e la selezione dell'input, a meno che un override non termini il turno con respond o un'altra funzione che completa il turno.
Argomenti della funzione:
- azione: l'azione da eseguire.
Per un'azione in linea, utilizza
my_function_name
. Per un'azione dello strumento, utilizzatools.my_tool_name.my_tool_action
. Per un'azione di flusso, utilizzaflows.my_flow_name
. - input: input facoltativi per l'azione.
Ad esempio:
{"location": "Omaha"}
.
Esempi:
# 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)
Override della risposta
Simile agli override delle azioni, ma specificamente per le risposte dell'agente, puoi utilizzare la funzione globale respond per forzare l'agente a rispondere all'utente con contenuti specifici.
Esempio:
respond("Hello")
Strumenti di chiamata
Nelle funzioni del blocco di codice, puoi chiamare gli strumenti definiti per l'agente. A differenza di quando esegui l'override di un'azione dello strumento, quando chiami direttamente uno strumento, i risultati dell'esecuzione dello strumento non sono disponibili per l'LLM.
Esempi:
# 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"]
Intenzione di corrispondenza
I blocchi di codice possono corrispondere in modo programmatico a un intent per un determinato flusso utilizzando la funzione Flow.match_intent.
Esempio:
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?")
Debug
Puoi utilizzare il simulatore per eseguire il debug delle funzioni del blocco di codice. Queste funzioni verranno mostrate come azioni nel simulatore e forniranno i nostri dettagli in base alle necessità.
Controllo aggiuntivo
Questa guida illustra alcuni utilizzi comuni della libreria di sistema dei blocchi di codice. Per altri tipi di controllo, consulta la documentazione della libreria.