File size: 9,500 Bytes
bfd4c2e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import json
import numpy as np
import os
os.environ["TOKENIZERS_PARALLELISM"] = "false"

# Load all test data into list of dictionaries
#summary_data_path = 'sci-news-sum-kr-50/data/'
#summary_objects = []
#for root, dirs, files in os.walk(summary_data_path):
#    files.sort() # Sort file names
#    for ifile, file_name in enumerate(files):
#        with open(os.path.join(root, file_name)) as f:
#            s = json.load(f)
#            s['index'] = file_name.replace('.json','') # index = 'XY' for file 'XY.json' 
#            s['sentences'] = [sen + '.' for sen in s['sentences']] # Add punctuation to all sentences
#            s['body'] = ' '.join(s['sentences']) # body is all sentenecs concantenatd with spaces in between
#            summary_objects.append(s)

# Load spacy to split text into sentences
import spacy

# Cache language model
nlp = spacy.load("ko_core_news_sm")
nlp.select_pipes(disable=
                        ['tok2vec','tagger','morphologizer','parser','lemmatizer','attribute_ruler','ner']
                        )
nlp.enable_pipe('senter')

def text_to_sentences(nlp, text):
    """Split Korean text into sentences."""
    doc = nlp(text)
    sentences = [sen for sen in doc.sents]
    return sentences

from transformers import AutoConfig, AutoTokenizer, AutoModel
from summarizer import Summarizer

model_path = 'skt/kobert-base-v1'

# Load model, model config and tokenizer via Transformers
custom_config = AutoConfig.from_pretrained(model_path)
custom_config.output_hidden_states=True
custom_tokenizer = AutoTokenizer.from_pretrained(model_path, do_lower_case=False)
custom_model = AutoModel.from_pretrained(model_path, config=custom_config)
model = Summarizer(custom_model=custom_model, custom_tokenizer=custom_tokenizer)

def create_summary(nlp, model, text):
    """Create summary from text of an article using given model"""
    
    # print(model(s['body']))
    k = model.calculate_optimal_k(text, k_max=10)
    return text_to_sentences(nlp, model(text, num_sentences=k))

from urllib.request import urlopen
from bs4 import BeautifulSoup

def extract_naver_news(url):
    """Get title, subtitle, and article body from Naver news"""
    html = urlopen(url).read()
    soup = BeautifulSoup(html, features="html.parser")
    
    title = soup.find(class_="media_end_head_headline").get_text()

    area = soup.find(id="dic_area")

    subtitle_tag = area.find('strong')
    if subtitle_tag: subtitle = area.strong.get_text('\n')
    else: subtitle = ''
    
    for tag in area.find_all(class_="img_desc"):
        tag.extract()
        
    # Add punctuation and spaces between sentences
    article = ' '.join( [text for text in area.stripped_strings if text[-1]=='.'] )
    result = {
        'title': title,
        'subtitle': subtitle,
        'article': article,
    }
    return result

import gradio as gr
def interface_handler(custom_text, naver_url, choice):
    if choice == 1:
        content = extract_naver_news(naver_url)
        summary_sentences = create_summary(nlp, model, content['article'])
        output_text = ""
        # output_text += f'제λͺ©:\n{content["title"]}\n'
        # output_text += f'λΆ€μ œ:\n{content["subtitle"]}\n'
        # output_text += '\nκ°œμš”:\n'
        for sen in summary_sentences:
            output_text += f'\n{sen}'
        return output_text
    else:
        output_text = ""
        summary_sentences = create_summary(nlp, model, custom_text)
        for sen in summary_sentences:
            output_text += f'\n{sen}'
        return output_text

