emotion-chatbot-app / DEVELOPMENT.md
hfexample's picture
Deploy clean snapshot of the repository
e221c83

๐Ÿง—โ€โ™‚๏ธ ๊ฐœ๋ฐœ ๊ณผ์ • ๋ฐ ๋ฌธ์ œ ํ•ด๊ฒฐ (Development Journey)

์ด ๋ฌธ์„œ์—์„œ๋Š” Emotion Diary ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ๊ฒช์—ˆ๋˜ ์ฃผ์š” ๊ธฐ์ˆ ์  ๋„์ „ ๊ณผ์ œ์™€ ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๊ณผ์ •์„ ์ƒ์„ธํžˆ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.


1. ๋Œ€์šฉ๋Ÿ‰ AI ๋ชจ๋ธ ๊ด€๋ฆฌ ๋ฐ ๋ฐฐํฌ ์ „๋žต ์ˆ˜๋ฆฝ

  • ๋ฌธ์ œ์ : 1GB๊ฐ€ ๋„˜๋Š” AI ๋ชจ๋ธ ํŒŒ์ผ์„ Git LFS๋กœ ๊ด€๋ฆฌํ–ˆ์œผ๋‚˜, Hugging Face Spaces์˜ 1GB ์ €์žฅ ๊ณต๊ฐ„ ํ•œ๊ณ„(Storage limit reached)์™€ LFS ํŒŒ์ผ-ํฌ์ธํ„ฐ ๋ถˆ์ผ์น˜(LFS pointer does not exist) ๋“ฑ ๋ฐฐํฌ ๊ณผ์ •์—์„œ ์ง€์†์ ์ธ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ ๊ณผ์ •: ๋ชจ๋ธ๊ณผ ์•ฑ ์ฝ”๋“œ์˜ ์™„์ „ํ•œ ๋ถ„๋ฆฌ ์ „๋žต์„ ์ฑ„ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ๋Œ€์šฉ๋Ÿ‰ ๋ชจ๋ธ์€ Hugging Face Hub์— ๋ณ„๋„๋กœ ์—…๋กœ๋“œํ•˜์—ฌ ๋ฒ„์ „ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
    • GitHub ์ €์žฅ์†Œ์—์„œ๋Š” Git LFS ์ถ”์ ์„ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜๊ณ  ์ˆœ์ˆ˜ ์•ฑ ์ฝ”๋“œ๋งŒ ๊ด€๋ฆฌํ•˜๋„๋ก ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.
    • GitHub Actions ์›Œํฌํ”Œ๋กœ์šฐ(sync-to-hub.yml)์˜ lfs ์˜ต์…˜์„ false๋กœ ์„ค์ •ํ•˜์—ฌ, ๋ฐฐํฌ ์‹œ์—๋Š” ์•ฑ ์ฝ”๋“œ๋งŒ Spaces๋กœ ํ‘ธ์‹œํ•˜๋„๋ก ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฒฐ๋ก : Spaces ์•ฑ ์‹คํ–‰ ์‹œ์ ์—์„œ emotion_engine.py๊ฐ€ Hub๋กœ๋ถ€ํ„ฐ ๋ชจ๋ธ์„ ๋‹ค์šด๋กœ๋“œํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ €์žฅ ๊ณต๊ฐ„ ๋ฌธ์ œ๋ฅผ ๊ทผ๋ณธ์ ์œผ๋กœ ํ•ด๊ฒฐํ•˜๊ณ , ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‹œ ๋ชจ๋ธ์„ ๋‹ค์‹œ ์—…๋กœ๋“œํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ํšจ์œจ์ ์ธ ๋ฐฐํฌ ํŒŒ์ดํ”„๋ผ์ธ์„ ์™„์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

