DEVOOK์ ๊ธฐ๋ฅ ์ค ์ฌ์ฉ์๊ฐ ์ ์ฅํ ๋ธ๋ก๊ทธ ๊ธ์ ์ฃผ์ ์ ์ ํฉํ ํค์๋๋ฅผ ์๋์ผ๋ก ์ถ์ถํ์ฌ ๊ธ์ ๋ถ๋ฅํ๋ ๊ธฐ๋ฅ์ด ์๋ค. ํด๋น ๊ธฐ๋ฅ ๊ตฌํ์ ์ํด ๊ด๋ จ ๊ธฐ์ ์ ์กฐ์ฌํ๊ณ ํค์๋ ์ถ์ถ ํ ์คํธ๋ฅผ ์งํํ์๋ค.
Azure Cognitive Service for Language์์ ํต์ฌ ๊ตฌ ์ถ์ถ
ํด๋น ๊ธฐ์ ์ Azure Cognitive Service for Language์์ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ผ๋ก ๋น์ ํ ํ
์คํธ๋ฅผ ํ๊ฐํ๊ณ ๊ฐ ์
๋ ฅ ๋ฌธ์์ ๋ํด ํ
์คํธ์ ํต์ฌ ๊ตฌ ๋ฐ ์ฃผ์ ์ง์ ๋ชฉ๋ก์ ๋ฐํํ๋ค.
(Azure Cognitive Service for Language๋ ํ
์คํธ๋ฅผ ์ดํดํ๊ณ ๋ถ์ํ๊ธฐ ์ํ NLP(์์ฐ์ด ์ฒ๋ฆฌ) ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ํด๋ผ์ฐ๋ ๊ธฐ๋ฐ ์๋น์ค์)
#1 ์ง์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๊ฒ๋ณด๋ค ์๊ฐ์ด ๋ ๋ค๊ณ ํจ์จ์ ์
AI ๋ชจ๋ธ์ ๊ฐ๋ฐํด๋ณธ ๊ฒฝํ์ด ์๋ ํ์์ด ์์๊ณ , ํด๋น ํ๋ก์ ํธ์์๋ AI ๊ธฐ์ ๋ณด๋ค ๋ฐฑ์๋ ์๋ฒ ๊ฐ๋ฐ์ ๋ ์ด์ ์ ๋๊ธฐ ์ํด์ ๋ฏธ๋ฆฌ ๊ตฌํ๋์ด ์ถ๊ฐ ์ฌ์ฉ์ ์ง์ ์์ด ๊ทธ๋๋ก ์ํ ๊ฐ๋ฅํ ์๋น์ค๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ํ์๋ค.
#2 ์๊ตฌ ๊ธฐ์ค ๋ชจ๋ ๋ง์กฑ
ํค์๋ ์ถ์ถ ์๋น์ค ์ค ์ฐ๋ฆฌ ํ๋ก์ ํธ ๊ธฐ๋ฅ ๊ตฌํ ์ ๊ฐ์ฅ ์ ํฉํ ๊ฒ์ ๊ณ ๋ฅด๊ธฐ ์ํด ๊ธฐ์ค์ ์ธ์ ์ ํํ์๋ค.
์ด๋ฆ | ๋ถ์ ์ธ์ด ์ง์(ํ๊ตญ์ด, ์์ด) | ํ๊ธ & ์์ด 2๊ฐ์ ์ธ์ด์ ๋ํ ๋์ ๋ถ์ ๊ฐ๋ฅ ์ฌ๋ถ | ํธ์ถ ๊ตฌํ ๋ฐฉ์ | ์ฝ๋ฉ ์ธ์ด ์ง์ | ์ฅ์ | ๊ฐ๊ฒฉ |
---|---|---|---|---|---|---|
Azure ํต์ฌ ๋ฌธ๊ตฌ ์ถ์ถ | ๋ชจ๋ ์ง์ | ๊ฐ๋ฅ | 1) REST API ํธ์ถ, 2) Azure ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ | .NET, Python, Java, Node.js | ๊ณต์๋ฌธ์๊ฐ ์ ๋์์์, ์ฌ์ฉ์ด ํธ๋ฆฌํจ(REST API & ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ชจ๋ ์ง์) | Language Service pricing |
์ฃผ์ ๋ด์ฉ : ํฌ๋กค๋งํ ๋ธ๋ก๊ทธ ๊ธ์ ๋ํ Azure ํต์ฌ ๊ตฌ ์ถ์ถ ํ
์คํธ
ํธ์ถ ๊ตฌํ ๋ฐฉ์ : Azure ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
๋์ ๋ธ๋ก๊ทธ : tistory, velog, medium
ํ
์คํธ ์ํ ์กฐ๊ฑด : ์ ์ฒ๋ฆฌ X (์๋ฌธ ํฌ๋กค๋ง๋ง ํด์ด), Azure ํต์ฌ ๊ตฌ ์ถ์ถ ๊ธฐ๋ฅ ํธ์ถ ์ ์ค์ ๋์ด์๋ ๋ฌธ์ ์ ์ ํ(5120 text)์ ๋ง์ถฐ ํฌ๋กค๋งํ ๋ฌธ์์ด์ ์๋ผ์(Python ๋ฌธ์์ด ์ธ๋ฑ์ฑ ์ฌ์ฉ) List์ ์ ์ฅํจ
Step1. Azure Cognitive Service for Language์์ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ ๋ํ ์ก์ธ์ค ๊ถํ์ ๋ถ์ฌํ๋ Azure ์ธ์ด ๋ฆฌ์์ค๋ฅผ ์์ฑ (API ์์ฒญ ์ธ์ฆ์ ์ฌ์ฉํ๋ Key ๋ฐ ์๋ํฌ์ธํธ URL ์์ฑ)
์ฐธ๊ณ ) Azure ๋ฆฌ์์ค ๊ทธ๋ฃน ๋ง๋ค๊ธฐ, ๋ฆฌ์์ค ๊ณต๊ธ์ ๋ฑ๋ก(subscription)
Step2. Python ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์์ฒญ ์์ฑ ํ ํ
์คํธ
1) ์์ฒญ์ ์ํ ์ธ์ฆ ๋ฐ ํต์ฌ ๊ตฌ ์ถ์ถ ๊ธฐ๋ฅ ํธ์ถ ์ฝ๋
# -*- coding: utf-8 -*-
import json
import os.path
# Azure ํต์ฌ ๊ตฌ ์ถ์ถ ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
from azure.ai.textanalytics import TextAnalyticsClient
from azure.core.credentials import AzureKeyCredential
from key_phrase_with_crawler.get_test_document import get_test_document
# ใฑ. ์์ฒญ ์ธ์ฆ์ ์ฌ์ฉ๋๋ Endpoint & ๋น๋ฐ ํค
endpoint = "https://koreacentral.api.cognitive.microsoft.com/"
secret_file = os.path.join('.', 'secrets.json')
with open(secret_file) as f:
secrets = json.loads(f.read())
# Authenticate the client using your key and endpoint
def authenticate_client():
ta_credential = AzureKeyCredential(secrets["azure_secret_key"])
text_analytics_client = TextAnalyticsClient(
endpoint = endpoint,
credential = ta_credential)
return text_analytics_client
client = authenticate_client()
# Test key phrase extraction with crawler
def key_phrase_extraction_example(client):
try:
documents = get_test_document()
response = client.extract_key_phrases(documents=documents, language="ko") # ใด. ๋ฐ์ดํฐ๊ฐ ํฌํจ๋ ๋น์ ํ ์์ ํ
์คํธ ์ ๋ฌ
print(response)
except Exception as err:
print("Encountered exception. {}".format(err))
key_phrase_extraction_example(client)
ใฑ. ์์ฒญ ์ธ์ฆ์ ์ฌ์ฉ๋๋ Endpoint & ๋น๋ฐ ํค
๋ฐ๊ธ๋ฐ์ ๋น๋ฐ ํค๋ ๋
ธ์ถ๋๋ฉด ์๋๊ธฐ ๋๋ฌธ์ secrets.json ํ์ผ์ ๋ฐ๋ก ์ ์ฅํด๋๊ณ ํด๋น ํ์ผ์ ํตํด ๋น๋ฐ ํค ์ ๊ทผํ๋๋ก ์ค์ ํจ
ใด. ๋ฐ์ดํฐ๊ฐ ํฌํจ๋ ๋น์ ํ ์์ ํ
์คํธ ์ ๋ฌ
TextAnalyticsClient ํด๋์ค์ ์ ์๋์ด ์๋ extract_key_phrase()๋ฅผ ํธ์ถํ์ฌ ํต์ฌ ๊ตฌ ์ถ์ถ ์ํํจ. ์ด๋ ์ธ์๋ก ๋น์ ํ ์์ ํ
์คํธ ์ ๋ฌํจ
2) ํฌ๋กค๋งํ ๋ฐ์ดํฐ ์๋ผ์ ๋ฆฌ์คํธ์ ์ ์ฅํ๋ ์ฝ๋
from key_phrase_with_crawler.lambda_function_for_test import lambda_handler
def get_test_document():
content = lambda_handler(
{
"url": "https://medium.com/musinsa-tech/mab-211d14d2090b"
},
None,
)
# ๊ธฐ๋ฅ : ํฌ๋กค๋งํ ๋ฐ์ดํฐ(๋ฌธ์์ด)๋ฅผ 5120 ๋งํผ์ฉ ์๋ผ์ list์ ์ ์ฅํ๊ธฐ
test_document = []
for i in range(0, len(content), 5120):
if len(content) - 1 - i < 5119:
test_document.append(content[i:])
else:
test_document.append(content[i:i + 5119])
return test_document
โ ํฌ๋กค๋งํ ๋ฐ์ดํฐ(๋ฌธ์์ด)๊ฐ Azure ํต์ฌ ๊ตฌ ์ถ์ถ ์๋น์ค ๋ฐ์ดํฐ ํ์ฉ ํ๋๋ณด๋ค ํฐ ๊ฒฝ์ฐ๊ฐ ์๊ธฐ ๋๋ฌธ์ ํด๋น ํ ์คํธ๋ฅผ ์ ํ๋ ํฌ๊ธฐ์ธ 5120์ ์ฉ ์๋ผ์ ๋ฆฌ์คํธ์ ์ ์ฅํ์์
์ฐธ๊ณ )
# azure.ai.textanalytics.TextAnalyticsClient ํด๋์ค์ ์ ์๋์ด ์๋ extract_key_phrases()์ ์ฝ๋ ์ค ์ผ๋ถ
@distributed_trace
def extract_key_phrases( # type: ignore
self,
documents, # type: Union[List[str], List[TextDocumentInput], List[Dict[str, str]]]
**kwargs # type: Any
):
โ ์์ฒญ ์ ์ธ์๋ก ์ ๋ฌํ ๋ฐ์ดํฐ์ ํํ๋ List[str], List[TextDocumentInput], List[Dict[str, str]] ์ด 3๊ฐ์ง ์ค ์ ํ ๊ฐ๋ฅํจ
Step3. ํ ์คํธ ์ํ ๊ฒฐ๊ณผ ํ์ธ
# ex) Medium ๋ธ๋ก๊ทธ ๊ธ์ ๋ํ ํต์ฌ ๊ตฌ ์ถ์ถ ๊ฒฐ๊ณผ
{
'id': '0',
'key_phrases': ['Thompson Sampling ์๊ณ ๋ฆฌ์ฆThompson Sampling', 'Upper Confidence Bound', 'MUSINSA techFollow', 'Event Bus', 'BetaDistribution betaDistribution', 'new BetaDistribution', 'BigDecimal bd', 'new BigDecimal', 'return bd', 'Armed Bandit', 'double impression', 'double number', 'Apache Kafka', 'Apache Druid', 'Druid ์๋ฒ๋', 'MAB ์๊ณ ๋ฆฌ์ฆ', 'ug', '์ค์๊ฐ MAB ์ ๋ ฌ ์์คํ
๊ตฌ์ถ', 'CTR', 'Multi', 'fresh', 'MAB๋ ์นด์ง๋
ธ', 'Exploration', 'Exploitation', 'Greedy ์๊ณ ๋ฆฌ์ฆฮต', 'UDB', 'Elasticsearch', 'Lucene', 'Master', 'Data', 'Query', 'Cluster', 'Segment', 'SQL', 'Rollup', 'day', 'hour', 'thompsonSampling', 'click', 'Round', 'sample', 'FAULT', 'CALE', 'LIMIT', 'public', 'HALF', 'Value', 'score', 'brand', 'wvproject', 'impCnt', 'kCnt', 'travel', 'vans', 'newbalance', 'fit', 'mindbridge', 'Redis', '์๋น์ค API', 'MAB ์ ๋ ฌ ๋ฐ์ดํฐ', '๋ฌด์ ์ฌ ์ ์๊ฐ๋ฐํ', '์ด๋ฒคํธ ๋ฒ์ค', 'ํ์นํ', '๋ฌด์ ์ฌ๋', '์ฝํ
์ธ ๊ธฐ๋ฐ', '์ปค๋ฎค๋ํฐ', '์คํ ์ด', '๊ณ ๊ฐ', '๋ค์ํ ์ ๋ณด', '์ค์๊ฐ ์ด๋ฒคํธ', '๋ฐฐ๋', '๊ฒ์', 'ํ๊ทธ', '์ํ', '์์ด๋ดํฐํฐ', '๋ธ๋๋', 'ํ์ด์ง', '์ ๋ณด๊ฐ', '๋ฌธ์ ๋', '์ ๋๋น', '์น', '์ฑ', '๊ณต๊ฐ', '์ํฉ์์', '๊ฒฐ๊ณผ', '๋ฐฉ์', '์ด๋ฒ', '๊ธ', '๋ฌด์ ์ฌ๊ฐ', '๋ฌธ์ ๊ฐ์ ๋ฐฉํฅ', '๋ ๊ด๋ฆฌ', 'ํจ์จ์ฑ', '์๋ ๊ด๋ฆฌ', '๋
ธ์ถ ์์', 'ํ์', '์์', '๋ฌธ์ ์ ', 'ํ์', 'ํด๋ฆญ', 'ํ๋ฅ ', '๋ฏธ', '๋', '์ค์๊ฐ์ผ๋ก', '์ฌ์ฉ์', 'ํธ๋ ๋', '์ฑ๋ณ', '์ฐ๋ น', '๋ถ๋ฅ', '์ฅ์ ', '์๋ํ', '๊ธฐ์ค', '๊ด์ฌ', 'ํน์ ', '์ฐฉ', '์ ๋ชฉํ๋ก', '๊ด๋ฆฌ์', '์๋์ง', '์๋ชจ', '์ฒ์', '๋ณํ๊ฐ', 'ํ๋งค์ ํต๊ณ', '์์ ์ ๋ ฌ', 'ํ ์ธ ์ด๋ฒคํธ์', '๋ฆฌํ๋ ์ฌ', '๊ตฌ์ฒด์ ์ธ ์ ์ฉ ๋ฐฉ๋ฒ', '๊ฐ๋
', '๋ ๋ฒ', '์ฌ๋กฏ๋จธ์ ', '์น๋ฅ ', '์์ต', 'ํ์', '์ํ', '๊ณผ์ ', '๋น์ฉ', '์ต๋ํ', '์ ์ ํ', '์กฐํ', 'ํ๋๋ง', 'ํ์', '์ข
๋ฅ๊ฐ', '์ฅ๋จ์ ', 'ฮต ๋น์จ', '๋ณด์', '์ ํ', '์ฑ๊ณผ', '๊ณณ์', '๋์', '๊ธฐํ', '๋ฆฌ์์ค๊ฐ', '์ ๋ขฐ๋', 'ํ๋ ๋ฒ์ ์๊ณ ๋ฆฌ์ฆ', '์๋', '์ฐ์ฐ', '์กฐ๊ฑด์์', 'ํ๊ฒฝ', '์์ธ', '์ข', '์ฑ๋ฅ', 'ํผ๋๋ฐฑ', '์ฑ๊ณต', '์คํจ', '๋ถ๋ฐฐ', '๋ก๊ทธ ๋ฐ์ดํฐ', '์ปดํจํ
๋ถํ', '์์
์', '๋ฐ์ดํฐ ์์ง', '๊ธฐ๋ณธ ์ ๋ณด', 'ํ๋', '๋ฐ์ดํฐ๋', '๋ฐ์ดํฐ ์คํธ๋ฆฌ๋ฐ ํ๋ซํผ์', '์๊ณ์ด ๋ฐ์ดํฐ ์ ์ฅ์', '์ญํ ', '์์ค์', '๋ฐ์ดํฐ๋ฒ ์ด์ค', 'ํ
์คํธ', '์ซ์', '์์น ๊ธฐ๋ฐ ์ ๋ณด', '์ ํ', '์ ํ', '๋ฃจ์ฌ', '๋ถ์ ์์ง', '๋์๋ณด๋', '์คํ์์ค', '์คํธ๋ฆผ ํ๋ก์ธ์', '๋ฐ์ดํฐ์', '๋กค์
', '์คํ ๋ฆฌ์ง', '์ง์์', '๋น ๋ฅธ ์๋', '๊ธฐ์กด', '๊ฒฝํ', '๋ค๋ฃจ๋', '์๋ฒ ๊ตฌ์ฑ', 'ํด๋ฌ์คํฐ', 'ํํ๋ก', '๋ฉํ๋ฐ์ดํฐ ๊ด๋ฆฌ', '์คํธ๋ฆผ ๋ฐ์ดํฐ', '์ธ๊ทธ๋จผํธ', '๋ฐ์ดํฐ ์ง', '์๋ต', '๋น์ ์ต์ ๋ฒ์ ', '์ต๊ทผ', '๋ฐ์ดํฐ ์คํธ๋ฆผ', '๊ธฐ๋ฅ', '์๊ฐ ๋จ์', 'ํ๋ ๋จ์๋ก', '์ํ๋ง ๊ฐ', '๋ฉ๋ชจ๋ฆฌ ์บ์ฑ', '๋จ๊ณ', '์ฝํ
์ธ ์', '๋ฎ'],
'warnings': [],
'statistics': None,
'is_error': False
}
{
'id': '1',
'key_phrases': ['MAB ์ ๋ ฌ ์์คํ
', 'MAB ์๊ณ ๋ฆฌ์ฆ', 'MAB ์ ๋ ฌ ์์ ๋ณ๊ฒฝ', 'MAB์ ๋ ฌ', 'Druid', 'Discount', 'Thompson', 'ling', 'https', 'medium', 'com', 'data', 'reply', 'it', 'tech', 'apache', 'ad', 'bb', 'cd', 'f', 'wonyong', 'jang', 'gi', 'ub', 'io', 'Big', 'html', 'ichi', 'pro', 'ko', 'hyeondae', 'bunseog', 'pilsu', 'yoso', 'en', 'wikipedia', 'org', 'armed', 'sanghy', 'ukch', 'seing', 'tistory', '์ง๊ธ', '๋ฆฐ', '์ ์ฒด์ ์ธ ์ํคํ
์ฒ', '์๋ ๊ทธ๋ฆผ', '์ ์ธ๊ธฐ ๋ธ๋๋ ๋ฆฌ์คํธ', '์ข', '์ฐ', '๊ธฐ์กด', '๊ณ ์ ๋', '์์๋ก', '์ ์
', '์์', '์ค์๊ฐ ์ฑ๊ณผ', '์ฌ์ฉ์ ๊ด์ฌ๋', 'ํ๋ฆ', '์์๊ฐ', '๊ธฐํ', 'ํจ๊ณผ', 'ํด๋ฆญ์จ', '์ผ์ ์์ค', '๋
ธ์ถ', 'ํ์', '์ ์ฌ๋', '๋ก๊ทธ', '๋ฐ์ดํฐ', '๊ธฐ๊ฐ', '๋ฌด์ ์ฌ ์คํ ์ด', 'ํด๋น', '์์ญ', 'ํด๋ฆญ๋ฅ ', '๊ฒฐ๊ณผ', '๋ง์น', '์์์', '์บ ํ์ธ', '๊ธฐํ์ ', '๋ค์ํ', 'ํ์ด์ง', '์ํ', '์๊ฐ', '์์
', '์ฑ๋ณ', '๊ตฌ์ฑ', '๊ณผ๊ฑฐ', '๊ฐ์ค์น', '๋ณํ', '์ฐ์ ', '๊ธฐ๋ฅ', '๊ตฌ๋งค', '์ฅ๋ฐ๊ตฌ๋', 'ํฅํ', '์ฐ๋ น', '๊ฐ์ฌ'],
'warnings': [],
'statistics': None,
'is_error': False
}