Tabla de contenidos

Introducción

Los grandes modelos lingüísticos (LLM), al igual que las interfaces de usuario conversacionales en general, son eficientes a la hora de recibir datos altamente desestructurados en forma de lenguaje natural conversacional. A continuación, estos datos desestructurados se estructuran, se procesan y, posteriormente, se vuelven a desestructurar en forma de salida de lenguaje natural de la mano de OpenAI.

OpenAI Function Calling estructura la salida para el consumo de la máquina en forma de API, en oposición al consumo humano en forma de lenguaje natural no estructurado.

Llamada a funciones

Con la llamada a la API, puede proporcionar funciones a gpt-3.5-turbo-0613 y gpt-4-0613, y hacer que el modelo genere de forma inteligente un objeto JSON con argumentos que, a su vez, puedes utilizar para llamar a la función en tu código.

La API de finalización de chat no llama directamente a la función, sino que genera un documento JSON que puedes utilizar en tu código.

Más información sobre OpenAI Function Calling aquí.

Con OpenAI Function Calling, la atención se centra en la salida JSON.

OpenAI

He aquí tres ejemplos prácticos de llamada a funciones:

Crear chatbots que respondan a preguntas llamando a API externas:

En este ejemplo, se compila un correo electrónico con algunos campos definidos, que deben rellenarse a partir de la entrada de lenguaje natural.

Si el documento JSON no se define correctamente, el modelo OpenAI generará un error. Por lo tanto, existe un nivel de rigidez en cuanto a la definición de la estructura JSON que debe rellenarse.

pip install openai

import os
import openai
import requests
import json
openai.api_key = «xxxxxxxxxxxxxxxxxx»


url = «https://api.openai.com/v1/chat/completions»
payload = json.dumps({
«model»: «gpt-4-0613»,
«messages»: [
{
«role»: «user»,
«content»: «Send Cobus from HumanFirst AI an email and ask him for the sales forecast spreadsheet. Schedule the mail for tomorrow at 12 noon.»
}
],
«functions»: [
{
«name»: «send_email»,
«description»: «template to have an email sent.»,
«parameters»: {
«type»: «object»,
«properties»: {
«to_address»: {
«type»: «string»,
«description»: «To address for email»
},
«body»: {
«type»: «string»,
«description»: «Body of the email»
},
«date»: {
«type»: «string»,
«description»: «the date the email must be sent.»
},
«time»: {
«type»: «string»,
«description»: «the time the email must be sent.»
}
}
}
}
]
})
headers = {
‘Content-Type’: ‘application/json’,
‘Authorization’: ‘Basic xxxxxxxxxxxx’
}

response = requests.request(«POST», url, headers=headers, data=payload)

print(response.text)

Y la respuesta de la modelo:

{
"id": "chatcmpl-7RjMh7I0rVmCJkTCk4wvHDSNg8uQQ",
"object": "chat.completion",
"created": 1686843595,
"model": "gpt-4-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"function_call": {
"name": "send_email",
"arguments": "{\n \"to_address\": \"Cobus@HumanFirst.ai\",\n \"body\": \"Hello Cobus, \\n\\nCould you please provide the sales forecast spreadsheet? \\n\\nBest Regards\",\n \"date\": \"tomorrow\",\n \"time\": \"12 noon\"\n}"
}
},
"finish_reason": "function_call"
}
],
"usage": {
"prompt_tokens": 118,
"completion_tokens": 65,
"total_tokens": 183
}
}

Convierte el lenguaje natural no estructurado en llamadas a la API:

En este ejemplo, un pedido se convierte en una estructura JSON con fecha, notas, tipo de pedido, dirección de entrega, etc.


url = "https://api.openai.com/v1/chat/completions"
payload = json.dumps({
"model": "gpt-4-0613",
"messages": [
{
"role": "user",
"content": "I would like to order two packs of cans, and have it delivered to 22 Fourth Avenue, Woodlands. I need this on the 27th of July. Just leave the order at the door, we live in a safe area."
}
],
"functions": [
{
"name": "order_detail",
"description": "template to capture an order.",
"parameters": {
"type": "object",
"properties": {
"to_address": {
"type": "string",
"description": "To address for the delivery"
},
"order": {
"type": "string",
"description": "The detail of the order"
},
"date": {
"type": "string",
"description": "the date for delivery."
},
"notes": {
"type": "string",
"description": "Any delivery notes."
}
}
}
}
]
})
headers = {
'Content-Type': 'application/json',
'Authorization': 'Basic xxxxxxxxxxx'
}

