ChatGPT의 OpenAI Api를 활용해 간단한 챗봇을 만들어 보았다.
OpenAi에서 API Key를 발급받았다는 전제 하에 작성되었습니다.
⌨️ API key는 dovenv를 활용
const openAiKey = process.env.REACT_APP_OPENAI_API_KEY;
type.ts
⌨️ ChatGPT와의 대화 내용을 담을 State의 Type 선언
type ChatMessage = {
test: string;
sender: "user" | "bot";
}
src/pages/index.tsx
⌨️ ChatGPT와의 대화 내용을 담을 State 선언
const [messages, setMessages] = useState<ChatMessage[]>([]);
⌨️ User의 입력 input이 될 State 선언
const [inputText, setInputText] = useState<string>("");
⌨️ ChatGPT로부터의 응답을 return 해주는 fn, generateText() 작성
*Parameters 관련 글: ChatGPT-ConverSation-Patterns-Prompt
const generateText = async (prompt: string) => {
try {
const response = await axios.post(
"https://api.openai.com/v1/completions",
{
model: "text-davinci-003",
prompt: `${prompt}`,
temperature: 0.9,
max_tokens: 2048,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0.6,
stop: ["user:", "bot:"],
},
{
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + openAiKey,
},
}
);
const { choices } = response.data;
const text = choices[0].text.trim();
return text;
} catch (e: any) {
console.log(e.response?.status);
if (e.response?.status === 500) {
alert("OpenAI 서버에 오류가 발생했습니다.");
setMessages([
...messages,
{ text: inputText, sender: "user" },
{ text: "오류가 발생했습니다.", sender: "bot" },
]);
}
}
};
⌨️ generateText()의 param이 되는 User의 input text를 핸들링하는 fn, handleSendMessage() 작성
async function handleSendMessage() {
if (inputText.trim() === "") {
return;
}
const response = await generateText(inputText);
// 예외처리
if (!response || response === undefined) {
setMessages([
...messages,
{ text: inputText, sender: "user" },
{ text: "에러가 발생했습니다.", sender: "bot" },
]);
} else {
setMessages([
...messages,
{ text: inputText, sender: "user" },
{ text: response, sender: "bot" },
]);
}
setInputText("");
}
⌨️ Enter 누르면 handleSendMessage() 작동하도록 하는 fn, handlekeyPress() 작성
const handlekeyPress = (e: any) => {
if (e.key === "Enter") {
handleSendMessage();
// 전송되면 input State 초기화
setInputText("");
}
};
활용하여 jsx에 UI를 그려 표출해주면 된다.
*OpenAI로부터의 응답이 많이 늦기 때문에, 응답 중 Loading시의 Suspense를 추가로 구현해주면 더 좋을 것 같다.