Quando definisci un playbook, puoi facoltativamente fornire blocchi di codice, ovvero codice Python incorporato che può essere utilizzato per controllare meglio il comportamento dell'agente. Questo codice è costituito da funzioni con decoratori speciali e da tutte le funzioni di utilità di cui hai bisogno.
Quando scrivi il codice, puoi utilizzare la libreria di sistema dei blocchi di codice per controllare il comportamento dell'agente.
Limitazioni
Si applicano le seguenti limitazioni:
- I blocchi di codice non possono contenere oggetti che mantengono 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 di richieste Python. Tuttavia, puoi utilizzare gli strumenti per effettuare chiamate remote indirettamente.
- I nomi delle risorse convertiti in nomi Python devono essere nomi Python validi.
- I blocchi di codice non possono scrivere parametri di sessione, a meno che non avvenga una transizione di flusso.
Azioni in linea
Le azioni in linea si comportano in modo simile alle azioni degli strumenti. Hanno uno schema di input e output definito, determinato dalla firma della funzione Python, incluse le annotazioni dei tipi e la docstring. Analogamente alle chiamate degli 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."""
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
Per questa funzione, l'LLM riceverà informazioni sull'azione, sul suo input e sul suo output.
Per fare riferimento a un'azione incorporata nelle istruzioni del playbook, basta fare riferimento al nome dell'azione tra apici inversi e descrivere come deve essere utilizzata.
Esempio di 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 incorporate, utilizza il tipo di strumento inline-action nella sezione Input e output.
Per saperne di più, consulta la documentazione di riferimento di @Action.
Attiva le funzioni
Le funzioni di attivazione vengono utilizzate per definire le azioni condizionali nel codice.
Le funzioni di attivazione vengono dichiarate utilizzando i decoratori. Puoi utilizzare i seguenti decoratori delle funzioni di attivazione:
| 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 |
Si attiva la prima volta che viene avviato un playbook. |
Ad esempio, queste funzioni mostrano come utilizzare questi decoratori e i relativi parametri, nonché come utilizzare la funzione della 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 validi.
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 fare riferimento anche alle 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 dall'LLM, con la possibilità di eseguirne l'override. Puoi creare 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 l'LLM. Una volta svuotata la coda, l'operazione torna all'LLM per la selezione dell'azione e dell'input, a meno che un override non termini il turno con respond o un'altra funzione che completa il turno.
Argomenti della funzione:
- action: 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. - inputs: 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 delle risposte
Analogamente 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")
Chiamata degli strumenti
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 uno strumento direttamente, 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"]
Intent di corrispondenza
I blocchi di codice possono trovare in modo programmatico 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?")
Leggi i parametri di sessione
I blocchi di codice possono leggere i parametri disponibili al momento dell'esecuzione.
Esempio:
state["$session.params.my-param"]
state["$request.session-id"]
Debug
Puoi utilizzare il simulatore per eseguire il debug delle funzioni dei blocchi di codice. Queste funzioni verranno visualizzate come azioni nel simulatore e forniranno i dettagli necessari.
Controllo aggiuntivo
Questa guida illustra alcuni usi comuni della libreria di sistema dei blocchi di codice. Per altri tipi di controllo, consulta la documentazione della libreria.