Skip to main content

Match recall segments with story segments.

Project description

rMatch

Automatic recall & story matching tool.

Ruff packaging framework: uv pre-commit

Automated matching of recall segments to respective story segments. Compared to human ratings, best performance is achieved with Claude Opus 4.6. However, google/gemma-4-31B-it runs locally and achieves comparable performance:

Model short text (N=21) long text (N=19) movie transcripts (N=138)
Claude Opus 4.6 0.87 0.8 0.7
google/gemma-4-31B-it 0.84 ? 0.67

Quick start

Command line

pip install rmatch

# single recall file
rmatch story.txt sub-001-recall.txt --matcher anthropic

# directory of recall files (one per subject)
rmatch story.txt recalls/ --matcher openai --model gpt-5.4

# estimate API cost without sending requests
rmatch story.txt recalls/ --matcher openai --model gpt-5.4 --dry-run

# run rMatch locally, -q flag quantizes the model
rmatch story.txt recalls/ --matcher huggingface --model google/gemma-4-31B-it -q 4bit
  • Each sub-001-recall.txt contains data for one subject.
  • Each line is considered a separate segment (e.g. each line could be a sentence, or event.)

Python API

from rmatch import Matcher

# cloud
matcher = Matcher(matcher_name="anthropic", api_key="your_api_key", model_name="claude-haiku-4-5")
matches = matcher.match(
    story_segments=["The cat sat on the mat.", "It purred softly."],
    recall_segments=["A cat was on a mat."],
)
# [(0, [0])]  — recall segment 0 matched story segment 0


# local
matcher = Matcher(matcher_name="huggingface", model_name="google/gemma-4-E4B-it", quantization="4bit")
matches = matcher.match(
    story_segments=["The cat sat on the mat.", "It purred softly."],
    recall_segments=["A cat was on a mat."],
)
# [(0, [0])]  — recall segment 0 matched story segment 0

Or use run_matching to load files, run matching, and save results in one call:

from rmatch.match import run_matching

results = run_matching(
    story_file="story.txt",
    recall_file="recalls/",
    matcher_name="anthropic",
    api_key="your_api_key",
)

Setup API keys

API keys are resolved in this order (first match wins):

  1. api_key argument passed directly in Python
  2. .env file in the current working directory
  3. Environment variables already set in your shell

Set them as environment variables:

export ANTHROPIC_API_KEY="your_api_key"   # for --matcher anthropic (default)
export OPENAI_API_KEY="your_api_key"      # for --matcher openai
export HF_TOKEN="your_hf_token"           # for --matcher huggingface

Or put a .env file in your working directory:

ANTHROPIC_API_KEY="your_api_key"
OPENAI_API_KEY="your_api_key"
HF_TOKEN="your_hf_token"

Output format

A JSON file with:

{
  "matcher_name": "anthropic",
  "story_name": "story",
  "story_segmentation": "lines",
  "recall_segmentation": "lines",
  "matches": {
    "sub-001": [[0, [3, 7]], [1, [12]]],
    "sub-002": [[0, [1]], [1, [5, 6]]]
  }
}

Each entry in matches maps a subject ID to a list of [recall_segment_id, [matched_story_segment_ids...]] pairs.

Running local models

You can run any model capable of text-generation from https://huggingface.co/models.

To speed up inference, you can install flash-att MAX_JOBS=8 uv pip install flash-attn --no-build-isolation. Note that some models may not support flash-attn. If the model flash-attn is not automatically disabled for these models, pass the flag --no-flash-attn.

Benchmarking

Requires rBench:

# outside of this dir
git clone git@github.com:GabrielKP/rBench.git

Add to .env or environment:

BENCHMARK_ROOT="path/to/rBench"

Run:

uv run src/rmatch/evaluate.py {alice,monthiversary,memsearch}

API / Documentation

Input formats

Story file — a .txt or .json file containing the story segments to match against.

  • .txt: one segment per line (blank lines are ignored).
  • .json: must contain a "segments" array of strings. Optionally includes "segmentation_method".
{
  "segmentation_method": "sentences",
  "segments": [
    "The cat sat on the mat.",
    "It purred softly."
  ]
}

Recall file — a .txt file, a .json file, or a directory of either.

  • .txt file: one recall segment per line. The filename stem is used as the subject ID.
  • .json file: must contain a "recalls" object mapping subject IDs to segment arrays.
  • Directory: all .txt or all .json files inside are loaded (mixing formats is not allowed). Each .txt file becomes one subject; .json files are merged.
{
  "segmentation_method": "clauses",
  "recalls": {
    "sub-001": ["A cat was on a mat.", "It was purring."],
    "sub-002": ["There was a cat on something."]
  }
}

CLI reference

rmatch STORY_FILE RECALL_FILE [options]

General options

  • STORY_FILE (positional, required) — Path to the story .txt or .json file.
  • RECALL_FILE (positional, required) — Path to a recall .txt/.json file or a directory of them.
  • -M, --matcher (str) — Which matcher backend to use. One of: anthropic, openai, huggingface. Default: anthropic.
  • -m, --model-name (str) — Override the matcher's default model (see defaults below).
  • -f, --overwrite — Overwrite the output file if it already exists.

