๐Ÿ“๊ธฐ๋ก

OpenAI๋กœ ์„œ๋น„์Šค ์‚ฌ์šฉ์„ฑ ๊ฐœ์„ ํ•˜๊ธฐ

Hugehoo 2023. 5. 29. 01:52

๊ฐœ์š”

 

์ตœ๊ทผ์— ์•ฑ์„ ์ถœ์‹œํ–ˆ๋‹ต๋‹ˆ๋‹ค.โญ๏ธ 

Tidify ๋Š” ๋งํฌ ์•„์นด์ด๋น™ ์„œ๋น„์Šค๋กœ, ๋งํฌ๋ฅผ ๋ณต์‚ฌํ•˜๊ฑฐ๋‚˜ Share Extension ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ถ๋งˆํฌ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๋Š” ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ํŽธ์˜์„ฑ์„ ์œ„ํ•ด ๋งํฌ ์ž…๋ ฅ ํ›„ ๋ถ๋งˆํฌ์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด, url(๋งํฌ)์„ ๋ถ๋งˆํฌ์˜ ์ด๋ฆ„์œผ๋กœ ์ž๋™ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํŽธ์˜์„ฑ์„ ์œ„ํ•œ ์ด ๊ธฐ๋Šฅ์ด ์–ด๋Š๋‚  ์—๋Ÿฌ๋ฅผ ๋‚ด๋ฒ„๋ฆฌ๋Š”๋ฐ…
(์•„์ง ๋ฒ ํƒ€๋ฒ„์ „์ด๋ผ ๋ณธ๊ฒฉ์ ์ธ ํ™๋ณด๋Š” ํ•˜์ง€ ์•Š์•˜์ง€๋งŒ ๐Ÿ”—์•ฑ์Šคํ† ์–ด ์—์„œ ๋‹ค์šด๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค)

 

 

 

 

Open AI ๋„์ž…๋ฐฐ๊ฒฝ

 

ํŠน์ • ๋งํฌ(url)์˜ ๊ธธ์ด๊ฐ€ 300์ž๋ฅผ ๋„˜์„ ๊ฒฝ์šฐ DB table ์˜ name column ์—์„œ Too long for column ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋‹น์‹œ์—๋Š” ๋‹จ์ˆœํžˆ ์ปฌ๋Ÿผ์˜ ์ตœ๋Œ€ ๊ธธ์ด๋ฅผ 500์ž๋กœ ๋Š˜๋ ค ๋Œ€์ฒ˜ํ–ˆ์ง€๋งŒ, ๊ทผ๋ณธ์ ์ธ ๋Œ€์ฒ˜ ๋ฐฉ๋ฒ•์€ ์•„๋‹ˆ๋ผ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ํŠน์ • ์ผ€์ด์Šค๋งŒ์„ ์œ„ํ•ด name column ์„ 500์ž๋กœ ๋Š˜๋ฆฌ๋Š” ๊ฑด ์˜ค๋ฐ”๋ผ ์ƒ๊ฐํ–ˆ๊ฑฐ๋“ ์š”.

com.mysql.cj.jdbc.exceptions.MysqlDataTruncation:
Data truncation: Data too long for column 'name' at row 1

DB ์—์„œ Table column ์„ค์ •์„ ๋ฐ”๊พธ๊ธฐ ๋ณด๋‹จ, ๋งํฌ์˜ ์ ์ ˆํ•œ name ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ๊ตฌ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์ฒ˜์Œ์—” 2๊ฐ€์ง€ ์ ‘๊ทผ์„ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. url ์„ ํŒŒ์‹ฑํ•˜์—ฌ 1) ๋„๋ฉ”์ธ๋งŒ ์ €์žฅํ•˜๊ฑฐ๋‚˜ 2) ์ „์ฒด url ๋Œ€์‹ , ํŠน์ • ๊ธธ์ด๊นŒ์ง€๋งŒ slicing ํ•˜์—ฌ ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹์„ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

