๐ก 20230807 TIL : OpenAI api ๋ฆฌ์กํธ ํ๋ก์ ํธ์ ์ธํ ํ ๊ณผ์ ์ ๋ฆฌ
์ด๋ฒ ํ๋ก์ ํธ์์ ์ฑ๋ด ๊ธฐ๋ฅ์ ๋ด๋นํ์๋ค. ์ฑ๋ด์ ์น ์ฌ์ดํธ ์ด๋์์๋ ๋ชจ๋ฌ์ฐฝ์ผ๋ก ์ ๊ทผํ ์ ์์ผ๋ฉฐ, ๋ชจ๋ฌ์์ OpenAI api๋ฅผ ์ด์ฉํ์ฌ ํจ์๋ช , ๋ณ์๋ช ์ ์ง์ด๋ฌ๋ผ๊ณ ์์ฒญํ ์ ์๋ ์ฑ๋ด์ ๋ง๋๋๊ฒ ๋ชฉํ์ด๋ค. OpenAI api๋ ์ฒ์ ์ฌ์ฉํด๋ณด๋๊ฑฐ๋ผ, ๊ณต์ ๋ฌธ์์ ๋ธ๋ก๊ทธ๋ค์ ์ฐธ๊ณ ํ์ฌ ์ผ๋จ์ ์ด์คํ๊ฒ ๊ตฌํ์ ์ฑ๊ณตํ์ฌ ๊ทธ ๊ณผ์ ์ ์ ๋ฆฌํด๋ณด๋ ค๊ณ ํ๋ค.
์ฐธ๊ณ ๋ก ์งํ ์ค์ธ ๋ฆฌ์กํธ ํ๋ก์ ํธ๋ ํ์ ์คํฌ๋ฆฝํธ ๊ธฐ๋ฐ์ผ๋ก ์งํ ์ค์ด๋ค.
1. ์ธํ
API ์ฌ์ฉ ์ , APIํค ๋ฐ๊ธ ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น ์ธํ ์ ์๋ฃํ์ฌ์ผ ํ๋ค.
1) React ํ๋ก์ ํธ์ openai ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น
// npm ์ค์น
npm install openai
// yarn ์ค์น
yarn install openai
2) API Key ์ธํ
- OpenAI ๊ณต์ ํํ์ด์ง์์ ๋ฐ๊ธ๋ฐ์ API Key๋ฅผ .env ํ์ผ์ `REACT_APP_OPENAI_API_KEY` ๋ณ์๋ช ์ ์ค์ ํด์ค๋ค.
- .env ํ์ผ์ package.json๊ณผ .gitignore ํ์ผ์ด ์์นํ๋ ๋ฃจํธ ๊ฒฝ๋ก์ ์์นํ์ฌ์ผ ํ๋ค.
REACT_APP_OPENAI_API_KEY = "๋ฐ๊ธ๋ฐ์ API KEY ์
๋ ฅ"
OpenAI API ํค ๋ฐ๊ธ๋ฐ๋ ๋ฐฉ๋ฒ์ ์๋ ๋ฒจ๋ก๊ทธ์ ์์ธํ ๋์์์ผ๋ ์ฐธ๊ณ
ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๋ฅผ ์ํ chatGPT API ํ์ฉ๋ฒ (+ react, flask)
2. ์์ฑ ์ฝ๋
์ฝ๋๋ ์ฐ์ api ํ์ผ์ธ openaiapi.ts ํ์ผ๊ณผ, ChatGPT.tsx ์ปดํฌ๋ํธ ๋ ํ์ผ๋ก ๋ถ๋ฆฌํ์ฌ ์์ฑํ์๋ค.
1) openaiapi.ts - api ์ค์ ํ์ผ
import { Configuration, OpenAIApi } from "openai";
const configuration = new Configuration({
apiKey: process.env.REACT_APP_OPENAI_API_KEY,
});
export const openai = new OpenAIApi(configuration);
- api ์ค์ ์ฝ๋๋ฅผ ๋ฐ๋ก ํ์ผ๋ก ๋ถ๋ฆฌํ ํ์ ์์ด ChatGPT.tsx ์ปดํฌ๋ํธ์ ์์ฑํด๋ ๋๋๋ฐ, ๊ทธ๋ฅ ํ ์ค์ด๋ผ๋ ๊น๋ํ๊ฒ ์์ฑํ๊ณ ์ถ์ด์ ์ผ๋จ ๋ถ๋ฆฌํ์๋ค.
2) ChatGPT.tsx ์ปดํฌ๋ํธ
import { useState } from "react";
import { openai } from "../../libs/services/openaiapi";
import styled from "styled-components";
const ChatGPT = () => {
const [prompt, setPrompt] = useState("");
const [apiRes, setApiRes] = useState<string>("");
const [loading, setLoading] = useState(false);
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setPrompt(e.currentTarget.value);
}
const handlePromptSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setLoading(true);
try {
const res = await openai.createCompletion({
model: "text-davinci-003",
prompt,
temperature: 0.8,
max_tokens: 256,
})
console.log(res);
if (res?.data.choices[0]?.text) {
setApiRes(res.data.choices[0].text);
} else {
setApiRes("์ ์์ ์ผ๋ก ์ ๋ฌ๋์ง ์์์ต๋๋ค. ๋ค์ ์๋ํด์ฃผ์ธ์.");
}
} catch (err) {
console.log(err);
setApiRes("์ ์์ ์ผ๋ก ์ ๋ฌ๋์ง ์์์ต๋๋ค. ๋ค์ ์๋ํด์ฃผ์ธ์.")
}
setLoading(false);
}
return (
<>
<ChatBotContainer>
<div>
<ChatBotTitle>๋ณ์๋ช
, ํจ์๋ช
์ ๋ฌผ์ด๋ณด์ธ์!</ChatBotTitle>
{apiRes && (
<ChatBotResContainer>
<h3>์ฑ๋ด ๐ค</h3>
<pre>{apiRes}</pre>
</ChatBotResContainer>
)}
<form onSubmit={handlePromptSubmit}>
<ChatBotPromptInput
type="text"
value={prompt}
onChange={onChange}
placeholder="์ง๋ฌธ์ ์
๋ ฅํ์ธ์!"
/>
<button
disabled={loading}
>{loading ? "๋ต๋ณ ์์ฑ ์ค.." : "์ ์ก"}
</button>
</form>
</div>
</ChatBotContainer>
</>
);
};
export default ChatGPT;
const ChatBotContainer = styled.div`
width: 70%;
margin: 10px;
padding: 10px;
border: 1px solid gray;
border-radius: 10px;
`
const ChatBotResContainer = styled.div`
padding: 10px;
margin: 10px;
border: 1px solid gray;
border-radius: 10px;
`
const ChatBotTitle = styled.h1`
font-size: 18px;
text-align: center;
margin: 20px;
`
const ChatBotPromptInput = styled.input`
width: 80%;
margin: 10px;
padding: 10px;
`;
3. ๊ฒฐ๊ณผ
ํจ์๋ช ์ ์ง์ด๋ฌ๋ผ๊ณ ํ๋๋ฐ ํจ์ ์ ์ฒด๋ฅผ ๋ง๋ค์ด์คฌ๋ค..ใ ใ (๋ฐ๋ณด๊ฐ์ ๋ ์) CSS๋ ์๋ง์ด๊ณ ๋ต๋ณ๋ ์๋ง์ด์ง๋ง ์ผ๋จ ๊ฒ์ํ๋ฉด ๊ทธ์ ๋ง๋ ๋ต๋ณ์ด ๋์ค๋๊ฒ ์ ๊ธฐํ๋ค!
4. ํด์ผ ํ ์ผ
- ์ฐ์ธก ํ๋จ์ ์ฑ๋ด ๋ฒํผ ๋ง๋ค๊ธฐ
- ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ผ์ ํฌ๊ธฐ์ ์ฑ๋ด ๋ชจ๋ฌ์ด ๋ํ๋๋๋ก ๋ง๋ค๊ธฐ
- ์ ์ ๊ฐ ๋จ๊ธด ์ง๋ฌธ, ์ฑGPT๊ฐ ๋จ๊ธด ๋ต๋ณ์ ์ฑํ
์ฐฝ์ฒ๋ผ ๋ก๊ทธ ๋จ๊ธฐ๊ธฐ
- ์ง๊ธ์ ์ง๋ฌธ ํ๋กฌํํธ๋ฅผ ์๋ก submitํ๋ฉด ๊ธฐ์กด ์ง๋ฌธ๊ณผ ๋ต๋ณ์ด ๋จ์ง ์๊ณ ์๋ก์ด ์ง๋ฌธ๊ณผ ๋ต๋ณ๋ง ๋ณด์
์ฐธ๊ณ ์ฌ์ดํธ
ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๋ฅผ ์ํ chatGPT API ํ์ฉ๋ฒ (+ react, flask)