Instructions to use Elda-AI/memory-resoner with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Elda-AI/memory-resoner with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("feature-extraction", model="Elda-AI/memory-resoner", trust_remote_code=True)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Elda-AI/memory-resoner", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Access to memory-resoner
Released for research, evaluation, internal validation and education. Tell us who you are and we will grant access.
By requesting access you agree to the Elda Community License 1.0: no commercial use, no redistribution of the weights or derivatives, and attribution as "Built with Elda". Commercial licensing is available on request.
Log in or Sign Up to review the conditions and access this model content.
memory-resoner β the reference step of conversational memory
A conversation can only be stored if you know what γκ·Έ λλ€γ meant. memory-resoner reads the turns of a conversation and says, for each mention, which earlier mention it refers to β so the layer above can write a memory entry that points at the right words.
"ν©μ λμ κ°κ²λ₯Ό μ΄μ΄μ . κ·Έ λλ€λ μ λμΈκ΅¬κ° λ§λμ ?"
mentions ν©μ λμ (s0, w0β0)
κ·Έ λλ€λ (s1, w0β1)
chains [ν©μ λμ Β· κ·Έ λλ€λ]
version 0.1.4 Β· 149M parameters Β· fp32 Β· 35 ms per sentence on CPU.
Where it sits
memory-resoner is one stage of a Korean conversational stack. Each stage answers one question and hands the next stage a span, never prose.
utterance
β
ββ Elda-AI/intenter what was said, and what kind of thing it is ββ spans come from here
ββ slot extraction which of those the user said about themselves
β
βΌ
β
memory-resoner β
which earlier mention does this one refer to
β
βΌ
memory write a pointer into the user's own words β checkable, not generated
Where the spans come from. In the Elda stack, mention spans are produced upstream by Elda-AI/intenter and this model consumes them; its card is the reference for how a span is drawn, which types exist, and what the channels mean. Used standalone, memory-resoner will find its own mentions instead β the linking answer is the same either way.
β The two sides count spans in different units, and the conversion is yours to make. Upstream spans are character offsets with the particle left outside (γν©μ λγ). This model works in μ΄μ (word) indices, and a μ΄μ contains its particle, so the same mention is γν©μ λμγ here. Neither is wrong; they are different units. Align on the μ΄μ that contains the upstream span.
What it returns. Span indices and chains. Not a rewritten sentence, not a summary β an index into the words you sent, which the layer above can verify before storing anything.
What it does not decide. Whether a fact is true, whether it is worth keeping, how long it lives. Those belong to the system around it. This stage answers one question and stops.
Why a small encoder
| this model | LLM prompting | |
|---|---|---|
| Parameters | 149M | 7B β 70B |
| Latency per sentence, CPU | p50 35 ms | seconds |
| Output | span index β checkable byte-for-byte | free text to be parsed |
| Determinism | same input, same chains | sampling |
Memory is written on every turn. A stage that runs that often has to be cheap, and its answer has to be something the next stage can check rather than trust. A span index is both.
Output contract
input sentences, in order β a string per sentence, or a list of μ΄μ
output mentions Β· antecedents Β· chains (links closed transitively)
spans inclusive word (μ΄μ ) indices β Korean particles stay attached (see the note above)
window 6 previous sentences of context Β· 40 previous mentions as candidates
A mention with no antecedent opens a chain of its own β that is how the next stage learns it has seen a new entity, so singleton chains are kept rather than dropped.
Usage
from transformers import AutoModel, AutoTokenizer
m = AutoModel.from_pretrained("Elda-AI/memory-resoner", trust_remote_code=True).eval()
tok = AutoTokenizer.from_pretrained("Elda-AI/memory-resoner", trust_remote_code=True)
out = m.coref(["ν©μ λμ κ°κ²λ₯Ό μ΄μ΄μ .",
"κ·Έ λλ€λ μ λμΈκ΅¬κ° λ§λμ ?"], tok)
out["mentions"] # [{'sent': 0, 'words': [0, 0], 'text': 'ν©μ λμ'}, ...]
out["antecedents"] # [None, 0] β per mention: what it points back at
out["chains"] # [[0, 1]]
| call | does |
|---|---|
m.coref(sentences, tok) |
finds the mentions and links them |
m.mentions(sentences, tok) |
finds mentions only β a span provider for another linker |
m.resolve(units, mentions, tok) |
links only β you supply the mentions |
Notes that matter in practice:
- fp32. The config pins it. In bf16 near-ties flip and chains change.
- Pass sentences, not a paragraph. The sentence boundary is what the window is counted in.
- Send the resolved span downstream, not the reference. The output is an index into the words you sent, so whatever consumes it can verify what it was handed.
- Strip the particle at display time, not at span time. Keeping it inside the μ΄μ is what makes the span a plain index into your own input; trimming belongs to whatever renders the value.
Measurements
Public Korean coreference, held out from training; document overlap with the training split is 0 and the benchmark script asserts it. Both scripts ship in this repository.
pip install torch transformers datasets
python bench_corefud_ko.py --model Elda-AI/memory-resoner
Mention detection β boundaries must match exactly
| precision | recall | F1 |
|---|---|---|
| 0.811 | 0.7874 | 0.799 |
Linking, mentions given
| scored mentions | 10263 |
| accuracy | 0.8568 |
| non-NULL accuracy | 0.5744 (n=2721) |
| deictic, non-NULL | 0.5277 (n=271) |
| reference β always NULL | 0.7349 |
| reference β always most-recent | 0.0448 |
Read the non-NULL rows. Most mentions open a chain, so answering NULL every time already scores 0.7349; the rows that require actually linking are the ones in bold.
End-to-end β (mention, antecedent) pairs, the model finding its own mentions
| precision | recall | F1 |
|---|---|---|
| 0.6387 | 0.6534 | 0.646 |
Every run first pushes the gold answers back through the scorer and asserts they survive intact (1.0000). A scorer that cannot return its own gold is not grading anything.
On dialogue
The numbers above are prose. On dialogue β references mined from a public multi-turn Korean
corpus, with the antecedent taken from that corpus's own annotation rather than chosen by us β
this version resolves γκ·Έ μλΉγ-style references at 0.2091, against 0.1077 for 0.1.1,
and locates the referring mention in 483/483 cases.
python bench_wos_references.py --model Elda-AI/memory-resoner
That gain was paid for: on prose, deictic non-NULL moved from .524 (0.1.1) to 0.5277.
If your text is prose rather than conversation, 0.1.1 is the stronger checkpoint and it remains
in this repository's history.
What comes next
Conversational memory here is built in three layers. They are not future versions of this model β they are different kinds of component, and saying so is the point.
| what it is for | how it is built | |
|---|---|---|
| Layer 1 Β· conversation memory | what was said in this conversation, and what refers to what | β this model + deterministic assembly |
| Layer 2 | blackbox β how a memory is addressed and kept apart from every other conversation | not described here |
| Layer 3 Β· authority and persona | whether something holds and on what grounds, and what an agent is like across conversations | a deterministic VM, and a decoder used off the request path |
Layer 1 is the only one this model sits in. Layer 2 is deliberately not described: it is where memories are separated from one another, and it is the part of the system we keep closed. Layer 3 is where facts acquire grounds and where a persona is formed, and it is built from two very different machines β one that must be exact, and one that must be fluent.
The VM β the exact one. Memory is written in a small closed language and executed by a deterministic machine, so a write is either accepted, a duplicate, a replacement, or refused, and the same inputs always produce the same store. Reads are queries against that store, not recollection. This is what makes memory auditable rather than merely plausible, and it is why the per-turn path carries no generation at all.
The decoder β the fluent one. Never on the request path. Writing and reading memory happen on every turn and stay on the encoder-and-machine side. Generation is for prose a person will read, and for periodic passes that look across many conversations at once to form a persona β a pass that can fail without the conversation stopping.
Versioning
v<major>.<minor>.<patch>, three digits. Minor moves when the task, the inputs or the heads
change β when your code has to change. Patch moves when the same job is done better. The version
lives in config.json and is cross-checked against this card at publish time.
Current: 0.1.4. Earlier weights remain in this repository's history.
This repository previously hosted a different model, a Korean slot tagger. It is not an earlier version of this one.
License & access
Released under the Elda Community License 1.0 (see LICENSE). Provenance of the training data
is recorded in LINEAGE.md; no user conversations were used.
- β Research, evaluation, internal validation, education β free of charge
- β³ Attribution: "Built with Elda"
- β Commercial use and redistribution require a separate agreement
Access is gated: tell us who you are and access is granted automatically.
Citation
@software{memoryresoner2026,
title = {memory-resoner: reference resolution for Korean conversational memory},
author = {Elda AI},
year = {2026},
url = {https://huggingface.co/Elda-AI/memory-resoner}
}
- Downloads last month
- 4