response = requests.request(«POST», url, headers=headers, data=payload)

 

print(response.text)

Y la respuesta:

{
"id": "chatcmpl-7RjQA8bEiPVRwh72gNUFouBq6urjo",
"object": "chat.completion",
"created": 1686843810,
"model": "gpt-4-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"function_call": {
"name": "order_detail",
"arguments": "{\n \"to_address\": \"22 Fourth Avenue, Woodlands\",\n \"order\": \"two packs of cans\",\n \"date\": \"27th of July\",\n \"notes\": \"Just leave the order at the door, we live in a safe area.\"\n}"
}
},
"finish_reason": "function_call"
}
],
"usage": {
"prompt_tokens": 132,
"completion_tokens": 61,
"total_tokens": 193
}
}

Extraer datos estructurados a partir de texto:

Este ejemplo final tiene una lista de nombres y cumpleaños, que necesita ser estructurada en JSON. Algo que encontré interesante, es que el modelo no itera a través de los nombres y fechas.

Sólo el primer nombre y la fecha se coloca dentro de la JSON, por lo tanto, el conjunto de datos no se reconoce y se itera a través.

url = «https://api.openai.com/v1/chat/completions»
payload = json.dumps({
«model»: «gpt-4-0613»,
«messages»: [
{
«role»: «user»,
«content»: «John has a birthday on 5 April and Adam has his on the 1 September, Elli is 24 December, Robert has his birthday on 6 March and lastly Adam is 15 April.»}
],
«functions»: [
{
«name»: «birthdays»,
«description»: «create a document of names and birthdays of 5 people»,
«parameters»: {
«type»: «object»,
«properties»: {
«name»: {
«type»: «string»,
«description»: «The name of the person»
},
«birthday»: {
«type»: «string»,
«description»: «and the date of the their birthday»
}
}
}
}
]
})
headers = {
‘Content-Type’: ‘application/json’,
‘Authorization’: ‘Basic xxxxxxxxxxxx’
}

response = requests.request(«POST», url, headers=headers, data=payload)

print(response.text)

Y el resultado:

{
«id»: «chatcmpl-7RjYzH9XaSAQ3Qn6X5j11J77vBGQX»,
«object»: «chat.completion»,
«created»: 1686844357,
«model»: «gpt-4-0613»,
«choices»: [
{
«index»: 0,
«message»: {
«role»: «assistant»,
«content»: null,
«function_call»: {
«name»: «birthdays»,
«arguments»: «{ \»name\»: \»John\», \»birthday\»: \»5 April\» }»
}
},
«finish_reason»: «function_call»
}
],
«usage»: {
«prompt_tokens»: 111,
«completion_tokens»: 21,
«total_tokens»: 132
}
}

En conclusión

Hay algunas consideraciones, sin embargo:

      1. Programáticamente, el chatbot/UI conversacional tendrá que saber que la salida al LLM debe estar en formato JSON. Por lo tanto, tendrá que haber algún tipo de clasificación o reconocimiento de intención para detectar que el tipo de salida debe ser JSON.

      1. Deberá existir y definirse una plantilla predefinida para la entrada al LLM de finalización. Como se ve en los ejemplos, la plantilla JSON guía al LLM sobre cómo rellenar los valores.

      1. Y lo que es más importante, como se ve en los ejemplos, los parámetros que deben rellenarse deben estar bien definidos. Un fallo produce el siguiente error: “We could not parse the JSON body of your request. (HINT: This likely means you aren’t using your HTTP library correctly. The OpenAI API expects a JSON payload, but what was sent was not valid JSON. If you have trouble figuring out how to fix this, please contact us through our help center at help.openai.com.)”

     Sígueme en LinkedIn para estar al día sobre la IA conversacional 

    Actualmente soy el Evangelista Jefe @ HumanFirst. Exploro y escribo sobre todas las cosas en la intersección de la IA y el lenguaje; que van desde LLMs, Chatbots, Voicebots, marcos de desarrollo, espacios latentes centrados en datos y más.

    Por Cobus Greyling

    Rasa Hero. NLP / NLU, Chatbots, Voz, UI / UX conversacional, Diseñador CX, Desarrollador, Interfaces de usuario ubicuas.

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *