-
Notifications
You must be signed in to change notification settings - Fork 0
/
page.tsx
100 lines (90 loc) · 2.79 KB
/
page.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"use client";
import { FormEvent, useState } from "react";
import Together from "together-ai";
import { ChatCompletionStream } from "together-ai/lib/ChatCompletionStream";
export default function Chat() {
const [prompt, setPrompt] = useState("");
const [messages, setMessages] = useState<
Together.Chat.Completions.CompletionCreateParams.Message[]
>([]);
const [isPending, setIsPending] = useState(false);
async function handleSubmit(e: FormEvent<HTMLFormElement>) {
e.preventDefault();
setPrompt("");
setIsPending(true);
setMessages((messages) => [
...messages,
{
role: "user",
content: prompt,
},
]);
const res = await fetch("/api/chat", {
method: "POST",
body: JSON.stringify({
messages: [
...messages,
{
role: "user",
content: prompt,
},
],
}),
});
if (!res.body) return;
ChatCompletionStream.fromReadableStream(res.body)
.on("content", (delta, content) => {
setMessages((messages) => {
const lastMessage = messages.at(-1);
if (lastMessage?.role !== "assistant") {
return [...messages, { role: "assistant", content }];
} else {
return [...messages.slice(0, -1), { ...lastMessage, content }];
}
});
})
.on("end", () => {
setIsPending(false);
});
}
return (
<>
<div className="flex h-0 grow flex-col-reverse overflow-y-scroll">
<div className="space-y-4 py-8">
{messages.map((message, i) => (
<div key={i} className="mx-auto flex max-w-3xl">
{message.role === "user" ? (
<div className="ml-auto rounded-full bg-blue-500 px-4 py-2 text-white">
{message.content}
</div>
) : (
<div className="whitespace-pre-wrap">{message.content}</div>
)}
</div>
))}
</div>
</div>
<div className="mb-8 flex justify-center gap-2">
<form onSubmit={handleSubmit} className="flex w-full max-w-3xl">
<fieldset className="flex w-full gap-2">
<input
autoFocus
placeholder="Send a message"
required
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
className="block w-full rounded border border-gray-300 p-2 outline-black"
/>
<button
className="rounded bg-black px-3 py-1 font-medium text-white outline-offset-[3px] outline-black disabled:opacity-50"
type="submit"
disabled={isPending}
>
Submit
</button>
</fieldset>
</form>
</div>
</>
);
}