Package kiwipiepy

Kiwipiepy란?

Kiwipiepy는 한국어 형태소 분석기인 Kiwi(Korean Intelligent Word Identifier)의 Python 모듈입니다. C++로 작성되었고 다른 패키지에 의존성이 없으므로 C++ 컴파일이 가능한 환경이라면 어디에서나 Kiwipiepy를 사용 가능합니다.

kiwipiepy

시작하기

pip를 이용해 쉽게 설치할 수 있습니다. (https://pypi.org/project/kiwipiepy/)

$ pip install kiwipiepy

지원하는 OS와 Python 버전은 다음과 같습니다:

  • Python 3.6 이상이 설치된 Linux (x86-64)
  • Python 3.6 이상이 설치된 macOS 10.13이나 그 이후 버전
  • Python 3.6 이상이 설치된 Windows 7 이나 그 이후 버전 (x86, x86-64)
  • Python 3.6 이상이 설치된 다른 OS: 이 경우 소스 코드 컴파일을 위해 C++11이 지원되는 컴파일러가 필요합니다.

Kiwipiepy가 제대로 설치되었는지 확인하기 위해서는 다음 명령어를 실행해보십시오.

$ python -m kiwipiepy

위 명령어는 대화형 인터페이스를 시작합니다. 인터페이스에 원하는 문장을 입력하면 형태소 분석 결과를 확인할 수 있습니다.

>> 안녕?
[Token(form='안녕', tag='IC', start=0, len=2), Token(form='?', tag='SF', start=2, len=3)]

인터페이스를 종료하려면 Ctrl + C 를 누르십시오.

예제

간단한 분석

다음 예제 코드는 kiwipiepy 인스턴스를 생성해 형태소 분석을 수행하는 간단한 예제 코드입니다.

from kiwipiepy import Kiwi
kiwi = Kiwi()
for result, score in kiwi.analyze("형태소 분석 결과입니다", top_n=5):
    print(score, result, sep='\t')

# 위 코드를 실행하면 다음과 같은 결과가 나옵니다.
# -34.33329391479492      [Token(form='형태소', tag='NNG', start=0, len=3), Token(form='분석', tag='NNG', start=4, len=2), Token(form='결과', tag='NNG', start=7, len=2), Token(form='이', tag='VCP', start=9, len=1), Token(form='ᆸ니다', tag='EF', start=10, len=2)]
# -38.10548400878906      [Token(form='형태소', tag='NNG', start=0, len=3), Token(form='분석', tag='NNG', start=4, len=2), Token(form='결과', tag='NNG', start=7, len=2), Token(form='이', tag='MM', start=9, len=1), Token(form='ᆸ니다', tag='EC', start=10, len=2)]
# -51.977012634277344     [Token(form='형태소', tag='NNG', start=0, len=3), Token(form='분석', tag='NNG', start=4, len=2), Token(form='결과', tag='NNG', start=7, len=2), Token(form='이', tag='MM', start=9, len=1), Token(form='ᆸ니다', tag='NNP', start=10, len=2)]
# -51.978363037109375     [Token(form='형태소', tag='NNG', start=0, len=3), Token(form='분석', tag='NNG', start=4, len=2), Token(form='결과', tag='NNG', start=7, len=2), Token(form='이', tag='MM', start=9, len=1), Token(form='ᆸ', tag='NNG', start=10, len=0), Token(form='니', tag='EC', start=10, len=1), Token(form='다', tag='EC', start=11, len=1)]
# -52.152374267578125     [Token(form='형태소', tag='NNG', start=0, len=3), Token(form='분석', tag='NNG', start=4, len=2), Token(form='결과', tag='NNG', start=7, len=2), Token(form='이', tag='MM', start=9, len=1), Token(form='ᆸ', tag='NNG', start=10, len=0), Token(form='니다', tag='EF', start=10, len=2)]

# 간단하게 형태소 분석 결과만 얻고 싶다면 `tokenize` 메소드를 사용하면 됩니다.

result = kiwi.tokenize("형태소 분석 결과입니다")
print(result)
# [Token(form='형태소', tag='NNG', start=0, len=3), Token(form='분석', tag='NNG', start=4, len=2), Token(form='결과', tag='NNG', start=7, len=2), Token(form='이', tag='VCP', start=9, len=1), Token(form='ᆸ니다', tag='EF', start=10, len=2)]

사용자 단어 추가

사용자 정의 단어를 추가하여 형태소 분석을 수행하는 예제입니다. 사용자 정의 단어를 등록하면 이는 Kiwi 분석기의 사전에 포함되어 결과의 후보로 등장할 수 있게 됩니다.

종종 동일한 형태의 단어가 여러 가지로 분석되는 경우가 있습니다. 이 경우 사용자 정의 단어를 우선할지, 분석기가 가지고 있는 형태소 정보를 우선할지 사용자 단어 점수를 조절함으로써 통제 가능합니다. 아래 예제는 '골리'라는 고유 명사 단어가 포함된 문장을 분석하는 경우에 부여하는 단어 점수에 따라 결과가 어떻게 달라지는지를 보여줍니다.

from kiwipiepy import Kiwi

# 사용자 단어 추가 없이 분석해보겠습니다.

kiwi = Kiwi()

print(*kiwi.analyze('사람을 골리다', top_n=5), sep='\n')
# 결과
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'VV', 4, 2), ('다', 'EC', 6, 1)], -36.505615234375)
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'VV', 4, 2), ('다', 'MAG', 6, 1)], -40.310791015625)
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'VV', 4, 2), ('하', 'XSA', 6, 1), ('다', 'EC', 6, 1)], -40.388427734375)
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'VV', 4, 2), ('하', 'XSV', 6, 1), ('다', 'EC', 6, 1)], -42.22119140625)
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'VV', 4, 2), ('다', 'EF', 6, 1)], -42.44189453125)

print(*kiwi.analyze('골리는 사람이다', top_n=5), sep='\n')
# 결과
# ([('골리', 'VV', 0, 2), ('는', 'ETM', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'VCP', 6, 1), ('다', 'EC', 7, 1)], -39.06201171875)
# ([('골리', 'VV', 0, 2), ('는', 'ETM', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'VCP', 6, 1), ('다', 'EF', 7, 1)], -41.10693359375)
# ([('골리', 'VV', 0, 2), ('는', 'ETM', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'JKS', 6, 1), ('다', 'MAG', 7, 1)], -41.588623046875)
# ([('골리', 'VV', 0, 2), ('는', 'JX', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'VCP', 6, 1), ('다', 'EC', 7, 1)], -41.6220703125)
# ([('골리', 'VV', 0, 2), ('는', 'JX', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'JKS', 6, 1), ('다', 'MAG', 7, 1)], -43.114990234375)

# 사용자 단어 '골리'를 추가해보도록 하겠습니다.
kiwi = Kiwi()
kiwi.add_user_word('골리', 'NNP', 0)

print(*kiwi.analyze('사람을 골리다', top_n=5), sep='\n')
# 결과
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'NNP', 4, 2), ('다', 'EC', 6, 1)], -31.064453125)
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'NNP', 4, 2), ('다', 'MAG', 6, 1)], -34.109619140625)
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'NNP', 4, 2), ('다', 'EF', 6, 1)], -37.097900390625)
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골', 'NNG', 4, 1), ('리다', 'EF', 5, 2)], -45.919189453125)
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골', 'VV', 4, 1), ('리다', 'EF', 5, 2)], -49.18359375)

print(*kiwi.analyze('골리는 사람이다', top_n=5), sep='\n')
# 결과
# ([('골리', 'NNP', 0, 2), ('는', 'JX', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'VCP', 6, 1), ('다', 'EC', 7, 1)], -25.12841796875)
# ([('골리', 'NNP', 0, 2), ('는', 'JX', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'JKS', 6, 1), ('다', 'MAG', 7, 1)], -26.621337890625)
# ([('골리', 'NNP', 0, 2), ('는', 'JX', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'VCP', 6, 1), ('다', 'EF', 7, 1)], -27.17333984375)
# ([('골리', 'NNP', 0, 2), ('는', 'ETM', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'VCP', 6, 1), ('다', 'EC', 7, 1)], -29.90185546875)
# ([('골리', 'NNP', 0, 2), ('는', 'ETM', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'VCP', 6, 1), ('다', 'EF', 7, 1)], -31.94677734375)

# 사용자 단어 '골리'의 점수를 낮춰서 추가해보도록 하겠습니다.
kiwi = Kiwi()
kiwi.add_user_word('골리', 'NNP', -6)

print(*kiwi.analyze('사람을 골리다', top_n=5), sep='\n')
# 결과
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'VV', 4, 2), ('다', 'EC', 6, 1)], -36.505615234375)
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'NNP', 4, 2), ('다', 'EC', 6, 1)], -37.064453125)
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'NNP', 4, 2), ('다', 'MAG', 6, 1)], -40.109619140625)
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'VV', 4, 2), ('다', 'MAG', 6, 1)], -40.310791015625)
# ([('사람', 'NNG', 0, 2), ('을', 'JKO', 2, 1), ('골리', 'VV', 4, 2), ('다', 'EF', 6, 1)], -42.44189453125)

print(*kiwi.analyze('골리는 사람이다', top_n=5), sep='\n')    
# 결과
# ([('골리', 'NNP', 0, 2), ('는', 'JX', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'VCP', 6, 1), ('다', 'EC', 7, 1)], -31.12841796875)
# ([('골리', 'NNP', 0, 2), ('는', 'JX', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'JKS', 6, 1), ('다', 'MAG', 7, 1)], -32.621337890625)
# ([('골리', 'NNP', 0, 2), ('는', 'JX', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'VCP', 6, 1), ('다', 'EF', 7, 1)], -33.17333984375)
# ([('골리', 'NNP', 0, 2), ('는', 'ETM', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'VCP', 6, 1), ('다', 'EC', 7, 1)], -35.90185546875)
# ([('골리', 'NNP', 0, 2), ('는', 'ETM', 2, 1), ('사람', 'NNG', 4, 2), ('이', 'VCP', 6, 1), ('다', 'EF', 7, 1)], -37.94677734375)

멀티스레딩 analyze

다음 예제 코드는 멀티스레드를 활용하여 test.txt 파일을 줄별로 읽어들여 형태소 분석한 뒤 그 결과를 result.txt 에 저장합니다.

from kiwipiepy import Kiwi
# 4개의 스레드에서 동시에 처리합니다.
# num_workers 생략시 현재 환경에서 사용가능한 모든 코어를 다 사용합니다.
kiwi = Kiwi(num_workers=4)
with open('result.txt', 'w', encoding='utf-8') as output:
    for res in kiwi.analyze(open('test.txt', encoding='utf-8')):
        output.write(' '.join(map(lambda x:x[0]+'/'+x[1], res[0][0])) + '\n')

Kiwi 생성시 인자로 준 num_workers에 따라 여러 개의 스레드에서 작업이 동시에 처리됩니다. 반환되는 값은 입력되는 값의 순서와 동일합니다.

analyze 를 인자를 str의 iterable로 준 경우 이 iterable을 읽어들이는 시점은 analyze 호출 이후일 수도 있습니다. 따라서 이 인자가 다른 IO 자원(파일 입출력 등)과 연동되어 있다면 모든 분석이 끝나기 전까지 해당 자원을 종료하면 안됩니다. 예를 들어 다음과 같이 open을 통해 생성한 파일 입출력 객체를 미리 종료하는 경우 오류가 발생할 수 있습니다.

from kiwipiepy import Kiwi
kiwi = Kiwi(num_workers=4)
file = open('long_text.txt', encoding='utf-8')
result_iter = kiwi.analyze(file)
file.close() # 파일이 종료됨
next(result_iter) # 종료된 파일에서 분석해야할 다음 텍스트를 읽어들이려고 시도하여 오류 발생

# ValueError: I/O operation on closed file.
# The above exception was the direct cause of the following exception:
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# SystemError: <built-in function next> returned a result with an error set

normalize_coda 0.10.2버전부터 normalize_coda 기능이 추가되었습니다. 이 기능은 웹이나 채팅 텍스트 데이터에서 자주 쓰이는 ㅋㅋㅋ, ㅎㅎㅎ와 같은 초성체가 어절 뒤에 붙는 경우 분석에 실패하는 경우를 막아줍니다.

from kiwipiepy import Kiwi
kiwi = Kiwi()
kiwi.tokenize("안 먹었엌ㅋㅋ", normalize_coda=False)
# 출력
 [Token(form='안', tag='NNP', start=0, len=1), 
  Token(form='먹었엌', tag='NNP', start=2, len=3), 
  Token(form='ㅋㅋ', tag='SW', start=5, len=2)]

kiwi.tokenize("안 먹었엌ㅋㅋ", normalize_coda=True)
# 출력
 [Token(form='안', tag='MAG', start=0, len=1), 
  Token(form='먹', tag='VV', start=2, len=1), 
  Token(form='었', tag='EP', start=3, len=1), 
  Token(form='어', tag='EF', start=4, len=1), 
  Token(form='ㅋㅋㅋ', tag='SW', start=5, len=2)]

z_coda 0.15.0버전부터 z_coda 기능이 추가되었습니다. 이 기능은 조사 및 어미에 덧붙은 받침을 분리해줍니다. 기본적으로 True로 설정되어 있으며, 이 기능을 사용하지 않으려면 인자로 z_coda=False를 주어야 합니다.

from kiwipiepy import Kiwi
kiwi = Kiwi()
kiwi.tokenize('우리집에성 먹었어욥', z_coda=False)
# 출력
 [Token(form='우리', tag='NP', start=0, len=2), 
  Token(form='집', tag='NNG', start=2, len=1), 
  Token(form='에', tag='JKB', start=3, len=1), 
  Token(form='성', tag='NNG', start=4, len=1), 
  Token(form='먹었어욥', tag='NNG', start=6, len=4)]

kiwi.tokenize("우리집에성 먹었어욥", z_coda=True) # 기본값이 True므로 z_coda=True는 생략 가능
# 출력
 [Token(form='우리', tag='NP', start=0, len=2), 
  Token(form='집', tag='NNG', start=2, len=1), 
  Token(form='에서', tag='JKB', start=3, len=2), 
  Token(form='ᆼ', tag='Z_CODA', start=4, len=1), 
  Token(form='먹', tag='VV', start=6, len=1), 
  Token(form='었', tag='EP', start=7, len=1), 
  Token(form='어요', tag='EF', start=8, len=2), 
  Token(form='ᆸ', tag='Z_CODA', start=9, len=1)]

split_complex 0.15.0버전부터 split_complex 기능이 추가되었습니다. 이 기능은 더 잘게 분할 가능한 형태소들을 최대한 분할하도록 합니다. 이런 형태소에는 '고마움(고맙 + 음)'과 같은 파생 명사, '건강히(건강 + 히)'와 같은 파생 부사, '반짝거리다(반짝 + 거리다)', '걸어다니다(걸어 + 다니다)'와 같은 파생 동/형용사 등이 포함됩니다.

from kiwipiepy import Kiwi
kiwi = Kiwi()
kiwi.tokenize('고마움에 건강히 지내시라고 눈을 반짝거리며 인사했다', split_complex=False)
# 출력
 [Token(form='고마움', tag='NNG', start=0, len=3),
  Token(form='에', tag='JKB', start=3, len=1), 
  Token(form='건강히', tag='MAG', start=5, len=3), 
  Token(form='지내', tag='VV', start=9, len=2), 
  Token(form='시', tag='EP', start=11, len=1), 
  Token(form='라고', tag='EC', start=12, len=2), 
  Token(form='눈', tag='NNG', start=15, len=1), 
  Token(form='을', tag='JKO', start=16, len=1), 
  Token(form='반짝거리', tag='VV', start=18, len=4), 
  Token(form='며', tag='EC', start=22, len=1), 
  Token(form='인사', tag='NNG', start=24, len=2), 
  Token(form='하', tag='XSV', start=26, len=1), 
  Token(form='었', tag='EP', start=26, len=1), 
  Token(form='다', tag='EF', start=27, len=1)]

kiwi.tokenize('고마움에 건강히 지내시라고 눈을 반짝거리며 인사했다', split_complex=True)
# 출력
 [Token(form='고맙', tag='VA-I', start=0, len=3), 
  Token(form='음', tag='ETN', start=2, len=1), 
  Token(form='에', tag='JKB', start=3, len=1), 
  Token(form='건강', tag='NNG', start=5, len=2), 
  Token(form='히', tag='XSM', start=7, len=1), 
  Token(form='지내', tag='VV', start=9, len=2), 
  Token(form='시', tag='EP', start=11, len=1), 
  Token(form='라고', tag='EC', start=12, len=2), 
  Token(form='눈', tag='NNG', start=15, len=1), 
  Token(form='을', tag='JKO', start=16, len=1), 
  Token(form='반짝', tag='MAG', start=18, len=2), 
  Token(form='거리', tag='XSV', start=20, len=2), 
  Token(form='며', tag='EC', start=22, len=1), 
  Token(form='인사', tag='NNG', start=24, len=2), 
  Token(form='하', tag='XSV', start=26, len=1), 
  Token(form='었', tag='EP', start=26, len=1), 
  Token(form='다', tag='EF', start=27, len=1)]   

blocklist 0.15.0부터 split_complex 와 더불어 blocklist 기능도 추가되었습니다. 이 기능은 split_complex 와는 다르게 세부적으로 분석 결과에 등장하면 안되는 형태소 목록을 지정할 수 있습니다.

from kiwipiepy import Kiwi
kiwi = Kiwi()
kiwi.tokenize('고마움에 건강히 지내시라고 눈을 반짝거리며 인사했다')
# 출력
 [Token(form='고마움', tag='NNG', start=0, len=3),
  Token(form='에', tag='JKB', start=3, len=1), 
  Token(form='건강히', tag='MAG', start=5, len=3), 
  Token(form='지내', tag='VV', start=9, len=2), 
  Token(form='시', tag='EP', start=11, len=1), 
  Token(form='라고', tag='EC', start=12, len=2), 
  Token(form='눈', tag='NNG', start=15, len=1), 
  Token(form='을', tag='JKO', start=16, len=1), 
  Token(form='반짝거리', tag='VV', start=18, len=4), 
  Token(form='며', tag='EC', start=22, len=1), 
  Token(form='인사', tag='NNG', start=24, len=2), 
  Token(form='하', tag='XSV', start=26, len=1), 
  Token(form='었', tag='EP', start=26, len=1), 
  Token(form='다', tag='EF', start=27, len=1)]

kiwi.tokenize('고마움에 건강히 지내시라고 눈을 반짝거리며 인사했다', blocklist=['고마움/NNG'])
# 출력
 [Token(form='고맙', tag='VA-I', start=0, len=3), 
  Token(form='음', tag='ETN', start=2, len=1), 
  Token(form='에', tag='JKB', start=3, len=1), 
  Token(form='건강히', tag='MAG', start=5, len=3), 
  Token(form='지내', tag='VV', start=9, len=2), 
  Token(form='시', tag='EP', start=11, len=1), 
  Token(form='라고', tag='EC', start=12, len=2), 
  Token(form='눈', tag='NNG', start=15, len=1), 
  Token(form='을', tag='JKO', start=16, len=1), 
  Token(form='반짝거리', tag='VV', start=18, len=4), 
  Token(form='며', tag='EC', start=22, len=1), 
  Token(form='인사', tag='NNG', start=24, len=2), 
  Token(form='하', tag='XSV', start=26, len=1), 
  Token(form='었', tag='EP', start=26, len=1), 
  Token(form='다', tag='EF', start=27, len=1)]

Iterable한 입력을 받는 메소드

analyze, tokenize, extract_words, extract_add_words는 iterable str을 입력받을 수 있습니다.

analyze의 사용법

from kiwipiepy import Kiwi

kiwi = Kiwi()
kiwi.load_user_dictionary('userDict.txt')
with open('result.txt', 'w', encoding='utf-8') as out:
    for res in kiwi.analyze(open('test.txt', encoding='utf-8')):
        score, tokens = res[0] # top-1 결과를 가져옴
        print(*(token.tagged_form for token in tokens), file=out)

# tokenize 메소드를 사용하면 위와 동일한 동작을 수행하되 더 간결한 코드도 가능합니다.
with open('result.txt', 'w', encoding='utf-8') as out:
    for tokens in kiwi.tokenize(open('test.txt', encoding='utf-8')):
        print(*(token.tagged_form for token in tokens), file=out)

extract_words의 사용법 extract_words , extract_add_words의 경우 메소드 내에서 입력된 str을 여러번 순회하는 작업이 수행합니다. 따라서 단순히 str의 iterable를 입력하는 것은 안되며, 이를 list로 변환하거나 IterableTextFile 처럼 str의 iterable을 반환하는 객체를 만들어 사용해야 합니다.

# 다음 코드는 test.txt의 내용을 한 번만 순회 가능하기 때문에 오류가 발생합니다.
kiwi.extract_words(open('test.txt'), 10, 10, 0.25)

# list로 변환하면 여러 번 순회가 가능하여 정상적으로 작동합니다.
kiwi.extract_words(list(open('test.txt')), 10, 10, 0.25) 

# test.txt 파일의 크기가 수 GB 이상으로 큰 경우 전체를 메모리에 올리는 것이 비효율적일 수 있습니다.
# 이 경우 다음과 같이 `IterableTextFile`를 정의하여 파일 내용을 여러 번 순회가능한 객체를 사용하면
# 메모리 효율적인 방법으로 extract_words를 사용할 수 있습니다.
class IterableTextFile:
    def __init__(self, path):
        self.path = path

    def __iter__(self):
        yield from open(path, encoding='utf-8')

kiwi.extract_words(IterableTextFile('test.txt'), 10, 10, 0.25)

사용자 정의 사전 포맷

사용자 정의 사전은 UTF-8로 인코딩된 텍스트 파일이어야 하며, 다음과 같은 구조를 띄어야 합니다.

#으로 시작하는 줄은 주석 처리됩니다.
# 각 필드는 Tab(\t)문자로 구분됩니다.
#
# <단일 형태소를 추가하는 경우>
# (형태) \t (품사태그) \t (점수)
# * (점수)는 생략시 0으로 처리됩니다.
키위  NNP -5.0

# <이미 존재하는 형태소의 이형태를 추가하는 경우>
# (이형태) \t (원형태소/품사태그) \t (점수)
# * (점수)는 생략시 0으로 처리됩니다.
기위  키위/NNG  -3.0

# <기분석 형태를 추가하는 경우>
# (형태) \t (원형태소/품사태그 + 원형태소/품사태그 + ...) \t (점수)
# * (점수)는 생략시 0으로 처리됩니다.
사겼다 사귀/VV + 었/EP + 다/EF -1.0
#
# 현재는 공백을 포함하는 다어절 형태를 등록할 수 없습니다.
#
# <규칙 기반의 변형된 이형태를 추가하는 경우>
# (형태 규칙)$ \t (변형된 형태/품사태그) \t (점수)
# 예) 요$ 용/EF    -5

단어점수는 생략 가능하며, 생략 시 기본값인 0으로 처리됩니다. 실제 예시에 대해서는 Kiwi에 내장된 기본 사전 파일인 https://raw.githubusercontent.com/bab2min/Kiwi/main/ModelGenerator/default.dict 을 참조해주세요.

