"ํ๋น๋ฏธ๋์ด ์ํ๋จ <๋๋๋ฆฌ๋ทฐ์ด๋ค> ํ๋์ ์ํด์ ์ฑ ์ ํ์ฐฌ ๋ฐ์ ์์ฑ๋ ์ํ์ ๋๋ค."
์ฑ ์๊ฐ
- ์ ์
- ๋ฌธํ์ผ
- ์ถํ
- ํ๋น๋ฏธ๋์ด
- ์ถํ์ผ
- 2025.02.14
25๋ 2์์ ์ถ๊ฐ๋ ์ฑ ์ผ๋ก, ํ์ด์ฌ ๊ธฐ์ด๋ฅผ ๋ฐฐ์ด ๋ค์ ์ด๋ป๊ฒ ํ์ฉํ๋ฉด ์ข์์ง, ๋ ๊น์ด ๊ณต๋ถํ๊ณ ์ถ์ ์ฌ๋๋ค์ ์ํ ์ฑ ์ด๋ค.
ํ์ด์ฌ์ ํ์ฉํด ์๋ํด๋ณผ ์ ์๋ ๋ค์ํ ํ ์ด ํ๋ก์ ํธ๋ค์ ์ ์ํ๊ณ ์์ผ๋ฉฐ ๋ฐ๋ผ๊ฐ๋ณด๋ฉด์ ๋ค์ํ ๋ถ์ผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํ ๊ณต๋ถ๋ฅผ ํ ์ ์๋๋ก ๋์ด ์๋ค
- ์ฃผ์ & ๊ฒฝ์ ๋ฐ์ดํฐ ๋ถ์ – ์๊ฐ์ด์ก, ๊ธฐ์ค๊ธ๋ฆฌ, ์ฃผ์ ๊ฒฝ์ ์งํ ๋ฐ์ดํฐ ๋ถ์ ๋ฐ ์๊ฐํํ๊ธฐ
- ๋ถ๋์ฐ ์ค๊ฑฐ๋๊ฐ ๋ถ์ – ์ง์ญ๋ณ ๋จ์๋ฉด์ ๋น ์ํํธ ๋งค๋งค ์ค๊ฑฐ๋๊ฐ ํ๊ท ์ง๋๋ก ๋ง๋ค๊ธฐ
- ๋ฉํฐ๋ชจ๋ฌ AI & ์ฑ๋ด ๊ฐ๋ฐ – ์์ฑํ AI์ ์ฑ๋ด์ ํ์ฉํ ์ค์๊ฐ ์์ ์ ๋ฌธ ์คํฌ๋ ์ดํ
- ์น ์๋ํ & ํฌ๋กค๋ง – ์ฐ๊ด ํค์๋ ๋ถ์์ ํตํ ์ฐ๋ น๋ณ, ์ฑ๋ณ ์ผํ ํธ๋ ๋ ๋ถ์
- ๊ฒ์ & GUI ๊ฐ๋ฐ – ์ฌ๋ผ์ด๋ฉ ํผ์ฆ, ์์ด ๋ฐ์์ฐ๊ธฐ ์ฑ์ผ๋ก ์ง์ ๋ง๋ค์ด ๋ณด๋ ์ธํฐ๋ํฐ๋ธ ํ๋ก์ ํธ
์๋์ ๊ฒฐ๊ณผ๋ฌผ๋ค์ ํ๋์ฉ ๋ง๋ค์ด๋ณผ ์ ์๋ค
๋ชฉ์ฐจ
Chapter01. ํด๋ ํฌ๊ธฐ ์ธก์ ํ๋ก๊ทธ๋จ
- ํ์ด์ฌ ๊ฐ๋ฐ ํ๊ฒฝ ์ค์ , ํด๋ ํฌ๊ธฐ ์ธก์ ํ๋ก๊ทธ๋จ, ๋ฐ์ดํฐ ์๊ฐํํ๊ธฐ
Chapter02. ์๋ณ ์นด๋ ์ง์ถ ๋ด์ญ ๋ถ์
- ์๋ณ ๋ช
์ธ์ ์ทจํฉ, ์นด๋ ์ง์ถ ๋ด์ญ ๋ถ์, 1๋ถ๊ธฐ ์ง์ถ ์ฐจํธ ๋ง๋ค๊ธฐ
Chapter03. ์ด๋ฏธ์ง ์ฝ๋ผ์ฃผ
- ์ด๋ฏธ์ง ๋ถ๋ฌ์ค๊ธฐ, ๊ฐ๊ณตํ๊ธฐ, ์ฝ๋ผ์ฃผ ๋ง๋ค๊ธฐ
Chapter04. QR์ฝ๋๋ก ์ฐ๋ฝ์ฒ ๊ณต์
- QR ์ฝ๋ ๊ธฐ์ด ๋ค์ง๊ธฐ, ์ฐ๋ฝ์ฒ๋ฅผ QR ์ฝ๋๋ก ๋ง๋ค๊ธฐ, QR ์ฝ๋์ ์ด๋ฏธ์ง ์ฝ์
ํ๊ธฐ
Chapter05. ์ด๋ฏธ์ง ์ ํ
์คํธ ๋ฒ์ญํ๊ธฐ
- ์น ์๋ ์๋ฆฌ, ์ด๋ฏธ์ง ์ ๋ฌธ์ ์ธ์, DeepL ๋ฒ์ญ ๊ธฐ๋ฅ ์ถ๊ฐํ๊ธฐ
Chapter06. ์ผํ ํธ๋ ๋ ๋ณด๊ณ ์
- ์น์์ ๋์ ์๋ํํ๊ธฐ, ์ผํ ํธ๋ ๋ ์ ๋ณด ์์ง, ๋ณด๊ณ ์ ์์ฑ
Chapter07. ์๊ฐ์ด์ก ๋ถ์
- ์ข
๋ชฉ๋ณ ์๊ฐ์ด์ก ๋ฐ์ดํฐ ์์ง, ํ์ด์ง ์ด๋ ์๋ํ, ์๊ฐ์ด์ก ๋ฐ์ดํฐ ์๊ฐํ
Chapter08. ์ฐ๊ด ํค์๋ ๊ฒฝ์ ๊ฐ๋ ๋ถ์
- ๋ค์ด๋ฒ ์ผํ ์ฐ๊ด ํค์๋ ๊ฒ์, ๊ฒฝ์ ๊ฐ๋ ๋ถ์, ์ฐ๊ด ํค์๋ ๋ถ์ ์ฑ ๋ง๋ค๊ธฐ
Chapter09. ์ฃผ์ ๊ฒฝ์ ์งํ ๊ทธ๋ํ
- ๊ธฐ์ค ๊ธ๋ฆฌ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ, ๋ค์ํ ๊ฒฝ์ ์งํ ๋ฐ์ดํฐ ์์ง, ์ฃผ์ ๊ฒฝ์ ์งํ ๊ทธ๋ํ ๊ทธ๋ฆฌ๊ธฐ
Chapter10. ์ ๊ธฐ์๊ธ ๊ธ๋ฆฌ ํํฉํ
- ์ ๊ธฐ์๊ธ ๋ฐ์ดํฐ ์์ง, ์ฃผ์ ๊ธ๋ฆฌ์งํ ์๊ฐํ, ์ ๊ธฐ์๊ธ ๊ธ๋ฆฌ ํํฉํ ์์ฑ
Chapter11. ์ํํธ ๋งค๋งค ์ค๊ฑฐ๋๊ฐ ์ง๋
- ๋จ์ ๋ฉด์ ๋น ํ๊ท ์ค๊ฑฐ๋๊ฐ ๋ถ์ ๋ฐ ์๊ฐํ
Chapter12. ๋ฏธ์๋ฆฐ ๊ฐ์ด๋ ์ง๋
- ๋ง์ง ํ์ ์๋ํ, ์ขํ ์์ง, ์ง๋ ๊ทธ๋ฆฌ๊ธฐ
Chapter13. ์์ฑํ AI ๊ธฐ์ฌ ๋ฒ์ญ ์ฑ
- LLM ๋ง๋ณด๊ธฐ, ์ฑ๋ด ๋ง๋ค๊ธฐ, ๊ธฐ์ฌ ๋ฒ์ญ ์น ์ฑ ๋ง๋ค๊ธฐ
Chapter14. ์์ด ๋ฐ์์ฐ๊ธฐ ์ฑ
- ๋ฉํฐ๋ชจ๋ฌ AI ์ฑ๋ด ๋ง๋ค๊ธฐ, ํ ์คํธ->์์ฑ์ผ๋ก ๋ณํ, ์์ด ๋ฐ์์ฐ๊ธฐ ์ฑ ๋ง๋ค๊ธฐ
Chapter15. ์ฌ๋ผ์ด๋ฉ ํผ์ฆ ๋ง๋ค๊ธฐ
- ํผ์ฆ ๋ณด๋ ๋ง๋ค๊ธฐ, ์ฌ๋ผ์ด๋ฉ ํผ์ฆ ๊ตฌํ, ๊ฒ์ ๊ทธ๋ํฝ ๊ตฌํ
๋ด์ฉ
15๊ฐ์ ๋ฏธ๋ ํ๋ก์ ํธ ์ค AI์ ๊ด๋ จ๋ ์ฑํฐ๋ค์ ๋จผ์ ์ง์ ๋ฐ๋ผ๊ฐ๋ณด์๋ค
๊ด๋ จ๋ ์ฝ๋์ ์์ค๋ค์ ์๋ ๊นํ์ ์ฐธ๊ณ ํ๋ฉด ๋๋ค
https://github.com/himoon/gopython
GitHub - himoon/gopython
Contribute to himoon/gopython development by creating an account on GitHub.
github.com
Chapter05. ์ด๋ฏธ์ง ์ ํ ์คํธ ๋ฒ์ญํ๊ธฐ
1. ์น์ ์๋ ์๋ฆฌ
- ์น ๋ธ๋ผ์ฐ์ : ํฌ๋กฌ, ์ฃ์ง, ์ฌํ๋ฆฌ
- ์น ๋ธ๋ผ์ฐ์ ์๋ ์น์ฌ์ดํธ ๊ฐ๋ฐ ๋ฐ ๋๋ฒ๊น
์ ๋๊ธฐ ์ํ ๊ฐ๋ฐ์ ๋๊ตฌ๋ผ๋ ๋๊ตฌ ๋ชจ์์ด ๋ด์ฅ๋์ด ์์
- ๋ธ๋ผ์ฐ์ ์ ์๋ฒ์ ์๋ฐฉํฅ ํต์ ๊ธฐ๋ก ์ด๋
- ๊ฒ์ฌ ๋ชจ๋๋ฅผ ์ฌ์ฉํด ์น ๋ฌธ์์ HTML ์์ ๋ถ์ ๊ฐ๋ฅ
- ๊ฐ์ํ๊ฒฝ ์ค์ ๋ฐ ํ์ํ ํจํค์ง๋ค ์ค์นํ๊ธฐ
- ์ฑ ์์๋ venv ์ฐ์ง๋ง conda ์ฌ์ฉ
- python 3.12
- ํ์ ํจํค์ง (numpy, torch, easyocr)
- easyocr์ pytorch ๊ธฐ๋ฐ์ผ๋ก ์ ์๋จ
- numpy 1.26.4
- torch 2.2.2
- easyocr 1.7.2
- pillow 10.4.0
- deepl
- streamlit
pip install -U "numpy<=1.26.4" "torch<=2.5.1" "torchvision<=0.20.1" "easyocr<=1.7.2" "pillow<=10.4.0" deepl streamlit
์น์ ์๋ ์๋ฆฌ ์ดํดํ๊ธฐ
HTTP ์์ฒญ๊ณผ ์๋ต
- ์น ๋ธ๋ผ์ฐ์ ์ ํ์ด์ง๋ฅผ ๋ถ๋ฌ์ค๋ ค๋ฉด ์น ์๋ฒ์์ ์ ๊ณตํ๋ ๋ฐ์ดํฐ์ธ ๋ฆฌ์์ค๊ฐ ํ์
- ์ฌ์ฉ์๊ฐ URL์ ์
๋ ฅํ๋ฉด ์น ๋ธ๋ผ์ฐ์ ๊ฐ ์น ์๋ฒ์ ๋ฆฌ์์ค๋ฅผ ์์ฒญ, HTTP๋ผ๋ ํน์ ๊ท์น์ ๋ฐ๋ผ ์์ฒญ ๋ฉ์ธ์ง๋ฅผ ์์ฑํด์ผํจ
- ์น ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ฒ์ HTTP ์์ฒญ ๋ฉ์ธ์ง๋ฅผ ์ ๋ฌ
โก๏ธ ์น ๋ธ๋ผ์ฐ์ — HTTP ์์ฒญ ๋ฉ์ธ์ง ์ ์ก —> ์น ์๋ฒ - ์น ์๋ฒ๋ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ณด๋ธ HTTP ์์ฒญ ๋ฉ์ธ์ง๋ฅผ ๋ถ์.์๋ฒ๊ฐ ์์ฑํ ์๋ต ๋ฉ์ธ์ง๋ฅผ HTTP ์๋ต ๋ฉ์ธ์ง๋ผ ํ๋ค.
โก๏ธ ์น ๋ธ๋ผ์ฐ์ <— HTTP ์๋ต ๋ฉ์ธ์ง ์ ์ก — ์น ์๋ฒ - ์์ฒญ ๋ฉ์ธ์ง ๊ท์น, ์์ฒญ ๊ถํ, ์์ฒญ ๋ฆฌ์์ค๊ฐ ์น ์๋ฒ์ ์กด์ฌํ๋์ง ๋ฑ์ ํ์ธ ํ ํด๋น ๊ฒฐ๊ณผ์ ๋ฐ๋ผ ์ ์ ํ ์๋ต ๋ฉ์ธ์ง๋ฅผ ์น ๋ธ๋ผ์ฐ์ ์ ์ ๋ฌ
- ์น ๋ธ๋ผ์ฐ์ ๋ HTTP ์๋ต ๋ฉ์ธ์ง๋ฅผ ๋ถ์ํ์ฌ ๊ทธ ๊ฒฐ๊ณผ์ ๋ฐ๋ผ ํ๋ฉด์ ๋ฆฌ์์ค๋ฅผ ์ถ๋ ฅ. ์ด๋ ๊ฒ ์๋ฒ์์ ๋ฐ์ ๋ฐ์ดํฐ๊ฐ ์น ๋ธ๋ผ์ฐ์ ์ ์ถ๋ ฅ๋๋ ๊ณผ์ ์ ๋ ๋๋ง์ด๋ผ ํจ
- ์น ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ฒ์ HTTP ์์ฒญ ๋ฉ์ธ์ง๋ฅผ ์ ๋ฌ
streamlit ์น ์ฑ
- ์น ์ฑ : ์น ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด ์ ๊ทผํ๊ณ ์ฌ์ฉํ ์ ์๋ ํ๋ก๊ทธ๋จ. URL๋ง ์๋ค๋ฉด ๋ฐ๋ก ์ ๊ทผ ๊ฐ๋ฅ
- streamlit : ํ์ด์ฌ๋ง์ผ๋ก ์น ์ฑ์ ๋ง๋ค ์ ์๋๋ก ํด์ฃผ๋ ํจํค์ง
๊ฐ๋ฐ์ ๋๊ตฌ์์ HTTP ๋ฉ์ธ์ง ๋ถ์
- ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ํตํด ์น ๋ธ๋ผ์ฐ์ ๊ฐ ์น ์๋ฒ์ ์ฃผ๊ณ ๋ฐ์ HTTP ๋ฉ์ธ์ง๋ฅผ ๊ธฐ๋กํ๊ณ ๋ถ์ํ ์ ์์
- ํฌ๋กฌ ์น ๋ธ๋ผ์ฐ์ ์์ ๋ค์ด๋ฒ ์ ์ ํ F12๋ก ๊ฐ๋ฐ์ ๋๊ตฌ ์คํ
- ์น ๋ธ๋ผ์ฐ์ ์ ์๋ฒ๊ฐ ์ฃผ๊ณ ๋ฐ์ HTTP ๋ฉ์์ง๋ฅผ ํ์ธํ๊ธฐ ์ํด ๋คํธ์ํฌ ํญ ํด๋ฆญ ํ Ctrl+R๋ก ์๋ก๊ณ ์นจ
- Name ๋ชฉ๋ก์์ ์น์ฌ์ดํธ ์ฃผ์, www.naver.comํญ๋ชฉ์ ํด๋ฆญํ๋ฉด ์ค๋ฅธ์ชฝ HTTP ๋ฉ์์ง๋ฅผ ํ์ธํ ์ ์๋ ํญ์ด ์ด๋ฆผ.
- Headers์์ Reponse Headers ์์ ์น ์๋ฒ๊ฐ ๋ณด๋ธ HTTP ์๋ต ๋ฉ์ธ์ง, Request Headers์์ ์น ๋ธ๋ผ์ฐ์ ๊ฐ ๋ณด๋ธ HTTP ์์ฒญ ๋ฉ์ธ์ง๋ฅผ ํ์ธ ๊ฐ๋ฅ
- Response์์ ์น ์๋ฒ๊ฐ ์น ๋ธ๋ผ์ฐ์ ์ ์ ๋ฌํ ์ค์ ๋ฆฌ์์ค ํ์ธ ๊ฐ๋ฅ
2. ์ด๋ฏธ์ง ์ ๋ฌธ์ ์ธ์ํ๊ธฐ
- easyocr ํจํค์ง๋ก ์ด๋ฏธ์ง์ ํฌํจ๋ ๋ฌธ์๋ฅผ ์ธ์ํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ pillow ํจํค์ง๋ก ์๊ฐํ
- ์ด๋ฌํ ์ธ์ ํ๋ก๊ทธ๋จ์ streamlit ํจํค์ง์ ๊ฒฐํฉํ์ฌ ์น ์ฑ์ผ๋ก ๊ตฌํ
๋ฌธ์ ์ธ์ ํ๋ก๊ทธ๋จ ๋ง๋ค๊ธฐ
- easyocr์์ Reader ํด๋์ค
- easyocr์ ํต์ฌ ํด๋์ค๋ก ๋ฌธ์ ์ธ์์ ์ฌ์ฉํ ์ธ์ด๋ฅผ ๋ฆฌ์คํธ ํ์ ์ผ๋ก Reader ๊ฐ์ฒด๋ก ์ ๋ฌํ๋ค์, ํจ์ readtext()๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฏธ์ง ์ ๋ฌธ์๋ฅผ ๊ฐ์งํ ์ ์๋ค
- readtext() ๋ ์ด๋ฏธ์ง ํ์ผ์ ์ ๋ ฅ๋ฐ๊ณ , ์ด๋ฏธ์ง ์ ๋ฌธ์์ ์ขํ์ ์ธ์ํ ๋ฌธ์, ์ธ์๋ฅ ์ ํํ ํ์ ์ผ๋ก ๋ฐํํ๋ค
- ํจ์ readtext() ๋ ๋ฌธ์์ด ํ์ ์ ์ด๋ฏธ์ง ๊ฒฝ๋ก, bytes ํ์ ์ ์ด๋ฏธ์ง ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅ๊ฐ์ผ๋ก ๋ฐ๋๋ค
- ๋ฐํ๊ฐ์ ์ธ์๋ฅ ์ 1์ ๊ฐ๊น์ธ์๋ก ์ ํํ๋ค
- result :
[([[85, 288], [1088, 288], [1088, 457], [85, 457]], 'Being a vegetarian', 0.9823604886339942),
([[77, 417], [1159, 417], [1159, 574], [77, 574]], 'is a big missed steak', 0.4830981879580033)] - [85, 288], [1088, 288], [1088, 457], [85, 457]] : ์ขํ
- 'Being a vegetarian' : ๋ฌธ์
- 0.9823604886339942 : ์ธ์๋ฅ
- ๊ฐ๋จ ์์ ์คํ์ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ 6.5์ด.
- result :
- ๋ฐ์ด๋ฉ ๋ฐ์ค ์ถ๊ฐ
- pillow์ polygon() ์ด์ฉ
- ํํ ํํ์ ์ขํ๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์
๋ฌธ์ ์ธ์ ์น ์ฑ ๋ง๋ค๊ธฐ
- streamlit ์ฌ์ฉ
- ์น ์ฑ์ ์ด๋ฏธ์ง ํ์ผ์ ์ ๋ก๋ํ๋ฉด, ํจ์ read_text_and_draw_line() ์ ์ฌ์ฉํด ์ด๋ฏธ์ง ์ ๋ฌธ์๋ฅผ ์ธ์ํ๊ณ ๋ฐ์ด๋ฉ ๋ฐ์ค๋ฅผ ๊ทธ๋ฆฐ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅ
3. DeepL ๋ฒ์ญ ๊ธฐ๋ฅ ์ถ๊ฐํ๊ธฐ
์์์ ๋ง๋ค์ด์จ ์ฝ๋์ DeepL API๋ฅผ ์ถ๊ฐํ์ฌ ๋ฒ์ญ ๊ธฐ๋ฅ์ ์ถ๊ฐํ ์ ์๋ค
DeepL ์ฌ์ดํธ์ ํ์ ๊ฐ์ ํ ๋ฌด๋ฃ ํ๋์ผ๋ก API๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์นด๋ ๋ฑ๋ก์ด ํ์ํ๋ค
๋ฒ์ญ ๊ธฐ๋ฅ ์ถ๊ฐํ ๊ฒฐ๊ณผ๋ฌผ์ ์๋์ ๊ฐ๋ค
๋ด์ฉ์ ์ญ ๋ฐ๋ผ๊ฐ๋ค๋ณด๋ฉด ์ด๋ ๊ฒ ์์ ๊ฐ์ ๊ฐ๋จํ ์ด๋ฏธ์ง ์ธ์ ์น ํ์ด์ง๋ฅผ ๋ง๋ค ์ ์๋ค
๋ฌผ๋ก ๋จ์ ํ์ดํ๋ง์ผ๋ก๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฝ๋ ์ฌ์ฉ๋ฒ์ ์จ์ ํ ๋ด๊ฒ์ผ๋ก ๋ง๋ค๊ธฐ๋ ํ๋ค์ง๋ง.. ์ฌ์ฉํ๋ ๊ฒ๋ค์ ๋ฐํ์ผ๋ก ์กฐ๊ธ์ฉ ์ปค์คํ ํด๋ณด๋ฉด์ ์ต์ํด์ง๋ ์๊ฐ๋ ํ์ํ๋ค
์ฑํฐ๋ณ ๋ง์ง๋ง์ ์๋ ๋ฏธ๋ ํ๋ก์ ํธ๋ ๊ทธ๋์ ์ฌ์ฉํด์๋ ์ฝ๋์ ๊ธฐ๋ฅ๋ค์ ์ ์์ฉํด์ ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ฑฐ๋ ๋ณํํ๋ ์ฐ์ต ๋ฌธ์ ์ด๋ค
Chapter13. ์์ฑํ AI ๊ธฐ์ฌ ๋ฒ์ญ ์ฑ
1. ollama ์ตํ๊ธฐ
- ollama๋ ์คํ์์ค AI ๋ชจ๋ธ์ ํธํ๊ฒ ๊ด๋ฆฌํ ์ ์๋ ๋๊ตฌ๋ก, ๋ค์ํ ์คํ์์ค LLM ์ ์ง์ํ๋ค
- ๊ฐํธํ ์ค์น, ์ฌ์ด ์ฌ์ฉ๋ฒ๊ณผ CLI ๊ธฐ๋ฐ์ ์คํ ๋ฐฉ์์ด ํน์ง
- ollama ์ฌ์ดํธ์์ ๋ค์ด๋ฐ๊ณ ์ค์นํ๊ธฐ
Download Ollama on macOS
Download Ollama for macOS
ollama.com
๋ค์ด๋ฐ๊ณ ํ์ผ ์คํ์์ผ ์ค์นํ๋ค ํฐ๋ฏธ๋์์ ollama๋ฅผ ์คํ์ ์์ ๊ฐ์ ์ด๋ฏธ์ง์ฒ๋ผ ์ ์์ ์ผ๋ก ์คํ๋๋ค
ํฐ๋ฏธ๋์ฐฝ์์ gemma2 ๋ชจ๋ธ์ ์ฌ์ฉํ๊ธฐ
์ ฌ๋ง ๋ชจ๋ธ ๋ถ๋ฌ์ค๊ธฐ
๊ฐ๋จํ ๋ฌธ์ฅ ๋ฒ์ญ
ollama์ ํจ์๋ฅผ ํตํด ๋ฌธ๋ต ๊ฐ๋ฅ
import ollama
resp1 = ollama.chat(
model="gemma2:9b",
messages=[{'role':'user', 'content':'๋ด ์ด๋ฆ์ ๊น์ถ์์ด์ฌ!!'}]
)
print(resp1['message'])
๋ค๋ง ์ด๋ ๊ฒ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ด์ ์ ๋ํ ๋ด์ญ๋ค์ด ์ด์ด์ง์ง ์์ผ๋ฏ๋ก LLM๊ณผ ์ฃผ๊ณ ๋ฐ์ ๋ํ๋ฅผ ๋ชจ๋ ๊ธฐ๋กํ๊ณ , ๋ํํ ๋๋ง๋ค ๊ทธ ๊ธฐ๋ก์ ํจ๊ป ์ ๋ฌํ๋ฉด ์ด์ ๋ํ๋ฅผ ์ด์ด๋๊ฐ ์ ์๋ค ⇒ ๋ฌธ๋งฅ ํ์ฑ
import ollama
msgs = [{'role':'user', 'content':'๋ด ์ด๋ฆ์ ๊น์ถ์์ด์ฌ!!'}]
resp1 = ollama.chat(model="gemma2:9b", messages=msgs)
msgs.append(resp1['message'])
msgs.append({'role':'user', 'content':'๋ด ์ด๋ฆ์ด ๋ญ๋ผ๊ณ ํ์ง???'})
resp2 = ollama.chat(model="gemma2:9b", messages=msgs)
msgs.append(resp2['message'])
print(msgs)
---
[{'role': 'user', 'content': '๋ด ์ด๋ฆ์ ๊น์ถ์์ด์ฌ!!'},
Message(role='assistant', content='์๋
ํ์ธ์, ๊น์ถ์๋! ๐
\n\n๋ง๋์ ๋ฐ๊ฐ์์. ๋ฌด์์ ๋์๋๋ฆด๊น์? ๐', images=None, tool_calls=None),
{'role': 'user', 'content': '๋ด ์ด๋ฆ์ด ๋ญ๋ผ๊ณ ํ์ง???'},
Message(role='assistant', content='๊น์ถ์์ด๋ผ๊ณ ๋ง์ํ์
จ์ด์! ๐ ๊ธฐ์ตํ๋?
\n\n\n\n\n๋ฌด์จ ์ด์ผ๊ธฐ๋ฅผ ํ๊ณ ์ถ์ผ์ ๊ฐ์, ๊น์ถ์๋? ๐ค', images=None, tool_calls=None)]
์ด๋ ๊ฒ ๋ํ ๋ด์ญ์ ์ถ์ ํ์ฌ ๋ฌธ๋งฅ์ ์ญ ์ด์ ์ ์๋ค. ๋ค๋ง LLM๋ง๋ค ํ ๋ฒ์ ์ฒ๋ฆฌํ ์ ์๋ ๋ํ ๊ฐ๋ก์ ๊ธธ์ด์๋ ์ ํ์ด ์๋ค
2. ์ฑ๋ด ๋ง๋ค๊ธฐ
streamlit์ผ๋ก ๊ตฌํํ ์น ์ฑ์ ๊ตฌ๊ธ gemma2, ๋ฉํ์ llama3.1์ ๋์์ ์ฌ์ฉํ์ฌ, ์ฌ์ฉ์๊ฐ ํ ๋ฒ ๋ฉ์ธ์ง๋ฅผ ์ ๋ ฅํ๋ฉด ๋ LLM์ผ๋ก๋ถํฐ ์๋ต์ ๋ฐ์ ๋น๊ตํ ์ ์๊ฒ ๋ง๋ค์ด๋ณผ ๊ฒ์ด๋ค
LLM์ ํ์ฉํ ์ฑ๋ด ์น ์ฑ ๋ง๋ค๊ธฐ
- streamlit ํจํค์ง์ ์ฑํ
์์ ฏ
- ํด๋น ํจํค์ง์์๋ ์ฑ๋ด ๊ตฌํ์ ์ง์ํ๋ ์ฌ๋ฌ ๋ช ๋ น์ด๋ค์ ์ง์ํ๋ค
- ๊ทธ ์ค ์๋์ ๋ ํจ์๋ ์ฑ๋ด ๊ตฌํ์ ๊ฑฐ์ ํ์์ ์ผ๋ก ์ฌ์ฉ๋๋ค
- st.chat_message() : ์ฑ์ ์ฑํ ๋ฉ์์ง ์ปจํ ์ด๋๋ฅผ ์ฝ์ ํ๋ค
- st.chat_input() : ์ฌ์ฉ์๊ฐ ์ฑํ ๋ฉ์ธ์ง๋ฅผ ์ ๋ ฅํ ์ ์๋ ์์ ฏ์ ํ์ํ๋ค
import streamlit as st
with st.chat_message('user'):
st.write('Hello')
prompt = st.chat_input('Say something')
์์ ๊ฐ๋จํ streamlit ์ฝ๋๋ฅผ ์คํํ๋ฉด ์๋์ ๊ฐ๋จํ ์น ํ์ด์ง๊ฐ ๋์จ๋ค
streamlit ์์๋ ์์ฑํ AI๋ฅผ ์ํ ์ฑํ ์์ ฏ์ ์ ๊ณตํ๋ค. ์ฌ์ฉํ ํจ์๋ ์ธ ๊ฐ์ง์ด๋ค
- init_session_state() : streamlit ์ธ์ ์ ์ด๊ธฐํ
- chat_message_user() : LLM ๋ชจ๋ธ์ ์ ๋ฌํ ์ฌ์ฉ์ ๋ฉ์ธ์ง๋ฅผ ์น ์ฑ์ ํ๋ฉด์ ์ถ๋ ฅ
- chat_message_llm() : LLM ๋ชจ๋ธ์ ์๋ต์ ์น ์ฑ์ ํ๋ฉด์ ์ถ๋ ฅ
์ฌ๋ฌ ๊ฐ์ LLM์ ๋์์ ์ฌ์ฉํ๊ธฐ
์คํ์์ค LLM, ๊ตฌ๊ธ์ gemma2์ ๋ฉํ์ llama3.1์ ์ฌ์ฉ
3. ๊ฐ์ฌ ๋ฒ์ญ ์น ์ดํ๋ฆฌ์ผ์ด์ ๋ง๋ค๊ธฐ
- HTML ๋ฌธ์์์ ํ ์คํธ ์ถ์ถํ๋ ๋ฐฉ๋ฒ์ ํ์ตํ๋ค
- ๊ทธ๋ฆฌ๊ณ LLM์ ํ์ฉํ์ฌ ์ธ๊ตญ์ด ๊ธฐ์ฌ๋ฅผ ๋ฒ์ญํ๋ ์น ์ฑ์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋ค๋ฃฌ๋ค
- trafilatura ํจํค์ง๋ ์น ํฌ๋กค๋ง ๋ฐ ์คํฌ๋ ์ดํ์ ์ฌ์ฉ๋๋ฉฐ, ํนํ HTML ๋ฌธ์์์ ํ ์คํธ๋ฅผ ํจ์จ์ ์ผ๋ก ์ถ์ถํ๋ค. ์ค๊ฐ์ ๋ถ์ ๊ณผ์ ์ ์๋ตํ ์ ์๊ธฐ ๋๋ฌธ์ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ ์ฝ๊ฒ ์ถ์ถํ ์ ์๋ค
ํ ์คํธ ์ถ์ถํ๊ธฐ
trafilatura ํจํค์ง๋ก ์น์ฌ์ดํธ์์ ํ ์คํธ ์ถ์ถ
- featch_url() : ์ฃผ์ด์ง URL์ ์ ์ํ์ฌ HTML์ ์์ง
- extract() : ์ฃผ์ด์ง HTML์์ ํ ์คํธ๋ฅผ ์ถ์ถ
- extract_metadata() : ์ฃผ์ด์ง HTML์์ ์ ๋ชฉ, ์์ฑ์, ์ด๋ฏธ์ง ๋ฑ ๋ฉํ ๋ฐ์ดํฐ๋ฅผ ์ถ์ถ
import json
import trafilatura
url = "https://www.koreaherald.com/view.php?ud=20240725050618"
html: str = trafilatura.fetch_url(url) # HTML ์์ง
extracted: str = trafilatura.extract(html, output_format="json", with_metadata=True,)
parsed = json.loads(extracted)
print(parsed)
---
{'title': 'Seventeen announces world tour at fan meeting',
'author': 'Kim Jae-heun', 'hostname': 'koreaherald.com',
'date': '2024-07-25', 'fingerprint': '36598b35bd9b2394',
'id': None, 'license': None, 'comments': '',
'raw_text': 'K-pop sensation Seventeen of Pledis Entertainment concluded its eighth fan meeting with a surprise announcement of a world tour later this year.
Seventeen held two editions of "2024 SVT 8th Fan Meeting (Seventeen in Carat Land)" at Gocheok Sky Dome in Seoul on Tuesday and Wednesday.
The event left unforgettable memories for both the fans in attendance and those from 118 countries and regions watching live.
...
'language': None,
'image': 'https://wimg.heraldcorp.com/content/default/2024/07/25/20240725050564_0.jpg',
'pagetype': 'article', 'filedate': '2025-03-19', 'source': 'https://www.koreaherald.com/article/3441040',
'source-hostname': 'The Korea Herald',
'excerpt': 'K-pop sensation Seventeen of Pledis Entertainment concluded its eighth fan meeting with a surprise announcement of a world tour later this year.
Seventeen held two editions of "2024 SVT 8th Fan Meeting (Seventeen in Carat Land)" at Gocheok Sky Dome in Seoul on Tuesday and Wednesday.
The event left unforgettable memories for both the fans in attendance and those from 118 countries and regions watching live. By the end on Wednesday, Seventeen released a teaser video announcing its world',
'categories': '', 'tags': ''}
๊ฐ์ฌ ๋ฒ์ญ ๊ธฐ๋ฅ ์ถ๊ฐ
- ํ๋กฌํํธ ์ ๋ ฅ ์์ ฏ์ ์๋ฌธ ๊ธฐ์ฌ ๋งํฌ๋ฅผ ์ ๋ฌํ๋ฉด ์ด๋ฅผ ๋ฒ์ญํ์ฌ ์๋ฌธ๊ณผ ํจ๊ป ๋ฒ์ญ๋ ํ ์คํธ๋ฅผ ์ถ๋ ฅํ๋ ์ฑ๋ด
- ์ด๋ฅผ ์ํด ๊ตฌํํด์ผํ ๊ธฐ๋ฅ๋ค ๋ช๊ฐ์ง๊ฐ ์กด์ฌํ๋ค
- ํ๋กฌํํธ์ ์ ๋ ฅ๋ URL์ ์ ์ํด ๊ธฐ์ฌ์ ๋ณธ๋ฌธ์ ์ถ์ถ
- ์ถ์ถํ ํ ์คํธ๋ฅผ ์์ฑํ AI๋ฅผ ์ฌ์ฉํด ๋ฒ์ญ
- ์น ์ฑ์ ๋ ์ด์์์ ๊ตฌ์ถํ๊ณ ๊ธฐ์ฌ์ ์๋ฌธ๊ณผ ๋ฒ์ญํ ํ ์คํธ๋ฅผ ์ถ๋ ฅ
- ์์คํ
ํ๋กฌํํธ ์ค์
- ์์คํ ํ๋กฌํํธ๋ AI ๋ชจ๋ธ์ด ์ง์ผ์ผํ ์ง์นจ์ด๋ ๋งฅ๋ฝ์ ์ค์ ํ๋ ์ญํ
- AI๊ฐ ์ฌ์ฉ์์ ๋ฉ์ธ์ง๋ ์์
์์ฒญ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ง์ ๋ํ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํ๋ค
- ์ญํ ์ค์ : “๋น์ ์ ์๋ จ๋ ๋ฒ์ญ๊ฐ์ ๋๋ค. ์ฃผ์ด์ง ํ ์คํธ๋ฅผ ํ๊ตญ์ด๋ก ๋ฒ์ญํ๋ ๊ฒ์ด ๋น์ ์ ์๋ฌด์ ๋๋ค”
- ์ด์กฐ ์ค์ : “์น์ ํ๊ณ ๋ช ํํ๊ฒ ๋ต๋ณํด ์ฃผ์ธ์”
- ๊ท์น ์ค์ : “๋งํฌ๋ค์ด ์์์ ์ ์งํด ์ฃผ์ธ์”
์ฌ๊ธฐ์ ์ฌ์ฉํ ์์คํ ํ๋กฌํํธ
๋น์ ์ ๋ง์ ์ธ์ด์ ๋ํ ์ ๋ฌธ ์ง์์ ๊ฐ์ถ ๋งค์ฐ ์๋ จ๋ ๋ฒ์ญ๊ฐ์ ๋๋ค. ๋ด๊ฐ ์ ๊ณตํ๋ ํ ์คํธ์ ์ธ์ด๋ฅผ ์๋ณํ ๋ค์, ์๋ฌธ์ ์๋ฏธ, ์ด์กฐ, ๋์์ค๋ฅผ ์ ์งํ๋ฉด์ ํ๊ตญ์ด๋ก ์ ํํ๊ฒ ๋ฒ์ญํ๋ ๊ฒ์ด ๋น์ ์ ์๋ฌด์ ๋๋ค. ๋ฒ์ญ๋ ๋ฒ์ ์์๋ ๋ฌธ๋ฒ, ์ฒ ์, ๊ตฌ๋์ , ์ค๋ฐ๊ฟ, ๋งํฌ๋ค์ด ์์์ ์ ํํ๊ฒ ์ ์งํด ์ฃผ์ธ์.
ollama ์์ ์์คํ ํ๋กฌํํธ๋ฅผ ์ค์ ํ๊ธฐ ์ํด์๋ ‘role’ ํค์ ๊ฐ์ ‘system’์ ์ง์ ํ์ฌ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ฉด ๋๋ค
import ollama
msgs = [
{'role':'system', 'content':'์
๋ ฅ๋ ํ
์คํธ๋ฅผ ํ๊ตญ์ด๋ก ๋ฒ์ญํด์ฃผ์ธ์'},
{'role':'user', 'content':'Hello, World!'},
]
resp = ollama.chat(model='gemma2:9b', messages=msgs)
print(resp['message']['content]
๊ฒฐ๊ณผ๋ฌผ
The use_column_width parameter has been deprecated and will be removed in a future release. Please utilize the use_container_width parameter instead.
์ฌ์ฉํ ํ๋ผ๋ฏธํฐ ์ค ๋ฐ๋ ๋ถ๋ถ์ด ์๋ ๊ฒ ๊ฐ๋ค
์ง๊ธ๊น์ง ์ฑ , ํผ์ ๋ง๋ค๋ฉด์ ๊ณต๋ถํ๋ ํ์ด์ฌ์ ์ฑ ์๊ฐ์ ๊ณต๋ถํ ๋ด์ฉ ์ผ๋ถ๋ฅผ ๊ฐ์ ธ์์ ์ ๋ฆฌํด๋ณด์๋ค
์ฝ๋๋ฅผ ๋ฐ๋ผ์ณ๋ณด๋ฉด์ ์ฌ๋ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ฌ์ฉํ๊ณ ๊ณต๋ถํด๋ณผ ์ ์์๊ณ ๋ฏธ๋ ํ๋ก์ ํธ๋ฅผ ํตํด ๋จ์ ์ฝ๋ ๋ฐ๋ผ์น๊ธฐ๊ฐ ์๋ ํ์ฉ๋ฒ๊น์ง ์ตํ ์ ์์๋ค
ํ์ด์ฌ ๊ธฐ์ด์ฑ ์ ๊ณต๋ถํ ๋ค ์ด๋ค ๊ณต๋ถ๋ฅผ, ์ฑ ์ ๋ด์ผํ ์ง ์ ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด ํด๋น ์ฑ ์ ์ถ์ฒํ๋ค