1. ํ•˜์ง€๋งŒ ๋„๋ฉ”์ธ์„ ํŒŒ์‹ฑํ•  ๊ฒฝ์šฐ, ์—ฌ๋Ÿฌ url ๋งˆ๋‹ค ๋„๋ฉ”์ธ ๋„ค์ž„์˜ ์œ„์น˜๊ฐ€ ๋ถˆ๊ทœ์น™ํ•˜๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

2. ํŠน์ • ๊ธธ์ด๊นŒ์ง€ slicing ํ•˜๋Š” ๋ฐฉ๋ฒ•์€, ์‚ฌ์šฉ์ž์—๊ฒŒ ์ข‹์ง€ ์•Š์€ UI ๋ผ๋Š” ๋””์ž์ด๋„ˆ์˜ ํ”ผ๋“œ๋ฐฑ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€๋ น ์•„๋ž˜์ฒ˜๋Ÿผ ๊ธธ์ด๊ฐ€ ๊ธด url ์„ ํŠน์ • ๊ธธ์ด๊นŒ์ง€ slicing ํ•˜์—ฌ ์ €์žฅํ•˜๋ฉด ์–ด์ค‘๊ฐ„ํ•œ ์ด๋ฆ„์ด ์ƒ์„ฑ๋˜๋ฒ„๋ฆฝ๋‹ˆ๋‹ค.

before: https://docs.google.com/presentation/d/1XnBMiHbgZmclXT4dLfI6Q7fnNnXQwfo165458o3Qzv4/mobilepresent?slide=id.p 
after : https://docs.google.com/presen

 

์ด๋ ‡๊ฒŒ ์งค๋ ค๋ฒ„๋ฆด์ง€๋„ ๋ชจ๋ฅด๋Š” ์ผ์ด๋‹ˆ๊นŒ์š”. ์•ฑ UI ์ƒ์—” ์ด๋ ‡๊ฒŒ ์ €์žฅ๋˜๊ฒ ์ฃ .

์ƒ‰๋‹ค๋ฅธ ์ ‘๊ทผ์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ถ๋งˆํฌ ์ด๋ฆ„ ์ž…๋ ฅ์„ ๊ฐ•์ œํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ์‹์œผ๋กœ ํ•ด๊ฒฐํ•˜๋ฉด ์šฐ์„  ์ €๋ถ€ํ„ฐ ์•ฑ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™์œผ๋‹ˆ๊นŒ์š”.

url ์„ ๋Œ€ํ‘œํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ๋งˆํฌ ์ด๋ฆ„์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ๋ฌธ์ œ์˜ ๊ด€๊ฑด์ธ๋ฐ, ์ด ๋•Œ ๋– ์˜ค๋ฅด๋Š” ๊ทธ ์ด๋ฆ„ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. ๊ทธ๋ถ„์ด ๋“ฑ์žฅํ•  ๋•Œ ์ž…๋‹ˆ๋‹ค.

GPT ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด url ๋งŒ์œผ๋กœ ๊ทธ์— ๋งž๋Š” ๋ถ๋งˆํฌ ์ด๋ฆ„์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฆฌ๋ผ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋กฌํ”„ํŠธ์— url ๊ณผ ๊ทธ์— ๋งž๋Š” ์ด๋ฆ„์„ ๋ฏธ๋ฆฌ ์˜ˆ์‹œ๋กœ ์ฃผ๊ณ , ์ƒˆ๋กœ์šด url ์„ ์ž…๋ ฅํ•˜์—ฌ ์›ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ด๋ฆ„์ด ์ƒ์„ฑ๋˜๋Š”์ง€ ํ…Œ์ŠคํŠธ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„  ๋คผํŠผ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์ƒ๊ฐ๋ณด๋‹ค ๊ฒฐ๊ณผ๊ฐ€ ์ž˜๋‚˜์™€์„œ ๋†€๋ž์Šต๋‹ˆ๋‹ค. ์œ„ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์„ธํŒ…ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ถฉ๋ถ„ํžˆ url ์˜ ์ด๋ฆ„์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์ง€์ฒด์—†์ด ์ฝ”๋“œ๋ฅผ ์งœ๋ณด๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 



 

 

์‚ฌ์šฉ ๊ธฐ์ˆ ๊ณผ ์„ ์ • ๋ฐฐ๊ฒฝ

 

