madipy — madi (마디) 한국어 형태소 분석기
순수 Rust 로 만든 한국어 형태소 분석기 madi(마디) 의 Python 패키지입니다. 국립국어원 모두의 말뭉치 형태 분석 지침을 따르는 세종 품사 체계로 분석하고, 형태소 분석을 이용한 문장 분리도 합니다. 품사는 기본으로 한글 축약(일반명·동사·주격조 …)으로 보여 주고, tags='code' 를 주면 NNG·VV·JKS 같은 코드로 보여 줍니다.
English. A Korean morphological analyzer written in pure Rust, with Python bindings. It follows the NIKL "Modu" corpus tagging guidelines (Sejong tag set) and also splits sentences using the morphological analysis. Part-of-speech labels are shown as short Korean names by default; pass tags='code' for the usual codes (NNG, VV, JKS …). Install with pip install madipy, import as madi. Models (about 87 MB) are downloaded automatically on first use and cached. Token fields are listed in §3.2 (attribute names are in English).
- 소개 페이지: https://p14jeffwest.github.io/madi-release/
- 모델·이용 조건: https://github.com/p14jeffwest/madi-release
- Rust: https://crates.io/crates/madi · https://docs.rs/madi
차례
- 개요 — 설치부터 첫 분석까지
- 설치와 모델 파일
- 형태소 분리 방법
- 문장 분리 방법
- 여러 분석 후보 보기 —
analyze - madi 가 사용하는 모드
- 사용자 사전
- 불용어 · 구간 지정
- 여러 문장 · 큰 파일
- 명령줄
- Kiwi 에서 옮겨 오기
- 자주 묻는 질문
- 판본 · 이용 조건 · 인용
- 성능 요약
1. 개요 — 설치부터 첫 분석까지
설치하고, 분석기를 하나 만들고, 문장을 넣으면 됩니다. 이 세 줄이 전부입니다.
pip install madipy
import madi
m = madi.Analyzer() # 처음 한 번만 모델 파일(약 87 MB)을 받아 둡니다
m.pos('아버지가 방에 들어가신다.')
# [('아버지', '일반명'), ('가', '주격조'), ('방', '일반명'), ('에', '부사조'),
# ('들어가', '동사'), ('시', '선어말'), ('ㄴ다', '종결어'), ('.', '마침')]
m.pos('아버지가 방에 들어가신다.', tags='code') # 품사를 코드로
# [('아버지', 'NNG'), ('가', 'JKS'), ('방', 'NNG'), ('에', 'JKB'),
# ('들어가', 'VV'), ('시', 'EP'), ('ㄴ다', 'EF'), ('.', 'SF')]
결과를 읽는 법
- 띄어쓰기로 나뉜 덩이(어절)를 다시 형태소 단위로 나눕니다. "들어가신다" = 들어가(동사) + 시(선어말 어미) + ㄴ다(종결 어미).
- 형태는 사전에 올라 있는 기본 꼴로 나옵니다. 활용하면서 모양이 바뀐 말은 원래 꼴로 되돌립니다(들어 → 듣, 무서운 → 무섭 + ㄴ).
- 품사 이름의 뜻은 §3.5 품사표에 있습니다.
Analyzer 는 한 번 만들어 계속 쓰는 것이 좋습니다. 만들 때 모델을 메모리에 올리므로(1초 안팎) 문장마다 새로 만들면 느립니다.
2. 설치와 모델 파일
2.1 설치
- Windows · macOS(Intel·Apple Silicon) · Linux(x86_64·aarch64), Python 3.9 이상.
- 설치 이름은
madipy, 코드에서는import madi입니다.
pip install madipy
2.2 모델 파일은 자동으로 받습니다 — 따로 할 일이 없습니다
madi 가 분석에 쓰는 사전과 언어 모델은 크기 때문에 패키지에 들어 있지 않습니다. 대신 이렇게 동작합니다.
- 처음
madi.Analyzer()를 만들 때 모델 파일을 인터넷에서 받아 사용자 캐시 폴더에 풀어 둡니다(약 87 MB 내려받기, 풀면 240 MB, 수십 초). - 그다음부터
madi.Analyzer()는 받아 둔 파일을 그대로 씁니다. 다시 받지 않습니다. - 정밀 모드(
precise=True, §6)를 처음 쓸 때 교사 모델(+27 MB)을 한 번 더 받습니다. 이것도 한 번뿐입니다.
보통의 사용자는 여기까지 알면 됩니다. 아래 2.3·2.4 는 특별한 환경에서만 필요합니다.
2.3 미리 받아 두거나 확인하고 싶을 때 (선택)
프로그램을 처음 돌릴 때 모델을 받느라 기다리는 것이 싫거나, 배포·CI 환경에서 미리 준비해 두고 싶을 때 씁니다. 하지 않아도 됩니다.
python -m madi download # 기본 모델 미리 받기
python -m madi download --precise # 정밀 모드 교사까지
python -m madi verify # 받아 둔 파일이 온전한지(sha256) 확인
python -m madi info # 모델이 어디에 있고 무엇을 받았는지 보기
모델이 놓이는 곳은 Windows %LOCALAPPDATA%\madi\models\models-kword5, 그 밖에서는 ~/.cache/madi/models/models-kword5 입니다. 다른 폴더에 두고 싶으면 환경 변수 MADI_MODEL_DIR 을 쓰거나 madi.Analyzer(model_dir='폴더') 로 지정합니다.
2.4 인터넷이 막힌 곳에서 쓸 때 (선택)
분석할 PC 에서 GitHub 에 접속할 수 없을 때만 해당합니다.
- 회사·학교 프록시를 거치는 경우: 표준 환경 변수
HTTPS_PROXY를 설정하면 자동 내려받기가 그대로 됩니다. - 아예 접속이 안 되는 경우: 다른 PC 에서 Release 페이지의
.xz파일 네 개를 받아 한 폴더에 옮긴 뒤, 그 폴더를 가리켜 받게 합니다.
또는set MADI_MODEL_URL=D:\madi-models (Windows; Linux·macOS 는 export) python -m madi download.xz를 풀어 파일 경로를 직접 줍니다:madi.Analyzer('madi.dict', lm='knlm.bin', nlm='model.nlm'). - 자동으로 받는 것을 막고 싶으면
madi.Analyzer(download=False)— 모델이 없으면 받지 않고 오류를 냅니다.
3. 형태소 분리 방법
3.1 세 가지 기본 메서드 — tokenize · pos · morphs
같은 분석을 돌려주는 모양만 다릅니다.
| 메서드 | 돌려주는 것 | 언제 |
|---|---|---|
tokenize(text) |
Token 객체 목록(형태·품사·위치 …) |
위치나 세부 정보가 필요할 때 |
pos(text) |
[(형태, 품사), …] |
품사만 필요할 때 |
morphs(text) |
[형태, …] |
형태소 열만 필요할 때 |
m.tokenize('아버지가 방에 들어가신다.')
# [Token(form='아버지', tag='일반명', start=0, end=3), Token(form='가', tag='주격조', start=3, end=4),
# Token(form='방', tag='일반명', start=5, end=6), Token(form='에', tag='부사조', start=6, end=7),
# Token(form='들어가', tag='동사', start=8, end=11), Token(form='시', tag='선어말', start=11, end=13),
# Token(form='ㄴ다', tag='종결어', start=11, end=13), Token(form='.', tag='마침', start=13, end=14)]
m.pos('아버지가 방에 들어가신다.') # [('아버지', '일반명'), ('가', '주격조'), …]
m.morphs('아버지가 방에 들어가신다.') # ['아버지', '가', '방', '에', '들어가', '시', 'ㄴ다', '.']
여러 줄을 한 번에 주면 줄마다 분석합니다. 이때 위치(start·end)는 입력 전체 안의 글자 위치입니다.
3.2 Token 의 필드
| 필드 | 뜻 | 예 (들어가) |
|---|---|---|
form |
형태(사전 표기) | '들어가' |
tag |
품사 — 분석기에 설정한 표시 방식대로 | '동사' |
tag_code · tag_ko · tag_name |
코드 · 한글 축약 · 정식 이름(설정과 상관없이 늘 있음) | 'VV' · '동사' · '동사' |
start · end · len · span |
입력 안 글자 위치 [start, end), 길이 | 8 · 11 · 3 · (8, 11) |
word_position |
문장 안 어절 번호(0부터) | 2 |
sent_position |
입력 안 문장 번호(0부터) | 0 |
raw_form |
원문 표기 | '들어가' |
lemma |
원형(용언은 어간 + 다) | '들어가다' |
tagged_form |
'형태/코드' |
'들어가/VV' |
oov |
사전에 없는 말로 분석했는가 | False |
Token은 앞 네 칸(form, tag, start, end)로 튜플처럼 풀 수 있습니다:for form, tag, start, end in m.tokenize(s): …- 축약된 활용형은 여러 형태소가 같은 구간을 가리킵니다: "신다" → 시(11–13) + ㄴ다(11–13). 원문을 자르려면 §3.3 의
split_into_forms를 쓰세요. - 품사를 비교하거나 거를 때는 표시 방식을 바꿔도 변하지 않는
tag_code를 쓰는 것이 안전합니다.
3.3 원문을 형태소 경계로 자르기 — split_into_forms
원문 글자를 그대로 두고 경계만 나눕니다. 글자를 바꾸지 않고 자르기만 해야 할 때(형광펜 표시, 검색어 추출 등) 씁니다.
m.split_into_forms('아버지가 방에 들어가신다.')
# [SplitForm(form='아버지', tag='일반명', start=0, end=3), SplitForm(form='가', tag='주격조', start=3, end=4),
# SplitForm(form='방', tag='일반명', start=5, end=6), SplitForm(form='에', tag='부사조', start=6, end=7),
# SplitForm(form='들어가', tag='동사', start=8, end=11), SplitForm(form='신다', tag='선어말+종결어', start=11, end=13),
# SplitForm(form='.', tag='마침', start=13, end=14)]
한 원문 구간에 형태소가 여럿이면 한 조각으로 묶고 품사를 + 로 잇습니다.
3.4 품사 표시 바꾸기
madi.Analyzer(tags='code') # NNG 같은 코드
madi.Analyzer(tags='name') # 정식 이름(일반명사)
m.pos(text, tags='code') # 호출마다 바꾸기 (tokenize·analyze·split_into_sents 도 같음)
madi.tag_code('일반명') # 'NNG'
madi.tag_ko('JKS') # '주격조'
madi.tag_name('ETM') # '관형사형 전성어미'
madi.TAGS # [(코드, 한글 축약, 정식 이름), …] 전체 표
사용자 사전·불용어·pretokenized 에 품사를 적을 때는 코드·한글 축약·정식 이름 어느 것이든 됩니다.
3.5 품사표
| 코드 | 한글 | 이름 | 예 | 코드 | 한글 | 이름 | 예 | |
|---|---|---|---|---|---|---|---|---|
| NNG | 일반명 | 일반명사 | 학교 | JKS | 주격조 | 주격조사 | 가 | |
| NNP | 고유명 | 고유명사 | 서울 | JKC | 보격조 | 보격조사 | 이(되다) | |
| NNB | 의존명 | 의존명사 | 것, 수 | JKG | 관형조 | 관형격조사 | 의 | |
| NR | 수사 | 수사 | 하나 | JKO | 목적조 | 목적격조사 | 를 | |
| NP | 대명사 | 대명사 | 나, 그 | JKB | 부사조 | 부사격조사 | 에, 로 | |
| VV | 동사 | 동사 | 가, 듣 | JKV | 호격조 | 호격조사 | 아 | |
| VA | 형용사 | 형용사 | 무섭 | JKQ | 인용조 | 인용격조사 | 라고 | |
| VX | 보조용 | 보조용언 | (들어) 보 | JX | 보조사 | 보조사 | 는, 도 | |
| VCP | 긍정지 | 긍정지정사 | 이(다) | JC | 접속조 | 접속조사 | 와 | |
| VCN | 부정지 | 부정지정사 | 아니 | EP | 선어말 | 선어말어미 | 시, 았 | |
| MM | 관형사 | 관형사 | 새, 그 | EF | 종결어 | 종결어미 | 다, ㄴ다 | |
| MAG | 일반부 | 일반부사 | 어제 | EC | 연결어 | 연결어미 | 고, 어 | |
| MAJ | 접속부 | 접속부사 | 그리고 | ETN | 명사어 | 명사형 전성어미 | 기, ㅁ | |
| IC | 감탄사 | 감탄사 | 아 | ETM | 관형어 | 관형사형 전성어미 | ㄴ, 는 | |
| XPN | 체접두 | 체언 접두사 | 맨 | SF | 마침 | 마침표·물음표·느낌표 | . ? ! | |
| XSN | 명접미 | 명사 파생 접미사 | 들 | SP | 쉼표 | 쉼표·가운뎃점·콜론·빗금 | , · | |
| XSV | 동접미 | 동사 파생 접미사 | 하(다) | SS | 묶음 | 따옴표·괄호표·줄표 | " ( | |
| XSA | 형접미 | 형용사 파생 접미사 | 스럽 | SE · SO · SW | 줄임 · 붙임 · 기호 | 줄임표 · 붙임표 · 기타 기호 | … - * | |
| XR | 어근 | 어근 | 깨끗 | SL · SH · SN | 외국 · 한자 · 숫자 | 외국어 · 한자 · 숫자 | ABC 漢 3 | |
| NA · NF · NV | 불능 · 명추 · 용추 | 분석불능 · 명사추정 · 용언추정 | UN | 모름 | 미등록어 |
madi.TAGS 에는 세분 관형사(MMD·MMN·MMA)와 URL·이메일 같은 특수 표지까지 전부 들어 있습니다.
4. 문장 분리 방법
글을 문장 단위로 나눕니다. 마침표가 있는 글은 물론, 마침표 없이 이어 쓴 글(메신저·댓글·구어)도 형태소 분석으로 종결 어미를 찾아 끊습니다.
m.split_into_sents('밥 먹었니 나는 먹었어')
# [Sentence(text='밥 먹었니', start=0, end=5, tokens=None), Sentence(text='나는 먹었어', start=6, end=12, tokens=None)]
m.split_into_sents('비가 온다. 우산을 챙겨라', return_tokens=True)[1].tokens
# [Token(form='우산', tag='일반명', start=7, end=9), Token(form='을', tag='목적조', start=9, end=10),
# Token(form='챙기', tag='동사', start=11, end=13), Token(form='어라', tag='종결어', start=13, end=14)]
m.tokenize('비가 온다. 우산을 챙겨라', split_sents=True) # 문장별 [[Token…], [Token…]]
m.split_sentences('밥 먹었니 나는 먹었어') # 문자열 목록만 (0.1 호환)
- 종결 부호 뒤에서 끊고, 부호가 없어도 종결 어미 뒤에서 끊습니다. 괄호·따옴표 안에서는 끊지 않습니다. 줄바꿈은 언제나 경계입니다.
Sentence.start·end는 입력 안의 글자 위치라 원문에서 그 문장을 그대로 잘라 낼 수 있습니다.- 모델 없이 쓰는 규칙 분리기
madi.split_sentences(text)도 있습니다. 종결 부호 + 공백에서만 끊으므로 가볍지만 부호 없는 글은 못 나눕니다:madi.split_sentences('밥 먹었니 나는 먹었어. 너는?')→['밥 먹었니 나는 먹었어.', '너는?'].
5. 여러 분석 후보 보기 — analyze
한 문장은 여러 가지로 분석될 수 있습니다. tokenize 는 그중 가장 좋은 것 하나만 돌려주지만, analyze 는 상위 n 개 후보를 점수와 함께 돌려줍니다. 애매한 문장이 어떻게 갈렸는지 확인하거나, 뒤에서 다른 정보로 후보 가운데 고르거나, 분석이 이상할 때 원인을 볼 때 씁니다.
for tokens, score in m.analyze('감기는 무서운 병이다', top_n=3):
print(' '.join(t.tagged_form for t in tokens), round(score, 2))
# 감기/NNG 는/JX 무섭/VA ㄴ/ETM 병/NNG 이/VCP 다/EF -34.92
# 감기/NNG 는/JX 무섭/VA ㄴ/ETM 병/NNG 이/VCP 다/EC -42.5
# 감기/NNG 는/JX 무섭/VA ㄴ/ETM 병/NNG 이/JKS 다/EF -44.2
- 돌려주는 꼴은
[([Token, …], 점수), …]이고 좋은 것부터입니다(Kiwi 의analyze와 같은 꼴). 후보가top_n보다 적을 수 있습니다. - 점수는 탐색의 로그 확률 합이라 클수록(0 에 가까울수록) 좋습니다. 모드(§6)에 따라 눈금이 다르므로 다른 모드끼리 점수를 비교하지는 마세요.
- 1번 후보는 늘
tokenize의 결과와 같습니다. 정밀 모드에서는 교사가 고른 후보가 1번이고, 점수는 교사가 다시 채점하기 전의 값입니다. - 입력 전체를 한 문장으로 봅니다(문장을 나누지 않습니다).
6. madi 가 사용하는 모드
madi 에는 세 가지 분석 모드가 있습니다. 보통은 기본 모드면 충분합니다. 동사/형용사 구별이나 불규칙 활용처럼 헷갈리는 말이 중요하고 양이 적으면 정밀 모드, 속도와 메모리가 더 중요하면 가벼운 모드를 고릅니다.
| 모드 | 만드는 법 | 무엇이 다른가 | 언제 쓰나 | 속도 (KB/s) | 메모리 (MB) |
|---|---|---|---|---|---|
| 기본 | madi.Analyzer() |
사전 + n-gram 언어 모델 + 신경망 언어 모델 | 대부분의 경우 | 284 | 469 |
| 정밀 | madi.Analyzer(precise=True) |
기본 결과 가운데 애매한 어절을 작은 트랜스포머 교사가 다시 채점 | 모호한 어절이 중요할 때, 양이 적을 때 (약 10배 느림) | 26 | 525 |
| 가벼운 | madi.Analyzer(nlm=False) |
신경망 언어 모델 없이 n-gram 만 | 빠르게·메모리 적게 쓰고 싶을 때(정확도는 조금 낮음) | 398 | 338 |
(노트북 1스레드, 2026-10 측정. 정밀 모드는 교사 모델 +27 MB 를 처음 쓸 때 한 번 받습니다.)
모드와 별도로 출력 방식 옵션이 둘 있습니다.
std_2025=True: 2025년판 형태 분석 지침식 출력 — 사전에 있는 복합 명사 합치기(국회+의원 → 국회의원), 소수·천 단위 숫자를 통째로,X하/VV를 통째로 등.split_complex=True: 사전의 복합어 항목을 구성 형태소로 나눠 냅니다.
7. 사용자 사전
사전에 없는 말(신조어·제품명·전문어)이나 늘 잘못 분석되는 말을 바로잡습니다. 가장 흔한 방법은 파일을 만들어 생성자에 주는 것입니다.
m = madi.Analyzer(user=['내사전.tsv'])
파일 형식(탭 구분, # 뒤는 주석, 품사는 코드·한글 어느 것이든):
케데헌 NNP # 단어 ⇥ 품사 [⇥ 보너스] (기본 보너스 3.0)
먹깨비 고유명 5
달라고 = 달/VX 라고/EC # 표면형 ⇥ = ⇥ 형태/품사 … 기분석 (기본 보너스 6.0)
운주사 운주사/NNG => 운주사/NNP # 표면형 ⇥ 틀린 분석 ⇥ => ⇥ 맞는 분석 (분석 뒤 고치기)
- 단어·기분석 줄은 후보를 더하는 것이라 문맥이 분명히 다른 쪽을 가리키면 질 수 있습니다. 보너스를 올리거나(로그 확률 눈금, 클수록 강함), 반드시 바꿔야 하면
=>고치기 줄을 쓰세요. - 실행 중에 더할 수도 있습니다(다음 분석부터 적용되며, 그때 엔진을 다시 만드므로 몇 초 걸립니다):
m = madi.Analyzer()
m.pos('케데헌을 봤다') # [('케데헌', '고유명'), ('을', '목적조'), ('보', '동사'), …]
m.add_user_word('케데헌', 'NNG', 5)
m.pos('케데헌을 봤다') # [('케데헌', '일반명'), ('을', '목적조'), ('보', '동사'), …]
m.add_pre_analyzed_word('달라고', [('달', 'VX'), ('라고', 'EC')], score=30)
m.load_user_dictionary('내사전.tsv') # 읽은 항목 수를 돌려준다
m.version # '0.2.1+decdb.r3p.f11.k838c.n15e6.s-.u401f' — 사용자 사전이 붙으면 .u 가 생긴다
- 흔한 실수: 품사를 틀리게 적음(오류가 납니다 —
madi.TAGS확인), 용언을 활용형이나 '-다' 꼴로 넣음(용언은 어간만:달리다·달려가 아니라달리 ⇥ VV), 보너스가 너무 작음.
8. 불용어 · 구간 지정
8.1 불용어 — madi.utils.Stopwords
조사·어미·기호처럼 의미 분석에 필요 없는 형태소를 결과에서 뺍니다.
from madi.utils import Stopwords
sw = Stopwords() # 기본 목록
m.tokenize('나는 그것을 먹을 수 있다.', stopwords=sw)
# [Token(form='나', tag='대명사', start=0, end=1), Token(form='먹', tag='동사', start=7, end=8)]
sw.add('나/대명사'); sw.add(('수', 'NNB')); sw.add_tag('MAG') # 낱말·품사 통째 더하기
sw.remove('것/NNB'); sw.remove_tag('XSN')
list(sw.filter(tokens)); ('것', 'NNB') in sw
sw.save('sw.txt'); Stopwords('sw.txt', default=False) # 파일: '형태/품사' 또는 '@품사' 한 줄씩
기본 목록은 품사 통째(조사·어미·접사·지정사·기호)와 뜻이 약한 흔한 낱말(것/NNB·수/NNB·등/NNB, 하/VV·있/VA·되/VV, 보조 용언, 이·그·저 …)입니다. 전체는 madi.utils.DEFAULT_TAGS·DEFAULT_WORDS 에 있습니다.
8.2 구간 지정 — pretokenized
입력의 특정 글자 구간을 내가 정한 형태소로 분석하게 합니다(Kiwi 의 pretokenized 와 같은 쓰임). 이미 알고 있는 고유 명사 구간을 고정하거나, 분석을 일부러 다른 쪽으로 보내 볼 때 씁니다.
m.tokenize('감기는 무서운 병이다', pretokenized=[(0, 3, ('감', 'VV'))], tags='code')
# [Token(form='감', tag='VV', start=0, end=1), Token(form='기', tag='ETN', start=1, end=2), Token(form='는', tag='JX', …), …]
toks, ok = m.analyze_pretokenized(text, [(0, 2, 'NNG'), (5, 8)]) # ok = 구간마다 지켰는가
구간은 (시작, 끝)(그 원문 그대로 한 형태소) · (시작, 끝, 품사) · (시작, 끝, (형태, 품사)). 품사 코드는 앞부분만 맞아도 됩니다('NN' → NNG·NNP·NNB). 사전에 그런 후보가 없으면 지키지 못할 수 있고, 그때 ok 가 False 입니다.
9. 여러 문장 · 큰 파일
m = madi.Analyzer(num_workers=4)
results = m.tokenize(['첫 문장', '둘째 문장', …]) # 입력마다 [Token, …] — 4 스레드로
with open('big.txt', encoding='utf-8') as f:
lines = [l.rstrip('\n') for l in f]
for toks in m.tokenize(lines):
...
- 분석은 문장마다 독립이라 스레드 수와 관계없이 결과가 같습니다. 분석 중에는 GIL 을 놓으므로 파이썬 스레드에서 한
Analyzer를 함께 써도 됩니다. - 메모리는 모델(§6 표)이 대부분이고 입력 크기에 따라 거의 늘지 않습니다. 아주 큰 파일은 줄 묶음(수천 줄)씩 넘기세요.
tokenize_batch(texts, threads)는 0.1 의 이름을 그대로 둔 것입니다.
10. 명령줄
설치하면 python -m madi 로 바로 써 볼 수 있습니다.
python -m madi "아버지가 방에 들어가신다." # 아버지/일반명 가/주격조 …
python -m madi --tags code "아버지가 방에 들어가신다."
python -m madi --split < 글.txt # 한 줄에 한 문장
python -m madi --precise --threads 4 < 글.txt
python -m madi download [--precise] [--dir 폴더] # §2.3
python -m madi verify | info | version
11. Kiwi 에서 옮겨 오기
| Kiwi (kiwipiepy) | madi | 비고 |
|---|---|---|
Kiwi() |
madi.Analyzer() |
모델은 처음 쓸 때 자동으로 받음 |
tokenize(text) · tokenize(texts) |
같음 | Token 필드 이름도 같음(§3.2). 목록 입력은 목록을 돌려줌 |
tokenize(…, split_sents=True, stopwords=…) |
같음 | madi.utils.Stopwords |
analyze(text, top_n) |
같음 | [(tokens, score)] |
split_into_sents(text, return_tokens) |
같음 | Sentence(text, start, end, tokens) |
split_into_forms(text) |
같음 | |
add_user_word · add_pre_analyzed_word · load_user_dictionary |
같음 | 파일 형식은 §7 |
pretokenized= |
같음 | §8.2 |
num_workers |
같음 | |
split_complex=True |
생성자 인자 | |
| 품사 표시 | 기본이 한글 축약 | Kiwi 용 코드가 t.tag == 'NNG' 를 쓰면 Analyzer(tags='code') 로 만들거나 t.tag_code 로 바꾸세요 |
VA-I 같은 불규칙 표시 |
없음 | 품사는 VA, 형태는 원래 어간(무섭) |
join(morphs) · glue · extract_words · URL/이메일 통째(match_options) · blocklist |
0.3 계획 | |
space · typos |
넣지 않음 | 띄어쓰기·오타 교정은 madi 맞춤법 검사기(별도 배포)의 기능 |
| 형태소 유사도 · 다음 형태소 예측 · 방언 | 넣지 않음 | Kiwi 고유 모델이 필요한 기능 |
분석 관행은 모두의 말뭉치 지침을 따르므로 결과가 Kiwi 와 다른 곳이 있습니다(복합 명사 단위, 숫자, 문장 분리 등). 없는 메서드를 부르면 대신 쓸 수 있는 것을 오류 문구로 알려 줍니다.
12. 자주 묻는 질문
- 모델을 못 받아요. 회사·학교 망이면
HTTPS_PROXY를 설정하거나 §2.4 의 방법을 쓰세요.python -m madi info가 어디서 받아 어디에 두는지 보여 줍니다. - 처음이 느려요. 첫 실행은 모델을 받고 푸는 시간(수십 초)입니다. 그다음부터
Analyzer()만들기는 1초 안팎입니다. 한 번 만든Analyzer를 계속 쓰세요. - 결과가 Kiwi 와 달라요. 대부분 관행 차이(국회의원 vs 국회/의원, 숫자 나누기 등)입니다. madi 는 모두의 말뭉치 지침을 따릅니다. 2025년판 지침이 필요하면
std_2025=True. - 품사가 한글로 나와요. 0.2.0 부터 기본입니다.
tags='code'로 바꾸세요. - 메모리가 많이 들어요.
nlm=False(가벼운 모드)로 약 130 MB 줄어듭니다. - 같은 결과인지 확인하고 싶어요.
m.version이 같으면 사전·모델·설정이 같습니다.
13. 판본 · 이용 조건 · 인용
- 판본 문자열
m.version:0.2.1+decdb.r3p.f11.k838c.n15e6.s-= 패키지 판 + 사전·점수 가중·탐색·LM·신경망 해시. 정밀 모드는.p…, 사용자 사전은.u…가 붙습니다. - 패키지(코드): MIT 또는 Apache-2.0.
- 모델·사전 파일은 CC BY-SA 2.0 KR. 국립국어원 모두의 말뭉치(형태 분석 말뭉치 2018~2020, 형태 분석 말뭉치 2025, 어휘 의미 분석 말뭉치 2020)와 우리말샘을 활용하였음(국립국어원 공개 승인 2026-10-17). 말뭉치 원문을 담거나 복원할 수 없는 통계·가중치임. 신문 기사 원문으로 자기 라벨 학습.
- 사전은 mecab-ko-dic(Apache-2.0) 기반. 모델 이용 조건 전문·학습 입력 목록: https://github.com/p14jeffwest/madi-release (
LICENSE-MODELS.txt,MODEL-PROVENANCE.md). - 인용: madi(마디) 한국어 형태소 분석기, 박희진, https://p14jeffwest.github.io/madi-release/ (논문 준비 중).
Code: MIT OR Apache-2.0. Downloaded model files: CC BY-SA 2.0 KR (see the release repository).
14. 성능 요약
같은 잣대(세종 태그 사상, 관행 차이 정규화)로 다른 분석기와 비교했습니다. 차이는 Kiwi CoNg(kiwipiepy 0.24.0) 대비, 괄호는 95% 구간입니다.
| madi 기본 | madi 정밀 | Kiwi CoNg | |
|---|---|---|---|
| 모두의 말뭉치 형태 분석 2025 문어(학습과 독립, 6,953문장), 형태소 F1 | 0.9774 (+0.32p [+0.24, +0.39]) | 0.9784 (+0.42p) | 0.9742 |
| 같은 셋 구어(16,439문장) | 0.9640 (+0.53p [+0.44, +0.64]) | 0.9656 (+0.69p) | 0.9586 |
| 신문 1990~2025 평가셋(420문장, 손 교정), 중립 F1 | 0.9772 (+0.35p, 유의하지 않음) | 0.9786 (+0.49p) | 0.9737 |
| Kiwi 모호성 벤치마크 kiwi510, 정확도 | 0.7471 (열세, p 0.0002) | 0.8137 (차이 유의하지 않음) | 0.8275 |
| 속도(노트북 1스레드, Python 바인딩, KB/s) | 284 | 26 | 268 |
- 기본 모드는 모호성 벤치마크에서 Kiwi 보다 낮고, 정밀 모드(
precise=True)는 같은 수준입니다. 일반 문장의 형태소 F1 은 기본 모드도 앞섭니다. - 공개판의 기본 설정은 위 측정 설정에 전후향 가지치기(τ 11)를 더한 것입니다. 측정 셋 1만 7천 문장 중 5문장만 출력이 달라지고, 2단계 LM 질의가 44% 줄어 랩탑 CLI 에서 약 17% 빨라집니다.
- 자세한 표·방법은 논문(준비 중)에 싣습니다. 평가에는 국립국어원 모두의 말뭉치를 활용하였음.
Metadata
Release files for madipy 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| madipy-0.2.1-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details |
| madipy-0.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| madipy-0.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| madipy-0.2.1-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64 | Details |
Total release size: 4.2 MB
Release files / madipy-0.2.1-cp39-abi3-win_amd64.whl
| Download URL | madipy-0.2.1-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 797.3 kB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
7c578a1627fc92538be0e83e2925c306418387453b257803bb3b61c6d409e4fa
|
|
BLAKE2b-256 checksum How to use checksums |
8bd46a2f5f8f84263d9ab4214e6890c66a6f1c30777c103cdc54723df06bd353
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.
Transparency logRelease files / madipy-0.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | madipy-0.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 917.7 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
7d7ee78f33a60c44ac1c704018894afe726839979feb8217b42af8a0a91308ca
|
|
BLAKE2b-256 checksum How to use checksums |
527eca58160abc8085a6bcf59021ba64daff4d39c225d9f7d9d532add4ed0a32
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.
Transparency logRelease files / madipy-0.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | madipy-0.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 864.0 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
6b3ad49d0fd9a6ee4e213f79ebd122d69d9c6cce0baaca97a8b9b14b459123fe
|
|
BLAKE2b-256 checksum How to use checksums |
0ea1b66a2dd2b0c1b0f2b97c717cdace8bf943c20113f2524e0f5dbf3e91202e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.
Transparency logRelease files / madipy-0.2.1-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
| Download URL | madipy-0.2.1-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.9 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
e603f27e7086fec2c5b4aed19ce1985e076c24ebdf5592b4fbe2975b030053e8
|
|
BLAKE2b-256 checksum How to use checksums |
f2ab8c7c245d55d81dae527e3353fbf1f50b9948c7a124742d14fe06c2f74718
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.
Transparency log