Open-source Python library · Gemma 4 · runs locally

RALC: Relational Context Allocation

A language model only knows the text you send it. When a chat gets long, you can't send all of it, so you have to pick. RALC picks the messages that belong together, so the model gets the whole story inside a small token budget.

Example from our test conversation (234 messages)

Someone asks about something said long ago

“What did we use for hosting before we changed it?”Only a few messages can be sent to the model.
Picking by similarity

The model gets half the story

early in the chatLet us just push it to Heroku to begin with. I really do not want to spend our first week wrestling with servers.
The message about switching to AWS was thrown away because it “looked too similar” to this one.

The model can't tell that hosting ever changed.

RALC with Gemma

The model gets the full story

early in the chatLet us just push it to Heroku to begin with. I really do not want to spend our first week wrestling with servers.
↓ Gemma noticed: this later message replaces the one above
much laterHeroku has gotten expensive and we keep bumping into its ceilings, so we are moving where the app runs over to AWS and running it as containers.

The model can answer: Heroku first, then AWS.

Why the difference?

Two messages about the same thing look alike, so ordinary selection treats them as duplicates and keeps only one. RALC knows they are connected (one replaced the other), so it keeps both.

How it works

From a long chat to a small, connected context

RALC sits between your program and the model. It never rewrites the question and never touches the model's answer. Its only job is choosing which past messages to include.

  1. Store every message

    Each message becomes a point in a graph, saved in a local SQLite file.

  2. Connect the messages

    An extractor reads each message for names and decisions, and RALC draws links between messages.

    The free built-in extractor uses simple patterns. Gemma 4 can do this job instead and understands things a pattern can't, like one decision replacing another.

  3. Find starting points

    When a question arrives, a small embedding model on your machine finds the messages most similar to it.

  4. Follow the links

    From those starting points, RALC walks the links to related messages, even ones that share no words with the question.

  5. Rank the candidates

    Each candidate gets a score combining similarity to the question, how strongly it's linked, shared names, and how recent it is.

  6. Fill the budget

    RALC adds the best messages until the token budget is used. It skips near-duplicates, but not linked messages, since those complete each other. It stops early when nothing useful is left, so it can use fewer tokens than allowed.

  7. Hand off

    The chosen messages come back in conversation order. You add the unchanged question and send it to any model.

The kinds of links

TEMPORALLY_FOLLOWSThis message came right after that one.
ANSWERSThis reply answers that question.
MENTIONSBoth messages talk about the same named thing.
UPDATESThis decision replaces an earlier one. Gemma finds these; the pattern extractor found none in our test.
Where to use it

Anywhere history is long, things change, and space is tight

Long-running assistants

Remember what was decided months ago and why it changed.

Coding agents

Connect a bug, its cause, the file, and the fix across hours of work.

Small or local models

Models with small context windows, or a tight token budget, get only what matters.

Support bots

Keep the problem, the workaround, and the final fix together.

Team decision logs

“What did we agree on, and why?” across reversed and re-made decisions.

Not a good fit

Looking up one fact in documentation, or short chats where everything fits anyway. Ordinary search does as well there.

Guide

Add RALC to your own chatbot

1Install

Requires Python 3.10 or newer.

git clone https://github.com/Vivek0x6b/Ralc.git
cd Ralc
pip install -e ".[embed,tokens]"     # add ,gemma to use Gemma

2Create a context manager

The storage file keeps the graph between runs.

from ralc import ContextManager

ralc = ContextManager(storage="memory.db")

3Save every message as your chatbot runs

Add one line wherever your program sends or receives a message. RALC links each new message to the history automatically.

ralc.add_message(role="user", content=user_message)
ralc.add_message(role="assistant", content=reply)
ralc.save()

4Get the best context for a question

Pick a token budget that fits your model and your costs.

result = ralc.retrieve(query=question, token_budget=1000)

result.token_count      # tokens actually used (never above the budget)
result.nodes            # the chosen messages, in conversation order
result.metadata         # what happened: candidates, nodes explored, skips

5Send it to any model

The question goes in unchanged. Use whichever model you like.

prompt = result.to_text() + "\n\n" + question
# send prompt to Gemma, GPT, Claude, Llama, a local Ollama model...

6Optional: let Gemma build the links

Set GEMINI_API_KEY in your environment, then pass the Gemma extractor. Without it, RALC uses the free pattern extractor.

from ralc.extraction import GemmaExtractor

ralc = ContextManager(storage="memory.db",
                      extractor=GemmaExtractor(model="gemma-4-26b-a4b-it"))

Your chat history stays on your machine. Only the messages RALC selects are sent to the model, and with Gemma enabled, each message is sent once to Gemma to find links.

What we measured

Early results

Every budgetUsing relationships found more complete answers than the same system without them, on questions that need several messages.
0 vs 31“This replaced that” links found by the pattern extractor vs by Gemma.
TieOn simple one-fact questions, RALC and ordinary search do equally well.

Does using relationships help?

Share of multi-message questions where every needed message was selected. Same system, same number of candidates, relationships on vs off.

RALC (relationships on)Relationships off
00.250.50.751.0

Links Gemma found, and what they did

Pattern extractor
0 links
Gemma
31 links

“This replaced that” links in the 234-message test conversation.

Gemma graph
0.83
+ keep linked pairs
1.00

Complete answers on multi-message questions at a 1,000-token budget (5 of 6 → 6 of 6). The one recovered question is the hosting example above.

Limits

Code, tests, and every benchmark result: github.com/Vivek0x6b/Ralc