View Source Streaming Orderbot
Mix.install([
{:openai_ex, "~> 0.2.2"},
{:kino, "~> 0.10.0"}
])
alias OpenaiEx
alias OpenaiEx.ChatCompletion
alias OpenaiEx.ChatMessage
setup
Setup
This notebook creates an Orderbot, similar to the one in Deeplearning.AI Orderbot, but using the streaming version of the Chat Completion API.
openai = System.fetch_env!("LB_OPENAI_API_KEY") |> OpenaiEx.new()
defmodule OpenaiEx.Notebooks.StreamingOrderbot do
alias OpenaiEx
alias OpenaiEx.ChatCompletion
def create_chat_req(args = [_ | _]) do
args
|> Enum.into(%{
model: "gpt-3.5-turbo",
temperature: 0
})
|> ChatCompletion.new()
end
def get_completion_stream(openai = %OpenaiEx{}, cc_req = %{}) do
openai
|> ChatCompletion.create(cc_req, stream: true)
|> Stream.flat_map(& &1)
|> Stream.map(fn %{data: d} -> d |> Map.get("choices") |> Enum.at(0) |> Map.get("delta") end)
|> Stream.filter(fn map -> map |> Map.has_key?("content") end)
|> Stream.map(fn map -> map |> Map.get("content") end)
end
def stream_completion_to_frame(openai = %OpenaiEx{}, messages, frame) do
openai
|> get_completion_stream(create_chat_req(messages: messages))
|> Enum.reduce("", fn token, text ->
next = text <> token
Kino.Frame.render(frame, Kino.Text.new(next))
next
end)
end
def create_orderbot(openai = %OpenaiEx{}, context) do
chat_frame = Kino.Frame.new()
last_frame = Kino.Frame.new()
inputs = [prompt: Kino.Input.textarea("You")]
form = Kino.Control.form(inputs, submit: "Send", reset_on_submit: [:prompt])
Kino.Frame.render(chat_frame, Kino.Markdown.new("### Orderbot Chat"))
Kino.Layout.grid([chat_frame, last_frame, form], boxed: true, gap: 16) |> Kino.render()
bot_says = openai |> stream_completion_to_frame(context, last_frame)
Kino.listen(
form,
context ++ [ChatMessage.assistant(bot_says)],
fn %{data: %{prompt: you_say}}, history ->
Kino.Frame.render(last_frame, Kino.Text.new(""))
Kino.Frame.append(chat_frame, Kino.Text.new(List.last(history).content))
Kino.Frame.append(chat_frame, Kino.Markdown.new("**You** #{you_say}"))
bot_says =
openai |> stream_completion_to_frame(history ++ [ChatMessage.user(you_say)], last_frame)
{:cont, history ++ [ChatMessage.user(you_say), ChatMessage.assistant(bot_says)]}
end
)
end
end
alias OpenaiEx.Notebooks.StreamingOrderbot
orderbot
Orderbot
context = [
ChatMessage.system("""
You are OrderBot, an automated service to collect orders for a pizza restaurant. \
You first greet the customer, then collects the order, \
and then asks if it's a pickup or delivery. \
You wait to collect the entire order, then summarize it and check for a final \
time if the customer wants to add anything else. \
If it's a delivery, you ask for an address. \
Finally you collect the payment.\
Make sure to clarify all options, extras and sizes to uniquely \
identify the item from the menu.\
You respond in a short, very conversational friendly style. \
The menu includes \
pepperoni pizza 12.95, 10.00, 7.00 \
cheese pizza 10.95, 9.25, 6.50 \
eggplant pizza 11.95, 9.75, 6.75 \
fries 4.50, 3.50 \
greek salad 7.25 \
Toppings: \
extra cheese 2.00, \
mushrooms 1.50 \
sausage 3.00 \
canadian bacon 3.50 \
AI sauce 1.50 \
peppers 1.00 \
Drinks: \
coke 3.00, 2.00, 1.00 \
sprite 3.00, 2.00, 1.00 \
bottled water 5.00 \
""")
]
openai |> StreamingOrderbot.create_orderbot(context)