← all posts

CLM-8B Explained: How Contrastive Language Models Turn LLMs Into Fast Decision and Verification Engines

28 Sept 2026·12 min read
AICLMContrastive LearningLLMsQwenAI AgentsSystem OneMachine LearningModel InferenceAI VerificationEmbeddings

CLM-8B Explained: How Contrastive Language Models Turn LLMs Into Fast Decision and Verification Engines

A language model normally answers questions by generating language.

A new model family called Contrastive Language Models, or CLMs, takes a different route.

Instead of asking the model to generate:

"The best action is to restart the database."

CLM can compare:

current state
        ↓
candidate action 1
candidate action 2
candidate action 3
candidate action 4

and determine which candidate best matches the state.

That seemingly small change leads to a very different architecture.

The first publicly released model is CLM-v0.1-8B.

Its core consists of a frozen Qwen3-8B encoder with two small trainable projection heads:

State head
Action head

The model is trained with a bidirectional InfoNCE contrastive objective.


What is CLM?

CLM stands for Contrastive Language Model.

The project positions CLM as another type of System One model designed for fast structured decisions.

But its design philosophy is different from simply creating another classification head.

The key abstraction is:

state↔action\text{state} \leftrightarrow \text{action}

The model learns to put compatible states and actions close together in a shared representation space.

For example:

State:

"The database connection has failed."

Candidate actions:

A1 = restart database
A2 = open Photoshop
A3 = send marketing email
A4 = inspect database logs

The model wants something approximately like:

similarity(state, A1) → high
similarity(state, A4) → high

similarity(state, A2) → low
similarity(state, A3) → low

Once that representation exists, decision-making becomes a ranking problem.


The architecture

The architecture is unusually simple compared with a conventional generative LLM.

At the center is Qwen3-8B.

The official model card describes CLM-8B as:

mermaid diagram (6)

The Qwen3-8B backbone provides the semantic representation.

The two projection heads transform that representation into spaces suitable for state/action compatibility scoring.

The public repository describes each projection head as approximately 20 million trainable parameters, while the Qwen3-8B encoder remains frozen.

That means the training and serving problem is substantially different from fine-tuning all 8 billion parameters.


Why freeze Qwen3?

Qwen3-8B already contains a large amount of semantic knowledge.

CLM doesn't need to relearn that knowledge from scratch.

Instead, the contrastive heads learn a new representation:

"What does this state mean?"

and

"What does this action mean?"

then learn how those representations should align.

So the model effectively repurposes a generative LLM as a semantic encoder.

Qwen3-8B itself is an 8.2-billion-parameter causal language model with 36 layers and GQA attention, while the CLM system uses it in pooling/embedding mode rather than performing ordinary next-token generation.


The core idea: state/action disaggregation

This is arguably the most interesting engineering idea in CLM.

Imagine a tool ecosystem with 10,000 possible actions.

Many of those actions don't change very often.

For example:

restart_database()
search_web()
open_file()
run_tests()
deploy_service()

Their representations can be computed once.

restart_database()
        ↓
action embedding

search_web()
        ↓
action embedding

run_tests()
        ↓
action embedding

Those embeddings can then be reused across many different states.

The model doesn't need to repeatedly interpret every candidate action from scratch.

The CLM repository explicitly describes this as state and action caching.

This leads to an architecture like:

mermaid diagram (7)

This is especially attractive when the number of possible actions is large.


Contrastive learning

This is where the "CLM" part comes from.

Suppose we have a batch of matched state/action pairs:

State 1 ↔ Action 1
State 2 ↔ Action 2
State 3 ↔ Action 3
State 4 ↔ Action 4

The model should learn:

State 1 ↔ Action 1     high similarity
State 1 ↔ Action 2     low similarity
State 1 ↔ Action 3     low similarity
State 1 ↔ Action 4     low similarity

The same principle should work in the opposite direction:

Action 1 ↔ State 1     high similarity
Action 1 ↔ State 2     low similarity
...