2. CI/CD ํŒŒ์ดํ”„๋ผ์ธ์˜ ๋ถ„์‚ฐ ํ™˜๊ฒฝ ์ธ์ฆ ๋ฌธ์ œ ํ•ด๊ฒฐ

  • ๋ฌธ์ œ์ : ๋กœ์ปฌ์—์„œ git push๋กœ ํŠธ๋ฆฌ๊ฑฐ๋œ GitHub Actions๊ฐ€ Hugging Face Spaces์— ์ ‘๊ทผํ•  ๋•Œ Invalid credentials ์ธ์ฆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” Spaces์˜ Secret๊ณผ GitHub Actions์˜ Secret ์—ญํ• ์— ๋Œ€ํ•œ ํ˜ผ๋™ ๋•Œ๋ฌธ์ด์—ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ ๊ณผ์ •: '๋ฐฐํฌ ๋กœ๋ด‡(GitHub Actions)'๊ณผ '๋นŒ๋“œ ๋กœ๋ด‡(Spaces)'์˜ ๊ฐœ๋…์œผ๋กœ ์—ญํ• ์„ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•˜์—ฌ ์ ‘๊ทผํ–ˆ์Šต๋‹ˆ๋‹ค.
    • GitHub Actions Secret (HF_TOKEN): '๋ฐฐํฌ ๋กœ๋ด‡'์ด Hugging Face ์ €์žฅ์†Œ(Repository)์— ์ฝ”๋“œ๋ฅผ ํ‘ธ์‹œํ•  ๋•Œ ํ•„์š”ํ•œ write ๊ถŒํ•œ ํ† ํฐ์„ ๋“ฑ๋กํ–ˆ์Šต๋‹ˆ๋‹ค.
    • Hugging Face Spaces Secret (HF_TOKEN): '๋นŒ๋“œ ๋กœ๋ด‡'์ด ๋‚ด๋ถ€์ ์œผ๋กœ LFS ํŒŒ์ผ ์ฒ˜๋ฆฌ๋‚˜ ๋‹ค๋ฅธ private ์ €์žฅ์†Œ์— ์ ‘๊ทผํ•  ๋•Œ ํ•„์š”ํ•œ ํ† ํฐ์„ ๋“ฑ๋กํ–ˆ์Šต๋‹ˆ๋‹ค. (์ด ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋ชจ๋ธ์„ ๋ถ„๋ฆฌํ•˜๋ฉด์„œ Spaces Secret์˜ ํ•„์š”์„ฑ์€ ๋‚ฎ์•„์กŒ์Šต๋‹ˆ๋‹ค.)
  • ๊ฒฐ๋ก : ๊ฐ๊ธฐ ๋‹ค๋ฅธ ์‹คํ–‰ ํ™˜๊ฒฝ์—์„œ ํ•„์š”ํ•œ ์ธ์ฆ ์ •๋ณด๋ฅผ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•˜๊ณ  ์˜ฌ๋ฐ”๋ฅธ ๊ถŒํ•œ์˜ ํ† ํฐ์„ ์ œ๊ณตํ•จ์œผ๋กœ์จ CI/CD ํŒŒ์ดํ”„๋ผ์ธ์˜ ์ธ์ฆ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

3. Flask ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์กฐ ์„ค๊ณ„ ๋ฐ ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜ ๋””๋ฒ„๊น…

  • ๋ฌธ์ œ์ : ๊ฐœ๋ฐœ ์ดˆ๊ธฐ, ๋ชจ๋“  ๋กœ์ง์ด ๋‹ด๊ธด ๋‹จ์ผ ํŒŒ์ผ ๊ตฌ์กฐ(app.py)๋กœ ์ธํ•ด ์ˆœํ™˜ ์ฐธ์กฐ(Circular Import) ๋ฐ ModuleNotFoundError๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, API๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค AI ๋ชจ๋ธ์„ ๋กœ๋”ฉํ•˜์—ฌ ์‘๋‹ต ์†๋„๊ฐ€ ๋งค์šฐ ๋А๋ ธ์Šต๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ ๊ณผ์ •: Flask์˜ Application Factory ํŒจํ„ด์„ ๋„์ž…ํ•˜์—ฌ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ์žฌ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • src/__init__.py์˜ create_app ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์•ฑ์˜ ๋ชจ๋“  ๊ตฌ์„ฑ์š”์†Œ(DB, ๋ธ”๋ฃจํ”„๋ฆฐํŠธ, ์„ค์ •)๋ฅผ ์กฐ๋ฆฝํ•˜๋„๋ก ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ์•ฑ์ด ์‹œ์ž‘๋˜๋Š” ์‹œ์ (create_app ๋‚ด๋ถ€)์—์„œ AI ๋ชจ๋ธ์„ ๋‹จ ํ•œ ๋ฒˆ๋งŒ ๋กœ๋“œํ•˜์—ฌ app ๊ฐ์ฒด์— ์ €์žฅ(app.emotion_classifier)ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฒฐ๋ก : ๊ฐ API ์š”์ฒญ์—์„œ๋Š” current_app ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ๋ฏธ๋ฆฌ ๋กœ๋“œ๋œ ๋ชจ๋ธ์„ ์ฐธ์กฐํ•˜๊ฒŒ ํ•˜์—ฌ, ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ๊ณผ ์‘๋‹ต ์†๋„๋ฅผ ๊ทน๋Œ€ํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ™•์žฅ ๊ฐ€๋Šฅํ•˜๊ณ  ์•ˆ์ •์ ์ธ ๋ฐฑ์—”๋“œ ๊ตฌ์กฐ๋ฅผ ์™„์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