또한 0.14.0버전부터 내장된 기본 오타 사전이 추가되었습니다. 이에 대해서는 https://raw.githubusercontent.com/bab2min/Kiwi/main/ModelGenerator/typo.dict 을 참조해주세요.

언어 모델

Kiwi는 최적의 형태소 조합을 탐색하기 위해 내부적으로 언어 모델을 사용합니다. 0.13.0 버전 이전까지는 Kneser-ney 언어 모델(knlm)만을 사용했지만, 0.13.0버전부터 SkipBigram(sbg)이라는 새로운 언어 모델에 대한 지원이 추가되었습니다. 기본값은 knlm로 설정되어 있지만, 상황에 따라 이용자가 더 적절한 모델을 선택하여 사용할 수 있습니다. 각 모델의 특징은 다음과 같습니다.

  • knlm: 0.12.0버전까지 기본적으로 제공되던 모델로, 속도가 빠르고 짧은 거리 내의 형태소(주로 2~3개) 간의 관계를 높은 정확도로 모델링할 수 있습니다. 그러나 먼 거리의 형태소 간의 관계는 고려하지 못하는 한계가 있습니다.
  • sbg: 0.13.0버전에서 추가된 모델로, sbg를 사용시 내부적으로 knlm의 결과에 SkipBigram 결과를 보정하는 식으로 구동됩니다. knlm에 비해 약 30%정도 처리 시간이 늘어나지면, 먼 거리의 형태소(실질 형태소 기준 최대 8개까지) 간의 관계를 적당한 정확도로 모델링할 수 있습니다.

두 모델 간의 분석 결과 차이는 다음처럼 형태소의 모호성이 먼 거리의 형태소를 통해 해소되는 경우 잘 드러납니다.

>> kiwi = Kiwi(model_type='knlm')
>> kiwi.tokenize('이 번호로 전화를 이따가 꼭 반드시 걸어.')
[Token(form='이', tag='MM', start=0, len=1), 
 Token(form='번호', tag='NNG', start=2, len=2), 
 Token(form='로', tag='JKB', start=4, len=1), 
 Token(form='전화', tag='NNG', start=6, len=2), 
 Token(form='를', tag='JKO', start=8, len=1), 
 Token(form='이따가', tag='MAG', start=10, len=3), 
 Token(form='꼭', tag='MAG', start=14, len=1), 
 Token(form='반드시', tag='MAG', start=16, len=3), 
 Token(form='걷', tag='VV-I', start=20, len=1),  # 걷다/걸다 중 틀리게 '걷다'를 선택했음.
 Token(form='어', tag='EF', start=21, len=1), 
 Token(form='.', tag='SF', start=22, len=1)]

>> kiwi = Kiwi(model_type='sbg')
>> kiwi.tokenize('이 번호로 전화를 이따가 꼭 반드시 걸어.')
[Token(form='이', tag='MM', start=0, len=1), 
 Token(form='번호', tag='NNG', start=2, len=2), 
 Token(form='로', tag='JKB', start=4, len=1), 
 Token(form='전화', tag='NNG', start=6, len=2), 
 Token(form='를', tag='JKO', start=8, len=1), 
 Token(form='이따가', tag='MAG', start=10, len=3), 
 Token(form='꼭', tag='MAG', start=14, len=1), 
 Token(form='반드시', tag='MAG', start=16, len=3), 
 Token(form='걸', tag='VV', start=20, len=1), # 걷다/걸다 중 바르게 '걸다'를 선택했음.
 Token(form='어', tag='EC', start=21, len=1), 
 Token(form='.', tag='SF', start=22, len=1)]

오타 교정

연속적인 문자열을 처리하는 모델의 경우, 특정 지점에서 분석 오류가 발생하면 그 오류 때문에 뒤따르는 분석 결과들이 전부 틀려버리는 경우가 종종 있습니다. 이를 개선하기 위해 0.13.0버전부터 간단한 수준의 오타를 자동으로 교정하는 기능이 추가되었습니다. 오타 교정을 위해서는 특정 형태소가 어떤 식으로 오타로 변형되는지 정의한, 오타 정의자가 필요합니다. 패키지에 내장된 기본 오타 정의자인 basic_typos 혹은 'basic' 를 사용해도 되고, 직접 오타를 정의할 수도 있습니다.

>> from kiwipiepy import Kiwi, TypoTransformer, TypoDefinition, basic_typo
>> kiwi = Kiwi(typos=basic_typo) # basic_typo 대신 str으로 'basic'이라고 입력해도 됨
>> kiwi.tokenize('외않됀대?') # 초기에는 로딩 시간으로 5~10초 정도 소요됨
[Token(form='왜', tag='MAG', start=0, len=1),
 Token(form='안', tag='MAG', start=1, len=1),
 Token(form='되', tag='VV', start=2, len=1),
 Token(form='ᆫ대', tag='EF', start=2, len=2),
 Token(form='?', tag='SF', start=4, len=1)]
>> kiwi.typo_cost_weight = 6 # 오타 교정 비용을 변경할 수 있음. 기본값은 6
>> kiwi.tokenize('일정표를 게시했다')
[Token(form='일정표', tag='NNG', start=0, len=3),
 Token(form='를', tag='JKO', start=3, len=1), 
 Token(form='게시', tag='NNG', start=5, len=2), 
 Token(form='하', tag='XSV', start=7, len=1), 
 Token(form='었', tag='EP', start=7, len=1), 
 Token(form='다', tag='EF', start=8, len=1)]

>> kiwi.typo_cost_weight = 2 # 교정 비용을 낮추면 더 적극적으로 교정을 수행함. 맞는 표현도 과도교정될 수 있으니 주의
>> kiwi.tokenize('일정표를 게시했다')
[Token(form='일정표', tag='NNG', start=0, len=3),
 Token(form='를', tag='JKO', start=3, len=1), 
 Token(form='개시', tag='NNG', start=5, len=2), # '게시'가 맞는 표현이지만 '개시'로 잘못 교정되었음
 Token(form='하', tag='XSV', start=7, len=1), 
 Token(form='었', tag='EP', start=7, len=1), 
 Token(form='다', tag='EF', start=8, len=1)]

오타 정의자를 직접 정의하는 방법에 대해서는 TypoTransformer 를 참조하십시오. 현재 Kiwi에서 수행하는 오타 교정은 각각의 형태소를 경계로 적용되기에 여러 형태소를 넘나드는 오타는 교정하지 못합니다.

오타 교정 기능을 사용할 경우 Kiwi 초기화 시에 약 5~10초 정도의 시간이 추가로 소요되며, 문장 당 처리시간은 2배 정도로 늘어납니다. 메모리 사용량은 약 2~3배 정도 증가합니다.

데모

https://lab.bab2min.pe.kr/kiwi 에서 데모를 실행해 볼 수 있습니다.

라이센스

Kiwi는 LGPL v3 라이센스로 배포됩니다.

오류 제보

Kiwipiepy 사용 중 오류 발생시 깃헙 이슈탭을 통해 제보해주세요.

Python 모듈 관련 오류는 https://github.com/bab2min/kiwipiepy/issues, 형태소 분석기 전반에 대한 오류는 https://github.com/bab2min/kiwi/issues 에 올려주시면 감사하겠습니다.

태그 목록

세종 품사 태그를 기초로 하되, 일부 품사 태그를 추가/수정하여 사용하고 있습니다.