CLM uses a bidirectional InfoNCE loss for exactly this purpose.

A simplified form is:

L=−12B∑i[log⁡esi⊤ai/τ∑jesi⊤aj/τ+log⁡eai⊤si/τ∑jeai⊤sj/τ]L = -\frac{1}{2B} \sum_i \left[ \log \frac{e^{s_i^\top a_i/\tau}} {\sum_j e^{s_i^\top a_j/\tau}} + \log \frac{e^{a_i^\top s_i/\tau}} {\sum_j e^{a_i^\top s_j/\tau}} \right]

where:

  • (sis_i) is the embedding of state (ii)
  • (aia_i) is the embedding of the correct action
  • (τ\tau) is a temperature parameter
  • (BB) is the batch size

The training objective pulls matched pairs together and pushes mismatched pairs apart.


Why hard negatives matter

Easy negatives are not particularly useful.

Suppose:

State:
"The database is down."

Positive:
restart_database()

Negative:
bake_a_cake()

That's trivial.

The model learns much more when the negative is:

restart_database()

versus:

inspect_database_logs()

Both are plausible.

CLM's training pipeline includes approximately 30 million synthetic hard negatives during its mid-training stage.

The idea is to force the representation space to become sensitive to subtle differences between plausible actions.


CLM's training recipe

According to the current public model card, CLM-8B was trained through three major stages:

~60M Nemotron Q&A pairs
          ↓
pre-training


~30M synthetic hard negatives
          ↓
mid-training


~1M agentic trajectories
          ↓
post-training

This progression is important.

The first stage establishes broad semantic representation.

The second teaches discrimination between plausible and incorrect candidates.

The third exposes the model to actual agentic behavior and state/action relationships.


Turning CLM into a decision model

Suppose the state is:

"My invoice was charged twice and nobody answers the phone."

We can provide:

billing
technical
sales

The model encodes the state and the candidate descriptions.

Then it calculates compatibility scores.

Conceptually:

mermaid diagram (9)

The official examples produce a result such as:

billing   0.93878
technical 0.06122

for the example support ticket.


CLM is not a text generator

This is worth emphasizing.

Despite the word Language Model, CLM-v0.1-8B is a ranker/decision model, not a normal generative LLM.

The model card explicitly lists this as a limitation:

CLM has no generation capability and only scores candidates that you provide.

In other words:

LLM:

prompt → generated tokens


CLM:

state + candidates → scores

This distinction is fundamental.


Free-form ranking

The system becomes much more interesting when candidates are not simple labels.

Suppose an agent has generated four possible solutions:

Solution A
Solution B
Solution C
Solution D

CLM can rank them.

The official repository exposes an Engine.rank() interface for exactly this style of use.

For example:

"""Rank candidate actions or answers against a state using CLM."""

from clm import Engine


def main() -> None:
    engine = Engine(
        emb_url="http://127.0.0.1:8090/v1/embeddings"
    )

    results = engine.rank(
        "What causes tides on Earth?",
        [
            "The Moon's gravitational pull.",
            "Photosynthesis in plants.",
            "Because the Earth is round.",
        ],
    )

    for result in results:
        print(result)


if __name__ == "__main__":
    main()

The result is a ranking with probabilities relative to the supplied candidate set.

This makes CLM useful for:

best-of-N generation
tool selection
candidate ranking
agent action selection
retrieval reranking
solution verification

How CLM can verify an agent

This is one of the most interesting use cases.

Suppose a coding agent generates four possible solutions:

Agent
  │
  ├── Solution A
  ├── Solution B
  ├── Solution C
  └── Solution D
          │
          ▼
        CLM
          │
          ▼
      ranking
          │
          ▼
     best candidate

Rather than asking the agent itself:

"Which one of your solutions is best?"

a separate model can judge them.

That makes CLM useful as a verifier.