Tidify ์˜ ํ˜„์žฌ ์„œ๋ฒ„๋Š” Java, Springboot ์œผ๋กœ ๊ฐœ๋ฐœ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. OpenAI API ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์„ ๋•Œ ๋– ์˜ค๋ฅธ ์˜ต์…˜์€ 2๊ฐ€์ง€ ์˜€์Šต๋‹ˆ๋‹ค.

  • ๊ธฐ์กด Springboot ์„œ๋ฒ„์— OpenAI API Dependency ์ถ”๊ฐ€.
  • ๋ณ„๋„์˜ FastAPI ์„œ๋ฒ„์— OpenAI๋ฅผ Import.

 

๋‹จ์ˆœํžˆ OpenAI API ๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด์„œ๋ผ๋ฉด ๋ณ„๋„์˜ ์„œ๋ฒ„ ์ฆ์„ค ์—†์ด 1) Springboot ๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ–ˆ๊ฒ ์ง€๋งŒ, ๋ฌธ์ž์—ด ํŒŒ์‹ฑ๊ณผ ํŠน์ • ๋ฐ์ดํ„ฐ ์…‹(csv)์„ ํ›ˆ๋ จ์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„ , pandas ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํŒŒ์ด์ฌ ํ™˜๊ฒฝ์ด ๋” ์œ ๋ฆฌํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ด 2) FastAPI ๋ฅผ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋น„๋™๊ธฐ ํ˜ธ์ถœ์ด ์ง€์›๋˜๋Š” ์ ๋„ FastAPI ๋ฅผ ์„ ํƒํ•œ ์ด์œ  ์ค‘ ํ•˜๋‚˜์˜€์Šต๋‹ˆ๋‹ค. (๋ฌผ๋ก  ์Šคํ”„๋ง๋ถ€ํŠธ์—์„œ๋„ ๋น„๋™๊ธฐ ์ง€์›์€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค) ํ˜„ ๋‹จ๊ณ„์—์„  ๊ฐ„๋‹จํžˆ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์„ธํŒ…ํ•ด, Url ์— ๋งž๋Š” ๋ถ๋งˆํฌ ์ด๋ฆ„์„ ์ถ”์ฒœ ๋ฐ›๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. (Pandas ๋Š” ๋‹ค์Œ ๋ฒ„์ „๋ถ€ํ„ฐ ์ ์šฉํ•˜๊ธฐ๋กœ ใ…Ž)

 

๊ฐœ๋ฐœ

๊ฐœ๋ฐœ ํ™˜๊ฒฝ์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • python 3.9
  • fastapi 0.95
  • openai 0.27.7
  • uvicorn 0.22.0

Main.py (Set up) ์—”๋“œํฌ์ธํŠธ ๊ฐœ์„ค์„ ์œ„ํ•ด FastAPI()๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  Prompt ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

app = FastAPI()
openai.api_key = OPEN_AI_API_KEY

class Prompt(BaseModel):
    question: str

 

Main.py (End point)