LLM matcher options (anthropic, openai, huggingface)

  • --window-size (int) — Number of surrounding recall segments (before and after) to include as context for each target segment. Set to 0 to disable context. Default: 5.
  • --prompt (str) — Prompt type. Default: primary. See Prompts.
  • --dry-runanthropic & openai only. Estimate token usage and cost without making API calls.

Self-hosted / HuggingFace options

  • -q, --quantization (str) — Load the model in reduced precision: 4bit (NF4) or 8bit. Requires bitsandbytes.
  • -bs, --batch-size (int) — Number of prompts to process in parallel. Default: 4.
  • --max-new-tokens (int) — Maximum tokens the model may generate per prompt. Default: 64.
  • --verbose-errors — Print the raw model output when parsing fails. Useful for debugging prompt issues.

Default models

  • anthropicclaude-opus-4-6
  • openaigpt-4.1
  • huggingfacegoogle/gemma-4-E4B-it

Python API

Matcher (main entry point)

from rmatch import Matcher

matcher = Matcher(matcher_name="anthropic", model_name=None, **kwargs)
matches  = matcher.match(story_segments, recall_segments)

Matcher(matcher_name, **kwargs) is a factory — it returns the appropriate subclass based on matcher_name. All keyword arguments are forwarded to the subclass constructor.

Constructor arguments:

  • model_name (str) — Override the default model. Applies to all matchers.
  • window_size (int) — Context window radius around the target recall segment. Default: 5. Applies to: anthropic, openai, huggingface.
  • prompt_type (str) — Prompt type. Default: "primary". Applies to: anthropic, openai, huggingface. See Prompts.
  • dry_run (bool) — Estimate cost without calling the API. Applies to: anthropic, openai.
  • api_key (str) — API key. Falls back to .env, then environment variables. Applies to: anthropic, openai, huggingface.
  • device (str) — PyTorch device string. Applies to: huggingface.
  • quantization (str)"4bit" or "8bit". Applies to: huggingface.
  • batch_size (int) — Batch size for inference. Default: 4. Applies to: huggingface.
  • max_new_tokens (int) — Max generated tokens. Default: 64. Applies to: huggingface.
  • verbose_errors (bool) — Log raw output on parse failures. Applies to: huggingface.

matcher.match(story_segments, recall_segments)

  • story_segments (list[str]) — Ordered list of story segments (the ground-truth story elements).
  • recall_segments (list[str]) — Ordered list of a single participant's recall segments.

Returns list[tuple[int, list[int]]] — one entry per recall segment:

[
    (0, [2, 5]),   # recall segment 0 matched story segments 2 and 5
    (1, []),       # recall segment 1 had no matches
    (2, [0]),      # recall segment 2 matched story segment 0
]

run_matching (file-level convenience)

from rmatch.match import run_matching

results = run_matching(
    story_file,            # Path — story .txt or .json
    recall_file,           # Path — recall file or directory
    matcher_name,          # str  — "anthropic", "openai", "huggingface"
    story_name=None,       # str | None — override auto-detected story name
    story_segmentation=None,   # str | None — override detected segmentation method
    recall_segmentation=None,  # str | None — override detected segmentation method
    overwrite=False,       # bool — overwrite existing output file
    **kwargs,              # forwarded to the Matcher constructor (model_name, window_size, etc.)
)

Loads story and recall files, runs matching for every subject, and saves a JSON results file. Returns the output dictionary.

Prompts

All LLM matchers share the same set of prompt templates. The default is primary.

Prompt Full story Segmented story Chain of thought Notes
primary yes yes yes Default; most complete prompt.
primary_no_story no yes yes Useful for long stories where the full text would exceed the context window.
primary_no_cot yes yes no Ablation: removes chain-of-thought reasoning.
primary_no_story_no_cot no yes no Ablation: minimal prompt with only segments and recall window.
secondary yes yes yes Alternative prompt wording with XML-structured output.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rmatch-0.3.1.tar.gz (149.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rmatch-0.3.1-py3-none-any.whl (28.9 kB view details)

Uploaded Python 3

File details

Details for the file rmatch-0.3.1.tar.gz.

File metadata

  • Download URL: rmatch-0.3.1.tar.gz
  • Upload date:
  • Size: 149.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rmatch-0.3.1.tar.gz
Algorithm Hash digest
SHA256 47e2e75d99b59869f7ba6e1c373102c35ed26146af5a74e7a4e4b8110a11de3b
MD5 77490428d11c9161f8cfa6abfd93c2fa
BLAKE2b-256 ee4c49d2d4b9a6ab38861dcd3ec94b21f5593817349ae4f9c45da16262fd4744

See more details on using hashes here.

Provenance

The following attestation bundles were made for rmatch-0.3.1.tar.gz:

Publisher: publish.yml on GabrielKP/rMatch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rmatch-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: rmatch-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 28.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rmatch-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 78d8cd53ff78fb9bbd59e1610a996a23027966b8f28e54f07c2b6b2a1fd302da
MD5 2e4bfa377a7f12e2a2ab83ca1c52ddef
BLAKE2b-256 182325a183fb85ee7fb73adce0904a3b1f7623e2683f0a9371bbec10decc437d

See more details on using hashes here.

Provenance

The following attestation bundles were made for rmatch-0.3.1-py3-none-any.whl:

Publisher: publish.yml on GabrielKP/rMatch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page