The current project reports that fine-tuned CLM heads were used as verifiers for DeepSWE and Terminal-Bench 2.1. The repository reports 81.6% on 38 held-out DeepSWE tasks and 87.6% on 30 held-out Terminal-Bench 2.1 tasks, with latency on H100 hardware. These are project-reported benchmark results rather than independent evaluations.


Why caching changes the economics

Suppose there are:

1,000 candidate actions

and the same action set is repeatedly evaluated against different states.

A conventional approach repeatedly processes:

state + action 1
state + action 2
...
state + action 1000

CLM can separate these:

ACTION SIDE

action 1 → embedding
action 2 → embedding
...
action 1000 → embedding

cache all of them

Then each new state only requires:

new state
   ↓
state embedding
   ↓
compare against cached action vectors

The expensive semantic encoding work for candidate actions can therefore be amortized.

The CLM authors report that this architecture is particularly advantageous when candidate sets are large or candidates are reused. They report up to 13× speedup relative to Jev for approximately 1,000 candidates in their measurements.

Again, this is a model-author benchmark claim rather than a universal performance guarantee.


Running CLM locally

The current project is open source and provides a local serving setup.

The basic architecture is:

                 clm-serve
                    │
             CLM projection heads
                    │
                    ▼
             Qwen3-8B embeddings
                    │
                    ▼
                  vLLM

The project provides the following installation pattern:

pip install contrastive-lm

vllm serve Qwen/Qwen3-8B \
    --served-model-name qwen3-8b \
    --runner pooling \
    --max-model-len 2048 \
    --port 8090

clm-serve

The CLM server downloads the approximately 75 MB reference head checkpoint on first use. The project notes that states longer than 2,048 tokens are truncated under the default configuration and that both serving limits must be increased for longer states.


Using the typed API

CLM intentionally exposes an interface similar to the System One concept used by Jev.

For example:

"""Demonstrate CLM typed decisions using Choice, Noul, and Score."""

from clm import CLMClient, Choice, Noul, Score


def main() -> None:
    client = CLMClient()

    result = client.system_one(
        state=(
            "Customer: my invoice was charged twice "
            "and nobody answers the phone!"
        ),
        questions={
            "urgency": Noul(
                instructions="Is this urgent?"
            ),
            "department": Choice(
                instructions="Which team should handle this?",
                criteria={
                    "billing": "Charges, invoices, refunds",
                    "technical": "Bugs and outages",
                },
            ),
            "frustration": Score(
                instructions="How frustrated is the customer?",
                criteria=[
                    "Calm",
                    "Frustrated",
                    "Very angry",
                ],
            ),
        },
    )

    print(result.answers["urgency"].noul)
    print(result.answers["department"].choice)
    print(result.answers["department"].probabilities)
    print(result.answers["frustration"].score)


if __name__ == "__main__":
    main()

This is not a separate generative model hidden behind a special prompt. The model is directly scoring the state against the supplied structured candidates.


Fine-tuning CLM

One of the practical advantages of the architecture is that the large Qwen backbone can remain frozen.

Only the projection heads need to be trained.

That means a downstream task can specialize:

generic CLM
      ↓
task-specific examples
      ↓
new projection head
      ↓
specialized verifier

The public project provides fine-tuning tooling for tasks including DeepSWE and typed decisions.

This is substantially cheaper than fully fine-tuning an 8B generative model.


CLM versus conventional embeddings

At first glance, CLM might look like:

"Isn't this just an embedding model?"

There is an important difference.

A normal embedding model might be trained to produce semantically meaningful vectors.

CLM specifically trains:

state embedding
        ↕
action embedding

so that compatibility between the two becomes predictive of the correct action.

The training distribution is therefore oriented toward decision behavior, not just generic semantic similarity.

The hard-negative stage makes this particularly important.

The objective is not simply:

"These texts mean similar things."

It is closer to:

"Given this state, which of these actions is actually appropriate?"

CLM versus Jev

The two models belong to the same broader System One category, but their mechanisms differ.