open.Completion.create() ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜๊ณ  engine, prompt, max_tokens, n, temperature ์ธ์ž๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค.

  • engine : ์‚ฌ์šฉํ•  GPT ๋ชจ๋ธ์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์‚ฌ์šฉํ•œ ‘text-davinci-002’ ๋Š” OpenAi ๊ฐœ๋ฐœํ•œ GPT ๋ชจ๋ธ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.
  • prompt : ๋ง ๊ทธ๋Œ€๋กœ ํ”„๋กฌํ”„ํŠธ ์ž…๋‹ˆ๋‹ค. GPT engine ์— ์งˆ๋ฌธํ•  ๋‚ด์šฉ์— ํ•ด๋‹น๋ฉ๋‹ˆ๋‹ค.
  • max_tokens : ๊ฒฐ๊ณผ์— ์‚ฌ์šฉ๋  ์ตœ๋Œ€ ํ† ํฐ ์ˆ˜ ์ž…๋‹ˆ๋‹ค. ํ† ํฐ์€ ๋‹จ์–ด๋‚˜ ๊ตฌ๋‘์  ๋ถ€ํ˜ธ๋กœ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • n : ํ”„๋กฌํ”„ํŠธ์— ์ƒ์„ฑ๋  ์‘๋‹ต์˜ ์ˆ˜ ์ž…๋‹ˆ๋‹ค. 1 ๋กœ ์ง€์ •ํ•œ ๊ฒฝ์šฐ, ํ•œ ๊ฐ€์ง€์˜ ํ…์ŠคํŠธ ์‘๋‹ต์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  • temperature : ์ƒ˜ํ”Œ๋ง ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฌด์ž‘์œ„์„ฑ์„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. temperature ๊ฐ’์ด ๋†’์„ ์ˆ˜๋ก ๋ชจ๋ธ์€ ๋‹ค์–‘ํ•˜๊ณ  ์ฐฝ์˜์„ฑ ๋†’์€ ๋ฌธ์žฅ์„ ์ƒ์„ฑํ•˜๋ฉฐ, ๊ฐ’์ด ๋‚ฎ์„ ๊ฒฝ์šฐ ์ผ๊ด€์ ์ด๊ณ  ์˜ˆ์ƒ ๊ฐ€๋Šฅํ•œ ๋ฌธ์žฅ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
@app.post("/ask_openai")
async def ask_openai(prompt: Prompt) -> str:

    response = openai.Completion.create(
        engine="text-davinci-002",
        prompt=preset_prompt,
        max_tokens=100,
        n=1,
        temperature=0.5,
    )

    semi_answer: str = response.choices[0].text.strip()
    return semi_answer.split('\n')[0]


๊ทธ๋ฆฌ๊ณ  prompt ์— ์‚ฌ์šฉ๋  preset_prompt๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กฌํ”„ํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ ์ž‘์„ฑํ•˜๋ƒ์— ๋”ฐ๋ผ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๋ฒ„์ „๋ณ„๋กœ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋ฉฐ ์–ด๋–ค ์‘๋‹ต์„ ์–ป๋Š”์ง€ ๋น„๊ตํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

Version.1

prompt

preset_prompt = f"""
generate simple Korean name of this input URL: {prompt.question} \n
"""

๊ฒฐ๊ณผ

์ „ํ˜€ ๊น”๋”ํ•˜์ง€ ์•Š์€ Answer ์ด ๋Œ์•„์™”์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์›ํ•œ ๊ฑด ์ตœ์†Œ `OOO ํ…Œํฌ ๋ธ”๋กœ๊ทธ` ์ •๋„์˜€๋Š”๋ฐ, OpenAI ๋Š” `์›น์‚ฌ์ดํŠธ: https://techblog.woowahan.com/12044`๋ผ๊ณ  ๋‹ตํ–ˆ์Šต๋‹ˆ๋‹ค. ์•„์ง ํ›ˆ๋ จ์ด ํ•„์š”ํ•œ ์นœ๊ตฌ๋‹ˆ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ข€ ๋” ์ƒ์„ธํžˆ ์ž‘์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Input URL : https://techblog.woowahan.com/12044
OpenAI Answer : ์›น์‚ฌ์ดํŠธ: https://techblog.woowahan.com/12044



Version.2

Version.1 ๋ณด๋‹ค ์ƒ์„ธํžˆ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ์šฐ์„  ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ url ์˜ name ์„ ์ƒ์„ฑํ•˜๋ฉด ์ข‹์€์ง€ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด์คฌ์Šต๋‹ˆ๋‹ค.
    • input URL ์„ ์ œ์‹œํ•˜๊ณ , ํ•ด๋‹น url ์˜ name ์„ ์ง์ ‘ ์ž…๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ๊ทธ๋ฆฌํ•˜์—ฌ random URL ์ด ์ž…๋ ฅ๋˜๋”๋ผ๋„ ์ œ๊ฐ€ ์›ํ•˜๋Š” ํ˜•์‹์˜ name ์„ ์–ป์„ ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๋‘๋ฒˆ์งธ๋ก  ์ƒ์„ฑ๋œ name ์ด single line ์ด์–ด์•ผ ํ•œ๋‹ค๊ณ  ์žฌ์ฐจ ๊ฐ•์กฐํ–ˆ์Šต๋‹ˆ๋‹ค. Tidify ์„œ๋น„์Šค์— ์‚ฌ์šฉ๋  ๋ถ๋งˆํฌ name ์€ ๋Œ€๊ฒŒ ํ•œ์ค„๋กœ ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฐ ์ œ์•ฝ ์กฐ๊ฑด์„ ์คฌ์Šต๋‹ˆ๋‹ค.

