Update title and reformat with prettier

This commit is contained in:
simonpfish 2023-10-17 13:15:23 -07:00
parent ec414ee67b
commit 6d3db1374b
2 changed files with 130 additions and 123 deletions

View File

@ -1,4 +1,4 @@
# How to build an agent with the Node.js SDK and function-calling
# How to build an agent with the Node.js SDK
OpenAI functions enable your app to take action based on user inputs. This means that it can, e.g., search the web, send emails, or book tickets on behalf of your users, making it more powerful than a regular chatbot.
@ -27,12 +27,12 @@ internal knowledge to suggest suitable local activities for you.
We start by importing the OpenAI SDK at the top of our JavaScript file and authenticate with our API key, which we have stored as an environment variable.
``` js
```js
import OpenAI from "openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
dangerouslyAllowBrowser: true
apiKey: process.env.OPENAI_API_KEY,
dangerouslyAllowBrowser: true,
});
```
@ -44,11 +44,11 @@ Next, we'll create the two functions. The first one - `getLocation` -
uses the [IP API](https://ipapi.co/) to get the location of the
user.
``` js
```js
async function getLocation() {
const response = await fetch('https://ipapi.co/json/');
const locationData = await response.json();
return locationData;
const response = await fetch("https://ipapi.co/json/");
const locationData = await response.json();
return locationData;
}
```
@ -58,12 +58,12 @@ function `getCurrentWeather`. It uses the [Open Meteo
API](https://open-meteo.com/) to get the current weather data, like
this:
``` js
```js
async function getCurrentWeather(latitude, longitude) {
const url = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=apparent_temperature`;
const response = await fetch(url);
const weatherData = await response.json();
return weatherData;
const url = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=apparent_temperature`;
const response = await fetch(url);
const weatherData = await response.json();
return weatherData;
}
```
@ -74,33 +74,33 @@ describe them using a specific schema. We'll create an array called
`functionDefinitions` that contains one object per function. Each object
will have three keys: `name`, `description`, and `parameters`.
``` js
```js
const functionDefinitions = [
{
name: "getCurrentWeather",
description: "Get the current weather in a given location",
parameters: {
type: "object",
properties: {
longitude: {
type: "string",
},
latitude: {
type: "string",
}
},
required: ["longitude", "latitude"]
}
{
name: "getCurrentWeather",
description: "Get the current weather in a given location",
parameters: {
type: "object",
properties: {
longitude: {
type: "string",
},
latitude: {
type: "string",
},
},
required: ["longitude", "latitude"],
},
{
name: "getLocation",
description: "Get the user's location based on their IP address",
parameters: {
type: "object",
properties: {}
}
}
]
},
{
name: "getLocation",
description: "Get the user's location based on their IP address",
parameters: {
type: "object",
properties: {},
},
},
];
```
## Setting up the messages array
@ -108,15 +108,17 @@ const functionDefinitions = [
We also need to define a `messages` array. This will keep track of all of the messages back and forth between our app and OpenAI.
The first object in the array should always have the `role` property set to `"system"`, which tells OpenAI that this is how we want it to behave.
``` js
const messages = [{
```js
const messages = [
{
role: "system",
content: "You are a helpful assistant. Only use the functions you have been provided with."
}];
content:
"You are a helpful assistant. Only use the functions you have been provided with.",
},
];
```
## Creating the agent function
We are now ready to build the logic of our app, which lives in the
@ -125,18 +127,20 @@ We are now ready to build the logic of our app, which lives in the
We start by pushing the `userInput` to the messages array. This time, we set the `role` to `"user"`, so that OpenAI knows that this is the input from the user.
``` js
```js
async function agent(userInput) {
messages.push([{
messages.push([
{
role: "user",
content: userInput,
}]);
const response = await openai.chat.completions.create({
model: "gpt-4",
messages: messages,
functions: functionDefinitions
});
console.log(response);
},
]);
const response = await openai.chat.completions.create({
model: "gpt-4",
messages: messages,
functions: functionDefinitions,
});
console.log(response);
}
```
@ -145,27 +149,26 @@ Next, we'll send a request to the Chat completions endpoint via the
configuration object as an argument. In it, we'll specify three
properties:
- `model` - Decides which AI model we want to use (in our case,
GPT-4).
- `messages` - The entire history of messages between the user and the
AI up until this point.
- `functions` - A description of the functions our app has access to.
Here, we'll we use the `functionDefinitions` array we created
earlier.
- `model` - Decides which AI model we want to use (in our case,
GPT-4).
- `messages` - The entire history of messages between the user and the
AI up until this point.
- `functions` - A description of the functions our app has access to.
Here, we'll we use the `functionDefinitions` array we created
earlier.
## Running our app with a simple input
Let's try to run the `agent` with an input that requires a function call to give a suitable reply.
``` js
```js
agent("Where am I located right now?");
```
When we run the code above, we see the response from OpenAI logged out
to the console like this:
``` js
```js
{
id: "chatcmpl-84ojoEJtyGnR6jRHK2Dl4zTtwsa7O",
object: "chat.completion",
@ -203,10 +206,10 @@ Now that we have the name of the function as a string, we'll need to
translate that into a function call. To help us with that, we'll gather
both of our functions in an object called `availableFunctions`:
``` js
```js
const availableFunctions = {
getCurrentWeather,
getLocation
getCurrentWeather,
getLocation,
};
```
@ -214,17 +217,16 @@ This is handy because we'll be able to access the `getLocation` function
via bracket notation and the string we got back from OpenAI, like this:
`availableFunctions["getLocation"]`.
``` js
```js
const { finish_reason, message } = response.choices[0];
if (finish_reason === "function_call") {
const functionName = message.function_call.name;
const functionToCall = availableFunctions[functionName];
const functionArgs = JSON.parse(message.function_call.arguments);
const functionArgsArr = Object.values(functionArgs);
const functionResponse = await functionToCall.apply(null, functionArgsArr);
console.log(functionResponse);
const functionName = message.function_call.name;
const functionToCall = availableFunctions[functionName];
const functionArgs = JSON.parse(message.function_call.arguments);
const functionArgsArr = Object.values(functionArgs);
const functionResponse = await functionToCall.apply(null, functionArgsArr);
console.log(functionResponse);
}
```
@ -232,25 +234,26 @@ We're also grabbing ahold of any arguments OpenAI wants us to pass into
the function: `message.function_call.arguments`.
However, we won't need any arguments for this first function call.
If we run the code again with the same input
(`"Where am I located right now?"`), we'll see that `functionResponse`
is an object filled with location about where the user is located right
now. In my case, that is Oslo, Norway.
``` js
```js
{ip: "193.212.60.170", network: "193.212.60.0/23", version: "IPv4", city: "Oslo", region: "Oslo County", region_code: "03", country: "NO", country_name: "Norway", country_code: "NO", country_code_iso3: "NOR", country_capital: "Oslo", country_tld: ".no", continent_code: "EU", in_eu: false, postal: "0026", latitude: 59.955, longitude: 10.859, timezone: "Europe/Oslo", utc_offset: "+0200", country_calling_code: "+47", currency: "NOK", currency_name: "Krone", languages: "no,nb,nn,se,fi", country_area: 324220, country_population: 5314336, asn: "AS2119", org: "Telenor Norge AS"}
```
We'll add this data to a new item in the `messages` array, where we also
specify the name of the function we called.
``` js
```js
messages.push({
role: "function",
name: functionName,
content: `The result of the last function was this: ${JSON.stringify(functionResponse)}
`
content: `The result of the last function was this: ${JSON.stringify(
functionResponse
)}
`,
});
```
@ -279,31 +282,32 @@ the next iteration of the loop, triggering a new request.
If we get `finish_reason: "stop"` back, then GPT has found a suitable
answer, so we'll return the function and cancel the loop.
``` js
```js
for (let i = 0; i < 5; i++) {
const response = await openai.chat.completions.create({
model: "gpt-4",
messages: messages,
functions: functionDefinitions
model: "gpt-4",
messages: messages,
functions: functionDefinitions,
});
const { finish_reason, message } = response.choices[0];
if (finish_reason === "function_call") {
const functionName = message.function_call.name;
const functionToCall = availableFunctions[functionName];
const functionArgs = JSON.parse(message.function_call.arguments);
const functionArgsArr = Object.values(functionArgs);
const functionResponse = await functionToCall.apply(null, functionArgsArr);
const functionName = message.function_call.name;
const functionToCall = availableFunctions[functionName];
const functionArgs = JSON.parse(message.function_call.arguments);
const functionArgsArr = Object.values(functionArgs);
const functionResponse = await functionToCall.apply(null, functionArgsArr);
messages.push({
role: "function",
name: functionName,
content: `
The result of the last function was this: ${JSON.stringify(functionResponse)}
`
});
} else if (finish_reason === "stop") {
messages.push({
role: "function",
name: functionName,
content: `
The result of the last function was this: ${JSON.stringify(
functionResponse
)}
`,
});
} else if (finish_reason === "stop") {
messages.push(message);
return message.content;
}
@ -319,14 +323,16 @@ we'll return a message saying we couldnt find a suitable answer.
At this point, we are ready to try our app! I'll ask the agent to
suggest some activities based on my location and the current weather.
``` js
const response = await agent("Please suggest some activities based on my location and the current weather.");
```js
const response = await agent(
"Please suggest some activities based on my location and the current weather."
);
console.log(response);
```
Here's what we see in the console (formatted to make it easier to read):
``` js
```js
Based on your current location in Oslo, Norway and the weather (15°C and snowy),
here are some activity suggestions:
@ -349,7 +355,7 @@ to call the `getCurrentWeather` function with
`"longitude": "10.859", "latitude": "59.955"` passed in as the
arguments. This is data it got back from the first function call we did.
``` js
```js
{role: "assistant", content: null, function_call: {name: "getLocation", arguments: "{}"}}
{role: "assistant", content: null, function_call: {name: "getCurrentWeather", arguments: " { "longitude": "10.859", "latitude": "59.955" }"}}
```

View File

@ -1029,13 +1029,14 @@
- tiktoken
- completions
- title: How to build an agent with the Node.js SDK and function-calling
- title: How to build an agent with the Node.js SDK
path: examples/How_to_build_an_agent_with_the_node_sdk.md
date: 2023-10-05
authors:
- perborgen
tags:
- completions
- functions
- title: What makes documentation good
path: articles/what_makes_documentation_good.md