PropertyJevCLM-8B
Primary ideaTyped decision modelState/action compatibility
Public architectureProprietaryFrozen Qwen3-8B + two projection heads
Main training conceptRLCDContrastive learning / InfoNCE
Text generationNoNo
Structured decisionsYesYes
Candidate rankingYes, through structured choicesCore capability
Cached candidate representationsNot the central public designCentral design
Open weightsNo public weights describedYes
Base modelProprietaryQwen3-8B
Fine-tuningManaged serviceLightweight head fine-tuning

Jev emphasizes the decision primitive and calibrated probability.

CLM emphasizes state/action representation and efficient ranking.

The distinction is subtle but important.


CLM's most interesting use case: AI agents

Consider an agent operating a computer.

Its current state might be:

Browser is open.
Search results are visible.
The user wants information about a specific paper.

Possible actions:

click result 1
click result 2
open new tab
scroll
search again
return to previous page

CLM can represent:

current state

and compare it against:

candidate actions

to determine which action best fits.

That becomes:

mermaid diagram (10)

This is a much more natural formulation of action selection than asking a generative model to write the name of the tool it wants to invoke.


Limitations

CLM has several important limitations.

It cannot generate text

This is not a ChatGPT replacement.

You must provide candidate answers/actions for it to rank.

Probabilities are candidate-relative

If the candidate set is:

A
B
C

the probability distribution describes the model's preference among those candidates.

Adding or removing candidates changes the normalization.

So:

A = 0.90

does not necessarily mean:

90% probability that A is objectively correct.

It means that A received most of the probability mass among the candidates presented.

This matters enormously when using CLM as a verifier.

The released model is encoder-locked

The projection heads are designed for the Qwen3-8B embedding interface used by the checkpoint.

You cannot simply replace Qwen3 with another backbone and expect the heads to work unchanged.

Benchmark verifier results require fine-tuning

The reported DeepSWE and Terminal-Bench results use task-specific fine-tuned heads.

They should not be interpreted as the zero-shot performance of the base CLM-8B checkpoint.


Why CLM is scientifically interesting

The most interesting part of CLM is not simply that it is faster.

It changes the computational abstraction.

A conventional LLM asks:

P(yt∣x,y<t)P(y_t \mid x,y_{<t})

CLM instead approximates something closer to:

P(a∣s)P(a \mid s)

where:

  • (s) = current state
  • (a) = candidate action

and implements that relationship through learned state/action representations.

This means a huge space of agent problems can potentially be reduced to:

encode state
      ↓
compare against candidate representations
      ↓
rank

That is an extremely different computational primitive from autoregressive generation.


Jev and CLM point toward a broader shift

The interesting thing about both systems is that neither starts by asking:

"How do we make an LLM generate better text?"

Instead, they ask:

"What if the model did not need to generate text at all?"

Jev's answer is:

typed probabilistic decisions

CLM's answer is:

state/action compatibility

And they suggest a broader architecture for future AI agents:

mermaid diagram (11)

The generative model provides flexibility.

The decision model provides a controlled interface for software.


Final assessment

CLM-8B is interesting because it demonstrates that an 8-billion-parameter generative model can be repurposed into a much narrower but potentially much faster decision engine without training all 8 billion parameters for every downstream application.

Its most important ideas are:

frozen semantic backbone
        +
separate state/action representations
        +
contrastive training
        +
hard negatives
        +
candidate caching
        +
ranking instead of generation

The result is not a better chatbot.

It is a different kind of model.

And perhaps the most interesting research question is what happens when this idea is extended beyond simple text actions:

text state
    ↓
multimodal state
    ↓
persistent state
    ↓
candidate actions
    ↓
parallel decisions
    ↓
verification

That direction is particularly relevant to agentic systems because the model can operate as a decision and verification layer around a generative model, rather than trying to replace the generator entirely.

The current CLM project also indicates a planned multimodal CLM-35B, which would extend the approach beyond text-only states. That is listed as an upcoming model rather than a currently released checkpoint, so it should be treated as a project announcement rather than an available model today.