prompt

preset_prompt = f"""
make a simple Korean name of the url base on examples.
It's important to generate a result in Korean words as a single line,
not multiple line sentences.

the result will be used as simple bookmark,
so it's important to generate a result as simple korean words.

- example 1:
input URL: https://google.com
generated name: ๊ตฌ๊ธ€

- example 2:
input URL: https://medium.com/29cm/backend/home
generated name: 29CM ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ

- example 3:
input URL: https://ios-development.tistory.com/945
generated name: iOS ๊ฐœ๋ฐœ ๋ธ”๋กœ๊ทธ

- example 4:
input URL: https://29cm.career.greetinghr.com/o/77203
generated name: 29cm ์ฑ„์šฉ ๊ณต๊ณ  ํŽ˜์ด์ง€

- example 5:
input URL: https://www.linkedin.com/posts/catalin-patrascu_swift-concatenation-
generated name: LinkedIn Swift Concatenation ํฌ์ŠคํŠธ

- example 6:
input URL: https://wrtn.ai/
generated name: ๋คผํŠผ

- example 7:
input URL: https://jh-bk.tistory.com/23
generated name: jh-bk ์˜ ํ‹ฐ์Šคํ† ๋ฆฌ

- example 8:
input URL: https://docs.google.com/presentation/d/1XnBMiHbgZmclXT4dLfI6Q7fnNnXQwfo165458o3Qzv4/mobilepresent?slide=id.p 
generated name: Google Presentation ์Šฌ๋ผ์ด๋“œ

Generate simple Korean name of this input URL: {prompt.question} \n
"""


๊ฒฐ๊ณผ

Version.1๊ณผ ๋™์ผํ•œ url ๋กœ ํ…Œ์ŠคํŠธ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


ํ”„๋กฌํ”„ํŠธ๋งŒ ๋ฐ”๊ฟจ์„ ๋ฟ์ธ๋ฐ ์„ฑ๋Šฅ(?)์ด ๋น„์•ฝ์ ์œผ๋กœ ์ข‹์•„์ง„ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Input URL : https://techblog.woowahan.com/12044 
OpenAI Answer : ์šฐ์•„ํ•œ ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ

 

 

๋˜ ๋‹ค๋ฅธ url ๋กœ ํ…Œ์ŠคํŠธ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Version.1

 

Input URL : https://docs.google.com/forms/d/e/1FAIpQLSciq7dwuIV7t0g9cITjCnf1vq1xRjj6dTfAT7hDLiwcfUn17w/viewform
OpenAI Answer : ์ด๋ฆ„:

 

Version.2

 

Input URL : https://docs.google.com/forms/d/e/1FAIpQLSciq7dwuIV7t0g9cITjCnf1vq1xRjj6dTfAT7hDLiwcfUn17w/viewform
OpenAI Answer : Goolge Form ์„ค๋ฌธ์กฐ์‚ฌ

 

 

๋‚œํ•ดํ•œ url ์ด๋”๋ผ๋„ Prompt ๋ฅผ ์–ด๋–ป๊ฒŒ ์„ธํŒ…ํ•˜๋ƒ์— ๋”ฐ๋ผ ์‘๋‹ต ๊ฒฐ๊ณผ๊ฐ€ ์ฒœ์ฐจ๋งŒ๋ณ„์ธ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Main.py (์ „์ฒด ์ฝ”๋“œ)


