ํ์: ๋ณ๊ฐ์, ๊น์งํ, ๋จ๊ฒฝํ, ์ด๋ํ, ์ด์ฑ๋ฏผ, ์ต๋ฏผ์ฌ
ํ๋
ธ์
ํ์ด์ง: Notion
- About
- Main Fuctions
- Architecture
- Setting
- Engine
- General_Summarization
- Keysentence_Extraction
- Question_Answering
- Code_Architecture
๐ก์ฃผ์ : ์ธ๊ณต์ง๋ฅ ํ์ฉ ์๊ธฐ์๊ฐ์ ์์ฝ ํ์ด์ง
#NLP
#Text_Summarization
#Question_Answering
#Flask
-
- ๋งค ์ฑ์ฉ์ ์ง์์๋ ๋์ผํ ์ง๋ฌธ์ ์ ํ๋ ๊ธ์ ์ ๋ด์์ ๋ต๋ณ์ ํ๊ณ ์๋ค.
- ์ ์
์ฌ์ ์ฑ์ฉ์ ์ด๋ ฅ์๋ณด๋ค ์๊ธฐ์๊ฐ์๋ฅผ ์ค์ํ๊ฒ ํ๊ฐ
- ๊ฒฝ๋ ฅ์ด ์๋ ์ ์ ์ฌ์์ ์ ๋ฌด ์ํ๋ฅ๋ ฅ์ ๋น์ทํ๊ธฐ ๋๋ฌธ์ ์ง์์์ ์ ์ฌ๋ ฅ์ ํ์ ํ๊ธฐ ์ํ ๋๊ตฌ๋ก ์๊ธฐ์๊ฐ์๊ฐ ํฐ ๋น์ค์ ์ฐจ์งํ๋ค.
โโ์์์ ์์ฝ๋จโ์ ๊ธฐ์ ์์์ง์ ๋์์ผ๋ก ์๊ธฐ์๊ฐ์์ ๋ด์ฉ์ ์์ฝํ์ฌ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉ์์๊ฒ ์ ๋ฌํ๊ณ , ์ํธ์์ฉํ ์ ์๋ ์ธ๊ณต์ง๋ฅ ๊ธฐ๋ฐ์ ์๊ธฐ์๊ฐ ์์ฝ ํ์ด์ง๋ฅผ ์ ๊ณตํ๋ค.
- ๋๋ฉ ํ์ด์ง
- ์์ฐ ์์
default.mp4
- General Summarization: ์์ฐ์ด ์ฒ๋ฆฌ ๋ชจ๋ธ์ ํ์ฉํ ์๊ธฐ์๊ฐ์ ์์ฝ
- Keysentence Extraction: ํค์๋ ์ค์ฌ์ ๋ฌธ์ฅ ์ถ์ถ
- Question Answering: ์ง๋ฌธ์ ๋ํ ๋ต๋ณ ์ ๊ณต
- Frontend: HTML, CSS, JS
- Engine : Pytorch
- Kobart, Textrankr, Bert
- Backend: Flask
- Install modules
pip install -r requirements.txt
- Execute
flask run
https://github.com/SKT-AI/KoBART
- BART(Bidirectional and Auto-Regressive Transformers)๋ ์
๋ ฅ ํ
์คํธ ์ผ๋ถ์ ๋
ธ์ด์ฆ๋ฅผ ์ถ๊ฐํ์ฌ ์ด๋ฅผ ๋ค์ ์๋ฌธ์ผ๋ก ๋ณต๊ตฌํ๋ autoencoder์ ํํ๋ก ํ์ต์ด ๋ฉ๋๋ค.
- Bart๋ Transformer์ ๊ธฐ๋ณธ ์ํคํ ์ฒ์ธ Encoder-Decoder๊ตฌ์กฐ๋ฅผ ๊ฐ๊ณ ์๋ค.
- ๋ฐ๋ผ์ ์ฝ๋๋ Encoder์ Decoder๋ฅผ ์ฐจ๋ก๋ก ํต๊ณผํ๋ค.
- Input data๋ Encoder_input๊ณผ Decoder_input์ ๋ฐ๋ก ์ค๋นํด์ผํ๋ค.
- ์ด๋ป๊ฒ input์ ๋ฃ์ด์ฃผ๋์ ๋ฐ๋ผ Task๋ง๋ค ํ์ต/์ถ๋ก ๋ฐฉ๋ฒ์ด ๊ฐ๋ฆฐ๋ค.
-
ํ๊ตญ์ด BART๋ ๋ ผ๋ฌธ์์ ์ฌ์ฉ๋ Text Infilling ๋ ธ์ด์ฆ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ 40GB ์ด์์ ํ๊ตญ์ด ํ ์คํธ์ ๋ํด์ ํ์ตํ ํ๊ตญ์ด encoder-decoder ์ธ์ด ๋ชจ๋ธ์ ๋๋ค.
์ด๋ฅผ ํตํด ๋์ถ๋ KoBART-base๋ฅผ ๋ฐฐํฌํฉ๋๋ค. ํ๊ตญ์ด ์ํค ๋ฐฑ๊ณผ ์ด์ธ, ๋ด์ค, ์ฑ , ๋ชจ๋์ ๋ง๋ญ์น v1.0(๋ํ, ๋ด์ค, ...), ์ฒญ์๋ ๊ตญ๋ฏผ์ฒญ์ ๋ฑ์ ๋ค์ํ ๋ฐ์ดํฐ๊ฐ ๋ชจ๋ธ ํ์ต์ ์ฌ์ฉ๋์์ต๋๋ค. -
KoBART๋ ํ์ด์ค๋ถ์์ ๊ณต๊ฐํ BART๋ชจ๋ธ์ SKT์์ 40GB์ด์์ ํ๊ตญ์ด ํ ์คํธ๋ก ์ฌ์ ํ์ต์ํจ ๋ชจ๋ธ์ด๋ค.
BART๋ seq2seq ๋ชจ๋ธ์ ์ฌ์ ํ์ตํ๊ธฐ ์ํ denoising autoencoder(DAE, ์ก์์ ๊ฑฐ ์คํ ์ธ์ฝ๋)๋ก, ์์์ noising function์ผ๋ก ํ ์คํธ๋ฅผ ์์์ํจ ํ ๋ชจ๋ธ์ด ์๋ณธ ํ ์คํธ๋ฅผ ์ฌ๊ตฌ์ถํ๋ ๋ฐฉ์์ผ๋ก ํ์ต์ด ์งํ๋๋ค.
BART๋ ๊ธฐ์กด BERT๋ชจ๋ธ๊ณผ GPT๋ฅผ ํฉ์น ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์๋๋ฐ, ์ด๋ก ์ธํด BERT์ Bidirectional ํน์ง๊ณผ GPT์ Auto-Regressiveํ ํน์ง์ ๋ชจ๋ ๊ฐ์ง๋ค. ๋๋ถ์ BART๋ ๊ธฐ์กด MLM๋ชจ๋ธ๋ค์ ๋นํด ๋ค์ํ ๋ถ์ผ์์ ๋์ ํ์ฉ์ฑ์ ๋ํ๋ธ๋ค.
Fig.1 Bart๊ตฌ์กฐ -
BART๋ ์์๋ Text๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์ Bidirectional ๋ชจ๋ธ๋ก encodingํ๊ณ ์ ๋ต Text์ ๋ํ likelihood๋ฅผ autoregressive ๋ชจ๋ธ๋ก decodingํ์ฌ ๊ณ์ฐํ๋ค. BART์์๋ ๋ค์๊ณผ ๊ฐ์ 5๊ฐ์ง noising ๊ธฐ๋ฒ์ด ์กด์ฌํ๋ฉฐ, ์ด๋ฅผ ํตํด ์์๋ Text๋ฅผ ์ป๋๋ค.
Fig.2 Noising๊ธฐ๋ฒ -
BART๋ ์๊ธฐํ๊ท ๋์ฝ๋๋ฅผ ๊ฐ๊ธฐ ๋๋ฌธ์, abstractive QA์ summarization๊ณผ ๊ฐ์ ์ํ์ค ์ผ๋ฐํ(Sequence Generation) ํ์คํฌ์ ์ง์ ์ ์ผ๋ก ํ์ธํ๋ ๋ ์ ์๋ค. ์ด๋ฒ ํ๋ก์ ํธ์์๋ ์ด๋ ฅ์ ์์ฝ ๊ธฐ๋ฅ์ ์ํํ๊ธฐ ์ํด KoBART๋ชจ๋ธ์ ์ฑ์ฉ๋ฉด์ ๋ฐ์ดํฐ๋ก ํ์ธํ๋์ ์งํํ์๋ค.(๋ฐ์ดํฐ์ : https://www.aihub.or.kr/aihubdata/data/view.do?currMenu=&topMenu=&aihubDataSe=realm&dataSetSn=71592)
์ฐธ๊ณ ๋ฌธํ
[1] Mike Lewis์ธ(2019), "BART: Denoising Sequence-to-Sequence Pre-training for Natural Language Generation, Translation, and Comprehension", ACL[2] ์๋ค๋ฅด์ฐ ๋ผ๋น์ฐฌ๋๋(2021), "๊ตฌ๊ธ BERT์ ์ ์", ํ๋น๋ฏธ๋์ด
- TextRank ์๊ณ ๋ฆฌ์ฆ์ 2004๋
๊ตฌ๊ธ์์ ๋ฐํํ PageRank ์๊ณ ๋ฆฌ์ฆ์ ๊ธฐ๋ฐ์ผ๋ก ํ ์๊ณ ๋ฆฌ์ฆ์ด๋ค[1].
PageRank ์๊ณ ๋ฆฌ์ฆ์ ์์ง๋ ์ธํฐ๋ท ๋ฌธ์ ๊ฐ๊ฐ์ ๊ทธ๋ํ์ ๋ ธ๋, ๋ฌธ์ ๋ด๋ถ์ ๋งํฌ ์ ๋ณด๋ฅผ ๊ฐ์ ์ผ๋ก ๊ฐ์ ํ์ฌ ๋ฐฉํฅ์ฑ์ด ์๋ ๊ทธ๋ํ๋ฅผ ๋ง๋ค์ด ๋ฌธ์์ ์ค์๋๋ฅผ ๊ณ์ฐํ๋ค[2]. ์กฐ๊ธ ๋ ์ฝ๊ฒ ๋งํ์๋ฉด PageRank๋ ๊ฐ ์นํ์ด์ง๋ง๋ค ํ์ดํผ๋งํฌ๊ฐ ์์ ๋ ์ผ๋ง๋ ๋งํฌ๋ฅผ ๋ฐ๋๋์ ๋ฐ๋ผ ์์๋ฅผ ๋งค๊ธฐ๋ ์๊ณ ๋ฆฌ์ฆ์ ๋งํ๋ค. ์ฆ, ํด๋น ๋งํฌ๋ฅผ ํด๋ฆญํ ํ๋ฅ ๋ก ๊ทธ ์์๋ฅผ ๋งค๊ธฐ๋ ๊ฒ์ด๋ค. - TextRank ์๊ณ ๋ฆฌ์ฆ์ PageRank์ ๊ฐ๋
์ ์์ฐ์ด ์ฒ๋ฆฌ์ ์์ฉํ ๊ฒ์ผ๋ก ๋ฌธ์ฅ, ๋จ์ด์ ๊ฐ์ ํน์ ๋จ์๋ค ๊ฐ์ ์ค์๋๋ฅผ ๊ณ์ฐํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. ๋ฌธ์ ๋ด์ ๊ฐ ๋ฌธ์ฅ์ ๊ทธ๋ํ์ ์ ์ (vertex)์ผ๋ก ๊ฐ์ ํ๋ ๊ฒฝ์ฐ ์ค์ํ ๋ฌธ์ฅ๋ค์ ์ ๋ณํ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ๋ฌธ์ ์์ฝ์ด ๊ฐ๋ฅํ๋ค. ๊ฒฐ๊ตญ, TextRank๋ ์์ PageRank์์์ ํ์ด์ง ๊ฐ๋
์ ๋จ์ด์ ๊ฐ๋
์ผ๋ก ๋ฐ๊พผ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. ํ
์คํธ๋ก ์ด๋ฃจ์ด์ง ๊ธ์์ ํน์ ๋จ์ด๊ฐ ๋ค๋ฅธ ๋ฌธ์ฅ๊ณผ ์ผ๋ง๋งํผ์ ๊ด๊ณ๋ฅผ ๋งบ๊ณ ์๋์ง๋ฅผ ๊ณ์ฐํ๋ค.
- ์ ์ด๋ฏธ์ง๋ ์ฃผ์ด์ง ๊ธ์ ๋ํด ํ
์คํธ ๊ฐ ๊ด๊ณ๋ฅผ ๋ํ๋ธ ๊ทธ๋ํ๋ก ๊ทธ๋ฆฐ ์ํ ์ด๋ฏธ์ง์ด๋ค. ๊ฐ ๋ฌธ์ฅ์์ ๋จ์ด ๊ฐ์ ๊ด๊ณ๋ฅผ ์ ์ผ๋ก ์ฐ๊ฒฐํ ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด ํต์ฌ ๋ฌธ์ฅ์ ์ถ์ถํ๊ธฐ ์ํด์๋ ์ด๋ป๊ฒ ํด์ผ ํ ๊น? ์๋์ ๊ทธ๋ฆผ์ฒ๋ผ ๋ฌธ์ฅ ๊ทธ๋ํ๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค. ๊ฐ ๋ฌธ์ฅ์ด ๋ง๋๊ฐ ๋๋ ๊ฒ์ด๋ค.
์ ์์ ์ธ(2017) "TextRank ์๊ณ ๋ฆฌ์ฆ๊ณผ ์ฃผ์ ์ง์ค ์ํ ์ ๊ฒฝ๋ง์ ์ด์ฉํ ํ์ด๋ธ๋ฆฌ๋ ๋ฌธ์ ์์ฝ" ๋ ผ๋ฌธ์์๋ TextRank ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ ๋ฌธ์ฅ์ ์ค์๋๋ฅผ ๊ตฌํ ๋, ๋ฌธ์ฅ ๊ฐ ์๊ดํ๋ ฌ์ ์ด์ฉํ์ฌ ๊ตฌํ์๋ค.
- ์
๋ ฅ ๋ฌธ์์ ๊ฐ ๋ฌธ์ฅ๋ค์ ๋ํด ํํ์ ๋ถ์์ ์ํํ๊ณ , ์ฒด์ธ๋ฅ์ ์ฉ์ธ๋ฅ์ TF-IDF๋ฅผ ๊ณ์ฐํ์ฌ ๋ฌธ์ฅ-๋จ์ด ํ๋ ฌ์ ์์ฑํ๋ค. ๊ทธ ๋ค ์์ฑ๋ ๋ฌธ์ฅ-๋จ์ด ํ๋ ฌ์ ์ ์น ํ๋ ฌ์ ๊ตฌํ์ฌ ์๋ก ๊ณฑํด์ฃผ๋ฉด ๋ฌธ์ฅ ๊ฐ์ ์๊ด๊ด๊ณ(correlation)์ ๋ํ๋ด๋ ํ๋ ฌ์ ์ป์ ์ ์๋ค. ์ด๋ ๊ฒ ๊ตฌํ ๋ฌธ์ฅ ๊ฐ ์๊ดํ๋ ฌ์ ๋ฌธ์ฅ ๊ฐ์ ๊ฐ์ค์น ๊ทธ๋ํ๋ก ๋ํ๋ผ ์ ์๊ณ , TextRank ์๊ณ ๋ฆฌ์ฆ์ ํตํด ๊ฐ ๋ฌธ์ฅ์ ์ค์๋๋ฅผ ๊ตฌํ ์ ์๋ค. ์ด๋ ๊ฒ ๊ตฌํ ์ค์๋ ์์ผ๋ก ๋ฌธ์ฅ๋ค์ ์ ๋ ฌํ ๋ค ์์ n๊ฐ์ ๋ฌธ์ฅ๋ค์ ์ฌ๋ฐฐ์นํ๋ฉด ์์ฝ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ค[3].
์ฐธ๊ณ ๋ฌธํ
[1] ์ด์์ ์ธ(2023), "TextRank ์๊ณ ๋ฆฌ์ฆ ๋ฐ ์ธ๊ณต์ง๋ฅ์ ํ์ฉํ ๋ธ๋ ์ธ์คํ ๋ฐ", JPEE : Journal of practical engineering education = ์ค์ฒ๊ณตํ๊ต์ก๋ ผ๋ฌธ์ง, v.15 no.2, pp.509 - 517[2] ๋ฐฐ์์๊ณผ ์ฐจ์ ์(2010), "TextRank ์๊ณ ๋ฆฌ์ฆ์ ์ด์ฉํ ๋ฌธ์ ๋ฒ์ฃผํ", ์ ๋ณด๊ณผํํ๋ ผ๋ฌธ์ง. Journal of KIISE. ์ปดํจํ ์ ์ค์ ๋ฐ ๋ ํฐ, v.16 no.1, pp.110-114
[3] ์ ์์ ์ธ(2017), "TextRank ์๊ณ ๋ฆฌ์ฆ๊ณผ ์ฃผ์์ง์ค ์ํ ์ ๊ฒฝ๋ง์ ์ด์ฉํ ํ์ด๋ธ๋ฆฌ๋ ๋ฌธ์ ์์ฝ", ํ๊ตญ์ด์ ๋ณดํํ 2017๋ ๋ ์ 29ํ ํ๊ธ๋ฐํ๊ตญ์ด์ ๋ณด์ฒ๋ฆฌํ์ ๋ํ, pp.47 - 50
-
Question Answering model์ ์ฌ์ฉ์๋ก๋ถํฐ ๋ฐ์ ํน์ ํ ์ง์์ ๊ด๋ จ๋ ์ ๋ต์ ์์ฐ์ด๋ก ์๋์ผ๋ก ์ถ๋ ฅํ๋ ์์คํ ์ด๋ค. [1]
-
QA ์์ ์ ์ฃผ์ด์ง ์ง๋ฌธ๊ณผ ๋ฌธ๋งฅ์ ์ดํดํ์ฌ ๋ต๋ณ์ ์ ์ํ๋ ๊ฒ์ด ๋ชฉํ์ธ๋ฐ, ๋ต๋ณ์ ์ฐพ๋ ๋ฐฉ์์ ๋ฐ๋ผ ์ถ์ถํ(extractive), ์ถ์ํ(abstractive) ์ผ๋ก ๋๋๋ค. ๋ฌธ์ฅ ๋ด์์ ์ง๋ฌธ์ ํด๋นํ๋ ๋ต๋ณ์ ์ฐพ์๋ด๋์ง / ์ฃผ์ด์ง ์ง๋ฌธ์ ๋ํ ๋ต๋ณ์ ์ง์ ์์ฑํ๋ ๋ฐฉ์์ ์ฐจ์ด์ด๋ค. QA ์์ ์ ์งํํ๊ธฐ ์ํด, ๊ตฌ๊ธ์์ ๊ฐ๋ฐํ NLP ์ฒ๋ฆฌ ๋ชจ๋ธ์ธ BERT ๋ชจ๋ธ์ ํ์ฉํ์๋ค.
-
BERT ๋ชจ๋ธ์ ์ฌ์ ํ๋ จ ์ธ์ด ๋ชจ๋ธ๋ก์, ํน์ ๋ถ์ผ์ ๊ตญํ๋ ๊ธฐ์ ์ด ์๋๋ผ ๋ชจ๋ ์์ฐ์ด ์ฒ๋ฆฌ ๋ถ์ผ์์ ์ข์ ์ฑ๋ฅ์ ๋ด๋ ๋ฒ์ฉ Language Model์ด๋ค. Transformer architerture์์ encoder๋ง ์ฌ์ฉํ๋ค๋ ํน์ง์ด ์๋ค.๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- Input์ Token Embedding + Segment Embedding + Position Embedding 3๊ฐ์ง ์๋ฒ ๋ฉ์ ๊ฒฐํฉํ ๋ฐฉ์์ผ๋ก ์งํํ๋ค. -Token Embedding : Word Piece ์๋ฒ ๋ฉ ๋ฐฉ์์ ์ฌ์ฉํ๋ค. Char ๋จ์๋ก ์๋ฒ ๋ฉ ํ ๋ฑ์ฅ ๋น๋์ ๋ฐ๋ผ sub-word ๋ก ๊ตฌ๋ถํ๋ค. -Segment Embedding : Sentence Embedding์ผ๋ก, ํ ํฐ ์ํจ ๋จ์ด๋ค์ ๋ค์ ํ๋์ ๋ฌธ์ฅ์ผ๋ก ๋ง๋๋ ์์ ์ด๋ค. ๊ตฌ๋ถ์ [SEP] ๋ฅผ ํตํด ๋ฌธ์ฅ์ ๊ตฌ๋ถํ๊ณ ๋ ๋ฌธ์ฅ์ ํ๋์ Segment ๋ก ์ง์ ํ๋ค. -Position Embedding : ์ ๋ ฅ ํ ํฐ์ ์์น ์ ๋ณด๋ฅผ ๊ณ ๋ คํ์ง ์๊ณ , ํ ํฐ ์์๋๋ก ์ธ์ฝ๋ฉํ๋ค.
-
MLM(masked Language Model) : ์ ๋ ฅ ๋ฌธ์ฅ์์ ์์๋ก ํ ํฐ์ ๋ฒ๋ฆฌ๊ณ (Mask) ๊ทธ ํ ํฐ์ ๋ง์ถ๋ ๋ฐฉ์์ผ๋ก ํ์ต์ ์งํํ๋ค.
-
NSP(Next Sentence Prediction) : ๋ ๋ฌธ์ฅ์ด ์ฃผ์ด์ก์ ๋, ๋ ๋ฌธ์ฅ์ ์์๋ฅผ ์์ธกํ๋ ๋ฐฉ์์ด๋ค. ๋ ๋ฌธ์ฅ ๊ฐ ๊ด๋ จ์ด ๊ณ ๋ ค๋์ผ ํ๋ NLI์ QA์ ํ์ธ ํ๋์ ์ํด ๋ ๋ฌธ์ฅ์ ์ฐ๊ด์ ๋ง์ถ๋ ํ์ต์ ์งํํ๋ค.
-
Bert๋ fine-tuning ๋จ๊ณ์์ pre-training ๊ณผ ๊ฑฐ์ ๋์ผํ ํ์ดํผํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ๋ค. ๊ฐ NLP task๋ง๋ค fine-tuning ํ Bert ๋ชจ๋ธ์ transfer learning์์ผ ์ฑ๋ฅ์ ํ์ธํ๋ค.
-
BERT ๊ธฐ๋ฐ QA ๋ชจ๋ธ์ ํฌ๊ฒ ๋ ๊ฐ์ง ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ค.
- ์ง๋ฌธ๊ณผ ๋ฌธ๋งฅ์ ํจ๊ป ์ ๋ ฅ์ผ๋ก ๋ฐ์ ๋ต๋ณ์ ์์ธกํ๋ ๋ฐฉ์
- ์ง๋ฌธ๊ณผ ๋ฌธ๋งฅ์ ๊ฐ๊ฐ ๋ฐ๋ก ์ ๋ ฅ์ผ๋ก ๋ฐ์ ๊ฐ๊ฐ์ ๋ํ ์๋ฒ ๋ฉ์ ์์ฑํ๊ณ , ์ด๋ฅผ ๋ค์ํ ๋ฐฉ์์ผ๋ก ๊ฒฐํฉํ์ฌ ๋ต๋ณ์ ์์ธกํ๋ ๋ฐฉ์ ๋ณธ ํ๋ก์ ํธ์์๋ question๊ณผ reference๋ฅผ ๋์์ input ์ผ๋ก ์ฌ์ฉํ์ฌ extractive question answering ๋ชจ๋ธ์ ๊ตฌ์ฑํ์๋ค.
์ฐธ๊ณ ๋ฌธํ
[1] ๊ถ์ธ๋ฆฐ, et al. "์๋ฃ ๊ด๋ จ ์ง์์๋ต์ ์ํ BERT ๊ธฐ๋ฐ ํ๊ตญ์ด QA ๋ชจ๋ธ." Proceedings of KIIT Conference. 2022.[2] Devlin, Jacob, et al. "Bert: Pre-training of deep bidirectional transformers for language understanding." arXiv preprint arXiv:1810.04805 (2018).
[3] ์ก๋ค์ฐ, ์กฐ์ํ, and ๊ถํ์ฒ . "ํ๊ตญ์ด ๋ฌธ๋ฒ QA ์์คํ ์ ์ํ BERT ๊ธฐ๋ฐ ์ํ์ค ๋ถ๋ฅ๋ชจ๋ธ." ํ๊ตญ์ ๋ณด๊ณผํํ ํ์ ๋ฐํ๋ ผ๋ฌธ์ง (2021): 754-756.
โ๏ธ app.py
app.py
์์๋ ์์ง์ ์ด๊ธฐ ์ธํ ํ๊ณ , flask ์๋ฒ ์ค์ ์ ํตํด ํ๋ก ํธ์ ํต์ ์ ํ ์ ์๋๋ก ํ๋ค. ์์ง์์ ๊ฐ์ฅ ์ค์ ์ผ๋ก ์คํ๋๋ ์ฝ๋ ํ์ผ์ด๋ฉฐ, ๋ฐฑ์๋์์ ์์ฒญ์ด ๋ค์ด์ฌ ๊ฒฝ์ฐ, ๊ทธ์ ๋ง๋ ์์ ์ ์ํํ์ฌ ์ฒ๋ฆฌํ๋ค.- flask_cors๋ฅผ ํ์ฉํ์ฌ CORS ์ด์๋ฅผ ํด๊ฒฐํ๋ค.
from flask import Flask,render_template,request, jsonify
from flask_cors import CORS
import torch
from sum_model import summarize_model
from ext import textrank_summarize
from qa_model import get_qa_model
app = Flask(__name__)
cors = CORS(app)
- flask ์ฑ์ ์์ฑํ๊ณ ๋ค์ ๊ฒฝ๋ก์ ๋ํ ๋ผ์ฐํ
์ ์ค์ ํ๋ค.
'/'
: ํ ํ์ด์ง๋ฅผ ๋ ๋๋ง'/sum'
: ์์ฝ ํ์ด์ง๋ฅผ ๋ ๋๋ง'/sum/gsummarize'
: ์ผ๋ฐ์ ์ธ ์์ฝ์ ์ํ'/sum/key'
: ํค์๋ ์ค์ฌ์ ๋ฌธ์ฅ ์ถ์ถ์ ์ํ'/sum/qa'
: ์ง๋ฌธ์ ๋ํ ๋ต๋ณ์ ์ ๊ณต
#home
@app.route('/')
def home():
return render_template('home.html')
#summary page
@app.route('/sum')
def index():
return render_template('index.html')
#general summarization
@app.route('/sum/gsummarize', methods=['POST'])
def gsummarize():
try:
data = request.get_json(force=True)
context = data['context']
gsum = summarize_model(context)
response = jsonify({'gsum': gsum})
except Exception as e:
response = jsonify({'error': str(e)})
return response
# keysentence extraction
@app.route('/sum/key',methods=['POST'])
def key():
try:
data = request.get_json(force=True)
context = data['context']
keytext = textrank_summarize(context,1) #๋ฌธ์ฅ ์ ์กฐ์ ํ์
response = jsonify({'keytext': keytext})
except Exception as e:
response = jsonify({'error': str(e)})
return response
#qa
@app.route('/sum/qa', methods=['POST'])
def qa_endpoint():
try:
data = request.get_json(force=True)
context = data['context']
question = data['question']
if question == "":
response = jsonify({'error': '์ง๋ฌธ์ ์
๋ ฅํด์ฃผ์ธ์.'})
return response
to_predict = [{"context": context, "qas": [{"question": question, "id": "0"}]}]
result = qa_model.predict(to_predict)
answer = result[0][0]['answer'][0]
answer = "์ ์ ํ ๋ต๋ณ์ ์ฐพ์ ์ ์์ต๋๋ค." if answer == '' else answer
response = jsonify({'answer': answer})
except Exception as e:
response = jsonify({'error': str(e)})
return response
- ์ง์ ๋ ๋ชจ๋ธ์ ๊ฒฝ๋ก๋ก๋ถํฐ CUDA๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ชจ๋ธ์ ๋ก๋ํ๋ฉฐ, ํด๋น ๋ชจ๋ธ์
'qa_model'
๋ณ์์ ์ ์ฅ๋๋ค. ๋ง์ง๋ง์ผ๋ก, ํฌํธ '5000'์์ flask ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํ์ํจ๋ค.
if __name__ == '__main__':
model_path = 'model/checkpoint-1119-epoch-1'
qa_model = get_qa_model(model_path, use_cuda=False)
app.run(host='127.0.0.1',port=5000,debug=True)
โ๏ธ ext.py
- ํค์๋ ์ค์ฌ์ผ๋ก ์ค์๋ฌธ์ฅ์ ์ถ์ถํ๋๋ ๋ชจ๋์ด๋ค.
- ์ฌ์ฉ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ:
konlpy
: ํ๊ตญ์ด ์์ฐ์ด ์ฒ๋ฆฌ๋ฅผ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
textrankr
: TextRank ์๊ณ ๋ฆฌ์ฆ์ ํ์ฉํ ํ ์คํธ ์์ฝ์ ์ ๊ณตํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
from typing import List
from konlpy.tag import Okt
from textrankr import TextRank
class OktTokenizer:
okt: Okt = Okt()
def __call__(self, text: str) -> List[str]:
tokens: List[str] = self.okt.phrases(text)
return tokens
def textrank_summarize(text: str, num_sentences: int, verbose: bool = True) -> str:
mytokenizer: OktTokenizer = OktTokenizer()
textrank: TextRank = TextRank(mytokenizer)
summarized: str = textrank.summarize(text, num_sentences, verbose)
return summarized
โ๏ธ qa_model.py
- ์ง๋ฌธ์ ๋ํ ๋ต๋ณ์ ์ ๊ณตํ๋ ๋ชจ๋์ด๋ค.
- ์ฌ์ฉ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ:
simpletransformers
: ๊ฐํธํ ์ฌ์ฉ์ ์ํ ํธ๋์คํฌ๋จธ ๋ชจ๋ธ ๋ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
import simpletransformers
from simpletransformers.question_answering import QuestionAnsweringModel, QuestionAnsweringArgs
def get_qa_model(model_path, use_cuda=False):
print('Loading model from', model_path)
qa_model = QuestionAnsweringModel('bert', model_path, use_cuda=use_cuda)
return qa_model
โ๏ธ sum_model.py
- ์๊ธฐ์๊ฐ์๋ฅผ ํฌ๊ด์ ์ผ๋ก ์์ฑ์์ฝํ๋ ๋ชจ๋์ด๋ค.
- ์ฌ์ฉ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ:
transformers
: Hugging Face์ ํธ๋์คํฌ๋จธ ๋ชจ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
from transformers import PreTrainedTokenizerFast, BartForConditionalGeneration
def summarize_model(text: str, verbose: bool = True) -> str:
tokenizer = PreTrainedTokenizerFast.from_pretrained('digit82/kobart-summarization')
model = BartForConditionalGeneration.from_pretrained('digit82/kobart-summarization')
input_ids = tokenizer.encode(text, return_tensors="pt")
summary_text_ids = model.generate(
input_ids=input_ids,
bos_token_id=model.config.bos_token_id,
eos_token_id=model.config.eos_token_id,
length_penalty=2.0,
max_length=102,
min_length=20,
num_beams=4,
)
summarized_text = tokenizer.decode(summary_text_ids[0], skip_special_tokens=True)
return summarized_text