대분류태그설명
체언(N)NNG일반 명사
NNP고유 명사
NNB의존 명사
NR수사
NP대명사
용언(V)VV동사
VA형용사
VX보조 용언
VCP긍정 지시사(이다)
VCN부정 지시사(아니다)
관형사MM관형사
부사(MA)MAG일반 부사
MAJ접속 부사
감탄사IC감탄사
조사(J)JKS주격 조사
JKC보격 조사
JKG관형격 조사
JKO목적격 조사
JKB부사격 조사
JKV호격 조사
JKQ인용격 조사
JX보조사
JC접속 조사
어미(E)EP선어말 어미
EF종결 어미
EC연결 어미
ETN명사형 전성 어미
ETM관형형 전성 어미
접두사XPN체언 접두사
접미사(XS)XSN명사 파생 접미사
XSV동사 파생 접미사
XSA형용사 파생 접미사
XSM부사 파생 접미사*
어근XR어근
부호, 외국어, 특수문자(S)SF종결 부호(. ! ?)
SP구분 부호(, / : ;)
SS인용 부호 및 괄호(' " ( ) [ ] < > { } ― ‘ ’ “ ” ≪ ≫ 등)
SSOSS 중 여는 부호*
SSCSS 중 닫는 부호*
SE줄임표(…)
SO붙임표(- ~)
SW기타 특수 문자
SL알파벳(A-Z a-z)
SH한자
SN숫자(0-9)
SB순서 있는 글머리(가. 나. 1. 2. 가) 나) 등)*
분석 불능UN분석 불능*
웹(W)W_URLURL 주소*
W_EMAIL이메일 주소*
W_HASHTAG해시태그(#abcd)*
W_MENTION멘션(@abcd)*
W_SERIAL일련번호(전화번호, 통장번호, IP주소 등)*
기타Z_CODA덧붙은 받침*
USER0~4사용자 정의 태그*

* 세종 품사 태그와 다른 독자적인 태그입니다.

0.12.0 버전부터 VV, VA, VX, XSA 태그에 불규칙 활용여부를 명시하는 접미사 -R-I이 덧붙을 수 있습니다. -R은 규칙 활용,-I은 불규칙 활용을 나타냅니다.

역사

  • 0.16.0 (2023-08-31)

    • Kiwi 0.16.0의 기능들(https://github.com/bab2min/Kiwi/releases/tag/v0.16.0 )이 반영되었습니다.
      • PretokenizedSpan과 관련된 기능 추가
      • 순서 있는 글머리 기호를 나타내는 SB 태그 추가. 가., 나., 다. 등의 글머리 기호가 별도의 문장으로 분리되지 않도록 개선
      • 사용자지정 태그로 사용할 수 있는 USER0 ~ USER4 태그 추가
    • 정규표현식 기반으로 형태소를 사전에 추가하는 Kiwi.add_re_word() 메소드 추가
    • Token.span 추가
    • Token.user_value 추가 및 user_value를 설정할 수 있도록 Kiwi.add_user_word() 계열의 메소드에 user_value 인자 추가
    • deprecated 되었던 메소드들 제거
    • Kiwi.add_pre_analyzed_word()에서 시작위치/끝위치를 지정하지 않았지만 그 값이 자명한 경우, 자동으로 채워넣는 기능 추가
    • Kiwi.split_into_sents()stopwords 인자 추가
  • 0.15.2 (2023-06-14)

    • Kiwi 0.15.2의 기능들(https://github.com/bab2min/Kiwi/releases/tag/v0.15.2 )이 반영되었습니다.
      • 매우 긴 텍스트를 분석할 때 시작 지점이 잘못 나오는 버그 수정
      • U+10000 이상의 문자가 여러 개 포함된 텍스트를 SwTokenizer로 encode할때 offset이 누락되는 버그 수정
    • Kiwi.join()에서 형태소 결합 시 띄어쓰기 유무를 설정할 수 있는 기능 추가
    • Kiwi.tokenize()로 형태소 분석 후 다시 Kiwi.join()을 수행하는 경우 원본 텍스트의 띄어쓰기를 최대한 반영하여 결합하도록 개선
  • 0.15.1 (2023-05-07)

  • 0.15.0 (2023-03-23)

    • Kiwi 0.15.0의 기능들(https://github.com/bab2min/Kiwi/releases/tag/v0.15.0 )이 반영되었습니다.
      • 둘 이상의 형태소로 더 잘게 분리될 수 있는 형태소를 추가 분리하는 옵션인 splitComplex 도입
      • 부사파생접사를 위한 XSM 태그 추가 및 이에 해당하는 형태소 -이, -히, -로, -스레 추가
      • 조사/어미에 덧붙는 받침을 위한 Z_CODA 태그 추가 및 조사/어미에서 자동으로 Z_CODA를 분절해내는 기능 추가
      • 형태 분석 및 언어 모델 탐색 속도 최적화
      • 옛한글 문자를 특수 기호로 분리하지 않고 일반 한글과 동일하게 처리하도록 개선
      • 형태소 분석 기반의 Subword Tokenizer 구현 (현재 실험적으로 지원 중)
      • 문장 분리 성능 개선
        • 2010. 01. 01. 와 같이 공백이 포함된 serial 패턴 처리 보강
        • Dr., Mr. 와 같이 약자 표현의 .이 마침표로 처리되지 않도록 보강
        • '-음'으로 문장이 끝나는 경우를 판별하기 위해 음/EF 형태소 추가 및 모델 보강
      • 한 문장 내에서 사전에 미등재된 형태가 256개 이상 등장할 때 형태소 분석 결과가 잘못 나오는 문제 해결
      • 특정 경우에 문장 분리가 전혀 이뤄지지 않던 버그 수정
      • 이모지 등 U+10000 이상의 유니코드 문자를 모두 한자로 분류하던 버그 수정
    • Kiwi.glue()insert_new_lines 인자가 추가되었습니다.
    • 형태소의 사전 표제형을 보여주는 Token.lemma 프로퍼티가 추가되었습니다.
  • 0.14.1 (2022-12-24)

    • Kiwi 0.14.1의 기능들(https://github.com/bab2min/Kiwi/releases/tag/v0.14.1 )이 반영되었습니다.
      • 특정 텍스트에 대해 형태소 분할 없이 전체 결과를 그대로 반환하는 오류 해결
      • EF 뒤에 보조용언이 따라오는 경우 문장을 분리하지 않도록 개선
    • 이제 Python 3.11을 지원합니다.
      • 추가로 이제 macOS용 binary wheel을 arm64, x86_64로 나누어서 제공합니다.
  • 0.14.0 (2022-09-01)

    • Kiwi 0.14.0의 기능들(https://github.com/bab2min/Kiwi/releases/tag/v0.14.0 )이 반영되었습니다.
      • 동사 '이르다'의 모호성 해소 기능 추가
      • W_SERIAL 태그 추가. SS 태그를 SSO, SSC 태그로 세분화
      • 인용문 등으로 둘러싸인 안긴 문장이 포함된 문장에 대해 문장 분리 성능 개선
      • 랬/댔/잖의 분석 정확도 개선
      • 내장 오타 사전 추가. 사용을 원치 않는 경우 Kiwi(load_typo_dict=False)로 끌 수 있습니다.
    • 각종 버그가 수정되었습니다.
      • 오타 교정 기능이 켜져 있는 경우 Kiwi.join()이 실패하는 문제 해결
      • 사용자 사전에 숫자를 포함한 NNP를 추가해도 반영이 되지 않는 문제 해결
      • Kiwi.join()이 일부 텍스트를 잘못 결합시키는 오류 해결
  • 0.13.1 (2022-07-05)

  • 0.13.0 (2022-06-28)

    • Kiwi 0.13.0의 기능들(https://github.com/bab2min/Kiwi/releases/tag/v0.13.0 )이 반영되었습니다.
      • 형태소 분석 시 간단한 오타 교정을 수행하는 기능 추가
      • SkipBigram 언어 모델 추가. Kiwi(model_type='sbg') 로 사용 가능
      • 분석 결과에서 개별 형태소의 오타 교정 비용을 반환하는 Token.typo_cost 필드, 오타 교정 전 형태를 반환하는 Token.raw_form 필드 추가
    • 각종 버그가 수정되었습니다.
      • 배포 판에서 stopwords.txt 파일이 누락되었던 버그 수정
  • 0.12.0 (2022-05-10)

    • Kiwi 0.12.0의 기능들(https://github.com/bab2min/Kiwi/releases/tag/v0.12.0 )이 반영되었습니다.
      • 형태소에 불규칙 활용 여부를 반영하는 Token.regularity 필드 추가
      • 분석 결과에서 개별 형태소의 언어 모델 점수를 반영하는 Token.score 필드 추가
      • 동사 '걷다'와 '묻다'의 모호성 해소 기능 추가
      • 형태소 결합 기능을 수행하는 Kiwi.join() 메소드 추가
    • 각종 버그가 수정되었습니다.
      • 특정 상황에서 소수점 패턴이 숫자 - 마침표 - 숫자로 오분석되는 버그
      • 문장 분리 시 종결어미 - 조사로 이어지는 한 문장이 두 문장으로 분리되는 버그
      • 있소, 잇따라, 하셔 등의 표현이 제대로 분석되지 않는 버그
  • 0.11.2 (2022-04-14)

    • Kiwi 0.11.2의 기능들(https://github.com/bab2min/Kiwi/releases/tag/v0.11.2 )이 반영되었습니다.
      • 특수 문자가 섞인 텍스트 중 일부가 잘못 분석되는 버그가 수정되었습니다.
      • 특정한 패턴의 텍스트를 입력할 경우 분석 결과가 빈 값으로 나오는 버그가 수정되었습니다.
      • 받침 정규화 기능(normalizeCoda)이 모든 받침에 대해 적용되었습니다.
    • Kiwi.tokenize()echo 인자가 추가되었습니다.
  • 0.11.1 (2022-04-03)

    • Kiwi 0.11.1의 기능들(https://github.com/bab2min/Kiwi/releases/tag/v0.11.1 )이 반영되었습니다.
      • Windows 환경에서 한글이나 기타 유니코드를 포함한 경로에 위치한 모델을 읽지 못하는 버그가 수정되었습니다.
      • 이제 소수점, 자리 구분 쉼표가 섞인 숫자도 SN 품사태그로 제대로 분석됩니다.
      • Kiwi.space_tolerance, Kiwi.space_penalty 프로퍼티가 추가되었습니다.
    • 여러 줄의 텍스트를 결합할 때 공백을 적절히 삽입해주는 메소드인 Kiwi.glue(), 띄어쓰기 교정을 실시하는 메소드인 Kiwi.space()가 추가되었습니다.
  • 0.11.0 (2022-03-19)

    • Kiwi 0.11.0의 기능들(https://github.com/bab2min/Kiwi/releases/tag/v0.11.0 )이 반영되었습니다.
      • 이용자 사전을 관리하는 메소드 Kiwi.add_pre_analyzed_word(), Kiwi.add_rule(), Kiwi.add_re_rule()가 추가되었습니다.
      • 분석 시 접두사/접미사 및 동/형용사 파생접미사의 분리여부를 선택할 수 있는 옵션 Match.JOIN_NOUN_PREFIX, Match.JOIN_NOUN_SUFFIX, Match.JOIN_VERB_SUFFIX, Match.JOIN_ADJ_SUFFIX가 추가되었습니다.
      • 결합된 형태소 Tokenstart, end, length가 부정확한 버그를 수정했습니다.
      • 이제 형태소 결합 규칙이 Kiwi 모델 내로 통합되어 Kiwi.add_user_word()로 추가된 동/형용사의 활용형도 정상적으로 분석이 됩니다.
      • 언어 모델의 압축 알고리즘을 개선하여 초기 로딩 속도를 높였습니다.
      • SIMD 최적화가 개선되었습니다.
      • 언어 모델 및 기본 사전을 업데이트하여 전반적인 정확도를 높였습니다.
      • 문장 분리 기능의 정확도가 향상되었습니다.
  • 0.10.3 (2021-12-22)

  • 0.10.2 (2021-11-12)

    • Kiwi 0.10.2의 기능들(https://github.com/bab2min/Kiwi/releases/tag/v0.10.2 )이 반영되었습니다.
      • Tokenword_position 프로퍼티가 추가되었습니다.
      • Kiwi.analyze()normalize_coda 인자가 추가되었습니다.
    • Kiwi.tokenize() 메소드가 추가되었습니다. analyze 메소드와는 다르게 바로 분서결과인 Tokenlist를 반환하므로 더 간편하게 사용할 수 있습니다.
    • 불용어 관리 기능을 제공하는 Stopwords 클래스가 추가되었습니다.
  • 0.10.1 (2021-09-06)

    • macOS에서 pip를 통한 설치가 제대로 지원되지 않던 문제를 해결했습니다.
    • load_user_dictionary 사용시 품사 태그 뒤에 공백문자가 뒤따르는 경우 태그 해석에 실패하는 문제를 해결했습니다.
  • 0.10.0 (2021-08-15)

    • API를 Python에 걸맞게 개편하였습니다. 일부 불편한 메소드들은 사용법이 변경되거나 삭제되었습니다. 이에 대해서는 0.10.0 버전 변경사항 단락을 확인해주세요.
    • prepare 없이 analyze 를 호출할 때 크래시가 발생하던 문제를 수정했습니다.
    • Linux 환경에서 extract_words 를 호출할 때 크래시가 발생하던 문제를 수정했습니다.
    • Linux 환경에서 Options.INTEGRATE_ALLOMORPH 를 사용시 크래시가 발생하던 문제를 수정했습니다.
    • 이제 형태소 분석 결과가 tuple 이 아니라 Token 타입으로 반환됩니다.
    • 형태소 분석 모델 포맷이 최적화되어 파일 크기가 약 20% 작아졌습니다.
  • 0.9.3 (2021-06-06)

    • Linux 환경에서 특정 단어가 포함된 텍스트를 분석할 때 크래시가 발생하던 문제를 수정했습니다.
  • 0.9.2 (2020-12-03)

    • 0.9.1에서 제대로 수정되지 않은 mimalloc 충돌 문제를 수정했습니다.
    • 형태소 분석 모델을 분리하여 패키징하는 기능을 추가했습니다. 용량 문제로 업로드 못했던 대용량 모델을 차차 추가해나갈 예정입니다.
  • 0.9.1 (2020-12-03)

    • kiwipiepy가 다른 Python 패키지와 함께 사용될 경우 종종 mimalloc이 충돌하는 문제를 해결했습니다.
  • 0.9.0 (2020-11-26)

    • analyze 메소드에서 오류 발생시 exception 발생대신 프로그램이 죽는 문제를 해결했습니다.
    • default.dict 에 포함된 활용형 단어 때문에 발생하는 오분석을 수정했습니다.
    • 멀티스레딩 사용시 발생하는 메모리 누수 문제를 해결했습니다.
    • 형태소 탐색 시 조사/어미의 결합조건을 미리 고려하도록 변경하여 속도가 개선되었습니다.
    • 일부 명사(전랑 처럼 받침 + 랑으로 끝나는 사전 미등재 명사) 입력시 분석이 실패하는 버그를 수정했습니다.
    • 공백문자만 포함된 문자열 입력시 분석결과가 /UN 로 잘못나오는 문제를 수정했습니다.
  • 0.8.2 (2020-10-13)

    • W_URL, W_EMAIL, W_HASHTAG 일치 이후 일반 텍스트가 잘못 분석되는 오류를 수정했습니다.
    • W_MENTION을 추가했습니다.
    • 특정 상황에서 결합조건이 무시되던 문제를 해결했습니다. (ex: 고기를 굽다 -> 고기/NNG + 를/JKO + 굽/VV + 이/VCP + 다/EF + ./SF )
  • 0.8.1 (2020-04-01)

    • U+10000 이상의 유니코드 문자를 입력시 Python 모듈에서 오류가 발생하는 문제를 수정했습니다.
  • 0.8.0 (2020-03-29)

    • URL, 이메일, 해시태그를 검출하는 기능이 추가되었습니다. analyze 메소드의 match_options 파라미터로 이 기능의 사용 유무를 설정할 수 있습니다.
    • 치(하지), 컨대(하건대), 토록(하도록), 케(하게) 축약형이 포함된 동사 활용형을 제대로 분석하지 못하는 문제를 해결했습니다.
    • 사용자 사전에 알파벳이나 숫자, 특수 기호가 포함된 단어가 있을 때, 형태소 분석시 알파벳, 숫자, 특수 기호가 포함된 문장이 제대로 분석되지 않는 문제를 수정했습니다.
    • 사용자 사전에 형태는 같으나 품사가 다른 단어를 등록할 수 없는 제한을 해제하였습니다.
  • 0.7.6 (2020-03-24)

    • async_analyze 메소드가 추가되었습니다. 이 메소드는 형태소 분석을 비동기로 처리합니다. 처리 결과는 callable인 리턴값을 호출하여 얻을 수 있습니다.
    • U+10000 이상의 유니코드 문자에 대해 형태소 분석 결과의 위치 및 길이가 부정확하게 나오는 문제를 해결했습니다.
  • 0.7.5 (2020-03-04)

    • U+10000 이상의 문자를 입력시 extract 계열 함수에서 종종 오류가 발생하던 문제를 해결했습니다.
    • gcc 4.8 환경 및 manylinux 대한 지원을 추가했습니다.
  • 0.7.4 (2019-12-30)

    • reader, receiver를 사용하는 함수 계열에서 메모리 누수가 발생하던 문제를 해결했습니다.
    • 문서 내 reader, receiver의 사용법 내의 오류를 적절하게 수정했습니다.
    • 종종 분석 결과에서 빈 /UN 태그가 등장하는 문제를 수정했습니다.
    • 일부 특수문자를 분석하는데 실패하는 오류를 수정했습니다.
  • 0.7.3 (2019-12-15)

    • macOS 환경에서 extract 계열 함수를 호출할때 스레드 관련 오류가 발생하는 문제를 해결했습니다.
  • 0.7.2 (2019-12-01)

  • 0.7.1 (2019-09-23)

    • 사전 로딩 속도를 개선했습니다.
    • 음운론적 이형태 통합여부를 선택할 수 있도록 옵션을 추가했습니다.
  • 0.6.5 (2019-06-22)

  • 0.6.4 (2019-06-09)

  • 0.6.3 (2019-04-14)

    • 예외를 좀 더 정교하게 잡아내도록 수정했습니다.
    • 형태소 분석을 바로 테스트해볼 수 있도록 모듈에 대화형 인터페이스를 추가했습니다.
  • 0.6.1 (2019-03-26)

  • 0.6.0 (2018-12-04)

    • 형태소 검색 알고리즘 최적화로 분석 속도가 향상되었습니다.
    • 전반적인 정확도가 상승되었습니다.
  • 0.5.4 (2018-10-11)

  • 0.5.2 (2018-09-29)

  • 0.5.0 (2018-09-16)

    • Python 모듈 지원이 추가되었습니다.
Expand source code
"""
.. include:: ./documentation.md
"""
from kiwipiepy._c_api import Token
from kiwipiepy._version import __version__
from kiwipiepy._wrap import Kiwi, Sentence, TypoTransformer, TypoDefinition, HSDataset, MorphemeSet, PretokenizedToken
import kiwipiepy.sw_tokenizer as sw_tokenizer
import kiwipiepy.utils as utils
from kiwipiepy.const import Match

Kiwi.__module__ = 'kiwipiepy'
TypoTransformer.__module__ = 'kiwipiepy'
TypoDefinition.__module__ = 'kiwipiepy'
Sentence.__module__ = 'kiwipiepy'
PretokenizedToken.__module__ = 'kiwipiepy'
HSDataset.__module__ = 'kiwipiepy'
MorphemeSet.__module__ = 'kiwipiepy'

basic_typos = TypoTransformer([
    TypoDefinition(["ㅐ", "ㅔ"], ["ㅐ", "ㅔ"], 1.),
    TypoDefinition(["ㅐ", "ㅔ"], ["ㅒ", "ㅖ"], 1.5),
    TypoDefinition(["ㅒ", "ㅖ"], ["ㅐ", "ㅔ"], 1.5),
    TypoDefinition(["ㅒ", "ㅖ"], ["ㅒ", "ㅖ"], 1.),
    TypoDefinition(["ㅚ", "ㅙ", "ㅞ"], ["ㅚ", "ㅙ", "ㅞ", "ㅐ", "ㅔ"], 1.),
    TypoDefinition(["ㅝ"], ["ㅗ", "ㅓ"], 1.),
    TypoDefinition(["ㅟ", "ㅢ"], ["ㅣ"], 1.),
    TypoDefinition(["위", "의"], ["이"], float("inf")),
    TypoDefinition(["위", "의"], ["이"], 1., "any"),
    TypoDefinition(["자", "쟈"], ["자", "쟈"], 1.),
    TypoDefinition(["재", "쟤"], ["재", "쟤"], 1.),
    TypoDefinition(["저", "져"], ["저", "져"], 1.),
    TypoDefinition(["제", "졔"], ["제", "졔"], 1.),
    TypoDefinition(["조", "죠", "줘"], ["조", "죠", "줘"], 1.),
    TypoDefinition(["주", "쥬"], ["주", "쥬"], 1.),
    TypoDefinition(["차", "챠"], ["차", "챠"], 1.),
    TypoDefinition(["채", "챼"], ["채", "챼"], 1.),
    TypoDefinition(["처", "쳐"], ["처", "쳐"], 1.),
    TypoDefinition(["체", "쳬"], ["체", "쳬"], 1.),
    TypoDefinition(["초", "쵸", "춰"], ["초", "쵸", "춰"], 1.),
    TypoDefinition(["추", "츄"], ["추", "츄"], 1.),
    TypoDefinition(["유", "류"], ["유", "류"], 1.),
    TypoDefinition(["므", "무"], ["므", "무"], 1.),
    TypoDefinition(["브", "부"], ["브", "부"], 1.),
    TypoDefinition(["프", "푸"], ["프", "푸"], 1.),
    TypoDefinition(["르", "루"], ["르", "루"], 1.),
    TypoDefinition(["러", "뤄"], ["러", "뤄"], 1.),
    TypoDefinition(["\ㄲ", "\ㄳ"], ["\ㄱ", "\ㄲ", "\ㄳ"], 1.5),
    TypoDefinition(["\ㄵ", "\ㄶ"], ["\ㄴ", "\ㄵ", "\ㄶ"], 1.5),
    TypoDefinition(["\ㄺ", "\ㄻ", "\ㄼ", "\ㄽ", "\ㄾ", "\ㄿ", "\ㅀ"], ["\ㄹ", "\ㄺ", "\ㄻ", "\ㄼ", "\ㄽ", "\ㄾ", "\ㄿ", "\ㅀ"], 1.5),
    TypoDefinition(["\ㅅ", "\ㅆ"], ["\ㅅ", "\ㅆ"], 1.),

    TypoDefinition(["안"], ["않"], 1.5),
    TypoDefinition(["맞추", "맞히"], ["맞추", "맞히"], 1.5),
    TypoDefinition(["맞춰", "맞혀"], ["맞춰", "맞혀"], 1.5),
    TypoDefinition(["받치", "바치", "받히"], ["받치", "바치", "받히"], 1.5),
    TypoDefinition(["받쳐", "바쳐", "받혀"], ["받쳐", "바쳐", "받혀"], 1.5),
    TypoDefinition(["던", "든"], ["던", "든"], 1.),
    TypoDefinition(["때", "데"], ["때", "데"], 1.5),
    TypoDefinition(["빛", "빚"], ["빛", "빚"], 1.),

    TypoDefinition(["\ㄷ이", "지"], ["\ㄷ이", "지"], 1.),
    TypoDefinition(["\ㄷ여", "져"], ["\ㄷ여", "져"], 1.),
    TypoDefinition(["\ㅌ이", "치"], ["\ㅌ이", "치"], 1.),
    TypoDefinition(["\ㅌ여", "쳐"], ["\ㅌ여", "쳐"], 1.),
        
    TypoDefinition(["ㄱ", "ㄲ"], ["ㄱ", "ㄲ"], 1., "applosive"),
    TypoDefinition(["ㄷ", "ㄸ"], ["ㄷ", "ㄸ"], 1., "applosive"),
    TypoDefinition(["ㅂ", "ㅃ"], ["ㅂ", "ㅃ"], 1., "applosive"),
    TypoDefinition(["ㅅ", "ㅆ"], ["ㅅ", "ㅆ"], 1., "applosive"),
    TypoDefinition(["ㅈ", "ㅉ"], ["ㅈ", "ㅉ"], 1., "applosive"),

    TypoDefinition(["\ㅎㅎ", "\ㄱㅎ", "\ㅎㄱ"], ["\ㅎㅎ", "\ㄱㅎ", "\ㅎㄱ"], 1.),

    TypoDefinition(["\ㄱㄴ", "\ㄲㄴ", "ᆪㄴ", "ᆿㄴ", "ᆼㄴ"], ["\ㄱㄴ", "\ㄲㄴ", "ᆪㄴ", "ᆿㄴ", "ᆼㄴ"], 1.),
    TypoDefinition(["\ㄱㅁ", "\ㄲㅁ", "ᆪㅁ", "ᆿㅁ", "ᆼㅁ"], ["\ㄱㅁ", "\ㄲㅁ", "ᆪㅁ", "ᆿㅁ", "ᆼㅁ"], 1.),
    TypoDefinition(["\ㄱㄹ", "\ㄲㄹ", "ᆪㄹ", "ᆿㄹ", "ᆼㄹ", "ᆼㄴ",], ["\ㄱㄹ", "\ㄲㄹ", "ᆪㄹ", "ᆿㄹ", "ᆼㄹ", "ᆼㄴ",], 1.),
    TypoDefinition(["\ㄷㄴ", "\ㅅㄴ", "\ㅆㄴ", "\ㅈㄴ", "ᆾㄴ", "ᇀㄴ", "\ㄴㄴ"], ["\ㄷㄴ", "\ㅅㄴ", "\ㅆㄴ", "\ㅈㄴ", "ᆾㄴ", "ᇀㄴ", "\ㄴㄴ"], 1.),
    TypoDefinition(["\ㄷㅁ", "\ㅅㅁ", "\ㅆㅁ", "\ㅈㅁ", "ᆾㅁ", "ᇀㅁ", "\ㄴㅁ"], ["\ㄷㅁ", "\ㅅㅁ", "\ㅆㅁ", "\ㅈㅁ", "ᆾㅁ", "ᇀㅁ", "\ㄴㅁ"], 1.),
    TypoDefinition(["\ㄷㄹ", "\ㅅㄹ", "\ㅆㄹ", "\ㅈㄹ", "ᆾㄹ", "ᇀㄹ", "\ㄴㄹ", "\ㄴㄴ",], ["\ㄷㄹ", "\ㅅㄹ", "\ㅆㄹ", "\ㅈㄹ", "ᆾㄹ", "ᇀㄹ", "\ㄴㄹ", "\ㄴㄴ",], 1.),
    TypoDefinition(["\ㅂㄴ", "ᆹㄴ", "ᇁㄴ", "\ㅁㄴ"], ["\ㅂㄴ", "ᆹㄴ", "ᇁㄴ", "\ㅁㄴ"], 1.),
    TypoDefinition(["\ㅂㅁ", "ᆹㅁ", "ᇁㅁ", "\ㅁㅁ"], ["\ㅂㅁ", "ᆹㅁ", "ᇁㅁ", "\ㅁㅁ"], 1.),
    TypoDefinition(["\ㅂㄹ", "ᆹㄹ", "ᇁㄹ", "\ㅁㄹ", "\ㅁㄴ",], ["\ㅂㄹ", "ᆹㄹ", "ᇁㄹ", "\ㅁㄹ", "\ㅁㄴ",], 1.),
    TypoDefinition(["\ㄴㄹ", "\ㄴㄴ", "\ㄹㄹ", "\ㄹㄴ"], ["\ㄴㄹ", "\ㄴㄴ", "\ㄹㄹ", "\ㄹㄴ"], 1.),
        
    TypoDefinition(["\ㄱㅇ", "ㄱ"], ["\ㄱㅇ", "ㄱ"], 1., "vowel"),
    TypoDefinition(["\ㄲㅇ", "ㄲ"], ["\ㄲㅇ", "ㄲ"], 1., "vowel"),
    TypoDefinition(["\ㄴㅇ", "\ㄴㅎ", "ㄴ"], ["\ㄴㅇ", "\ㄴㅎ", "ㄴ"], 1., "vowel"),
    TypoDefinition(["\ㄵㅇ", "\ㄴㅈ"], ["\ㄵㅇ", "\ㄴㅈ"], 1., "vowel"),
    TypoDefinition(["\ㄶㅇ", "ㄴ"], ["\ㄶㅇ", "ㄴ"], 1., "vowel"),
    TypoDefinition(["\ㄷㅇ", "ㄷ"], ["\ㄷㅇ", "ㄷ"], 1., "vowel"),
    TypoDefinition(["\ㄹㅇ", "\ㄹㅎ", "ㄹ"], ["\ㄹㅇ", "\ㄹㅎ", "ㄹ"], 1., "vowel"),
    TypoDefinition(["\ㄺㅇ", "\ㄹㄱ"], ["\ㄺㅇ", "\ㄹㄱ"], 1., "vowel"),
    TypoDefinition(["\ㄺㅎ", "\ㄹㅋ"], ["\ㄺㅎ", "\ㄹㅋ"], 1., "vowel"),
    TypoDefinition(["\ㅁㅇ", "ㅁ"], ["\ㅁㅇ", "ㅁ"], 1., "vowel"),
    TypoDefinition(["\ㅂㅇ", "ㅂ"], ["\ㅂㅇ", "ㅂ"], 1., "vowel"),
    TypoDefinition(["\ㅅㅇ", "ㅅ"], ["\ㅅㅇ", "ㅅ"], 1., "vowel"),
    TypoDefinition(["\ㅆㅇ", "\ㅅㅅ", "ㅆ"], ["\ㅆㅇ", "\ㅅㅅ", "ㅆ"], 1., "vowel"),
    TypoDefinition(["\ㅈㅇ", "ㅈ"], ["\ㅈㅇ", "ㅈ"], 1., "vowel"),
    TypoDefinition(["\ㅊㅇ", "\ㅊㅎ", "\ㅈㅎ", "ㅊ"], ["\ㅊㅇ", "\ㅊㅎ", "\ㅈㅎ", "ㅊ"], 1., "vowel"),
    TypoDefinition(["\ㅋㅇ", "\ㅋㅎ", "\ㄱㅎ", "ㅋ"], ["\ㅋㅇ", "\ㅋㅎ", "\ㄱㅎ", "ㅋ"], 1., "vowel"),
    TypoDefinition(["\ㅌㅇ", "\ㅌㅎ", "\ㄷㅎ", "ㅌ"], ["\ㅌㅇ", "\ㅌㅎ", "\ㄷㅎ", "ㅌ"], 1., "vowel"),
    TypoDefinition(["\ㅍㅇ", "\ㅍㅎ", "\ㅂㅎ", "ㅍ"], ["\ㅍㅇ", "\ㅍㅎ", "\ㅂㅎ", "ㅍ"], 1., "vowel"),

    TypoDefinition(["은", "는"], ["은", "는"], 2.),
    TypoDefinition(["을", "를"], ["을", "를"], 2.),

    TypoDefinition(["ㅣ워", "ㅣ어", "ㅕ"], ["ㅣ워", "ㅣ어", "ㅕ"], 1.5),
    #TypoDefinition(["ㅡ아", "ㅏ"], ["ㅡ아", "ㅏ"], 1.5),
    #TypoDefinition(["ㅡ어", "ㅓ"], ["ㅡ어", "ㅓ"], 1.5),
    #TypoDefinition(["ㅡ오", "ㅗ"], ["ㅡ오", "ㅗ"], 1.5),
    #TypoDefinition(["ㅡ우", "ㅜ"], ["ㅡ우", "ㅜ"], 1.5),
])
'''
내장된 기본 오타 정보입니다.
'''

Sub-modules

kiwipiepy.const

const 모듈은 kiwipiepy에서 사용되는 주요 상수값들을 모아놓은 모듈입니다.

kiwipiepy.sw_tokenizer

Added in version: 0.15.1 …

kiwipiepy.sw_trainer

Added in version: 0.15.1 …

kiwipiepy.transformers_addon

Added in version: 0.15.1 …

kiwipiepy.utils

utils 모듈은 kiwipiepy를 사용하는 데에 있어서 다양한 편의 기능을 제공하기 위한 유틸리티성 클래스 및 함수를 제공합니다. 현재는 Stopwords 클래스만 포함되어 있으며, 이 클래스는 불용어를 관리하고 Kiwi의 형태소 분석 결과 중 불용어를 쉽게 …

Global variables

var basic_typos

내장된 기본 오타 정보입니다.

Classes

class HSDataset (*args, **kwargs)

Ancestors

  • kiwipiepy._HSDataset
class Kiwi (num_workers: Optional[int] = None, model_path: Optional[str] = None, integrate_allomorph: Optional[bool] = None, load_default_dict: Optional[bool] = None, load_typo_dict: Optional[bool] = None, model_type: str = 'knlm', typos: Union[str, TypoTransformer, None] = None, typo_cost_threshold: float = 2.5)

Kiwi 클래스는 실제 형태소 분석을 수행하는 kiwipiepy 모듈의 핵심 클래스입니다.

Parameters

num_workers : int
내부적으로 멀티스레딩에 사용할 스레드 개수. 0으로 설정시 시스템 내 가용한 모든 코어 개수만큼 스레드가 생성됩니다. 멀티스레딩은 extract 계열 함수에서 단어 후보를 탐색할 때와 analyze 함수에서만 사용됩니다.
model_path : str
읽어들일 모델 파일의 경로. 모델 파일의 위치를 옮긴 경우 이 값을 지정해주어야 합니다.
integrate_allormoph : bool
True일 경우 음운론적 이형태를 통합하여 출력합니다. /아/와 /어/나 /았/과 /었/ 같이 앞 모음의 양성/음성에 따라 형태가 바뀌는 어미들을 하나로 통합하여 출력합니다. 기본값은 True입니다.
load_default_dict : bool
True일 경우 인스턴스 생성시 자동으로 기본 사전을 불러옵니다. 기본 사전은 위키백과와 나무위키에서 추출된 고유 명사 표제어들로 구성되어 있습니다. 기본값은 True입니다.
load_typo_dict : bool

Added in version: 0.14.0

True일 경우 인스턴스 생성시 자동으로 내장 오타 사전을 불러옵니다. 오타 사전은 자주 틀리는 오타 일부와 인터넷에서 자주 쓰이는 변형된 종결 어미로 구성되어 있습니다. 기본값은 True입니다.

model_type : str

Added in version: 0.13.0

형태소 분석에 사용할 언어 모델을 지정합니다. 'knlm', 'sbg' 중 하나를 선택할 수 있습니다. 기본값은 'knlm'입니다. 각 모델에 대한 자세한 설명은 여기를 참조하세요.

typos : Union[str, TypoTransformer]

Added in version: 0.13.0

교정에 사용할 오타 정보입니다. 기본값은 None으로 이 경우 오타 교정을 사용하지 않습니다. 'basic'으로 입력시 내장된 기본 오타 정보를 이용합니다. 이에 대한 자세한 내용은 TypoTransformer여기를 참조하세요.

typo_cost_threshold : float

Added in version: 0.13.0

오타 교정시 고려할 최대 오타 비용입니다. 이 비용을 넘어서는 오타에 대해서는 탐색하지 않습니다. 기본값은 2.5입니다.

Ancestors

  • kiwipiepy._Kiwi

Instance variables

var cutoff_threshold

Added in version: 0.10.0

Beam 탐색 시 미리 제거할 후보의 점수 차를 설정합니다. 이 값이 클 수록 더 많은 후보를 탐색하게 되므로 분석 속도가 느려지지만 정확도가 올라갑니다. 반대로 이 값을 낮추면 더 적은 후보를 탐색하여 속도가 빨라지지만 정확도는 낮아집니다. 초기값은 5입니다.

Expand source code
    @property
    def cutoff_threshold(self):
        '''.. versionadded:: 0.10.0

Beam 탐색 시 미리 제거할 후보의 점수 차를 설정합니다. 이 값이 클 수록 더 많은 후보를 탐색하게 되므로 분석 속도가 느려지지만 정확도가 올라갑니다.
반대로 이 값을 낮추면 더 적은 후보를 탐색하여 속도가 빨라지지만 정확도는 낮아집니다. 초기값은 5입니다.
        '''

        return self._ns_cutoff_threshold
var integrate_allomorph

Added in version: 0.10.0

True일 경우 음운론적 이형태를 통합하여 출력합니다. /아/와 /어/나 /았/과 /었/ 같이 앞 모음의 양성/음성에 따라 형태가 바뀌는 어미들을 하나로 통합하여 출력합니다.

Expand source code
    @property
    def integrate_allomorph(self):
        '''.. versionadded:: 0.10.0

True일 경우 음운론적 이형태를 통합하여 출력합니다. /아/와 /어/나 /았/과 /었/ 같이 앞 모음의 양성/음성에 따라 형태가 바뀌는 어미들을 하나로 통합하여 출력합니다.
        '''

        return self._ns_integrate_allomorph
var max_unk_form_size

Added in version: 0.11.1

분석 과정에서 허용할 미등재 형태의 최대 길이입니다. 기본값은 6입니다.

Expand source code
    @property
    def max_unk_form_size(self):
        '''.. versionadded:: 0.11.1

분석 과정에서 허용할 미등재 형태의 최대 길이입니다. 기본값은 6입니다.
        '''

        return self._ns_max_unk_form_size
var model_type

Added in version: 0.13.0

형태소 분석에 사용 중인 언어 모델의 종류 (읽기 전용)

Expand source code
    @property
    def model_type(self):
        '''.. versionadded:: 0.13.0

형태소 분석에 사용 중인 언어 모델의 종류 (읽기 전용)
        '''
        return self._ns_model_type
var num_workers

Added in version: 0.10.0

병렬처리시 사용할 스레드의 개수입니다. (읽기 전용)

Expand source code
    @property
    def num_workers(self):
        '''.. versionadded:: 0.10.0

병렬처리시 사용할 스레드의 개수입니다. (읽기 전용)
        '''
        
        return self._num_workers
var space_penalty

Added in version: 0.11.1

형태소 중간에 삽입된 공백 문자가 있을 경우 언어모델 점수에 추가하는 페널티 점수입니다. 기본값은 7.0입니다.

Expand source code
    @property
    def space_penalty(self):
        '''.. versionadded:: 0.11.1

형태소 중간에 삽입된 공백 문자가 있을 경우 언어모델 점수에 추가하는 페널티 점수입니다. 기본값은 7.0입니다.
        '''

        return self._ns_space_penalty
var space_tolerance

Added in version: 0.11.1

형태소 중간에 삽입된 공백문자를 몇 개까지 허용할지 설정합니다. 기본값은 0이며, 이 경우 형태소 중간에 공백문자가 삽입되는 걸 허용하지 않습니다.

Kiwi.space() 메소드 참고.

Expand source code
    @property
    def space_tolerance(self):
        '''.. versionadded:: 0.11.1

형태소 중간에 삽입된 공백문자를 몇 개까지 허용할지 설정합니다. 기본값은 0이며, 이 경우 형태소 중간에 공백문자가 삽입되는 걸 허용하지 않습니다.

`Kiwi.space` 메소드 참고.
        '''

        return self._ns_space_tolerance
var typo_cost_threshold

Added in version: 0.15.0

오타 교정시 고려할 최대 오타 비용입니다. 이 비용을 넘어서는 오타에 대해서는 탐색하지 않습니다. 기본값은 2.5입니다.

Expand source code
    @property
    def typo_cost_threshold(self):
        '''.. versionadded:: 0.15.0

오타 교정시 고려할 최대 오타 비용입니다. 이 비용을 넘어서는 오타에 대해서는 탐색하지 않습니다. 기본값은 2.5입니다.
        '''
        return self._typo_cost_threshold
var typo_cost_weight

Added in version: 0.13.0

오타 교정 시에 사용할 교정 가중치. 이 값이 클수록 교정을 보수적으로 수행합니다. 기본값은 6입니다.

Expand source code
    @property
    def typo_cost_weight(self):
        '''.. versionadded:: 0.13.0

오타 교정 시에 사용할 교정 가중치. 이 값이 클수록 교정을 보수적으로 수행합니다. 기본값은 6입니다.
        '''

        return self._ns_typo_cost_weight

Methods

def add_pre_analyzed_word(self, form: str, analyzed: Iterable[Union[Tuple[str, POSTag], Tuple[str, POSTag, int, int]]], score: float = 0.0) ‑> bool

Added in version: 0.11.0

현재 모델에 기분석 형태소열을 추가합니다.

Parameters

form : str
추가할 형태
analyzed : Iterable[Union[Tuple[str, POSTag], Tuple[str, POSTag, int, int]]]
form의 형태소 분석 결과. 이 값은 (형태, 품사) 모양의 tuple, 혹은 (형태, 품사, 시작지점, 끝지점) 모양의 tuple로 구성된 Iterable이어야합니다. 이 값으로 지정되는 형태소는 현재 사전 내에 반드시 존재해야 하며, 그렇지 않으면 ValueError 예외를 발생시킵니다.
score : float
추가할 형태소열의 가중치 점수. 해당 형태에 부합하는 형태소 조합이 여러 개가 있는 경우, 이 점수가 높을 단어가 더 우선권을 가집니다.

Returns

inserted : bool
기분석 형태소열이 정상적으로 삽입된 경우 True, 이미 동일한 대상이 존재하여 삽입되지 않은 경우 False를 반환합니다.

Notes

이 메소드는 불규칙적인 분석 결과를 분석기에 추가하는 데에 용이합니다. 예를 들어 사귀다 동사의 과거형은 사귀었다가 맞지만, 흔히 사겼다로 잘못 쓰이기도 합니다. 사겼다사귀/VV + 었/EP + 다/EF로 바르게 분석되도록 하는데에 이 메소드를 사용할 수 있습니다.

kiwi.add_pre_analyzed_word('사겼다', ['사귀/VV', '었/EP', '다/EF'], -3)
kiwi.add_pre_analyzed_word('사겼다', [('사귀', 'VV', 0, 2), ('었', 'EP', 1, 2), ('다', 'EF', 2, 3)], -3)

후자의 경우 분석 결과의 각 형태소가 원본 문자열에서 차지하는 위치를 정확하게 지정해줌으로써, Kiwi 분석 결과에서 해당 형태소의 분석 결과가 정확하게 나오도록 합니다.

Expand source code
    def add_pre_analyzed_word(self,
        form:str,
        analyzed:Iterable[Union[Tuple[str, POSTag], Tuple[str, POSTag, int, int]]],
        score:float = 0.,
    ) -> bool:
        '''.. versionadded:: 0.11.0

현재 모델에 기분석 형태소열을 추가합니다.

Parameters
----------
form: str
    추가할 형태
analyzed: Iterable[Union[Tuple[str, POSTag], Tuple[str, POSTag, int, int]]]
    `form`의 형태소 분석 결과.
    이 값은 (형태, 품사) 모양의 tuple, 혹은 (형태, 품사, 시작지점, 끝지점) 모양의 tuple로 구성된 Iterable이어야합니다.
    이 값으로 지정되는 형태소는 현재 사전 내에 반드시 존재해야 하며, 그렇지 않으면 `ValueError` 예외를 발생시킵니다.
score: float
    추가할 형태소열의 가중치 점수. 
    해당 형태에 부합하는 형태소 조합이 여러 개가 있는 경우, 이 점수가 높을 단어가 더 우선권을 가집니다.

Returns
-------
inserted: bool
    기분석 형태소열이 정상적으로 삽입된 경우 True, 이미 동일한 대상이 존재하여 삽입되지 않은 경우 False를 반환합니다.

Notes
-----
이 메소드는 불규칙적인 분석 결과를 분석기에 추가하는 데에 용이합니다. 
예를 들어 `사귀다` 동사의 과거형은 `사귀었다`가 맞지만, 흔히 `사겼다`로 잘못 쓰이기도 합니다.
`사겼다`가 `사귀/VV + 었/EP + 다/EF`로 바르게 분석되도록 하는데에 이 메소드를 사용할 수 있습니다.
```python
kiwi.add_pre_analyzed_word('사겼다', ['사귀/VV', '었/EP', '다/EF'], -3)
kiwi.add_pre_analyzed_word('사겼다', [('사귀', 'VV', 0, 2), ('었', 'EP', 1, 2), ('다', 'EF', 2, 3)], -3)
```

후자의 경우 분석 결과의 각 형태소가 원본 문자열에서 차지하는 위치를 정확하게 지정해줌으로써, 
Kiwi 분석 결과에서 해당 형태소의 분석 결과가 정확하게 나오도록 합니다.
        '''
        analyzed = list(analyzed)
        if all(len(a) == 2 for a in analyzed) and ''.join(a[0] for a in analyzed) == form:
            new_analyzed = []
            cursor = 0
            for f, t in analyzed:
                p = form.index(f, cursor)
                if p < 0: break
                new_analyzed.append((f, t, p, p + len(f)))
                cursor = p
            if len(new_analyzed) == len(analyzed):
                analyzed = new_analyzed
        return super().add_pre_analyzed_word(form, analyzed, score)
def add_re_rule(self, tag: POSTag, pattern: Union[str, ForwardRef('re.Pattern')], repl: Union[str, Callable], score: float = 0.0, user_value: Optional[Any] = None) ‑> List[str]

Added in version: 0.11.0

Kiwi.add_rule()과 동일한 역할을 수행하되, 변형 규칙에 정규표현식을 사용합니다.

Parameters

tag : str
추가할 형태소들의 품사
pattern : Union[str, re.Pattern]
변형시킬 형태소의 규칙. 이 값은 re.compile로 컴파일가능한 정규표현식이어야 합니다.
repl : Union[str, Callable]
pattern에 의해 발견된 패턴은 이 값으로 교체됩니다. re.sub 함수의 repl 인자와 동일합니다.
score : float
추가할 변형된 형태소의 가중치 점수. 해당 형태에 부합하는 형태소 조합이 여러 개가 있는 경우, 이 점수가 높을 단어가 더 우선권을 가집니다.
user_value : Any

Added in version: 0.16.0

추가할 형태소의 사용자 지정값. 이 값은 형태소 분석 결과를 담는 Token 클래스의 Token.user_value값에 반영됩니다. 또한 만약 {'tag':'SPECIAL'}와 같이 dict형태로 'tag'인 key를 제공하는 경우, 형태소 분석 결과의 tag값이 SPECIAL로 덮어씌워져서 출력됩니다.

Returns

inserted_forms : List[str]
규칙에 의해 새로 생성된 형태소의 list를 반환합니다.

Notes

이 메소드는 규칙에 의해 변형되는 이형태들을 일괄적으로 추가할 때 굉장히 용이합니다. 예를 들어 -요-염으로 교체된 종결어미들(먹어염, 뛰었구염, 배불러염 등)을 일괄 등록하기 위해서는 다음을 수행하면 됩니다.

kiwi.add_re_rule('EF', r'요$', r'염', -3.0)

이런 이형태들을 대량으로 등록할 경우 이형태가 원본 형태보다 분석결과에서 높은 우선권을 가지지 않도록 score를 -3 이하의 값으로 설정하는걸 권장합니다.

Expand source code
    def add_re_rule(self,
        tag:POSTag,
        pattern:Union[str, 're.Pattern'],
        repl:Union[str, Callable],
        score:float = 0.,
        user_value:Optional[Any] = None,
    ) -> List[str]:
        '''.. versionadded:: 0.11.0

`kiwipiepy.Kiwi.add_rule`과 동일한 역할을 수행하되, 변형 규칙에 정규표현식을 사용합니다.

Parameters
----------
tag: str
    추가할 형태소들의 품사
pattern: Union[str, re.Pattern]
    변형시킬 형태소의 규칙. 이 값은 `re.compile`로 컴파일가능한 정규표현식이어야 합니다.
repl: Union[str, Callable]
    `pattern`에 의해 발견된 패턴은 이 값으로 교체됩니다. `re.sub` 함수의 `repl` 인자와 동일합니다.
score: float
    추가할 변형된 형태소의 가중치 점수. 
    해당 형태에 부합하는 형태소 조합이 여러 개가 있는 경우, 이 점수가 높을 단어가 더 우선권을 가집니다.
user_value: Any
    .. versionadded:: 0.16.0
    
    추가할 형태소의 사용자 지정값. 이 값은 형태소 분석 결과를 담는 `Token` 클래스의 `Token.user_value`값에 반영됩니다.
    또한 만약 `{'tag':'SPECIAL'}`와 같이 dict형태로 'tag'인 key를 제공하는 경우, 형태소 분석 결과의 tag값이 SPECIAL로 덮어씌워져서 출력됩니다.
Returns
-------
inserted_forms: List[str]
    규칙에 의해 새로 생성된 형태소의 `list`를 반환합니다.

Notes
-----
이 메소드는 규칙에 의해 변형되는 이형태들을 일괄적으로 추가할 때 굉장히 용이합니다.
예를 들어 `-요`가 `-염`으로 교체된 종결어미들(`먹어염`, `뛰었구염`, `배불러염` 등)을 일괄 등록하기 위해서는
다음을 수행하면 됩니다.

```python
kiwi.add_re_rule('EF', r'요$', r'염', -3.0)
```

이런 이형태들을 대량으로 등록할 경우 이형태가 원본 형태보다 분석결과에서 높은 우선권을 가지지 않도록
score를 `-3` 이하의 값으로 설정하는걸 권장합니다.
        '''
        if isinstance(pattern, str):
            pattern = re.compile(pattern)
        return self.add_rule(tag, lambda x:pattern.sub(repl, x), score, user_value)
def add_re_word(self, pattern: Union[str, ForwardRef('re.Pattern')], pretokenized: Union[Callable[[ForwardRef('re.Match')], Union[PretokenizedToken, List[PretokenizedToken]]], POSTag, PretokenizedToken, List[PretokenizedToken]], user_value: Optional[Any] = None) ‑> None

Added in version: 0.16.0

현재 모델에 정규표현식 기반의 패턴 매칭을 사용한 형태소 목록을 삽입합니다.

Parameters

pattern : Union[str, re.Pattern]
정규표현식 문자열 혹은 re.compile로 컴파일된 정규표현식 객체. 형태소 분석시 이 정규표현식에 일치하는 패턴을 발견하면 항상 pretokenized에 따라 분석합니다.
pretokenized : Union[Callable[['re.Match'], Union[PretokenizedToken, List[PretokenizedToken]]], POSTag, PretokenizedToken, List[PretokenizedToken]]

정규표현식으로 지정된 패턴이 분석될 형태를 지정합니다. POSTag, PretokenizedToken, PretokenizedToken의 리스트 또는 re.Match를 입력받아 PretokenizedToken의 리스트를 반환하는 콜백 함수 중 하나로 지정할 수 있습니다.

이 값을 POSTag로 지정한 경우, 전체 패턴은 단 하나의 형태소로 분석되며 그때의 품사태그는 POSTag로 지정한 값을 따릅니다. PretokenizedToken로 지정한 경우, 전체 패턴은 단 하나의 형태소로 분석되며, 그때의 형태/품사태그/시작위치/끝위치는 PretokenizedToken로 지정한 값을 따릅니다. PretokenizedToken의 리스트로 지정한 경우, 전체 패턴읜 리스트에서 제시한 형태소 개수에 분할되어 분석되며, 각각의 형태소 정보는 리스트에 포함된 PretokenizedToken 값들을 따릅니다. 마지막으로 콜백 함수로 지정한 경우, pattern.search의 결과가 함수의 인자로 제공되며, 이 인자를 처리한뒤 콜백 함수에서 반환하는 PretokenizedToken 값을 따라 형태소 분석 결과가 생성됩니다.

user_value : Any
추가할 형태소의 사용자 지정값. 이 값은 형태소 분석 결과를 담는 Token 클래스의 Token.user_value값에 반영됩니다. 또한 만약 {'tag':'SPECIAL'}와 같이 dict형태로 'tag'인 key를 제공하는 경우, 형태소 분석 결과의 tag값이 SPECIAL로 덮어씌워져서 출력됩니다.

Notes

이 메소드는 분석할 텍스트 내에 분할되면 안되는 텍스트 영역이 있거나, 이미 분석된 결과가 포함된 텍스트를 분석하는 데에 유용합니다.

참고로 이 메소드는 형태소 분석에 앞서 전처리 단계에서 패턴 매칭을 수행하므로, 이를 통해 지정한 규칙들은 형태소 분석 모델보다 먼저 우선권을 갖습니다. 따라서 이 규칙으로 지정한 조건을 만족하는 문자열 패턴은 항상 이 규칙에 기반하여 처리되므로 맥락에 따라 다른 처리를 해야하는 경우 이 메소드를 사용하는 것을 권장하지 않습니다.

>>> kiwi = Kiwi()
>>> text = '<평만경(平滿景)>이 사람을 시켜 <침향(沈香)> 10냥쭝을 바쳤으므로'
# <>로 둘러싸인 패턴은 전체를 NNP 태그로 분석하도록 설정
>>> kiwi.add_re_word(r'<[^>]+>', 'NNP') 
>>> kiwi.tokenize(text)
[Token(form='<평만경(平滿景)>', tag='NNP', start=0, len=10),
 Token(form='이', tag='JKS', start=10, len=1), 
 Token(form='사람', tag='NNG', start=12, len=2), 
 Token(form='을', tag='JKO', start=14, len=1), 
 Token(form='시키', tag='VV', start=16, len=2), 
 Token(form='어', tag='EC', start=17, len=1), 
 Token(form='<침향(沈香)>', tag='NNP', start=19, len=8), 
 Token(form='10', tag='SN', start=28, len=2), 
 Token(form='냥', tag='NNB', start=30, len=1), 
 Token(form='쭝', tag='NNG', start=31, len=1), 
 Token(form='을', tag='JKO', start=32, len=1), 
 Token(form='바치', tag='VV', start=34, len=2), 
 Token(form='었', tag='EP', start=35, len=1), 
 Token(form='으므로', tag='EC', start=36, len=3)]

>>> kiwi.clear_re_words() # 패턴 제거
# callback 함수를 입력하여 세부적인 조절이 가능
# 추출되는 패턴의 첫번째 괄호그룹을 형태소의 형태로 사용하도록 하여
# 분석 결과에 <, >가 포함되지 않도록 한다
>>> kiwi.add_re_word(r'<([^>]+)>', lambda m:PretokenizedToken(m.group(1), 'NNP', m.span(1)[0] - m.span(0)[0], m.span(1)[1] - m.span(0)[0]))
>>> kiwi.tokenize(text)
[Token(form='평만경(平滿景)', tag='NNP', start=0, len=10),
 Token(form='이', tag='MM', start=10, len=1), 
 Token(form='사람', tag='NNG', start=12, len=2), 
 Token(form='을', tag='JKO', start=14, len=1), 
 Token(form='시키', tag='VV', start=16, len=2), 
 Token(form='어', tag='EC', start=17, len=1), 
 Token(form='침향(沈香)', tag='NNP', start=19, len=8), 
 Token(form='10', tag='SN', start=28, len=2), 
 Token(form='냥', tag='NNB', start=30, len=1), 
 Token(form='쭝', tag='NNG', start=31, len=1), 
 Token(form='을', tag='JKO', start=32, len=1), 
 Token(form='바치', tag='VV', start=34, len=2), 
 Token(form='었', tag='EP', start=35, len=1), 
 Token(form='으므로', tag='EC', start=36, len=3)]

# 숫자 + 단위를 하나의 형태로 분석하도록 하는데에도 용이
>>> kiwi.add_re_word(r'[0-9]+냥쭝', 'NNG')
>>> kiwi.tokenize(text)
[Token(form='평만경(平滿景)', tag='NNP', start=0, len=10), 
 Token(form='이', tag='MM', start=10, len=1), 
 Token(form='사람', tag='NNG', start=12, len=2), 
 Token(form='을', tag='JKO', start=14, len=1), 
 Token(form='시키', tag='VV', start=16, len=2), 
 Token(form='어', tag='EC', start=17, len=1), 
 Token(form='침향(沈香)', tag='NNP', start=19, len=8), 
 Token(form='10냥쭝', tag='NNG', start=28, len=4), 
 Token(form='을', tag='NNG', start=32, len=1), 
 Token(form='바치', tag='VV', start=34, len=2), 
 Token(form='었', tag='EP', start=35, len=1), 
 Token(form='으므로', tag='EC', start=36, len=3)]

# 코드 영역의 분석을 방지하는 용도로도 사용이 가능
>>> import re
>>> text = """마크다운 코드가 섞인 문자열
```python
import kiwipiepy\n```
입니다."""
>>> pat = re.compile(r'^```python\n.*?^```', flags=re.DOTALL | re.MULTILINE)
# user_value를 지정하여 해당 패턴의 태그를 CODE로 덮어쓰기
>>> kiwi.add_re_word(pat, 'USER0', {'tag':'CODE'})
>>> kiwi.tokenize(text)
[Token(form='마크다운', tag='NNP', start=0, len=4),
 Token(form='코드', tag='NNG', start=5, len=2), 
 Token(form='가', tag='JKS', start=7, len=1), 
 Token(form='섞이', tag='VV', start=9, len=2), 
 Token(form='ᆫ', tag='ETM', start=10, len=1), 
 Token(form='문자열', tag='NNP', start=12, len=3), 
 Token(form='```python\nimport kiwipiepy\n```', tag='CODE', start=16, len=30), 
 Token(form='이', tag='VCP', start=47, len=1), 
 Token(form='ᆸ니다', tag='EF', start=47, len=3)]
Expand source code
    def add_re_word(self,
        pattern:Union[str, 're.Pattern'],
        pretokenized:Union[Callable[['re.Match'], Union[PretokenizedToken, List[PretokenizedToken]]], POSTag, PretokenizedToken, List[PretokenizedToken]],
        user_value:Optional[Any] = None,
    ) -> None:
        '''.. versionadded:: 0.16.0

현재 모델에 정규표현식 기반의 패턴 매칭을 사용한 형태소 목록을 삽입합니다.

Parameters
----------
pattern: Union[str, re.Pattern]
    정규표현식 문자열 혹은 `re.compile`로 컴파일된 정규표현식 객체. 형태소 분석시 이 정규표현식에 일치하는 패턴을 발견하면 항상 `pretokenized`에 따라 분석합니다.
pretokenized: Union[Callable[['re.Match'], Union[PretokenizedToken, List[PretokenizedToken]]], POSTag, PretokenizedToken, List[PretokenizedToken]]
    정규표현식으로 지정된 패턴이 분석될 형태를 지정합니다.
    POSTag, `PretokenizedToken`, `PretokenizedToken`의 리스트 또는 `re.Match`를 입력받아 `PretokenizedToken`의 리스트를 반환하는 콜백 함수 중 하나로 지정할 수 있습니다.

    이 값을 POSTag로 지정한 경우, 전체 패턴은 단 하나의 형태소로 분석되며 그때의 품사태그는 POSTag로 지정한 값을 따릅니다.
    PretokenizedToken로 지정한 경우, 전체 패턴은 단 하나의 형태소로 분석되며, 그때의 형태/품사태그/시작위치/끝위치는 PretokenizedToken로 지정한 값을 따릅니다.
    PretokenizedToken의 리스트로 지정한 경우, 전체 패턴읜 리스트에서 제시한 형태소 개수에 분할되어 분석되며, 각각의 형태소 정보는 리스트에 포함된 PretokenizedToken 값들을 따릅니다.
    마지막으로 콜백 함수로 지정한 경우, `pattern.search`의 결과가 함수의 인자로 제공되며, 이 인자를 처리한뒤 콜백 함수에서 반환하는 PretokenizedToken 값을 따라 형태소 분석 결과가 생성됩니다.
user_value: Any
    추가할 형태소의 사용자 지정값. 이 값은 형태소 분석 결과를 담는 `Token` 클래스의 `Token.user_value`값에 반영됩니다.
    또한 만약 `{'tag':'SPECIAL'}`와 같이 dict형태로 'tag'인 key를 제공하는 경우, 형태소 분석 결과의 tag값이 SPECIAL로 덮어씌워져서 출력됩니다.

Notes
-----
이 메소드는 분석할 텍스트 내에 분할되면 안되는 텍스트 영역이 있거나, 이미 분석된 결과가 포함된 텍스트를 분석하는 데에 유용합니다.

참고로 이 메소드는 형태소 분석에 앞서 전처리 단계에서 패턴 매칭을 수행하므로, 이를 통해 지정한 규칙들은 형태소 분석 모델보다 먼저 우선권을 갖습니다.
따라서 이 규칙으로 지정한 조건을 만족하는 문자열 패턴은 항상 이 규칙에 기반하여 처리되므로 맥락에 따라 다른 처리를 해야하는 경우 이 메소드를 사용하는 것을 권장하지 않습니다.

```python
>>> kiwi = Kiwi()
>>> text = '<평만경(平滿景)>이 사람을 시켜 <침향(沈香)> 10냥쭝을 바쳤으므로'
# <>로 둘러싸인 패턴은 전체를 NNP 태그로 분석하도록 설정
>>> kiwi.add_re_word(r'<[^>]+>', 'NNP') 
>>> kiwi.tokenize(text)
[Token(form='<평만경(平滿景)>', tag='NNP', start=0, len=10),
 Token(form='이', tag='JKS', start=10, len=1), 
 Token(form='사람', tag='NNG', start=12, len=2), 
 Token(form='을', tag='JKO', start=14, len=1), 
 Token(form='시키', tag='VV', start=16, len=2), 
 Token(form='어', tag='EC', start=17, len=1), 
 Token(form='<침향(沈香)>', tag='NNP', start=19, len=8), 
 Token(form='10', tag='SN', start=28, len=2), 
 Token(form='냥', tag='NNB', start=30, len=1), 
 Token(form='쭝', tag='NNG', start=31, len=1), 
 Token(form='을', tag='JKO', start=32, len=1), 
 Token(form='바치', tag='VV', start=34, len=2), 
 Token(form='었', tag='EP', start=35, len=1), 
 Token(form='으므로', tag='EC', start=36, len=3)]

>>> kiwi.clear_re_words() # 패턴 제거
# callback 함수를 입력하여 세부적인 조절이 가능
# 추출되는 패턴의 첫번째 괄호그룹을 형태소의 형태로 사용하도록 하여
# 분석 결과에 <, >가 포함되지 않도록 한다
>>> kiwi.add_re_word(r'<([^>]+)>', lambda m:PretokenizedToken(m.group(1), 'NNP', m.span(1)[0] - m.span(0)[0], m.span(1)[1] - m.span(0)[0]))
>>> kiwi.tokenize(text)
[Token(form='평만경(平滿景)', tag='NNP', start=0, len=10),
 Token(form='이', tag='MM', start=10, len=1), 
 Token(form='사람', tag='NNG', start=12, len=2), 
 Token(form='을', tag='JKO', start=14, len=1), 
 Token(form='시키', tag='VV', start=16, len=2), 
 Token(form='어', tag='EC', start=17, len=1), 
 Token(form='침향(沈香)', tag='NNP', start=19, len=8), 
 Token(form='10', tag='SN', start=28, len=2), 
 Token(form='냥', tag='NNB', start=30, len=1), 
 Token(form='쭝', tag='NNG', start=31, len=1), 
 Token(form='을', tag='JKO', start=32, len=1), 
 Token(form='바치', tag='VV', start=34, len=2), 
 Token(form='었', tag='EP', start=35, len=1), 
 Token(form='으므로', tag='EC', start=36, len=3)]

# 숫자 + 단위를 하나의 형태로 분석하도록 하는데에도 용이
>>> kiwi.add_re_word(r'[0-9]+냥쭝', 'NNG')
>>> kiwi.tokenize(text)
[Token(form='평만경(平滿景)', tag='NNP', start=0, len=10), 
 Token(form='이', tag='MM', start=10, len=1), 
 Token(form='사람', tag='NNG', start=12, len=2), 
 Token(form='을', tag='JKO', start=14, len=1), 
 Token(form='시키', tag='VV', start=16, len=2), 
 Token(form='어', tag='EC', start=17, len=1), 
 Token(form='침향(沈香)', tag='NNP', start=19, len=8), 
 Token(form='10냥쭝', tag='NNG', start=28, len=4), 
 Token(form='을', tag='NNG', start=32, len=1), 
 Token(form='바치', tag='VV', start=34, len=2), 
 Token(form='었', tag='EP', start=35, len=1), 
 Token(form='으므로', tag='EC', start=36, len=3)]

# 코드 영역의 분석을 방지하는 용도로도 사용이 가능
>>> import re
>>> text = """마크다운 코드가 섞인 문자열
```python
import kiwipiepy\\n```
입니다."""
>>> pat = re.compile(r'^```python\\n.*?^```', flags=re.DOTALL | re.MULTILINE)
# user_value를 지정하여 해당 패턴의 태그를 CODE로 덮어쓰기
>>> kiwi.add_re_word(pat, 'USER0', {'tag':'CODE'})
>>> kiwi.tokenize(text)
[Token(form='마크다운', tag='NNP', start=0, len=4),
 Token(form='코드', tag='NNG', start=5, len=2), 
 Token(form='가', tag='JKS', start=7, len=1), 
 Token(form='섞이', tag='VV', start=9, len=2), 
 Token(form='ᆫ', tag='ETM', start=10, len=1), 
 Token(form='문자열', tag='NNP', start=12, len=3), 
 Token(form='```python\\nimport kiwipiepy\\n```', tag='CODE', start=16, len=30), 
 Token(form='이', tag='VCP', start=47, len=1), 
 Token(form='ᆸ니다', tag='EF', start=47, len=3)]
```
        '''
        if isinstance(pattern, str):
            pattern = re.compile(pattern)
            
        self._pretokenized_pats.append((pattern, pretokenized, user_value))
def add_rule(self, tag: POSTag, replacer: Callable[[str], str], score: float = 0.0, user_value: Optional[Any] = None) ‑> List[str]

Added in version: 0.11.0

규칙에 의해 변형된 형태소를 일괄적으로 추가합니다.

Parameters

tag : str
추가할 형태소들의 품사
replacer : Callable[[str], str]
형태소를 변형시킬 규칙. 이 값은 호출가능한 Callable 형태로 제공되어야 하며, 원본 형태소 str를 입력으로 받아 변형된 형태소의 str을 반환해야합니다. 만약 입력과 동일한 값을 반환하면 해당 변형 결과는 무시됩니다.
score : float
추가할 변형된 형태소의 가중치 점수. 해당 형태에 부합하는 형태소 조합이 여러 개가 있는 경우, 이 점수가 높을 단어가 더 우선권을 가집니다.
user_value : Any

Added in version: 0.16.0

추가할 형태소의 사용자 지정값. 이 값은 형태소 분석 결과를 담는 Token 클래스의 Token.user_value값에 반영됩니다. 또한 만약 {'tag':'SPECIAL'}와 같이 dict형태로 'tag'인 key를 제공하는 경우, 형태소 분석 결과의 tag값이 SPECIAL로 덮어씌워져서 출력됩니다.

Returns

inserted_forms : List[str]
규칙에 의해 새로 생성된 형태소의 list를 반환합니다.
Expand source code
    def add_rule(self,
        tag:POSTag,
        replacer:Callable[[str], str],
        score:float = 0.,
        user_value:Optional[Any] = None,
    ) -> List[str]:
        '''.. versionadded:: 0.11.0

규칙에 의해 변형된 형태소를 일괄적으로 추가합니다.

Parameters
----------
tag: str
    추가할 형태소들의 품사
replacer: Callable[[str], str]
    형태소를 변형시킬 규칙. 
    이 값은 호출가능한 Callable 형태로 제공되어야 하며, 원본 형태소 str를 입력으로 받아 변형된 형태소의 str을 반환해야합니다.
    만약 입력과 동일한 값을 반환하면 해당 변형 결과는 무시됩니다.
score: float
    추가할 변형된 형태소의 가중치 점수. 
    해당 형태에 부합하는 형태소 조합이 여러 개가 있는 경우, 이 점수가 높을 단어가 더 우선권을 가집니다.
user_value: Any
    .. versionadded:: 0.16.0
    
    추가할 형태소의 사용자 지정값. 이 값은 형태소 분석 결과를 담는 `Token` 클래스의 `Token.user_value`값에 반영됩니다.
    또한 만약 `{'tag':'SPECIAL'}`와 같이 dict형태로 'tag'인 key를 제공하는 경우, 형태소 분석 결과의 tag값이 SPECIAL로 덮어씌워져서 출력됩니다.
Returns
-------
inserted_forms: List[str]
    규칙에 의해 새로 생성된 형태소의 `list`를 반환합니다.
        '''
        ret = super().add_rule(tag, replacer, score)
        if not ret: return []
        mids, inserted_forms = zip(*ret)
        for mid in mids:
            self._user_values[mid] = user_value
        return inserted_forms
def add_user_word(self, word: str, tag: POSTag = 'NNP', score: float = 0.0, orig_word: Optional[str] = None, user_value: Optional[Any] = None) ‑> bool

현재 모델에 사용자 정의 형태소를 추가합니다.

Parameters

word : str
추가할 형태소
tag : str
추가할 형태소의 품사 태그
score : float
추가할 형태소의 가중치 점수. 해당 형태에 부합하는 형태소 조합이 여러 개가 있는 경우, 이 점수가 높을 단어가 더 우선권을 가집니다.
orig_word : str

Added in version: 0.11.0

추가할 형태소의 원본 형태소. 추가할 형태소가 특정 형태소의 변이형인 경우 이 인자로 원본 형태소를 넘겨줄 수 있습니다. 없는 경우 생략할 수 있습니다. orig_word가 주어진 경우 현재 사전 내에 orig_word/tag 조합의 형태소가 반드시 존재해야 하며, 그렇지 않으면 ValueError 예외를 발생시킵니다.

user_value : Any

Added in version: 0.16.0

추가할 형태소의 사용자 지정값. 이 값은 형태소 분석 결과를 담는 Token 클래스의 Token.user_value값에 반영됩니다. 또한 만약 {'tag':'SPECIAL'}와 같이 dict형태로 'tag'인 key를 제공하는 경우, 형태소 분석 결과의 tag값이 SPECIAL로 덮어씌워져서 출력됩니다.

Returns

inserted : bool
사용자 정의 형태소가 정상적으로 삽입된 경우 True, 이미 동일한 형태소가 존재하여 삽입되지 않은 경우 False를 반환합니다.
Expand source code
    def add_user_word(self,
        word:str,
        tag:POSTag = 'NNP',
        score:float = 0.,
        orig_word:Optional[str] = None,
        user_value:Optional[Any] = None,
    ) -> bool:
        '''현재 모델에 사용자 정의 형태소를 추가합니다.

Parameters
----------
word: str
    추가할 형태소
tag: str
    추가할 형태소의 품사 태그
score: float
    추가할 형태소의 가중치 점수. 
    해당 형태에 부합하는 형태소 조합이 여러 개가 있는 경우, 이 점수가 높을 단어가 더 우선권을 가집니다.
orig_word: str
    .. versionadded:: 0.11.0

    추가할 형태소의 원본 형태소.
    추가할 형태소가 특정 형태소의 변이형인 경우 이 인자로 원본 형태소를 넘겨줄 수 있습니다. 없는 경우 생략할 수 있습니다.
    `orig_word`가 주어진 경우 현재 사전 내에 `orig_word`/`tag` 조합의 형태소가 반드시 존재해야 하며, 그렇지 않으면 `ValueError` 예외를 발생시킵니다.
user_value: Any
    .. versionadded:: 0.16.0
    
    추가할 형태소의 사용자 지정값. 이 값은 형태소 분석 결과를 담는 `Token` 클래스의 `Token.user_value`값에 반영됩니다.
    또한 만약 `{'tag':'SPECIAL'}`와 같이 dict형태로 'tag'인 key를 제공하는 경우, 형태소 분석 결과의 tag값이 SPECIAL로 덮어씌워져서 출력됩니다.
Returns
-------
inserted: bool
    사용자 정의 형태소가 정상적으로 삽입된 경우 True, 이미 동일한 형태소가 존재하여 삽입되지 않은 경우 False를 반환합니다.
        '''
        if re.search(r'\s', word): raise ValueError("Whitespace characters are not allowed at `word`")
        mid, inserted = super().add_user_word(word, tag, score, orig_word)
        self._user_values[mid] = user_value
        return inserted
def analyze(self, text: Union[str, Iterable[str]], top_n: int = 1, match_options: int = Match.ALL, normalize_coda: bool = False, z_coda: bool = True, split_complex: bool = False, blocklist: Union[MorphemeSet, Iterable[str], None] = None, pretokenized: Union[Callable[[str], List[Union[Tuple[int, int], Tuple[int, int, POSTag], Tuple[int, int, PretokenizedToken], Tuple[int, int, List[PretokenizedToken]]]]], List[Union[Tuple[int, int], Tuple[int, int, POSTag], Tuple[int, int, PretokenizedToken], Tuple[int, int, List[PretokenizedToken]]]], None] = None) ‑> List[Tuple[List[Token], float]]

형태소 분석을 실시합니다.

Changed in version: 0.10.0

이 메소드는 0.10.0 버전에서 사용법이 일부 변경되었습니다. 자세한 내용은 여기를 확인해주세요.

Parameters

text : Union[str, Iterable[str]]
분석할 문자열입니다. 이 인자를 단일 str로 줄 경우, 싱글스레드에서 처리하며 str의 Iterable로 줄 경우, 멀티스레드로 분배하여 처리합니다.
top_n : int
분석 결과 후보를 상위 몇 개까지 생성할 지 설정합니다.
match_options : Match
이 인자는 Kiwi.tokenize()에서와 동일한 역할을 수행합니다.
normalize_coda : bool
이 인자는 Kiwi.tokenize()에서와 동일한 역할을 수행합니다.
z_coda : bool
이 인자는 Kiwi.tokenize()에서와 동일한 역할을 수행합니다.
split_complex : bool
이 인자는 Kiwi.tokenize()에서와 동일한 역할을 수행합니다.
blocklist : Union[Iterable[str], MorphemeSet]
이 인자는 Kiwi.tokenize()에서와 동일한 역할을 수행합니다.
pretokenized : Union[Callable[[str], PretokenizedTokenList], PretokenizedTokenList]
이 인자는 Kiwi.tokenize()에서와 동일한 역할을 수행합니다.

Returns

result : List[Tuple[List[Token], float]]
text를 str으로 준 경우. 분석 결과는 최대 top_n개 길이의 리스트로 반환됩니다. 리스트의 각 항목은 (분석 결과, 분석 점수)로 구성된 튜플입니다. 분석 결과Token의 리스트로 구성됩니다.
results : Iterable[List[Tuple[List[Token], float]]]
text를 Iterable[str]으로 준 경우. 반환값은 iterator로 주어집니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.

Notes

textIterable로 준 경우 멀티스레딩으로 처리됩니다. 이 때 사용되는 스레드의 개수는 처음에 Kiwi를 생성할 때 num_workers로 준 값입니다.

kiwi.analyze('형태소 분석 결과입니다')
# 반환 값은 다음과 같이 `(형태소 분석 결과, 분석 점수)`의 형태입니다.
(
    [Token(form='형태소', tag='NNG', start=0, len=3), 
    Token(form='분석', tag='NNG', start=4, len=2), 
    Token(form='결과', tag='NNG', start=7, len=2), 
    Token(form='이', tag='VCP', start=9, len=1), 
    Token(form='ᆸ니다', tag='EF', start=10, len=2)
    ],
    -34.3332
)

# 4개의 스레드에서 동시에 처리합니다.
kiwi = Kiwi(num_workers=4)
with open('result.txt', 'w', encoding='utf-8') as output:
    for res in kiwi.analyze(open('test.txt', encoding='utf-8')):
        print(' '.join(map(lambda x:x[0]+'/'+x[1], res[0][0])), file=output)
Expand source code
    def analyze(self,
        text:Union[str, Iterable[str]],
        top_n:int = 1,
        match_options:int = Match.ALL,
        normalize_coda:bool = False,
        z_coda:bool = True,
        split_complex:bool = False,
        blocklist:Optional[Union[MorphemeSet, Iterable[str]]] = None,
        pretokenized:Optional[Union[Callable[[str], PretokenizedTokenList], PretokenizedTokenList]] = None,
    ) -> List[Tuple[List[Token], float]]:
        '''형태소 분석을 실시합니다.

.. versionchanged:: 0.10.0
    이 메소드는 0.10.0 버전에서 사용법이 일부 변경되었습니다. 자세한 내용은 <a href="#0100">여기</a>를 확인해주세요.

Parameters
----------
text: Union[str, Iterable[str]]
    분석할 문자열입니다. 
    이 인자를 단일 str로 줄 경우, 싱글스레드에서 처리하며
    str의 Iterable로 줄 경우, 멀티스레드로 분배하여 처리합니다.
top_n: int
    분석 결과 후보를 상위 몇 개까지 생성할 지 설정합니다.
match_options: kiwipiepy.const.Match
    이 인자는 `Kiwi.tokenize`에서와 동일한 역할을 수행합니다.
normalize_coda: bool
    이 인자는 `Kiwi.tokenize`에서와 동일한 역할을 수행합니다.
z_coda: bool
    이 인자는 `Kiwi.tokenize`에서와 동일한 역할을 수행합니다.
split_complex: bool
    이 인자는 `Kiwi.tokenize`에서와 동일한 역할을 수행합니다.
blocklist: Union[Iterable[str], MorphemeSet]
    이 인자는 `Kiwi.tokenize`에서와 동일한 역할을 수행합니다.
pretokenized: Union[Callable[[str], PretokenizedTokenList], PretokenizedTokenList]
    이 인자는 `Kiwi.tokenize`에서와 동일한 역할을 수행합니다.

Returns
-------
result: List[Tuple[List[Token], float]]
    text를 str으로 준 경우.
    분석 결과는 최대 `top_n`개 길이의 리스트로 반환됩니다. 리스트의 각 항목은 `(분석 결과, 분석 점수)`로 구성된 튜플입니다. 
    `분석 결과`는 `Token`의 리스트로 구성됩니다.

results: Iterable[List[Tuple[List[Token], float]]]
    text를 Iterable[str]으로 준 경우.
    반환값은 iterator로 주어집니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.

Notes
-----
`text`를 `Iterable`로 준 경우 멀티스레딩으로 처리됩니다. 
이 때 사용되는 스레드의 개수는 처음에 `Kiwi`를 생성할 때 `num_workers`로 준 값입니다.

```python
kiwi.analyze('형태소 분석 결과입니다')
# 반환 값은 다음과 같이 `(형태소 분석 결과, 분석 점수)`의 형태입니다.
(
    [Token(form='형태소', tag='NNG', start=0, len=3), 
    Token(form='분석', tag='NNG', start=4, len=2), 
    Token(form='결과', tag='NNG', start=7, len=2), 
    Token(form='이', tag='VCP', start=9, len=1), 
    Token(form='ᆸ니다', tag='EF', start=10, len=2)
    ],
    -34.3332
)

# 4개의 스레드에서 동시에 처리합니다.
kiwi = Kiwi(num_workers=4)
with open('result.txt', 'w', encoding='utf-8') as output:
    for res in kiwi.analyze(open('test.txt', encoding='utf-8')):
        print(' '.join(map(lambda x:x[0]+'/'+x[1], res[0][0])), file=output)
```
        '''
        if normalize_coda:
            match_options |= Match.NORMALIZING_CODA
        if z_coda:
            match_options |= Match.Z_CODA
        if split_complex:
            match_options |= Match.SPLIT_COMPLEX
        if isinstance(blocklist, MorphemeSet):
            if blocklist.kiwi != self: 
                warnings.warn("This `MorphemeSet` isn't based on current Kiwi object.")
                blocklist = MorphemeSet(self, blocklist.set)
        elif blocklist is not None:
            blocklist = MorphemeSet(self, blocklist)
        
        if blocklist: blocklist._update_self()

        if not isinstance(text, str) and pretokenized and not callable(pretokenized):
            raise ValueError("`pretokenized` must be a callable if `text` is an iterable of str.")
        pretokenized = partial(self._make_pretokenized_spans, pretokenized) if self._pretokenized_pats or pretokenized else None

        return super().analyze(text, top_n, match_options, False, blocklist, pretokenized)
def clear_re_words(self)

Added in version: 0.16.0

add_re_word로 추가했던 정규표현식 패턴 기반 처리 규칙을 모두 삭제합니다.

Expand source code
    def clear_re_words(self):
        '''.. versionadded:: 0.16.0

`add_re_word`로 추가했던 정규표현식 패턴 기반 처리 규칙을 모두 삭제합니다.
        '''
        self._pretokenized_pats.clear()
def evaluate(self, sequences: List[List[int]], prefix: Optional[List[int]] = None, suffix: Optional[List[int]] = None)
Expand source code
def evaluate(self,
    sequences:List[List[int]],
    prefix:Optional[List[int]] = None,
    suffix:Optional[List[int]] = None,
):
    raise NotImplementedError
def extract_add_words(self, texts, min_cnt: int = 10, max_word_len: int = 10, min_score: float = 0.25, pos_score: float = -3.0, lm_filter: bool = True)

말뭉치로부터 새로운 단어를 추출하고 새로운 명사에 적합한 결과들만 추려냅니다. 그리고 그 결과를 현재 모델에 자동으로 추가합니다.

Changed in version: 0.10.0

이 메소드는 0.10.0 버전에서 사용법이 일부 변경되었습니다. 자세한 내용은 여기를 확인해주세요.

Parameters

texts : Iterable[str]
분석할 문자열의 리스트, 혹은 Iterable입니다.
min_cnt : int
추출할 단어의 최소 출현 빈도입니다. 이 빈도보다 적게 등장한 문자열은 단어 후보에서 제외됩니다.
max_word_len : int
추출할 단어 후보의 최대 길이입니다. 이 길이보다 긴 단어 후보는 탐색되지 않습니다.
min_score : float
단어 후보의 최소 점수입니다. 이 점수보다 낮은 단어 후보는 고려되지 않습니다. 이 값을 낮출수록 단어가 아닌 형태가 추출될 가능성이 높아지고, 반대로 이 값을 높일 수록 추출되는 단어의 개수가 줄어들므로 적절한 수치로 설정할 필요가 있습니다.
pos_score : float
단어 후보의 품사 점수입니다. 품사 점수가 이 값보다 낮은 경우 후보에서 제외됩니다.
lm_filter : bool

Added in version: 0.10.0

True일 경우 품사 점수 및 언어 모델을 이용한 필터링을 수행합니다.

Returns

result : List[Tuple[str, float, int, float]]
추출된 단어후보의 목록을 반환합니다. 리스트의 각 항목은 (단어 형태, 최종 점수, 출현 빈도, 품사 점수)로 구성된 튜플입니다.
Expand source code
    def extract_add_words(self,
        texts,
        min_cnt:int = 10,
        max_word_len:int = 10,
        min_score:float = 0.25,
        pos_score:float = -3.,
        lm_filter:bool = True,
    ):
        '''말뭉치로부터 새로운 단어를 추출하고 새로운 명사에 적합한 결과들만 추려냅니다. 그리고 그 결과를 현재 모델에 자동으로 추가합니다.

.. versionchanged:: 0.10.0
    이 메소드는 0.10.0 버전에서 사용법이 일부 변경되었습니다. 자세한 내용은 <a href="#0100">여기</a>를 확인해주세요.

Parameters
----------
texts: Iterable[str]
    분석할 문자열의 리스트, 혹은 Iterable입니다.
min_cnt: int
    추출할 단어의 최소 출현 빈도입니다. 이 빈도보다 적게 등장한 문자열은 단어 후보에서 제외됩니다.
max_word_len: int
    추출할 단어 후보의 최대 길이입니다. 이 길이보다 긴 단어 후보는 탐색되지 않습니다.
min_score: float
    단어 후보의 최소 점수입니다. 이 점수보다 낮은 단어 후보는 고려되지 않습니다.
    이 값을 낮출수록 단어가 아닌 형태가 추출될 가능성이 높아지고, 반대로 이 값을 높일 수록 추출되는 단어의 개수가 줄어들므로 적절한 수치로 설정할 필요가 있습니다.
pos_score: float
    단어 후보의 품사 점수입니다. 품사 점수가 이 값보다 낮은 경우 후보에서 제외됩니다.
lm_filter: bool
    ..versionadded:: 0.10.0

    True일 경우 품사 점수 및 언어 모델을 이용한 필터링을 수행합니다.

Returns
-------
result: List[Tuple[str, float, int, float]]
    추출된 단어후보의 목록을 반환합니다. 리스트의 각 항목은 (단어 형태, 최종 점수, 출현 빈도, 품사 점수)로 구성된 튜플입니다.
        '''

        return super().extract_add_words(
            texts,
            min_cnt,
            max_word_len,
            min_score,
            pos_score,
            lm_filter,
        )
def extract_words(self, texts, min_cnt: int = 10, max_word_len: int = 10, min_score: float = 0.25, pos_score: float = -3.0, lm_filter: bool = True)

말뭉치로부터 새로운 단어를 추출합니다. 이 기능은 https://github.com/lovit/soynlp 의 Word Extraction 기법을 바탕으로 하되, 문자열 기반의 확률 모델을 추가하여 명사일 것으로 예측되는 단어만 추출합니다.

Changed in version: 0.10.0

이 메소드는 0.10.0 버전에서 사용법이 일부 변경되었습니다. 자세한 내용은 여기를 확인해주세요.

Parameters

texts : Iterable[str]
분석할 문자열의 리스트, 혹은 Iterable입니다.
min_cnt : int
추출할 단어의 최소 출현 빈도입니다. 이 빈도보다 적게 등장한 문자열은 단어 후보에서 제외됩니다.
max_word_len : int
추출할 단어 후보의 최대 길이입니다. 이 길이보다 긴 단어 후보는 탐색되지 않습니다.
min_score : float
단어 후보의 최소 점수입니다. 이 점수보다 낮은 단어 후보는 고려되지 않습니다. 이 값을 낮출수록 단어가 아닌 형태가 추출될 가능성이 높아지고, 반대로 이 값을 높일 수록 추출되는 단어의 개수가 줄어들므로 적절한 수치로 설정할 필요가 있습니다.
pos_score : float

Added in version: 0.10.0

단어 후보의 품사 점수입니다. 품사 점수가 이 값보다 낮은 경우 후보에서 제외됩니다.

lm_filter : bool

Added in version: 0.10.0

True일 경우 품사 점수 및 언어 모델을 이용한 필터링을 수행합니다.

Returns

result : List[Tuple[str, float, int, float]]
추출된 단어후보의 목록을 반환합니다. 리스트의 각 항목은 (단어 형태, 최종 점수, 출현 빈도, 품사 점수)로 구성된 튜플입니다.
Expand source code
    def extract_words(self,
        texts,
        min_cnt:int = 10,
        max_word_len:int = 10,
        min_score:float = 0.25,
        pos_score:float = -3.,
        lm_filter:bool = True,
    ):
        '''말뭉치로부터 새로운 단어를 추출합니다. 
이 기능은 https://github.com/lovit/soynlp 의 Word Extraction 기법을 바탕으로 하되, 
문자열 기반의 확률 모델을 추가하여 명사일 것으로 예측되는 단어만 추출합니다.

.. versionchanged:: 0.10.0
    이 메소드는 0.10.0 버전에서 사용법이 일부 변경되었습니다. 자세한 내용은 <a href="#0100">여기</a>를 확인해주세요.

Parameters
----------
texts: Iterable[str]
    분석할 문자열의 리스트, 혹은 Iterable입니다.
min_cnt: int
    추출할 단어의 최소 출현 빈도입니다. 이 빈도보다 적게 등장한 문자열은 단어 후보에서 제외됩니다.
max_word_len: int
    추출할 단어 후보의 최대 길이입니다. 이 길이보다 긴 단어 후보는 탐색되지 않습니다.
min_score: float
    단어 후보의 최소 점수입니다. 이 점수보다 낮은 단어 후보는 고려되지 않습니다.
    이 값을 낮출수록 단어가 아닌 형태가 추출될 가능성이 높아지고, 반대로 이 값을 높일 수록 추출되는 단어의 개수가 줄어들므로 적절한 수치로 설정할 필요가 있습니다.
pos_score: float
    ..versionadded:: 0.10.0

    단어 후보의 품사 점수입니다. 품사 점수가 이 값보다 낮은 경우 후보에서 제외됩니다.

lm_filter: bool
    ..versionadded:: 0.10.0
    
    True일 경우 품사 점수 및 언어 모델을 이용한 필터링을 수행합니다.
Returns
-------
result: List[Tuple[str, float, int, float]]
    추출된 단어후보의 목록을 반환합니다. 리스트의 각 항목은 (단어 형태, 최종 점수, 출현 빈도, 품사 점수)로 구성된 튜플입니다.
        '''

        return super().extract_words(
            texts,
            min_cnt,
            max_word_len,
            min_score,
            pos_score,
            lm_filter,
        )
def glue(self, text_chunks: Iterable[str], insert_new_lines: Optional[Iterable[bool]] = None, return_space_insertions: bool = False) ‑> Union[str, Tuple[str, List[bool]]]

Added in version: 0.11.1

여러 텍스트 조각을 하나로 합치되, 문맥을 고려해 적절한 공백을 사이에 삽입합니다.

Parameters

text_chunks : Iterable[str]
합칠 텍스트 조각들의 목록입니다.
insert_new_lines : Iterable[bool]

Added in version: 0.15.0

합칠 때 공백 대신 줄바꿈을 사용할지 여부를 각 텍스트 조각별로 설정합니다. insert_new_lines의 길이는 text_chunks의 길이와 동일해야 합니다. 생략 시 줄바꿈을 사용하지 않고 공백만을 사용합니다.

return_space_insertions : bool
True인 경우, 각 조각별 공백 삽입 유무를 List[bool]로 반환합니다. 기본값은 False입니다.

Returns

result : str
입력 텍스트 조각의 결합결과를 반환합니다.
space_insertions : Iterable[str]
이 값은 return_space_insertions=True인 경우에만 반환됩니다. 공백 삽입 유무를 알려줍니다.

Notes

이 메소드의 공백 자동 삽입 기능은 형태소 분석에 기반합니다.

>>> kiwi.glue([
    "그러나  알고보니 그 봉",
    "지 안에 있던 것은 바로",
    "레몬이었던 것이다."])
"그러나  알고보니 그 봉지 안에 있던 것은 바로 레몬이었던 것이다."

>>> kiwi.glue([
    "그러나  알고보니 그 봉",
    "지 안에 있던 것은 바로",
    "레몬이었던 것이다."], return_space_insertions=True)
("그러나  알고보니 그 봉지 안에 있던 것은 바로 레몬이었던 것이다.", [False, True])
Expand source code
    def glue(self,
        text_chunks:Iterable[str],
        insert_new_lines:Optional[Iterable[bool]] = None,
        return_space_insertions:bool = False,
    ) -> Union[str, Tuple[str, List[bool]]]:
        '''..versionadded:: 0.11.1

여러 텍스트 조각을 하나로 합치되, 문맥을 고려해 적절한 공백을 사이에 삽입합니다.

Parameters
----------
text_chunks: Iterable[str]
    합칠 텍스트 조각들의 목록입니다.
insert_new_lines: Iterable[bool]

    ..versionadded:: 0.15.0

    합칠 때 공백 대신 줄바꿈을 사용할지 여부를 각 텍스트 조각별로 설정합니다. `insert_new_lines`의 길이는 `text_chunks`의 길이와 동일해야 합니다.
    생략 시 줄바꿈을 사용하지 않고 공백만을 사용합니다.
return_space_insertions: bool
    True인 경우, 각 조각별 공백 삽입 유무를 `List[bool]`로 반환합니다.
    기본값은 False입니다.

Returns
-------
result: str
    입력 텍스트 조각의 결합결과를 반환합니다.

space_insertions: Iterable[str]
    이 값은 `return_space_insertions=True`인 경우에만 반환됩니다.
    공백 삽입 유무를 알려줍니다.

Notes
-----
이 메소드의 공백 자동 삽입 기능은 형태소 분석에 기반합니다. 

```python
>>> kiwi.glue([
    "그러나  알고보니 그 봉",
    "지 안에 있던 것은 바로",
    "레몬이었던 것이다."])
"그러나  알고보니 그 봉지 안에 있던 것은 바로 레몬이었던 것이다."

>>> kiwi.glue([
    "그러나  알고보니 그 봉",
    "지 안에 있던 것은 바로",
    "레몬이었던 것이다."], return_space_insertions=True)
("그러나  알고보니 그 봉지 안에 있던 것은 바로 레몬이었던 것이다.", [False, True])
```
        '''

        all_chunks = []
        def _zip_consequences(it):
            try:
                prev = next(it).strip()
            except StopIteration:
                return

            all_chunks.append(prev)
            for s in it:
                s = s.strip()
                yield prev + ' ' + s
                yield prev + s
                prev = s
                all_chunks.append(prev)
        
        def _repeat_false():
            while 1:
                yield False

        riter = super().analyze(_zip_consequences(iter(text_chunks)), 1, Match.ALL, False, None, None)
            
        if insert_new_lines is None: 
            insert_new_lines = _repeat_false()
        else:
            insert_new_lines = iter(insert_new_lines)
        i = 0
        ret = []
        space_insertions = []
        try:
            while 1:
                _, score_with_space = next(riter)[0]
                _, score_without_space = next(riter)[0]
                is_new_line = next(insert_new_lines)
                ret.append(all_chunks[i])
                if score_with_space >= score_without_space or re.search(r'[0-9A-Za-z]$', all_chunks[i]):
                    ret.append('\n' if is_new_line else ' ')
                    space_insertions.append(True)
                else:
                    space_insertions.append(False)
                i += 1
        except StopIteration:
            if i < len(all_chunks):
                ret.append(all_chunks[i])
        
        if return_space_insertions:
            return ''.join(ret), space_insertions
        else:
            return ''.join(ret)
def join(self, morphs: Iterable[Tuple[str, str]], lm_search: bool = True) ‑> str

Added in version: 0.12.0

형태소들을 결합하여 문장으로 복원합니다. 조사나 어미는 앞 형태소에 맞춰 적절한 형태로 변경됩니다.

Parameters

morphs : Iterable[Union[Token, Tuple[str, str], Tuple[str, str, bool]]]
결합할 형태소의 목록입니다. 각 형태소는 Kiwi.tokenize()에서 얻어진 Token 타입이거나, (형태, 품사) 혹은 (형태, 품사, 왼쪽 띄어쓰기 유무)로 구성된 tuple 타입이어야 합니다.
lm_search : bool
둘 이상의 형태로 복원 가능한 모호한 형태소가 있는 경우, 이 값이 True면 언어 모델 탐색을 통해 최적의 형태소를 선택합니다. False일 경우 탐색을 실시하지 않지만 더 빠른 속도로 복원이 가능합니다.

Returns

result : str
입력 형태소의 결합 결과를 반환합니다.

Notes

Kiwi.join()은 형태소를 결합할 때 Kiwi.space()에서 사용하는 것과 유사한 규칙을 사용하여 공백을 적절히 삽입합니다. 형태소 그 자체에는 공백 관련 정보가 포함되지 않으므로 특정 텍스트를 Kiwi.tokenize()로 분석 후 다시 Kiwi.join()으로 결합하여도 원본 텍스트가 그대로 복원되지는 않습니다.

>>> kiwi.join([('덥', 'VA'), ('어', 'EC')])
'더워'
>>> tokens = kiwi.tokenize("분석된결과를 다시합칠수있다!")
# 형태소 분석 결과를 복원. 
# 복원 시 공백은 규칙에 의해 삽입되므로 원문 텍스트가 그대로 복원되지는 않음.
>>> kiwi.join(tokens)
'분석된 결과를 다시 합칠 수 있다!'
>>> tokens[3]
Token(form='결과', tag='NNG', start=4, len=2)
>>> tokens[3] = ('내용', 'NNG') # 4번째 형태소를 결과->내용으로 교체
>>> kiwi.join(tokens) # 다시 join하면 결과를->내용을 로 교체된 걸 확인 가능
'분석된 내용을 다시 합칠 수 있다!'

# 불규칙 활용여부가 모호한 경우 lm_search=True인 경우 맥락을 고려해 최적의 후보를 선택합니다.
>>> kiwi.join([('길', 'NNG'), ('을', 'JKO'), ('묻', 'VV'), ('어요', 'EF')])
'길을 물어요'
>>> kiwi.join([('흙', 'NNG'), ('이', 'JKS'), ('묻', 'VV'), ('어요', 'EF')])
'흙이 묻어요'
# lm_search=False이면 탐색을 실시하지 않습니다.
>>> kiwi.join([('길', 'NNG'), ('을', 'JKO'), ('묻', 'VV'), ('어요', 'EF')], lm_search=False)
'길을 묻어요'
>>> kiwi.join([('흙', 'NNG'), ('이', 'JKS'), ('묻', 'VV'), ('어요', 'EF')], lm_search=False)
'흙이 묻어요'
# 동사/형용사 품사 태그 뒤에 -R(규칙 활용), -I(불규칙 활용)을 덧붙여 활용법을 직접 명시할 수 있습니다.
>>> kiwi.join([('묻', 'VV-R'), ('어요', 'EF')])
'묻어요'
>>> kiwi.join([('묻', 'VV-I'), ('어요', 'EF')])
'물어요'

# 0.15.2버전부터는 Tuple의 세번째 요소로 띄어쓰기 유무를 지정할 수 있습니다. 
# True일 경우 강제로 띄어쓰기, False일 경우 강제로 붙여쓰기를 수행합니다.
>>> kiwi.join([('길', 'NNG'), ('을', 'JKO', True), ('묻', 'VV'), ('어요', 'EF')])
'길 을 물어요'
>>> kiwi.join([('길', 'NNG'), ('을', 'JKO'), ('묻', 'VV', False), ('어요', 'EF')])
'길을물어요'

# 과거형 선어말어미를 제거하는 예시
>>> remove_past = lambda s: kiwi.join(t for t in kiwi.tokenize(s) if t.tagged_form != '었/EP')
>>> remove_past('먹었다')
'먹다'
>>> remove_past('먼 길을 걸었다')
'먼 길을 걷다'
>>> remove_past('전화를 걸었다.')
'전화를 걸다.'
Expand source code
    def join(self, 
        morphs:Iterable[Tuple[str, str]],
        lm_search:bool = True
    ) -> str:
        '''..versionadded:: 0.12.0

형태소들을 결합하여 문장으로 복원합니다. 
조사나 어미는 앞 형태소에 맞춰 적절한 형태로 변경됩니다.

Parameters
----------
morphs: Iterable[Union[Token, Tuple[str, str], Tuple[str, str, bool]]]
    결합할 형태소의 목록입니다. 
    각 형태소는 `Kiwi.tokenize`에서 얻어진 `Token` 타입이거나, 
    (형태, 품사) 혹은 (형태, 품사, 왼쪽 띄어쓰기 유무)로 구성된 `tuple` 타입이어야 합니다.
lm_search: bool
    둘 이상의 형태로 복원 가능한 모호한 형태소가 있는 경우, 이 값이 True면 언어 모델 탐색을 통해 최적의 형태소를 선택합니다.
    False일 경우 탐색을 실시하지 않지만 더 빠른 속도로 복원이 가능합니다.

Returns
-------
result: str
    입력 형태소의 결합 결과를 반환합니다.

Notes
-----
`Kiwi.join`은 형태소를 결합할 때 `Kiwi.space`에서 사용하는 것과 유사한 규칙을 사용하여 공백을 적절히 삽입합니다.
형태소 그 자체에는 공백 관련 정보가 포함되지 않으므로
특정 텍스트를 `Kiwi.tokenize`로 분석 후 다시 `Kiwi.join`으로 결합하여도 원본 텍스트가 그대로 복원되지는 않습니다.


```python
>>> kiwi.join([('덥', 'VA'), ('어', 'EC')])
'더워'
>>> tokens = kiwi.tokenize("분석된결과를 다시합칠수있다!")
# 형태소 분석 결과를 복원. 
# 복원 시 공백은 규칙에 의해 삽입되므로 원문 텍스트가 그대로 복원되지는 않음.
>>> kiwi.join(tokens)
'분석된 결과를 다시 합칠 수 있다!'
>>> tokens[3]
Token(form='결과', tag='NNG', start=4, len=2)
>>> tokens[3] = ('내용', 'NNG') # 4번째 형태소를 결과->내용으로 교체
>>> kiwi.join(tokens) # 다시 join하면 결과를->내용을 로 교체된 걸 확인 가능
'분석된 내용을 다시 합칠 수 있다!'

# 불규칙 활용여부가 모호한 경우 lm_search=True인 경우 맥락을 고려해 최적의 후보를 선택합니다.
>>> kiwi.join([('길', 'NNG'), ('을', 'JKO'), ('묻', 'VV'), ('어요', 'EF')])
'길을 물어요'
>>> kiwi.join([('흙', 'NNG'), ('이', 'JKS'), ('묻', 'VV'), ('어요', 'EF')])
'흙이 묻어요'
# lm_search=False이면 탐색을 실시하지 않습니다.
>>> kiwi.join([('길', 'NNG'), ('을', 'JKO'), ('묻', 'VV'), ('어요', 'EF')], lm_search=False)
'길을 묻어요'
>>> kiwi.join([('흙', 'NNG'), ('이', 'JKS'), ('묻', 'VV'), ('어요', 'EF')], lm_search=False)
'흙이 묻어요'
# 동사/형용사 품사 태그 뒤에 -R(규칙 활용), -I(불규칙 활용)을 덧붙여 활용법을 직접 명시할 수 있습니다.
>>> kiwi.join([('묻', 'VV-R'), ('어요', 'EF')])
'묻어요'
>>> kiwi.join([('묻', 'VV-I'), ('어요', 'EF')])
'물어요'

# 0.15.2버전부터는 Tuple의 세번째 요소로 띄어쓰기 유무를 지정할 수 있습니다. 
# True일 경우 강제로 띄어쓰기, False일 경우 강제로 붙여쓰기를 수행합니다.
>>> kiwi.join([('길', 'NNG'), ('을', 'JKO', True), ('묻', 'VV'), ('어요', 'EF')])
'길 을 물어요'
>>> kiwi.join([('길', 'NNG'), ('을', 'JKO'), ('묻', 'VV', False), ('어요', 'EF')])
'길을물어요'

# 과거형 선어말어미를 제거하는 예시
>>> remove_past = lambda s: kiwi.join(t for t in kiwi.tokenize(s) if t.tagged_form != '었/EP')
>>> remove_past('먹었다')
'먹다'
>>> remove_past('먼 길을 걸었다')
'먼 길을 걷다'
>>> remove_past('전화를 걸었다.')
'전화를 걸다.'
```
        '''
        return super().join(morphs, lm_search)
def load_user_dictionary(self, dict_path: str) ‑> int

사용자 정의 사전을 읽어옵니다. 사용자 정의 사전 파일은 UTF-8로 인코딩된 텍스트 파일이어야 합니다. 사용자 정의 사전으로 추가된 단어의 개수를 반환합니다.

Parameters

dict_path : str
사용자 정의 사전 파일의 경로

Returns

added_cnt : int
사용자 정의 사전 파일을 이용해 추가된 단어의 개수를 반환합니다.

Notes

사용자 정의 사전 파일의 형식에 대해서는 여기를 참조하세요.

Expand source code
    def load_user_dictionary(self,
        dict_path:str
    ) -> int:
        '''사용자 정의 사전을 읽어옵니다. 사용자 정의 사전 파일은 UTF-8로 인코딩된 텍스트 파일이어야 합니다.
사용자 정의 사전으로 추가된 단어의 개수를 반환합니다.
    
Parameters
----------
dict_path: str
    사용자 정의 사전 파일의 경로

Returns
-------
added_cnt: int
    사용자 정의 사전 파일을 이용해 추가된 단어의 개수를 반환합니다.

Notes
-----
사용자 정의 사전 파일의 형식에 대해서는 <a href='#_3'>여기</a>를 참조하세요.
        '''

        return super().load_user_dictionary(dict_path)
def morpheme(self, idx: int)
Expand source code
def morpheme(self,
    idx:int,
):
    return super().morpheme(idx)
def predict_next(self, prefix: List[int])
Expand source code
def predict_next(self,
    prefix:List[int],
):
    raise NotImplementedError
def space(self, text: Union[str, Iterable[str]], reset_whitespace: bool = False) ‑> Union[str, Iterable[str]]

Added in version: 0.11.1

입력 텍스트에서 띄어쓰기를 교정하여 반환합니다.

Parameters

text : Union[str, Iterable[str]]
분석할 문자열입니다. 이 인자를 단일 str로 줄 경우, 싱글스레드에서 처리하며 str의 Iterable로 줄 경우, 멀티스레드로 분배하여 처리합니다.
reset_whitespace : bool
True인 경우 이미 띄어쓰기된 부분을 붙이는 교정도 적극적으로 수행합니다. 기본값은 False로, 이 경우에는 붙어 있는 단어를 띄어쓰는 교정 위주로 수행합니다.

Returns

result : str
text를 str으로 준 경우. 입력 텍스트의 띄어쓰기 교정 결과를 반환합니다.
iterable_of_results : Iterable[str]
text를 Iterable[str]으로 준 경우. 입력 텍스트의 띄어쓰기 교정 결과를 반환합니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.

Notes

이 메소드의 띄어쓰기 교정 기능은 형태소 분석에 기반합니다. 따라서 형태소 중간에 공백이 삽입된 경우 교정 결과가 부정확할 수 있습니다. 이 경우 Kiwi.space_tolerance를 조절하여 형태소 내 공백을 무시하거나, reset_whitespace=True로 설정하여 아예 기존 공백을 무시하고 띄어쓰기를 하도록 하면 결과를 개선할 수 있습니다.

>>> kiwi.space("띄어쓰기없이작성된텍스트네이걸교정해줘")
"띄어쓰기 없이 작성된 텍스트네 이걸 교정해 줘."
>>> kiwi.space("띄 어 쓰 기 문 제 가 있 습 니 다")
"띄어 쓰기 문 제 가 있 습 니 다"
>>> kiwi.space_tolerance = 2 # 형태소 내 공백을 최대 2개까지 허용
>>> kiwi.space("띄 어 쓰 기 문 제 가 있 습 니 다")
"띄어 쓰기 문제가 있습니다"
>>> kiwi.space("띄 어 쓰 기 문 제 가 있 습 니 다", reset_whitespace=True) # 기존 공백 전부 무시
"띄어쓰기 문제가 있습니다"
Expand source code
    def space(self,
        text:Union[str, Iterable[str]],
        reset_whitespace:bool = False,
    ) -> Union[str, Iterable[str]]:
        '''..versionadded:: 0.11.1

입력 텍스트에서 띄어쓰기를 교정하여 반환합니다.

Parameters
----------
text: Union[str, Iterable[str]]
    분석할 문자열입니다. 
    이 인자를 단일 str로 줄 경우, 싱글스레드에서 처리하며
    str의 Iterable로 줄 경우, 멀티스레드로 분배하여 처리합니다.
reset_whitespace: bool
    True인 경우 이미 띄어쓰기된 부분을 붙이는 교정도 적극적으로 수행합니다. 
    기본값은 False로, 이 경우에는 붙어 있는 단어를 띄어쓰는 교정 위주로 수행합니다.

Returns
-------
result: str
    text를 str으로 준 경우.
    입력 텍스트의 띄어쓰기 교정 결과를 반환합니다.

iterable_of_results: Iterable[str]
    text를 Iterable[str]으로 준 경우.
    입력 텍스트의 띄어쓰기 교정 결과를 반환합니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.

Notes
-----
이 메소드의 띄어쓰기 교정 기능은 형태소 분석에 기반합니다. 
따라서 형태소 중간에 공백이 삽입된 경우 교정 결과가 부정확할 수 있습니다.
이 경우 `Kiwi.space_tolerance`를 조절하여 형태소 내 공백을 무시하거나, 
`reset_whitespace=True`로 설정하여 아예 기존 공백을 무시하고 띄어쓰기를 하도록 하면 결과를 개선할 수 있습니다.

```python
>>> kiwi.space("띄어쓰기없이작성된텍스트네이걸교정해줘")
"띄어쓰기 없이 작성된 텍스트네 이걸 교정해 줘."
>>> kiwi.space("띄 어 쓰 기 문 제 가 있 습 니 다")
"띄어 쓰기 문 제 가 있 습 니 다"
>>> kiwi.space_tolerance = 2 # 형태소 내 공백을 최대 2개까지 허용
>>> kiwi.space("띄 어 쓰 기 문 제 가 있 습 니 다")
"띄어 쓰기 문제가 있습니다"
>>> kiwi.space("띄 어 쓰 기 문 제 가 있 습 니 다", reset_whitespace=True) # 기존 공백 전부 무시
"띄어쓰기 문제가 있습니다"
```
        '''
        ws = re.compile(r'(?<=[가-힣])\s+(?=[가-힣.,?!:;])')
        any_ws = re.compile(r'\s+')
        space_insertable = re.compile('|'.join([
            r'(([^SUWX]|X[RS]|S[EH]).* ([NMI]|V[VAX]|VCN|XR|XPN|S[WLHN]))',
            r'(SN ([MI]|N[PR]|NN[GP]|V[VAX]|VCN|XR|XPN|S[WH]))',
            r'((S[FPL]).* ([NMI]|V[VAX]|VCN|XR|XPN|S[WH]))',
        ]))

        def _reset(t):
            return ws.sub('', t)

        def _space(arg):
            tokens, raw = arg
            tokens = tokens[0][0]
            chunks = []
            last = 0
            prev_tag = None
            for t in tokens:
                if last < t.start:
                    if (t.tag.startswith('E') or t.tag.startswith('J') or t.tag.startswith('XS')
                        or t.tag == 'VX' and t.form in '하지'
                    ):
                        s = any_ws.sub('', raw[last:t.start])
                    else:
                        s = raw[last:t.start]
                    if s: chunks.append(s)
                    last = t.start
                if prev_tag and space_insertable.match(prev_tag + ' ' + t.tag):
                    if t.tag == 'VX' and t.form in '하지':
                        pass # 보조 용언 중 `하다/지다`는 붙여쓴다.
                    elif not chunks[-1][-1].isspace():
                        # 이전에 공백이 없는 경우만 삽입
                        chunks.append(' ') 
                if last < t.end:
                    s = any_ws.sub('', raw[last:t.end])
                    if s: chunks.append(s)
                last = t.end
                prev_tag = t.tag
            if last < len(raw):
                chunks.append(raw[last:])
            return ''.join(chunks)

        if isinstance(text, str):
            if reset_whitespace: text = _reset(text)
            return _space((super().analyze(text, 1, Match.ALL | Match.Z_CODA, False, None, None), text))
        else:
            if reset_whitespace: text = map(_reset, text)
            return map(_space, super().analyze(text, 1, Match.ALL | Match.Z_CODA, True, None, None))
def split_into_sents(self, text: Union[str, Iterable[str]], match_options: int = Match.ALL, normalize_coda: bool = False, z_coda: bool = True, split_complex: bool = False, stopwords: Optional[Stopwords] = None, blocklist: Union[MorphemeSet, Iterable[str], None] = None, return_tokens: bool = False, return_sub_sents: bool = True) ‑> Union[List[Sentence], Iterable[List[Sentence]]]

Added in version: 0.10.3

입력 텍스트를 문장 단위로 분할하여 반환합니다. 이 메소드는 문장 분할 과정에서 내부적으로 형태소 분석을 사용하므로 문장 분할과 동시에 형태소 분석 결과를 얻는 데 사용할 수도 있습니다.

Parameters

text : Union[str, Iterable[str]]
분석할 문자열입니다. 이 인자를 단일 str로 줄 경우, 싱글스레드에서 처리하며 str의 Iterable로 줄 경우, 멀티스레드로 분배하여 처리합니다.
match_options : Match
이 인자는 Kiwi.tokenize()에서와 동일한 역할을 수행합니다.
normalize_coda : bool
이 인자는 Kiwi.tokenize()에서와 동일한 역할을 수행합니다.
z_coda : bool
이 인자는 Kiwi.tokenize()에서와 동일한 역할을 수행합니다.
split_complex : bool
이 인자는 Kiwi.tokenize()에서와 동일한 역할을 수행합니다.
stopwords : Stopwords

Added in version: 0.16.0

이 인자는 Kiwi.tokenize()에서와 동일한 역할을 수행합니다.

blocklist : Union[Iterable[str], MorphemeSet]
이 인자는 Kiwi.tokenize()에서와 동일한 역할을 수행합니다.
return_tokens : bool
True인 경우 문장별 형태소 분석 결과도 함께 반환합니다.
return_sub_sents : bool

Added in version: 0.14.0

True인 경우 문장 내 안긴 문장의 목록도 함께 반환합니다.

Returns

sentences : List[Sentence]
text를 str으로 준 경우. 문장 분할 결과인 Sentence의 리스트를 반환합니다.
iterable_of_sentences : Iterable[List[Sentence]]
text를 Iterable[str]으로 준 경우. 반환값은 sentences의 iterator로 주어집니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.

Notes

문장 분리 기능은 형태소 분석에 기반합니다. 따라서 return_tokens의 True/False여부에 상관없이 내부적으로 형태소 분석을 수행하며, 출력 시에만 형태소 목록을 넣거나 뺄 뿐이므로 이에 따른 실행 속도 차이는 없습니다. 그러므로 문장 분리 기능과 형태소 분석을 동시에 수행해야하는 경우 return_tokens=True로 설정하는 게, 문장 분리 후 따로 형태소 분석을 수행하는 것보다 효율적입니다.

>>> kiwi.split_into_sents("여러 문장으로 구성된 텍스트네 이걸 분리해줘")
[Sentence(text='여러 문장으로 구성된 텍스트네', start=0, end=16, tokens=None, subs=[]),
 Sentence(text='이걸 분리해줘', start=17, end=24, tokens=None, subs=[])]

>>> kiwi.split_into_sents("여러 문장으로 구성된 텍스트네 이걸 분리해줘", return_tokens=True)
[Sentence(text='여러 문장으로 구성된 텍스트네', start=0, end=16, tokens=[
  Token(form='여러', tag='MM', start=0, len=2), 
  Token(form='문장', tag='NNG', start=3, len=2), 
  Token(form='으로', tag='JKB', start=5, len=2), 
  Token(form='구성', tag='NNG', start=8, len=2), 
  Token(form='되', tag='XSV', start=10, len=1), 
  Token(form='ᆫ', tag='ETM', start=10, len=1), 
  Token(form='텍스트', tag='NNG', start=12, len=3), 
  Token(form='이', tag='VCP', start=15, len=1), 
  Token(form='네', tag='EF', start=15, len=1)
 ], subs=[]),
 Sentence(text='이걸 분리해줘', start=17, end=24, tokens=[
  Token(form='이거', tag='NP', start=17, len=2), 
  Token(form='ᆯ', tag='JKO', start=19, len=0), 
  Token(form='분리', tag='NNG', start=20, len=2), 
  Token(form='하', tag='XSV', start=22, len=1), 
  Token(form='어', tag='EC', start=22, len=1), 
  Token(form='주', tag='VX', start=23, len=1), 
  Token(form='어', tag='EF', start=23, len=1)
 ], subs=[])]

# 0.14.0 버전부터는 문장 안에 또 다른 문장이 포함된 경우도 처리 가능
>>> kiwi.split_into_sents("회사의 정보 서비스를 책임지고 있는 로웬버그John Loewenberg는" 
     "<서비스 산업에 있어 종이는 혈관내의 콜레스트롤과 같다. 나쁜 종이는 동맥을 막는 내부의 물질이다.>"
     "라고 말한다.")
[Sentence(text='회사의 정보 서비스를 책임지고 있는 로웬버그John Loewenberg는' 
  '<서비스 산업에 있어 종이는 혈관내의 콜레스트롤과 같다. 나쁜 종이는 동맥을 막는 내부의 물질이다.>'
  '라고 말한다.', start=0, end=104, tokens=None, subs=[
  Sentence(text='서비스 산업에 있어 종이는 혈관내의 콜레스트롤과 같다.', start=42, end=72, tokens=None, subs=None), 
  Sentence(text='나쁜 종이는 동맥을 막는 내부의 물질이다.', start=73, end=96, tokens=None, subs=None)
])]
Expand source code
    def split_into_sents(self, 
        text:Union[str, Iterable[str]], 
        match_options:int = Match.ALL, 
        normalize_coda:bool = False,
        z_coda:bool = True,
        split_complex:bool = False,
        stopwords:Optional[Stopwords] = None,
        blocklist:Optional[Union[Iterable[str], MorphemeSet]] = None,
        return_tokens:bool = False,
        return_sub_sents:bool = True,
    ) -> Union[List[Sentence], Iterable[List[Sentence]]]:
        '''..versionadded:: 0.10.3

입력 텍스트를 문장 단위로 분할하여 반환합니다. 
이 메소드는 문장 분할 과정에서 내부적으로 형태소 분석을 사용하므로 문장 분할과 동시에 형태소 분석 결과를 얻는 데 사용할 수도 있습니다.

Parameters
----------
text: Union[str, Iterable[str]]
    분석할 문자열입니다. 
    이 인자를 단일 str로 줄 경우, 싱글스레드에서 처리하며
    str의 Iterable로 줄 경우, 멀티스레드로 분배하여 처리합니다.
match_options: kiwipiepy.const.Match
    이 인자는 `Kiwi.tokenize`에서와 동일한 역할을 수행합니다.
normalize_coda: bool
    이 인자는 `Kiwi.tokenize`에서와 동일한 역할을 수행합니다.
z_coda: bool
    이 인자는 `Kiwi.tokenize`에서와 동일한 역할을 수행합니다.
split_complex: bool
    이 인자는 `Kiwi.tokenize`에서와 동일한 역할을 수행합니다.
stopwords: Stopwords

    .. versionadded:: 0.16.0

    이 인자는 `Kiwi.tokenize`에서와 동일한 역할을 수행합니다.
blocklist: Union[Iterable[str], MorphemeSet]
    이 인자는 `Kiwi.tokenize`에서와 동일한 역할을 수행합니다.
return_tokens: bool
    True인 경우 문장별 형태소 분석 결과도 함께 반환합니다.
return_sub_sents: bool
    
    ..versionadded:: 0.14.0

    True인 경우 문장 내 안긴 문장의 목록도 함께 반환합니다.

Returns
-------
sentences: List[kiwipiepy.Sentence]
    text를 str으로 준 경우.
    문장 분할 결과인 `kiwipiepy.Sentence`의 리스트를 반환합니다.

iterable_of_sentences: Iterable[List[kiwipiepy.Sentence]]
    text를 Iterable[str]으로 준 경우.
    반환값은 `sentences`의 iterator로 주어집니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.

Notes
-----
문장 분리 기능은 형태소 분석에 기반합니다. 따라서 return_tokens의 True/False여부에 상관없이 내부적으로 형태소 분석을 수행하며,
출력 시에만 형태소 목록을 넣거나 뺄 뿐이므로 이에 따른 실행 속도 차이는 없습니다.
그러므로 문장 분리 기능과 형태소 분석을 동시에 수행해야하는 경우 `return_tokens=True`로 설정하는 게, 
문장 분리 후 따로 형태소 분석을 수행하는 것보다 효율적입니다.

```python
>>> kiwi.split_into_sents("여러 문장으로 구성된 텍스트네 이걸 분리해줘")
[Sentence(text='여러 문장으로 구성된 텍스트네', start=0, end=16, tokens=None, subs=[]),
 Sentence(text='이걸 분리해줘', start=17, end=24, tokens=None, subs=[])]

>>> kiwi.split_into_sents("여러 문장으로 구성된 텍스트네 이걸 분리해줘", return_tokens=True)
[Sentence(text='여러 문장으로 구성된 텍스트네', start=0, end=16, tokens=[
  Token(form='여러', tag='MM', start=0, len=2), 
  Token(form='문장', tag='NNG', start=3, len=2), 
  Token(form='으로', tag='JKB', start=5, len=2), 
  Token(form='구성', tag='NNG', start=8, len=2), 
  Token(form='되', tag='XSV', start=10, len=1), 
  Token(form='ᆫ', tag='ETM', start=10, len=1), 
  Token(form='텍스트', tag='NNG', start=12, len=3), 
  Token(form='이', tag='VCP', start=15, len=1), 
  Token(form='네', tag='EF', start=15, len=1)
 ], subs=[]),
 Sentence(text='이걸 분리해줘', start=17, end=24, tokens=[
  Token(form='이거', tag='NP', start=17, len=2), 
  Token(form='ᆯ', tag='JKO', start=19, len=0), 
  Token(form='분리', tag='NNG', start=20, len=2), 
  Token(form='하', tag='XSV', start=22, len=1), 
  Token(form='어', tag='EC', start=22, len=1), 
  Token(form='주', tag='VX', start=23, len=1), 
  Token(form='어', tag='EF', start=23, len=1)
 ], subs=[])]

# 0.14.0 버전부터는 문장 안에 또 다른 문장이 포함된 경우도 처리 가능
>>> kiwi.split_into_sents("회사의 정보 서비스를 책임지고 있는 로웬버그John Loewenberg는" 
     "<서비스 산업에 있어 종이는 혈관내의 콜레스트롤과 같다. 나쁜 종이는 동맥을 막는 내부의 물질이다.>"
     "라고 말한다.")
[Sentence(text='회사의 정보 서비스를 책임지고 있는 로웬버그John Loewenberg는' 
  '<서비스 산업에 있어 종이는 혈관내의 콜레스트롤과 같다. 나쁜 종이는 동맥을 막는 내부의 물질이다.>'
  '라고 말한다.', start=0, end=104, tokens=None, subs=[
  Sentence(text='서비스 산업에 있어 종이는 혈관내의 콜레스트롤과 같다.', start=42, end=72, tokens=None, subs=None), 
  Sentence(text='나쁜 종이는 동맥을 막는 내부의 물질이다.', start=73, end=96, tokens=None, subs=None)
])]
```
        '''
        def _filter_tokens(tokens):
            return tokens if stopwords is None else stopwords.filter(tokens)

        def _make_result(arg):
            sents, raw_input = arg
            ret = []
            for sent in sents:
                start = sent[0].start
                end = sent[-1].end
                tokens = _filter_tokens(sent) if return_tokens else None
                subs = None
                if return_sub_sents:
                    subs = []
                    sub_toks = []
                    last = 0
                    for tok in sent:
                        if tok.sub_sent_position != last:
                            if last:
                                subs.append(Sentence(raw_input[sub_start:last_end], sub_start, last_end, _filter_tokens(sub_toks) if return_tokens else None, None))
                                sub_toks = []
                            sub_start = tok.start
                        if tok.sub_sent_position:
                            sub_toks.append(tok)
                        last = tok.sub_sent_position
                        last_end = tok.end
                ret.append(Sentence(raw_input[start:end], start, end, tokens, subs))
            return ret

        if isinstance(text, str):
            return _make_result((self._tokenize(text, match_options=match_options, normalize_coda=normalize_coda, z_coda=z_coda, split_complex=split_complex, blocklist=blocklist, split_sents=True), text))

        return map(_make_result, self._tokenize(text, match_options=match_options, normalize_coda=normalize_coda, z_coda=z_coda, split_complex=split_complex, blocklist=blocklist, split_sents=True, echo=True))
def tokenize(self, text: Union[str, Iterable[str]], match_options: int = Match.ALL, normalize_coda: bool = False, z_coda: bool = True, split_complex: bool = False, split_sents: bool = False, stopwords: Optional[Stopwords] = None, echo: bool = False, blocklist: Union[MorphemeSet, Iterable[str], None] = None, pretokenized: Union[Callable[[str], List[Union[Tuple[int, int], Tuple[int, int, POSTag], Tuple[int, int, PretokenizedToken], Tuple[int, int, List[PretokenizedToken]]]]], List[Union[Tuple[int, int], Tuple[int, int, POSTag], Tuple[int, int, PretokenizedToken], Tuple[int, int, List[PretokenizedToken]]]], None] = None) ‑> Union[List[Token], Iterable[List[Token]], List[List[Token]], Iterable[List[List[Token]]]]

Added in version: 0.10.2

analyze와는 다르게 형태소 분석결과만 간단하게 반환합니다.

Parameters

text : Union[str, Iterable[str]]
분석할 문자열입니다. 이 인자를 단일 str로 줄 경우, 싱글스레드에서 처리하며 str의 Iterable로 줄 경우, 멀티스레드로 분배하여 처리합니다.
match_options : Match
추출한 특수 문자열 패턴을 지정합니다. Match의 조합으로 설정할 수 있습니다.
normalize_coda : bool
True인 경우 '먹었엌ㅋㅋ'처럼 받침이 덧붙어서 분석에 실패하는 경우, 받침을 분리하여 정규화합니다.
z_coda : bool

Added in version: 0.15.0

기본값은 True로, True인 경우 '먹었어욥' => 먹었어요 + ㅂ, '우리집에성' => 우리집에서 + ㅇ과 같이 조사 및 어미에 덧붙는 받침을 'z_coda'라는 태그로 분리합니다. False로 설정 시 덧붙는 받침 분리를 수행하지 않는 대신 분석 속도가 향상됩니다.

split_complex : bool

Added in version: 0.15.0

True인 경우 둘 이상의 형태소로 더 잘게 분할될 수 있는 경우 형태소를 최대한 분할합니다. 예를 들어 '고마움을 전하다'의 경우 split_complex=False인 경우 고마움/NNG 을/JKO 전하/VV 다/EF와 같이 분석되지만, split_complex=True인 경우 고맙/VA-I 음/ETN 을/JKO 전하/VV 다/EF처럼 고마움/NNG이 더 잘게 분석됩니다.

split_sents : bool

Added in version: 0.10.3

True인 경우 형태소 리스트를 문장별로 묶어서 반환합니다. 자세한 내용은 아래의 Returns 항목을 참조하세요.

stopwords : Stopwords

Added in version: 0.10.3

이 인자로 None이 아닌 Stopwords 객체를 줄 경우, 형태소 분석 결과 중 그 객체에 포함되는 불용어를 제외한 나머지 결과만을 반환합니다.

echo : bool

Added in version: 0.11.2

이 값이 True이고 text를 str의 Iterable로 준 경우, 분석 결과뿐만 아니라 원본 입력을 함께 반환합니다. text가 단일 str인 경우 이 인자는 무시됩니다.

blocklist : Union[MorphemeSet, Iterable[str]]

Added in version: 0.15.0

분석 시 후보로 나타나는 걸 금지할 형태소 목록을 지정합니다. 예를 들어, blocklist=['고마움']으로 지정하는 경우, 분석 결과에서 '고마움'이라는 형태소가 등장하는 것을 막아 split_complex의 예시에서처럼 '고마움을 전하다'가 고맙/VA-I 음/ETN 을/JKO 전하/VV 다/EF처럼 분석되도록 강요할 수 있습니다. blocklist는 MorphemeSet 혹은 set으로 지정할 수 있으며, 동일한 blocklist가 반복적으로 사용되는 경우 사전에 MorphemeSet을 만들고 이를 재사용하는게 효율적입니다.

pretokenized : Union[Callable[[str], PretokenizedTokenList], PretokenizedTokenList]

Added in version: 0.16.0

형태소 분석에 앞서 텍스트 내 특정 구간의 형태소 분석 결과를 미리 정의합니다. 이 값에 의해 정의된 텍스트 구간은 항상 해당 방법으로만 토큰화됩니다. 이 값은 str을 입력 받아 PretokenizedTokenList를 반환하는 Callable로 주어지거나, PretokenizedTokenList 값 단독으로 주어질 수 있습니다. textIterable[str]인 경우 pretokenized는 None 혹은 Callable로 주어져야 합니다. 자세한 것은 아래 Notes의 예시를 참조하십시오.

Returns

result : List[Token]
split_sents=False일때 text를 str으로 준 경우. Token의 리스트를 반환합니다.
results : Iterable[List[Token]]
split_sents=False일때 text를 Iterable[str]으로 준 경우. 반환값은 result의 iterator로 주어집니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.
results_with_echo : Iterable[Tuple[List[Token], str]]
split_sents=False이고 echo=True일때 text를 Iterable[str]으로 준 경우. 반환값은 (result의 iterator, raw_input)으로 주어집니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.
result_by_sent : List[List[Token]]
split_sents=True일때 text를 str으로 준 경우. 형태소 분석 결과가 문장별로 묶여서 반환됩니다. 즉, 전체 문장이 n개라고 할 때, result_by_sent[0] ~ result_by_sent[n-1]에는 각 문장별 분석 결과가 들어갑니다.
results_by_sent : Iterable[List[List[Token]]]
split_sents=True일때 text를 Iterable[str]으로 준 경우. 반환값은 result_by_sent의 iterator로 주어집니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.
results_by_sent_with_echo : Iterable[Tuple[List[List[Token]], str]]
split_sents=True이고 echo=True일때 text를 Iterable[str]으로 준 경우. 반환값은 (result_by_sent의 iterator, raw_input)으로 주어집니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.

Notes

>>> kiwi.tokenize("안녕하세요 형태소 분석기 키위입니다.")
[Token(form='안녕', tag='NNG', start=0, len=2),
 Token(form='하', tag='XSA', start=2, len=1),
 Token(form='시', tag='EP', start=4, len=1),
 Token(form='어요', tag='EC', start=3, len=2),
 Token(form='형태소', tag='NNG', start=6, len=3),
 Token(form='분석', tag='NNG', start=10, len=2),
 Token(form='기', tag='NNG', start=12, len=1),
 Token(form='키위', tag='NNG', start=14, len=2),
 Token(form='이', tag='VCP', start=16, len=1),
 Token(form='ᆸ니다', tag='EF', start=17, len=2),
 Token(form='.', tag='SF', start=19, len=1)]

# normalize_coda 옵션을 사용하면 
# 덧붙은 받침 때문에 분석이 깨지는 경우를 방지할 수 있습니다.
>>> kiwi.tokenize("ㅋㅋㅋ 이런 것도 분석이 될까욬ㅋㅋ?", normalize_coda=True)
[Token(form='ㅋㅋㅋ', tag='SW', start=0, len=3),
 Token(form='이런', tag='MM', start=4, len=2),
 Token(form='것', tag='NNB', start=7, len=1),
 Token(form='도', tag='JX', start=8, len=1),
 Token(form='분석', tag='NNG', start=10, len=2),
 Token(form='이', tag='JKS', start=12, len=1),
 Token(form='되', tag='VV', start=14, len=1),
 Token(form='ᆯ까요', tag='EC', start=15, len=2),
 Token(form='ㅋㅋㅋ', tag='SW', start=17, len=2),
 Token(form='?', tag='SF', start=19, len=1)]

# Stopwords 클래스를 바로 적용하여 불용어를 걸러낼 수 있습니다.
>>> from kiwipiepy.utils import Stopwords
>>> stopwords = Stopwords()
>>> kiwi.tokenize("분석 결과에서 불용어만 제외하고 출력할 수도 있다.", stopwords=stopwords)
[Token(form='분석', tag='NNG', start=0, len=2),
 Token(form='결과', tag='NNG', start=3, len=2),
 Token(form='불', tag='XPN', start=8, len=1),
 Token(form='용어', tag='NNG', start=9, len=2),
 Token(form='제외', tag='NNG', start=13, len=2),
 Token(form='출력', tag='NNG', start=18, len=2)]

# pretokenized 값을 지정해 특정 구간의 분석 결과를 직접 설정할 수 있습니다.
>>> text = "드디어패트와 매트가 2017년에 국내 개봉했다."
>>> kiwi.tokenize(text, pretokenized=[
        (3, 9), # 시작지점과 끝지점만 지정
        (11, 16, 'NNG'), #  시작지점과 끝지점, 품사 태그를 지정
    ])
[Token(form='드디어', tag='MAG', start=0, len=3), 
 Token(form='패트와 매트', tag='NNP', start=3, len=6), 
 Token(form='가', tag='JKS', start=9, len=1), 
 Token(form='2017년', tag='NNG', start=11, len=5), 
 Token(form='에', tag='JKB', start=16, len=1), 
 Token(form='국내', tag='NNG', start=18, len=2), 
 Token(form='개봉', tag='NNG', start=21, len=2), 
 Token(form='하', tag='XSV', start=23, len=1), 
 Token(form='었', tag='EP', start=23, len=1), 
 Token(form='다', tag='EF', start=24, len=1), 
 Token(form='.', tag='SF', start=25, len=1)]
# 시작지점과 끝지점만 지정한 경우 해당 구간은 한 덩어리로 묶여서 분석되며, 
#  그때의 품사태그는 모델이 알아서 선택합니다.
# 시작지점, 끝지점에 품사 태그까지 지정한 경우, 해당 구간은 반드시 그 품사태그로 분석됩니다.

# 각 구간의 분석 결과를 PretokenizedToken를 이용해 더 구체적으로 명시하는 것도 가능합니다.
>>> res = kiwi.tokenize(text, pretokenized=[
        (3, 5, PretokenizedToken('페트', 'NNB', 0, 2)),
        (21, 24, [PretokenizedToken('개봉하', 'VV', 0, 3), PretokenizedToken('었', 'EP', 2, 3)])
    ])
[Token(form='드디어', tag='MAG', start=0, len=3), 
 Token(form='페트', tag='NNB', start=3, len=2), 
 Token(form='와', tag='JC', start=5, len=1), 
 Token(form='매트', tag='NNG', start=7, len=2), 
 Token(form='가', tag='JKS', start=9, len=1), 
 Token(form='2017', tag='SN', start=11, len=4), 
 Token(form='년', tag='NNB', start=15, len=1), 
 Token(form='에', tag='JKB', start=16, len=1), 
 Token(form='국내', tag='NNG', start=18, len=2), 
 Token(form='개봉하', tag='VV', start=21, len=3), 
 Token(form='었', tag='EP', start=23, len=1), 
 Token(form='다', tag='EF', start=24, len=1), 
 Token(form='.', tag='SF', start=25, len=1)]
Expand source code
    def tokenize(self, 
        text:Union[str, Iterable[str]], 
        match_options:int = Match.ALL,
        normalize_coda:bool = False,
        z_coda:bool = True,
        split_complex:bool = False,
        split_sents:bool = False,
        stopwords:Optional[Stopwords] = None,
        echo:bool = False,
        blocklist:Optional[Union[Iterable[str], MorphemeSet]] = None,
        pretokenized:Optional[Union[Callable[[str], PretokenizedTokenList], PretokenizedTokenList]] = None,
    ) -> Union[List[Token], Iterable[List[Token]], List[List[Token]], Iterable[List[List[Token]]]]:
        '''.. versionadded:: 0.10.2

`analyze`와는 다르게 형태소 분석결과만 간단하게 반환합니다.

Parameters
----------
text: Union[str, Iterable[str]]
    분석할 문자열입니다. 
    이 인자를 단일 str로 줄 경우, 싱글스레드에서 처리하며
    str의 Iterable로 줄 경우, 멀티스레드로 분배하여 처리합니다.
match_options: kiwipiepy.const.Match
    추출한 특수 문자열 패턴을 지정합니다. `kiwipiepy.const.Match`의 조합으로 설정할 수 있습니다.
normalize_coda: bool
    True인 경우 '먹었엌ㅋㅋ'처럼 받침이 덧붙어서 분석에 실패하는 경우, 받침을 분리하여 정규화합니다.
z_coda: bool

    .. versionadded:: 0.15.0

    기본값은 True로, True인 경우 '먹었어욥' => `먹었어요 + ㅂ`, '우리집에성' => `우리집에서 + ㅇ`과 같이 
    조사 및 어미에 덧붙는 받침을 'z_coda'라는 태그로 분리합니다. 
    False로 설정 시 덧붙는 받침 분리를 수행하지 않는 대신 분석 속도가 향상됩니다.
split_complex: bool

    .. versionadded:: 0.15.0

    True인 경우 둘 이상의 형태소로 더 잘게 분할될 수 있는 경우 형태소를 최대한 분할합니다. 
    예를 들어 '고마움을 전하다'의 경우 split_complex=False인 경우 `고마움/NNG 을/JKO 전하/VV 다/EF`와 같이 분석되지만,
    split_complex=True인 경우 `고맙/VA-I 음/ETN 을/JKO 전하/VV 다/EF`처럼 `고마움/NNG`이 더 잘게 분석됩니다.
split_sents: bool
    .. versionadded:: 0.10.3

    True인 경우 형태소 리스트를 문장별로 묶어서 반환합니다. 자세한 내용은 아래의 Returns 항목을 참조하세요.
stopwords: Stopwords
    .. versionadded:: 0.10.3

    이 인자로 None이 아닌 `kiwipiepy.utils.Stopwords` 객체를 줄 경우, 형태소 분석 결과 중 그 객체에 포함되는 불용어를 제외한 나머지 결과만을 반환합니다.
echo: bool
    .. versionadded:: 0.11.2

    이 값이 True이고 `text`를 str의 Iterable로 준 경우, 분석 결과뿐만 아니라 원본 입력을 함께 반환합니다. `text`가 단일 str인 경우 이 인자는 무시됩니다.
blocklist: Union[MorphemeSet, Iterable[str]]

    .. versionadded:: 0.15.0

    분석 시 후보로 나타나는 걸 금지할 형태소 목록을 지정합니다. 
    예를 들어, blocklist=['고마움']으로 지정하는 경우, 분석 결과에서 '고마움'이라는 형태소가 등장하는 것을 막아
    split_complex의 예시에서처럼 '고마움을 전하다'가 `고맙/VA-I 음/ETN 을/JKO 전하/VV 다/EF`처럼 분석되도록 강요할 수 있습니다.
    blocklist는 `MorphemeSet` 혹은 `set`으로 지정할 수 있으며, 
    동일한 blocklist가 반복적으로 사용되는 경우 사전에 `MorphemeSet`을 만들고 이를 재사용하는게 효율적입니다.
pretokenized: Union[Callable[[str], PretokenizedTokenList], PretokenizedTokenList]

    .. versionadded:: 0.16.0

    형태소 분석에 앞서 텍스트 내 특정 구간의 형태소 분석 결과를 미리 정의합니다. 이 값에 의해 정의된 텍스트 구간은 항상 해당 방법으로만 토큰화됩니다.
    이 값은 str을 입력 받아 `PretokenizedTokenList`를 반환하는 `Callable`로 주어지거나, `PretokenizedTokenList` 값 단독으로 주어질 수 있습니다.
    `text`가 `Iterable[str]`인 경우 `pretokenized`는 None 혹은 `Callable`로 주어져야 합니다. 자세한 것은 아래 Notes의 예시를 참조하십시오.
Returns
-------
result: List[Token]
    `split_sents=False`일때 text를 str으로 준 경우.
    `Token`의 리스트를 반환합니다.

results: Iterable[List[Token]]
    `split_sents=False`일때 text를 Iterable[str]으로 준 경우.
    반환값은 `result`의 iterator로 주어집니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.

results_with_echo: Iterable[Tuple[List[Token], str]]
    `split_sents=False`이고 `echo=True`일때 text를 Iterable[str]으로 준 경우.
    반환값은 (`result`의 iterator, `raw_input`)으로 주어집니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.

result_by_sent: List[List[Token]]
    `split_sents=True`일때 text를 str으로 준 경우.
    형태소 분석 결과가 문장별로 묶여서 반환됩니다.
    즉, 전체 문장이 n개라고 할 때, `result_by_sent[0] ~ result_by_sent[n-1]`에는 각 문장별 분석 결과가 들어갑니다.

results_by_sent: Iterable[List[List[Token]]]
    `split_sents=True`일때 text를 Iterable[str]으로 준 경우.
    반환값은 `result_by_sent`의 iterator로 주어집니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.

results_by_sent_with_echo: Iterable[Tuple[List[List[Token]], str]]
    `split_sents=True`이고 `echo=True`일때 text를 Iterable[str]으로 준 경우.
    반환값은 (`result_by_sent`의 iterator, `raw_input`)으로 주어집니다. iterator가 차례로 반환하는 분석결과 값은 입력으로 준 text의 순서와 동일합니다.

Notes
-----

```python
>>> kiwi.tokenize("안녕하세요 형태소 분석기 키위입니다.")
[Token(form='안녕', tag='NNG', start=0, len=2),
 Token(form='하', tag='XSA', start=2, len=1),
 Token(form='시', tag='EP', start=4, len=1),
 Token(form='어요', tag='EC', start=3, len=2),
 Token(form='형태소', tag='NNG', start=6, len=3),
 Token(form='분석', tag='NNG', start=10, len=2),
 Token(form='기', tag='NNG', start=12, len=1),
 Token(form='키위', tag='NNG', start=14, len=2),
 Token(form='이', tag='VCP', start=16, len=1),
 Token(form='ᆸ니다', tag='EF', start=17, len=2),
 Token(form='.', tag='SF', start=19, len=1)]

# normalize_coda 옵션을 사용하면 
# 덧붙은 받침 때문에 분석이 깨지는 경우를 방지할 수 있습니다.
>>> kiwi.tokenize("ㅋㅋㅋ 이런 것도 분석이 될까욬ㅋㅋ?", normalize_coda=True)
[Token(form='ㅋㅋㅋ', tag='SW', start=0, len=3),
 Token(form='이런', tag='MM', start=4, len=2),
 Token(form='것', tag='NNB', start=7, len=1),
 Token(form='도', tag='JX', start=8, len=1),
 Token(form='분석', tag='NNG', start=10, len=2),
 Token(form='이', tag='JKS', start=12, len=1),
 Token(form='되', tag='VV', start=14, len=1),
 Token(form='ᆯ까요', tag='EC', start=15, len=2),
 Token(form='ㅋㅋㅋ', tag='SW', start=17, len=2),
 Token(form='?', tag='SF', start=19, len=1)]

# Stopwords 클래스를 바로 적용하여 불용어를 걸러낼 수 있습니다.
>>> from kiwipiepy.utils import Stopwords
>>> stopwords = Stopwords()
>>> kiwi.tokenize("분석 결과에서 불용어만 제외하고 출력할 수도 있다.", stopwords=stopwords)
[Token(form='분석', tag='NNG', start=0, len=2),
 Token(form='결과', tag='NNG', start=3, len=2),
 Token(form='불', tag='XPN', start=8, len=1),
 Token(form='용어', tag='NNG', start=9, len=2),
 Token(form='제외', tag='NNG', start=13, len=2),
 Token(form='출력', tag='NNG', start=18, len=2)]

# pretokenized 값을 지정해 특정 구간의 분석 결과를 직접 설정할 수 있습니다.
>>> text = "드디어패트와 매트가 2017년에 국내 개봉했다."
>>> kiwi.tokenize(text, pretokenized=[
        (3, 9), # 시작지점과 끝지점만 지정
        (11, 16, 'NNG'), #  시작지점과 끝지점, 품사 태그를 지정
    ])
[Token(form='드디어', tag='MAG', start=0, len=3), 
 Token(form='패트와 매트', tag='NNP', start=3, len=6), 
 Token(form='가', tag='JKS', start=9, len=1), 
 Token(form='2017년', tag='NNG', start=11, len=5), 
 Token(form='에', tag='JKB', start=16, len=1), 
 Token(form='국내', tag='NNG', start=18, len=2), 
 Token(form='개봉', tag='NNG', start=21, len=2), 
 Token(form='하', tag='XSV', start=23, len=1), 
 Token(form='었', tag='EP', start=23, len=1), 
 Token(form='다', tag='EF', start=24, len=1), 
 Token(form='.', tag='SF', start=25, len=1)]
# 시작지점과 끝지점만 지정한 경우 해당 구간은 한 덩어리로 묶여서 분석되며, 
#  그때의 품사태그는 모델이 알아서 선택합니다.
# 시작지점, 끝지점에 품사 태그까지 지정한 경우, 해당 구간은 반드시 그 품사태그로 분석됩니다.

# 각 구간의 분석 결과를 PretokenizedToken를 이용해 더 구체적으로 명시하는 것도 가능합니다.
>>> res = kiwi.tokenize(text, pretokenized=[
        (3, 5, PretokenizedToken('페트', 'NNB', 0, 2)),
        (21, 24, [PretokenizedToken('개봉하', 'VV', 0, 3), PretokenizedToken('었', 'EP', 2, 3)])
    ])
[Token(form='드디어', tag='MAG', start=0, len=3), 
 Token(form='페트', tag='NNB', start=3, len=2), 
 Token(form='와', tag='JC', start=5, len=1), 
 Token(form='매트', tag='NNG', start=7, len=2), 
 Token(form='가', tag='JKS', start=9, len=1), 
 Token(form='2017', tag='SN', start=11, len=4), 
 Token(form='년', tag='NNB', start=15, len=1), 
 Token(form='에', tag='JKB', start=16, len=1), 
 Token(form='국내', tag='NNG', start=18, len=2), 
 Token(form='개봉하', tag='VV', start=21, len=3), 
 Token(form='었', tag='EP', start=23, len=1), 
 Token(form='다', tag='EF', start=24, len=1), 
 Token(form='.', tag='SF', start=25, len=1)]
```
        '''
        return self._tokenize(text, match_options, normalize_coda, z_coda, split_complex, split_sents, stopwords, echo, 
                              blocklist=blocklist, 
                              pretokenized=pretokenized
        )
class MorphemeSet (kiwi, morphs: Iterable[Union[str, Tuple[str, POSTag]]])

Added in version: 0.15.0

형태소 집합을 정의합니다. 정의된 형태소 집합은 Kiwi.analyze(), Kiwi.tokenize(), Kiwi.split_into_sents()에서 blocklist 인자로 사용될 수 있습니다.

Parameters

kiwi : Kiwi
형태소 집합을 정의할 Kiwi의 인스턴스입니다.
morphs : Iterable[Union[str, Tuple[str, POSTag]]]
집합에 포함될 형태소의 목록입니다. 형태소는 단일 str이나 tuple로 표기될 수 있습니다.

Notes

형태소는 다음과 같이 크게 3가지 방법으로 표현될 수 있습니다.

morphset = MorphemeSet([
    '고마움' # 형태만을 사용해 표현. 형태가 '고마움'인 모든 형태소가 이 집합에 포함됨
    '고마움/NNG' # 형태와 품사 태그를 이용해 표현. 형태가 '고마움'인 일반 명사만 이 집합에 포함됨
    ('고마움', 'NNG') # tuple로 분리해서 표현하는 것도 가능
])

Ancestors

  • kiwipiepy._MorphemeSet
class PretokenizedToken (form, tag, start, end)

미리 분석된 형태소를 나타내는 데 사용하는 namedtuple입니다.

Ancestors

  • builtins.tuple

Instance variables

var end : int

주어진 구간에서 형태소가 끝나는 시작 위치 (문자 단위)

var form : str

형태소의 형태

var start : int

주어진 구간에서 형태소가 시작하는 시작 위치 (문자 단위)

var tag : POSTag

형태소의 품사 태그

class Sentence (text, start, end, tokens, subs)

문장 분할 결과를 담기 위한 namedtuple입니다.

Ancestors

  • builtins.tuple

Instance variables

var end : int

전체 텍스트 내에서 분할된 문장이 끝나는 위치 (문자 단위)

var start : int

전체 텍스트 내에서 분할된 문장이 시작하는 위치 (문자 단위)

var subs : Optional[List[Sentence]]

Added in version: 0.14.0

현 문장 내에 포함된 안긴 문장의 목록

var text : str

분할된 문장의 텍스트

var tokens : Optional[List[Token]]

분할된 문장의 형태소 분석 결과

class Token (*args, **kwargs)

Instance variables

var base_form

Return an attribute of instance, which is of type owner.

var base_id

Return an attribute of instance, which is of type owner.

var end

Return an attribute of instance, which is of type owner.

var form

Return an attribute of instance, which is of type owner.

var form_tag

Return an attribute of instance, which is of type owner.

var id

Return an attribute of instance, which is of type owner.

var lemma

Return an attribute of instance, which is of type owner.

var len

Return an attribute of instance, which is of type owner.

var line_number

Return an attribute of instance, which is of type owner.

var paired_token

Return an attribute of instance, which is of type owner.

var raw_form

Return an attribute of instance, which is of type owner.

var regularity

Return an attribute of instance, which is of type owner.

var score

Return an attribute of instance, which is of type owner.

var sent_position

Return an attribute of instance, which is of type owner.

var span

Return an attribute of instance, which is of type owner.

var start

Return an attribute of instance, which is of type owner.

var sub_sent_position

Return an attribute of instance, which is of type owner.

var tag

Return an attribute of instance, which is of type owner.

var tagged_form

Return an attribute of instance, which is of type owner.

var typo_cost

Return an attribute of instance, which is of type owner.

var user_value

Return an attribute of instance, which is of type owner.

var word_position

Return an attribute of instance, which is of type owner.

class TypoDefinition (orig: List[str], error: List[str], cost: float, condition: Optional[str] = None)

Added in version: 0.13.0

오타 생성 규칙을 정의하는 dataclass

Parameters

orig : List[str]
원본 문자열
error : List[str]
교체될 오타의 문자열
cost : float
교체 비용
condition : str
오타 교체가 가능한 환경 조건. None, 'any'(아무 글자 뒤), 'vowel'(모음 뒤), 'applosive'(불파음 뒤) 중 하나. 생략 시 기본값은 None입니다.

Notes

origerror는 완전한 음절 혹은 모음이나 자음을 포함할 수 있습니다. 자음의 경우 종성은 '\'로 escape해주어야 합니다.

TypoDefinition(['개'], ['게'], 1.0) # '개'를 '게'로 교체
TypoDefinition(['ㅐ'], ['ㅔ'], 1.0) # 모든 'ㅐ'를 'ㅒ'로 교체
TypoDefinition(['ㄲ'], ['ㄱ'], 1.0) # 모든 초성 'ㄲ'을 초성 'ㄱ'으로 교체
TypoDefinition(['ㄳ'], ['ㄱ'], 1.0) # 'ㄳ'에 해당하는 초성은 없으므로 ValueError 발생
TypoDefinition(['\ㄳ'], ['\ㄱ'], 1.0) # 모든 종성 'ㄳ'을 종성 'ㄱ'으로 교체

Class variables

var condition : Optional[str]
var cost : float
var error : List[str]
var orig : List[str]
class TypoTransformer (defs: List[TypoDefinition])

Added in version: 0.13.0

오타 교정 기능에 사용되는 오타 생성기를 정의합니다.

Parameters

defs : List[TypoDefinition]
오타 생성 규칙을 정의하는 TypoDefinition의 List입니다.

Notes

이 클래스의 인스턴스를 Kiwi 생성시의 typos 인자로 주면 Kiwi의 오타 교정 기능이 활성화됩니다.

>>> from kiwipiepy import Kiwi, TypoTransformer, TypoDefinition
>>> typos = TypoTransformer([
    TypoDefinition(["ㅐ", "ㅔ"], ["ㅐ", "ㅔ"], 1.), # ㅐ 혹은 ㅖ를 ㅐ 혹은 ㅖ로 교체하여 오타를 생성. 생성 비용은 1
    TypoDefinition(["ㅔ"], ["ㅖ"], 2.), # ㅔ를 ㅖ로 교체하여 오타를 생성. 생성 비용은 2
])
>>> typos.generate('과제', 1.) # 생성 비용이 1.0이하인 오타들을 생성
[('과제', 0.0), ('과재', 1.0)]
>>> typos.generate('과제', 2.) # 생성 비용이 2.0이하인 오타들을 생성
[('과제', 0.0), ('과재', 1.0), ('과졔', 2.0)]

>>> kiwi = Kiwi(typos=typos, typo_cost_threshold=2.) # typos에 정의된 오타들을 교정 후보로 삼는 Kiwi 생성.
>>> kiwi.tokenize('과재를 했다') 
[Token(form='과제', tag='NNG', start=0, len=2), 
 Token(form='를', tag='JKO', start=2, len=1), 
 Token(form='하', tag='VV', start=4, len=1), 
 Token(form='었', tag='EP', start=4, len=1), 
 Token(form='다', tag='EF', start=5, len=1)]

Ancestors

  • kiwipiepy._TypoTransformer

Instance variables

var defs

현재 오타 생성기의 정의자 목록

Expand source code
@property
def defs(self):
    '''현재 오타 생성기의 정의자 목록'''
    return self._defs

Methods

def generate(self, text: str, cost_threshold: float = 2.5) ‑> List[Tuple[str, float]]

입력 텍스트로부터 오타를 생성합니다.

Parameters

text : str
원본 텍스트
cost_threshold : float
생성 가능한 오타의 최대 비용

Returns

errors : List[Tuple[str, float]]
생성된 오타와 그 생성 비용의 List
Expand source code
    def generate(self, text:str, cost_threshold:float = 2.5) -> List[Tuple[str, float]]:
        '''입력 텍스트로부터 오타를 생성합니다.

Parameters
----------
text: str
    원본 텍스트
cost_threshold: float
    생성 가능한 오타의 최대 비용

Returns
-------
errors: List[Tuple[str, float]]
    생성된 오타와 그 생성 비용의 List
        '''
        return super().generate(text, cost_threshold)