default_url = "https://n.news.naver.com/article/015/0004692703?sid=102"
default_text = """
'λ‚˜μ„ ν˜• 신경망' ν•™μŠ΅ 기술. μΉ΄λ©”λΌλ‘œ 찍은 μ΄λ―Έμ§€μ—μ„œ νŠΉμ •ν•œ 사물 μ°ΎλŠ” 기술 ν™œμš©. μˆ²μ†μ—μ„œ λ“±μ‚°λ‘œ μ²™μ²™ μ°Ύμ•„ λ“œλ‘ μ΄ μ‚°μ•…κ΅¬μ‘°λŒ€ 역할도. λ―Έκ΅­ κ΅­λ°©λΆ€λŠ” μ§€λ‚œλ‹¬ 말 인곡지λŠ₯(AI)을 μ΄μš©ν•΄ 인간 도움 없이 적을 식별해 νƒ€κ²©ν•˜λŠ” λ“œλ‘ (무인 항곡기)을 μ‹œμ—°ν–ˆλ‹€. 이 λ“œλ‘ μ€ 카메라 ν™”λ©΄μ—μ„œ 총으둜 무μž₯ν•œ μ‚¬λžŒκ³Ό 무기가 μ—†λŠ” μ‚¬λžŒμ„ ꡬ뢄할 수 μžˆλ‹€. ν‘œμ μœΌλ‘œ μ •ν•œ μ‚¬λžŒμ„ μ°Ύμ•„ κ·Έκ°€ 탄 μžλ™μ°¨λ₯Ό μΆ”μ ν•˜λŠ” κΈ°λŠ₯도 μžˆλ‹€. μ‘°λ§Œκ°„ 원격 μ‘°μ’… 없이도 μ „μž₯μ—μ„œ νŠΉμˆ˜λΆ€λŒ€ κ΅°μΈλ“€μ²˜λŸΌ μž„λ¬΄λ₯Ό μˆ˜ν–‰ν•˜λŠ” λ“œλ‘ μ΄ λ“±μž₯ν•  전망이닀. 이 λ“œλ‘ μ΄ μ‚¬λžŒ 도움 없이 카메라 μ˜μƒμ—μ„œ λͺ©ν‘œλ¬Όμ„ μΈμ‹ν•˜κ³  좔적할 수 μžˆλŠ” 것은 λ°”λ‘œ β€˜λ¨Έμ‹ λŸ¬λ‹β€™ 덕뢄이닀. λ¨Έμ‹ λŸ¬λ‹μ€ AI의 ν•œ λΆ„μ•Όλ‘œ 컴퓨터가 μΈκ°„μ²˜λŸΌ 슀슀둜 ν•™μŠ΅ν•  수 μžˆλŠ” λŠ₯λ ₯을 λΆ€μ—¬ν•˜λŠ” μž‘μ—…μ„ λ§ν•œλ‹€. λ¨Έμ‹ λŸ¬λ‹μ˜ μ›λ¦¬λŠ” 인간을 ν¬ν•¨ν•œ 영μž₯λ₯˜ λ‘λ‡Œμ˜ 정보 처리 ꡬ쑰인 β€˜μ‹ κ²½λ§β€™μ„ λͺ¨μ‚¬ν•˜λŠ” 방식이닀. λ°”λ‘‘ λŒ€κ²°μ—μ„œ μ΄μ„ΈλŒ 9단을 이긴 κ΅¬κΈ€μ˜ β€˜μ•ŒνŒŒκ³ β€™ λ“± μ§€κΈˆκΉŒμ§€ μ†Œκ°œλœ AI λŒ€λΆ€λΆ„μ€ 심측신경망을 기반으둜 ν•œ λ¨Έμ‹ λŸ¬λ‹ μ•Œκ³ λ¦¬μ¦˜μ„ μ΄μš©ν•œλ‹€. μ΄λ―Έμ§€μ—μ„œ νŠΉμ • 사물을 μ°ΎλŠ” κΈ°μˆ μ€ 인간이 μ•„λ‹ˆλΌ 고양이 λ‡Œμ—μ„œ μœ λž˜ν–ˆλ‹€. 고양이 λ‡Œμ˜ μ‹œμ‹ κ²½μ—μ„œ λ°œκ²¬λ˜λŠ” β€˜λ‚˜μ„ ν˜• 신경망’ κ΅¬μ‘°λŠ” μ‹œκ°μ„Έν¬λ“€μ΄ λ³΄λ‚΄μ˜€λŠ” λ°˜μ‘μ„ λͺ¨μ•„ μ—¬λŸ¬ 개의 μΈ΅(ε±€)으둜 λ‚˜λˆˆλ‹€. 이λ₯Ό 3단계에 걸쳐 점차적으둜 λ‹¨μˆœν™”ν•˜λ©΄μ„œ 물체의 μƒ‰κΉ”μ΄λ‚˜ λͺ¨μ–‘을 νŒŒμ•…ν•œλ‹€. 이λ₯Ό 처음으둜 μ—°κ΅¬ν•œ λ°μ΄λΉ„λ“œ 휴벨과 ν† μ–΄μŠ€ν… 비저은 1981λ…„ 노벨 μƒλ¦¬μ˜ν•™μƒμ„ λ°›μ•˜λ‹€. AI κ³Όν•™μžλ“€μ€ λ‚˜μ„ ν˜• μ‹ κ²½λ§μ—μ„œ 아이디어λ₯Ό μ–»μ–΄ μ΄λ―Έμ§€μ—μ„œ 사물을 νŒλ³„ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ„ μ„€κ³„ν–ˆλ‹€. μš°μ„  μ΄λ―Έμ§€μ—μ„œ 큰 νŠΉμ§•μ„ μΆ”μΆœν•œ λ‹€μŒ 점차 μž‘κ³  λ³΅μž‘ν•œ νŠΉμ§•μ„ λ°œκ²¬ν•΄ λ‚˜κ°€λŠ” 방식이닀. μ˜ˆμ»¨λŒ€ 사진 속에 μžλ™μ°¨κ°€ μžˆλ‹€κ³  ν•΄ 보자. μ•Œκ³ λ¦¬μ¦˜μ€ μš°μ„  μ‚¬λ¬Όμ˜ 전체적인 μœ€κ³½μ„ λ¨Όμ € ν™•μΈν•œ λ’€ 기쑴에 μž…λ ₯된 사진 데이터와 비ꡐ해 β€˜νƒˆ κ²ƒβ€™μœΌλ‘œ λ²”μœ„λ₯Ό μ’νžŒλ‹€. 이후 νƒ€μ΄μ–΄λ‚˜ μ œμ‘°μ‚¬ μ— λΈ”λŸΌμ²˜λŸΌ 세뢀적인 νŠΉμ§•μ„ νŒŒμ•…ν•˜κ³  β€˜μ‚¬μ§„ 속에 μžˆλŠ” λ¬Όμ²΄λŠ” μžλ™μ°¨β€™λΌλŠ” 결둠을 λ‚΄λ¦¬κ²Œ λœλ‹€. μ œν”„ λ”˜ ꡬ글 μˆ˜μ„μ—°κ΅¬μ›μ€ β€œλ‚˜μ„ ν˜• 신경망은 λ‹€λ₯Έ λ¨Έμ‹ λŸ¬λ‹ ꡬ쑰듀과 비ꡐ할 λ•Œ μ˜μƒ, μŒμ„± λΆ„μ•Όμ—μ„œ 쒋은 μ„±λŠ₯을 보인닀”며 β€œμ΄λ₯Ό μ΄μš©ν•˜λ©΄ 컴퓨터가 처음 λ³Έ 사물도 무엇인지 νŒŒμ•…ν•  수 μžˆλ‹€β€κ³  μ„€λͺ…ν–ˆλ‹€. μ£Όλ³€μ—μ„œ λ³Ό 수 μžˆλŠ” μ˜μƒμ΄¬μ˜μš© λ“œλ‘ μ—λ„ μ΄λ³΄λ‹€λŠ” κ°„λ‹¨ν•˜μ§€λ§Œ λΉ„μŠ·ν•œ 기술이 μ΄μš©λœλ‹€. 세계 1μœ„ λ“œλ‘ μ—…μ²΄μΈ 쀑ꡭ DJI의 β€˜νŒ¬ν…€4β€™λŠ” μ‚¬λžŒ 눈처럼 두 개의 카메라 μ„Όμ„œλ₯Ό μž₯μ°©ν–ˆλ‹€. 이λ₯Ό 톡해 λŒ€μƒ 물체λ₯Ό ν™•μΈν•˜κ³  일정 거리λ₯Ό μœ μ§€ν•˜λ©΄μ„œ λ”°λΌλ‹€λ‹Œλ‹€. 이λ₯Έλ°” β€˜μ•‘ν‹°λΈŒ νŠΈλž™β€™ κΈ°λŠ₯이닀. μ•‘ν‹°λΈŒ νŠΈλž™ κΈ°λŠ₯을 켜면 μ΄μš©μžκ°€ μ§€μ •ν•œ μ‚¬λ¬Όμ΄λ‚˜ μ‚¬λžŒμ˜ μœ€κ³½μ„ μ„ μΈμ‹ν•˜κ³  ν”½μ…€(이미지λ₯Ό κ΅¬μ„±ν•˜λŠ” κ°€μž₯ μž‘μ€ λ‹¨μœ„μΈ λ„€λͺ¨ λͺ¨μ–‘μ˜ 점) λ‹¨μœ„λ‘œ μΈμ‹ν•œλ‹€. κ·Έ 픽셀을 κ³„μ†μ μœΌλ‘œ 같은 크기둜 μœ μ§€ν•˜κΈ° μœ„ν•΄ 기체가 μ΄λ™ν•œλ‹€. μ˜ˆμ»¨λŒ€ 주변에 μžˆλŠ” μ‚¬λžŒμ„ μ§€μ •ν–ˆμ„ λ•Œ ν”½μ…€ 크기가 μƒν•˜μ’Œμš° 100Γ—100 ν”½μ…€μ΄μ—ˆλ‹€κ³  ν•΄ 보자. κ·Έ μ‚¬λžŒμ΄ μ•žμœΌλ‘œ μ›€μ§μ—¬μ„œ 80Γ—80 ν”½μ…€ 크기둜 쀄어듀면 μ›λž˜ 수치인 100Γ—100 픽셀을 되찾기 μœ„ν•΄ λ“œλ‘ λ„ λ”°λΌμ„œ μ•žμœΌλ‘œ μ›€μ§μ΄λŠ” 방식이닀. κ³Όν•™μžλ“€μ€ λ‚˜μ„ ν˜• 신경망을 본뜬 λ¨Έμ‹ λŸ¬λ‹ κΈ°μˆ μ„ μ‘μš©ν•΄ 인간 삢을 μœ€νƒν•˜κ²Œ ν•  수 μžˆλŠ” κΈ°μˆ μ„ κ°œλ°œν•˜κ³  μžˆλ‹€. μŠ€μœ„μŠ€ μ·¨λ¦¬νžˆλŒ€ μ—°κ΅¬νŒ€μ€ λ“œλ‘ μ„ μ΄μš©ν•΄ μ•Œν”„μŠ€ μ‚°λ§₯μ—μ„œ μ‘°λ‚œμžλ₯Ό μ°ΎλŠ” κΈ°μˆ μ„ 연ꡬ 쀑이닀. μ—°κ΅¬νŒ€μ΄ κ°œλ°œν•œ AI λ“œλ‘ μ€ 카메라가 μ΄¬μ˜ν•œ 이미지λ₯Ό μ΄μš©ν•΄ 숲이 μš°κ±°μ§„ κ³³κ³Ό λ“±μ‚°λ‘œλ₯Ό κ΅¬λΆ„ν•œλ‹€. 이λ₯Ό λ“œλ‘ μ˜ λΉ„ν–‰ μ œμ–΄κΈ°λ‘œ 전달해 이동 λ°©ν–₯을 κ²°μ •ν•œλ‹€. μ˜¬ν•΄ 초 μ·¨λ¦¬νžˆλŒ€κ°€ μ™„λ£Œν•œ 첫 μ‹€ν—˜μ—μ„œλŠ” β€˜λ“œλ‘ μ΄ 인간보닀 λ“±μ‚°λ‘œλ₯Ό 잘 μ°ΎλŠ”λ‹€β€™λŠ” κ²°κ³Όκ°€ λ‚˜μ™”λ‹€. μ—°κ΅¬νŒ€μ€ μ•½ 2만μž₯의 μ•Œν”„μŠ€ μ‚° λ“±μ‚°λ‘œ 사진을 λ°”νƒ•μœΌλ‘œ 3일간 λ“œλ‘ μ— νƒ‘μž¬λœ 인곡지λŠ₯의 심측신경망을 ν•™μŠ΅μ‹œμΌ°λ‹€. 이후 λ“œλ‘ μ΄ μ „ν˜€ 가보지 λͺ»ν•œ λ“±μ‚°λ‘œλ₯Ό 였λ₯΄λ„둝 ν–ˆλ‹€. μ‹€ν—˜ κ²°κ³Ό μ‚¬λžŒ 눈으둜 μƒˆλ‘œμš΄ λ“±μ‚°λ‘œλ₯Ό 식별할 ν™•λ₯ μ€ 82%μ˜€μœΌλ‚˜ AI λ“œλ‘ μ€ 85%의 성곡λ₯ μ„ 보여쀬닀. μ·¨λ¦¬νžˆλŒ€ μ—°κ΅¬νŒ€μ€ β€œAI λ“œλ‘ μ€ μ‘°λ§Œκ°„ 싀전에 νˆ¬μž…λΌ μ‚°μ•…κ΅¬μ‘°λŒ€κ°€ μ‘°λ‚œμžλ₯Ό μ°ΎλŠ” 일을 λ„μšΈ 수 μžˆμ„ 것”이라고 λ§ν–ˆλ‹€. 신경망 ν•™μŠ΅ κΈ°μˆ μ€ λ‹€μ–‘ν•œ μš©λ„λ‘œ ν™œμš©ν•  수 μžˆλ‹€. λ¬Ένƒœν˜„ DJI코리아 λŒ€ν‘œλŠ” β€œAIλ₯Ό νƒ‘μž¬ν•œ λ“œλ‘ μ€ μ†‘μ „μ„ μ΄λ‚˜ μ†‘μœ κ΄€ λ“± μ‚°μ—…μ‹œμ„€λ¬Όμ˜ 결함 발견, μ‚°λΆˆ 감지, μž₯μ• λ¬Όμ΄λ‚˜ κ΅°μ‚¬μš© λͺ©ν‘œλ¬Ό 탐지 λ“± 이용 κ°€λŠ₯ λ²”μœ„κ°€ λ¬΄κΆλ¬΄μ§„ν•˜λ‹€β€κ³  λ§ν–ˆλ‹€."),
"""

demo = gr.Interface(
    fn=interface_handler,
    inputs=[
              gr.inputs.Textbox(lines=5, placeholder=None, default=default_text, label="μž„μ˜ λ¬Έμž₯ (Custom text)", optional=False),
              gr.inputs.Textbox(lines=1, placeholder=None, default=default_url, label="넀이버 λ‰΄μŠ€ 기사 λ§ν¬μ£Όμ†Œ (Naver News article URL)", optional=False),
              gr.inputs.Radio(["μž…λ ₯ λ¬Έμž₯ μš”μ•½", "넀이버 λ‰΄μŠ€ 기사 μš”μ•½"], type="index", default=None, label=None, optional=False)
           ],
    outputs=[
            gr.outputs.Textbox(label="κ°œμš”"),
            ],
)

if __name__ == "__main__":
    demo.launch(debug=True)