Homonym sense disambiguation (beta)
Words that are spelled the same but have completely different meanings are called homonyms. 다리 can be a bridge (橋) to cross
or a leg (脚) on the body. 배 can be a boat (船) you ride, a pear (梨) you eat, or a stomach (腹) that hurts, all with the same spelling.
Looking at POS alone, all three are NNG (common noun), so they cannot be told apart.
Bareun can return which meaning was used in that context along with the morphological analysis result.
Just turn on the single with_sense option in the request, and each morpheme gets a superscript number (dictionary sense number) and a definition.
This is a beta feature
Homonym sense disambiguation is in the beta stage. You can use it on both api.bareun.ai (cloud) and a self-installed server. For a self-installed server, the model needed for sense disambiguation is downloaded together on first startup, so it works as is once you install the latest release and start the server.
Keep the following in mind during the beta period.
- The chosen sense can be wrong. It is not yet at a finished level. In particular, there are cases where the same spelling appears several times in one sentence, and cases where even a well-known homonym gets pulled toward its most common meaning (see Accuracy and limitations).
- The response format may change before the official release. We prefer changes that add fields, but detailed values and fields during the beta period are not final.
- Existing calls are not affected at all. If you do not turn on
with_sense, the response and the processing time are exactly the same as before.
What changes
The same 다리 is analyzed differently depending on context. The POS is the same NNG for both, but the meaning differs.
| Sentence | Morpheme | POS | Superscript number | Definition |
|---|---|---|---|---|
| 다리를 건넜다. (I crossed the bridge.) | 다리 | NNG | 5 | A structure built so that one can cross water or go from a high place on one side to a high place on the other. |
| 다리가 저리다. (My leg is numb.) | 다리 | NNG | 1 | The part of the body attached below the trunk of a person or animal. |
graph LR A["다리 / NNG"] --> B["다리를 건넜다<br/>→ superscript 5 (structure)"]; A --> C["다리가 저리다<br/>→ superscript 1 (body)"];
What is a superscript number?
A Korean dictionary lists words that are spelled the same but differ in meaning as separate entries and numbers each entry.
The small number placed at the upper right of a headword, as in 다리¹ and 다리², is the superscript number (eokkaebeonho).
The superscript numbers Bareun returns follow the sense numbering of Urimalsaem (the Open Korean Dictionary,
the National Institute of Korean Language's open Korean knowledge dictionary). So with the urimal_target_id that comes along with the superscript number,
you can open the corresponding Urimalsaem headword page directly.
https://opendict.korean.go.kr/dictionary/view?sense_no=836
The reference is Urimalsaem, not the Standard Korean Language Dictionary
Each Korean dictionary draws the boundaries between senses slightly differently, so the superscript number of the same word differs by dictionary. Bareun unified on Urimalsaem, which has the most headwords and is continually updated. The numbers may not match those of other dictionaries.
How to use
Put with_sense as true in the request. The default is false.
It can be used with all three morphological analysis APIs.
| API | Path | Notes |
|---|---|---|
| Morphological analysis | /bareun.LanguageService/AnalyzeSyntax | The most common call |
| Morphological analysis (no sentence splitting) | /bareun.LanguageService/AnalyzeSyntaxList | Takes an array of sentences |
| Morphological analysis without post-processing | /bareun.LanguageService/AnalyzeSyntaxRaw | Raw model output |
curl \
-H "api-key: koba-ABCDEFG-1234567-LMNOPQR-7654321" \
-H "Content-Type: application/json" \
-X POST https://api.bareun.ai/bareun.LanguageService/AnalyzeSyntax \
-d '{"document": {"content": "다리를 건넜다.", "language": "ko-KR"},
"encoding_type": "UTF32",
"with_sense": true}'
You can use it right away with the Python client bareunpy 2.1.0 or later.
pip install --upgrade "bareunpy>=2.1.0"
import bareunpy as brn
tagger = brn.Tagger(apikey="koba-ABCDEFG-1234567-LMNOPQR-7654321")
# Get only the morphemes that were assigned a sense
for s in tagger.senses('다리를 건넜다.'):
print(s.content, s.tag, s.sense_no, s.meaning)
# 다리 NNG 5 물을 건너거나 … 건너다닐 수 있도록 만든 시설물.
# 건너 VV 1 무엇을 사이에 두고 한편에서 맞은편으로 가다.
# Get the whole analysis result and pull values out of it
res = tagger.tag('다리가 저리다.', with_sense=True)
print(res.pos(join=True, sense=True))
# ['다리__001/NNG', '가/JKS', '저리__001/VA', '다/EF', './SF']
The SenseInfo returned by senses() holds content, tag, sense_no, meaning,
urimal_target_id, and probability, and urimal_url builds the Urimalsaem page URL for you.
tags(), taglist(), and tag_raw() have the same with_sense option.
For details, see the Python client (bareunpy) page.
import requests
URL = "https://api.bareun.ai/bareun.LanguageService/AnalyzeSyntax"
HEADERS = {"api-key": "koba-ABCDEFG-1234567-LMNOPQR-7654321"}
body = {
"document": {"content": "다리를 건넜다.", "language": "ko-KR"},
"encoding_type": "UTF32",
"with_sense": True, # homonym sense disambiguation (beta)
}
res = requests.post(URL, headers=HEADERS, json=body).json()
for sent in res["sentences"]:
for token in sent["tokens"]:
for m in token["morphemes"]:
sense = m.get("sense") # if missing, no sense was assigned to this morpheme
if sense:
print(m["text"]["content"], m["tag"],
sense["senseNo"], sense["meaning"])
The analyze_syntax and analyze_syntax_raw tools of the Bareun MCP server accept the same option.
{
"name": "analyze_syntax",
"arguments": { "text": "다리를 건넜다.", "with_sense": true }
}
If you set format to compact, the one-line summary also shows the superscript numbers.
다리__005/NNG 를/JKO 건너/VV 었/EP 다/EF ./SF
bareunpy 2.1.0 or later is required
with_sense and senses() were added in bareunpy 2.1.0. Lower versions do not have
the argument, so upgrade with pip install --upgrade bareunpy. Even if you do not upgrade the library,
you can call the API directly with the REST examples above.
Response format
A morpheme that was assigned a sense carries a sense object.
{
"text": { "content": "다리", "beginOffset": 0, "length": 2 },
"tag": "NNG",
"probability": 0.9917928,
"outOfVocab": "IN_WORD_EMBEDDING",
"sense": {
"senseNo": 5,
"meaning": "물을 건너거나 또는 한편의 높은 곳에서 다른 편의 높은 곳으로 건너다닐 수 있도록 만든 시설물.",
"urimalTargetId": 836,
"probability": 0.935963
}
}
| Field | Type | Description |
|---|---|---|
senseNo | Integer | Superscript number. A sense number based on Urimalsaem. To convert it back to the dictionary notation (005), zero-pad it to 3 digits. |
meaning | String | Korean definition. It can be empty (see below). |
urimalTargetId | Integer | Unique number of the Urimalsaem headword. You can open the dictionary page with …/dictionary/view?sense_no=<value>. 0 means not assigned. |
probability | Real [0,1] | How far you can trust that sense. See How to read the probability below. |
A morpheme without sense is normal
sense is attached only to morphemes that were assigned a sense. If there is none, the key does not appear in the response at all.
- Particles, endings, and symbols do not have a dictionary sense number to begin with (
를/JKO,다/EF,./SF). - Words that are not homonyms may also not be assigned a sense if they have only one meaning.
- Where no sense is trustworthy, the field is left empty instead of attaching a wrong meaning (see How to read the probability below).
- In a call where
with_senseis not turned on, no morpheme hassense.
So have the client decide based on whether the sense key exists. Treat it as possibly missing, for example m.get("sense") in Python
or m.sense?.senseNo in JavaScript.
When the definition is empty
The superscript number can be valid while meaning is an empty string. This happens when the headword itself is not in
Urimalsaem (for example, words with a number in front), and it is under 1% of all cases. Do not
assume a definition is always present, and prepare a display for when it is missing.
How to read the probability
sense.probability is how far you can trust that sense. It is not only the share with which this sense was chosen among the candidate senses,
but also takes into account how commonly that sense is actually used. If a sense that looks plausible from context but is rarely used was chosen,
the value comes out low.
Because it looks at both, the candidate probabilities of one morpheme do not add up to 1. Read it as a score for that single choice, not as a ratio among candidates.
It is not the same value as the morpheme's probability
A morpheme already has a probability field (the model's score for the POS decision), but it is different in nature.
morpheme.probability | sense.probability | |
|---|---|---|
| Meaning | The model's score for how likely this POS is | How far you can trust the chosen sense |
| When low | The POS decision is shaky | The sense decision is shaky |
Do not compare the two values against the same threshold or plot them side by side on one axis.
With a single candidate it is always 1.0
For a word with only one candidate sense, the probability always comes out as 1 (or close to 1). This does not mean "high
confidence" but "there is only one to choose." To use it as a reliability criterion, do not look at the probability alone;
also check whether the word is actually a homonym.
When confidence is very low, no sense is attached
Where no sense is trustworthy, sense is left out entirely instead of attaching a wrong meaning.
So you can see morphemes without a sense key even though they are homonyms.
The values that are in the response have been filtered that much, so a low probability does not appear without reason. However, as described in Accuracy and limitations below, results can be wrong even with a high probability, so where automatic confirmation is needed, also set a probability threshold.
What you can use it for
Homonym disambiguation separates data that used to get mixed together just because the spelling was the same.
- Search and indexing: Index
다리 (bridge)documents and다리 (leg)documents separately, so body-related documents do not get mixed into traffic-related searches. - Keyword and trend analysis: Count mentions of
배 (boat)and배 (pear)separately in news. - RAG document splitting and tagging: Attach sense numbers to chunks as metadata so the same spelling is grouped under different topics (Korean chunking for RAG).
- Linking to a terminology dictionary: Link straight to the Urimalsaem entry with
urimal_target_idand show users the definition. - Enriching LLM prompts: Include the definition of an ambiguous word so the model does not misread the context.
Performance and cost
When you turn on with_sense, one more inference runs to choose the sense.
- If it is off (the default), processing time and the response are exactly the same as before.
- When it is on, the extra time is proportional to the sentence length, and you can think of it as roughly one more computation of the same scale as the morphological analysis itself. For large batch processing, it is better to turn it on only for the documents that need it.
- The response size grows by the number of morphemes that get a sense (the definition strings are the largest part).
Accuracy and limitations
We write down how the beta stage actually behaves, without hiding it. All of the following are measured examples.
Where it works well: sentences with clear context cues
| Sentence | Result |
|---|---|
| 다리를 건넜다. (I crossed the bridge.) | 다리 → 5 (structure) ✅ |
| 다리가 저리다. (My leg is numb.) | 다리 → 1 (body) ✅ |
| 은행에서 돈을 찾았다. (I withdrew money at the bank.) | 은행 → 2 (financial institution) ✅ |
| 배가 아파서 병원에 갔다. (My stomach hurt, so I went to the hospital.) | 배 → 1 (body) ✅ |
| 그 말은 사실이 아니다. (That statement is not true.) | 말 → 4 (language) ✅ |
Where it is still weak
| Situation | Measured | Why |
|---|---|---|
| The same spelling appears several times in one sentence | 밤에 밤을 구웠다. (I roasted chestnuts at night.) → both 밤 judged as 'night' ❌ | It is still not good enough at treating the second occurrence of the same spelling differently from the first. |
| Words that get pulled toward the common meaning | 어부가 배를 저어 나갔다. (The fisherman rowed out in the boat.) → 배 judged as a body part ❌ · 은행나무에서 은행이 떨어졌다. (Ginkgo nuts fell from the ginkgo tree.) → 은행 judged as a financial institution ❌ | If a word has an overwhelmingly frequent meaning, it gets pulled there even when there are cues in the opposite direction. |
| Sentences with short context cues | 배를 먹었다. (I ate a pear.) → 배 judged as a body part ❌ | A short sentence lacks the cues needed to decide the meaning. |
| Rarely used senses | A sense that is in the dictionary but has very few real usage examples gets pulled toward the frequently used sense. | The number of training examples differs greatly by sense. |
Recommended usage during the beta period
- It is good enough for aggregation, but confirming individual sentences needs checking. For counting senses separately at the document or corpus level, it is clearly better than a most-frequent-sense rule.
- Do not confirm automatically; we recommend a pipeline that sends results with a low
sense.probabilityto human review or post-processing. - If you find a wrong decision, tell us with the sentence. We will reflect it directly in the quality of the official release.
For the principle and the training data, see How homonyms are distinguished; for a comparison with other tools and resources, see Comparison of Korean homonym analysis resources.
Frequently asked questions
Q. Do existing results change if I do not turn on with_sense?
A. No. For a call that does not turn the option on, the response content and the processing time are the same as before.
The sense field is not included at all.
Q. Which dictionary is the superscript number based on?
A. It is based on Urimalsaem (the National Institute of Korean Language's open Korean knowledge dictionary). With the accompanying urimal_target_id,
you can open the Urimalsaem page. It may differ from the numbers of the Standard Korean Language Dictionary.
Q. Is a sense attached to every morpheme?
A. No. It is not attached to morphemes that have no dictionary sense number, such as particles, endings, and symbols. Where no sense is
trustworthy, it is also left empty instead of attaching a wrong meaning. Decide based on whether the sense key exists.
Q. It is a homonym but there is no sense. Why?
A. It means no sense was trustworthy enough in that spot. We judge that leaving it empty is better for users than attaching a wrong meaning, so we do not include it when confidence is very low. It appears with short context cues or with words whose senses are split very finely.
Q. Can I use it on a self-installed Bareun too?
A. Yes. You can use it on both the cloud (api.bareun.ai) and a self-installed server. The model needed for sense disambiguation
is downloaded together when the server first runs, so if you installed the latest release, you only need to turn on the
with_sense option with no extra preparation.
Q. Is sense disambiguation also used in the spell checker?
A. This beta is a feature that attaches senses to the response of the morphological analysis API. It is not yet at the stage of being reflected directly in spell check results.