4. ๋ชจ๋ธ ์„ฑ๋Šฅ ํ•˜๋ฝ ๋ฐ ์ •ํ™•๋„ ๊ฐœ์„  ๊ณผ์ •

  • ๋ฌธ์ œ์ : ๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ ์›๋ณธ ํ•™์Šต ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ์‹ค๋˜์–ด ๋ชจ๋ธ์„ ์žฌํ•™์Šตํ•˜์ž, ์ •ํ™•๋„๊ฐ€ ์ดˆ๊ธฐ ๋ชจ๋ธ๋ณด๋‹ค ํ˜„์ €ํžˆ ๋‚ฎ์•„์ง€๋Š” ๋ฌธ์ œ์— ์ง๋ฉดํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ ๊ณผ์ •: ์„ฑ๋Šฅ์„ ๋ณต์›ํ•˜๊ณ  ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์„ ์ฒด๊ณ„์ ์œผ๋กœ ์‹คํ—˜ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ํ˜ผ๋™ ํ–‰๋ ฌ(Confusion Matrix) ๋ถ„์„: ๋ชจ๋ธ์ด ์–ด๋–ค ๊ฐ์ •๋“ค์„ ์„œ๋กœ ํ˜ผ๋™ํ•˜๋Š”์ง€ ํŒŒ์•…ํ•˜์—ฌ ๋ฌธ์ œ์˜ ์›์ธ์„ ์ง„๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ๋ ˆ์ด๋ธ” ์žฌ๊ตฌ์„ฑ (Label Remapping): ์„ธ๋ถ„ํ™”๋œ ๊ฐ์ • ๋ ˆ์ด๋ธ”์„ 6๊ฐœ ๋˜๋Š” 4๊ฐœ์˜ ์ฃผ์š” ๊ฐ์ •์œผ๋กœ ๊ทธ๋ฃนํ™”ํ•˜์—ฌ ๋ถ„๋ฅ˜ ๋ฌธ์ œ์˜ ๋ณต์žก๋„๋ฅผ ์กฐ์ ˆํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ๋ฐ์ดํ„ฐ ๋ถˆ๊ท ํ˜• ํ•ด์†Œ: ์†Œ์ˆ˜ ํด๋ž˜์Šค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฆ๊ฐ•ํ•˜๋Š” ์˜ค๋ฒ„์ƒ˜ํ”Œ๋ง(Oversampling) ๋ฐ ๊ฐ ํด๋ž˜์Šค์— ๋‹ค๋ฅธ ์ค‘์š”๋„๋ฅผ ๋ถ€์—ฌํ•˜๋Š” ์ˆ˜๋™ ํด๋ž˜์Šค ๊ฐ€์ค‘์น˜(Manual Class Weights)๋ฅผ ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ์ „์ด ํ•™์Šต(Transfer Learning) ๊ฐ•ํ™”: ๊ฐ์„ฑ ๋ถ„์„์— ํŠนํ™”๋œ NSMC(Naver Movie Corpus) ๋ฐ์ดํ„ฐ์…‹์œผ๋กœ 1์ฐจ ์‚ฌ์ „ ํ•™์Šตํ•œ ๋ชจ๋ธ์„ ๊ธฐ๋ฐ˜์œผ๋กœ, ์ตœ์ข… ๊ฐ์ • ๋ฐ์ดํ„ฐ์— 2์ฐจ ๋ฏธ์„ธ์กฐ์ •(Fine-tuning)์„ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฒฐ๋ก : ์—ฌ๋Ÿฌ ์‹คํ—˜ ๊ฒฐ๊ณผ, 'ํ•œ๊ตญ์–ด ๊ฐ์„ฑ๋Œ€ํ™” ๋ง๋ญ‰์น˜' ๋ฐ์ดํ„ฐ์˜ ๋ ˆ์ด๋ธ”์„ 6๊ฐœ์˜ ์ฃผ์š” ๊ฐ์ •์œผ๋กœ ๋งคํ•‘ํ•˜๊ณ , ๋ฐ์ดํ„ฐ ๋ถˆ๊ท ํ˜• ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ˆ˜๋™์œผ๋กœ ํด๋ž˜์Šค ๊ฐ€์ค‘์น˜๋ฅผ ์ •๊ตํ•˜๊ฒŒ ์กฐ์ •ํ•˜์—ฌ ํ•™์Šตํ•˜๋Š” ๋ฐฉ์‹์ด ์•ฝ 80%์˜ ์ •ํ™•๋„๋ฅผ ํšŒ๋ณตํ•˜๋ฉฐ ๊ฐ€์žฅ ์•ˆ์ •์ ์ด๊ณ  ํšจ๊ณผ์ ์ž„์„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.