์ „์ฒด ์ฝ”๋“œ๋„ ๊ณต์œ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ๊น”๋”ํžˆ ๋ณด๊ธฐ ์œ„ํ•ด Version2 ์—์„œ ํ™œ์šฉํ•œ prompt ๋Š” ๋ณ„๋„์˜ ํŒŒ์ผ(secret.py)์— ๋ถ„๋ฆฌํ•˜์—ฌ import ํ–ˆ์Šต๋‹ˆ๋‹ค.

import openai
from fastapi import FastAPI
from pydantic import BaseModel
from secret import OPEN_AI_API_KEY, PRE_PROMPT

app = FastAPI()
openai.api_key = OPEN_AI_API_KEY


class Prompt(BaseModel):
    question: str


@app.post("/ask_openai")
async def ask_openai(prompt: Prompt) -> str:
    preset_prompt = f"""
    {PRE_PROMPT}
    generate simple Korean name of this input URL: {prompt.question} \n
    """

    response = openai.Completion.create(
        engine="text-davinci-002",
        prompt=preset_prompt,
        max_tokens=100,
        n=1,
        temperature=0.5
    )

    semi_answer: str = response.choices[0].text.strip()
    return semi_answer.split('\n')[0]


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8000)

 

๋งˆ๋ฌด๋ฆฌ

As-Is ์™€ To-Be ๋ฅผ ๋น„๊ตํ•˜๋ฉฐ ๋งˆ๋ฌด๋ฆฌ ์ง“๊ฒ ์Šต๋‹ˆ๋‹ค.

As-Is

๊ธฐ์กด์—” ๋ถ๋งˆํฌ ์ด๋ฆ„์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด input url ๊ณผ ๋™์ผํ•œ ๊ฐ’์œผ๋กœ ์„œ๋ฒ„์—์„œ ์„ธํŒ…ํ•ด์ค๋‹ˆ๋‹ค. ์•ž์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ url ์ด ๋„ˆ๋ฌด ๊ธธ ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•ด name column ๋„ url column ๊ณผ ๋™์ผํ•œ ๊ธธ์ด๋กœ ์„ธํŒ…ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

To-Be

OpenAI ๋ฅผ ํ™œ์šฉํ•ด ์ด๋ฆ„์„ ์„ธํŒ…ํ•˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

url ์ž…๋ ฅ ํ›„ ๋ถ๋งˆํฌ ์ด๋ฆ„์„ ๋”ฐ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ, OpenAI ์—์„œ ์‘๋‹ต๋ฐ›์€ ์ถ”์ฒœ ์ด๋ฆ„ ์„ ์•ฑ์— ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กฌํ”„ํŠธ์—์„œ ๊ฒฐ๊ณผ๋ฅผ single line ์œผ๋กœ ์ง€์ •ํ•˜์—ฌ name ์ด ๊ธธ์–ด์ง€๋Š” ๋ฌธ์ œ๋„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ถ”๊ฐ€์ ์œผ๋กœ ask_openai() ๋ฉ”์„œ๋“œ return ๋ถ€๋ถ„์—์„œ split('\n') ํ›„์ฒ˜๋ฆฌ๋„ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— Data too long for column 'name' at row 1 ๊ฐ™์€ ๋ฌธ์ œ๋Š” ๋ฏธ์—ฐ์— ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ์ œ๊ฐ€ ์šด์˜์ค‘์ธ ์„œ๋น„์Šค์— OpenAI API ๋ฅผ ์ ์šฉํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ํŽธ์˜์„ฑ์„ ์œ„ํ•ด ์ ์šฉํ•œ ๊ธฐ๋Šฅ์ด ๋˜๋ ค ์žฅ์• ๋ฅผ ์ผ์œผํ‚จ ์ผ€์ด์Šค์˜€์ง€๋งŒ, ์ด๋ฅผ AI ๊ธฐ์ˆ ์„ ํ™œ์šฉํ•ด ํ•ด๊ฒฐํ•œ ๊ฒฝํ—˜์ด์—ˆ์Šต๋‹ˆ๋‹ค.

Tidify Ver.2 ๋ถ€ํ„ด URL ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ ํ•ฉํ•œ ๋ถ๋งˆํฌ ์ด๋ฆ„์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ์ „ Version.2 ์ค€๋น„ํ•˜๋Ÿฌ 20000