Created
January 21, 2024 01:40
-
-
Save shelling/118e44b2de0f5f193b11231adbd807cd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { readFileSync } from 'fs' | |
import OpenAI from 'openai'; | |
import { ChatCompletionMessageParam } from 'openai/resources/chat'; | |
import inquirer from 'inquirer'; | |
import input from '@inquirer/input'; | |
import { | |
Product, | |
LineItem, | |
Card, | |
} from './types'; | |
import { | |
searchItem, | |
addToCart, | |
removeFromCart, | |
updateItemInCart, | |
listCart, | |
checkout, | |
payment, | |
goodbye, | |
} from './functions'; | |
import { tools } from './tools'; | |
const menu: Product[] = JSON.parse(readFileSync("./menu.json", 'utf-8')).map((item: any) => ({ name: item.english, price: item.price })); | |
const cart: LineItem[] = []; | |
(async () => { | |
const openai: OpenAI = new OpenAI({ | |
apiKey: process.apiKey, | |
}); | |
const greeting = "What can I do for you today?"; | |
const messages: ChatCompletionMessageParam[] = [ | |
{ | |
role: "system", | |
content: `You are a restaurant cashier taking order from customers. identify available items and place orders for customers. If the item is not avilable, tell customers. Available items are ${JSON.stringify(menu)}.`, | |
}, | |
{ | |
role: 'assistant', | |
content: greeting, | |
}, | |
{ | |
role: 'user', | |
content: await input({ message: greeting }), | |
}, | |
] | |
while (true) { | |
const completions = await openai.chat.completions.create({ | |
model: "gpt-3.5-turbo", | |
messages: messages, | |
tools: tools, | |
tool_choice: "auto", | |
}); | |
console.log(`completion: ${JSON.stringify(completions, null, 2)}`) | |
const message = completions.choices[0].message | |
messages.push(message) | |
if (message.tool_calls) { | |
// console.log(JSON.stringify(message, null, 2)); | |
let invoked: number = 0; | |
message.tool_calls.map((tool_call: any) => { | |
switch (tool_call.function.name) { | |
case "addToCart": { | |
console.log(JSON.stringify(tool_call)); | |
const item = JSON.parse(tool_call.function.arguments).item; | |
const response = addToCart(item, cart, menu); | |
messages.push({ | |
tool_call_id: tool_call.id, | |
role: 'tool', | |
content: JSON.stringify(response), | |
}); | |
invoked += 1; | |
break; | |
} | |
case "removeFromCart": { | |
const item = JSON.parse(tool_call.function.arguments).item; | |
const removed = removeFromCart(item, cart); | |
messages.push({ | |
tool_call_id: tool_call.id, | |
role: 'tool', | |
content: JSON.stringify({ status: 200, body: { removed, description: "successfully removed" } }), | |
}); | |
invoked += 1; | |
break; | |
} | |
case "updateItemInCart": { | |
const { item, quantity } = JSON.parse(tool_call.function.arguments); | |
// console.log("udpate ", item, quantity); | |
const updated = updateItemInCart(item, quantity, cart); | |
messages.push({ | |
tool_call_id: tool_call.id, | |
role: 'tool', | |
content: JSON.stringify({ status: 200, body: { updated, description: "successfully updated" } }), | |
}) | |
invoked += 1; | |
break; | |
} | |
case "listCart": { | |
// console.log(JSON.stringify(cart, null, 2)); | |
messages.push({ | |
tool_call_id: tool_call.id, | |
role: 'tool', | |
content: JSON.stringify({ status: 200, body: listCart(cart) }), | |
}) | |
invoked += 1; | |
break; | |
} | |
case "checkout": { | |
// console.log(tool_call.function.arguments + " in checkout"); | |
// console.log(JSON.stringify(cart, null, 2)); | |
checkout(cart); | |
const total = cart.map((lineItem: LineItem) => (lineItem.price * lineItem.quantity)).reduce((a: number, b: number) => (a + b), 0); | |
messages.push({ | |
tool_call_id: tool_call.id, | |
role: 'tool', | |
content: JSON.stringify({ status: 200, body: { total: total, prompt: "cart has been sent to kitchen, ask customers card number to pay"} }), | |
}); | |
invoked += 1; | |
break; | |
} | |
case "payment": { | |
// console.log(tool_call.function.arguments + " in payment"); | |
const { number, expiration, cvv } = JSON.parse(tool_call.function.arguments); | |
const response = payment(number, expiration, cvv); | |
messages.push({ | |
tool_call_id: tool_call.id, | |
role: 'tool', | |
content: JSON.stringify({ status: 200, body: response }), | |
}); | |
invoked += 1; | |
break; | |
} | |
case "searchItem": { | |
// console.log(tool_call.function.arguments); | |
const result = searchItem(JSON.parse(tool_call.function.arguments).item, menu); | |
messages.push({ | |
tool_call_id: tool_call.id, | |
role: 'tool', | |
content: JSON.stringify({ status: 200, body: result}), | |
}); | |
invoked += 1; | |
break; | |
} | |
case "goodbye": { | |
// console.log(tool_call.function.arguments + " in goodbye"); | |
input({ message: "thank you for dining with us. enjoy your meal!\n" }).then(() => { process.exit(0) }); | |
break; | |
} | |
} | |
// console.log(JSON.stringify(messages, null, 2)); | |
}) | |
if (invoked == 0) { | |
messages.push({ | |
tool_call_id: message.tool_calls[0].id, | |
role: 'tool', | |
content: JSON.stringify({ status: 400, body: "sorry, function is not available" }), | |
}) | |
} | |
} else { | |
const assistantMessage: string = message.content as string; | |
const userMessage = await input({ message: assistantMessage }); | |
messages.push({ role: 'user', content: userMessage }); | |
} | |
} | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment