Skip to main content

SemAxis

Interpretable NLI-based text features for scikit-learn.

SemAxis turns raw text into a feature matrix by asking an LLM to generate natural-language hypotheses and scoring each text against them with an NLI model. Every feature is a human-readable sentence — no black-box embeddings.

texts  ──►  LLM (hypothesis generation)  ──►  NLI scoring  ──►  X: (n_texts, n_features)

Both transformers are sklearn-compatible: they work inside Pipeline and are safe to use with cross_val_score.


Installation

pip install semaxis

Unsupervised

UnsupervisedTransformer generates hypotheses that characterize the text collection without labels.

from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from semaxis import UnsupervisedTransformer

pipe = Pipeline([
    ("vect", UnsupervisedTransformer(
        llm="gpt-4o",
        nli_model="cross-encoder/nli-deberta-v3-large",
        n_features=20,
    )),
    ("clf", LogisticRegression()),
])

cross_val_score(pipe, texts, labels, cv=5)

Supervised

SupervisedTransformer generates hypotheses that discriminate between classes.

Binary

from semaxis import SupervisedTransformer

pipe = Pipeline([
    ("vect", SupervisedTransformer(
        llm="gpt-4o",
        nli_model="cross-encoder/nli-deberta-v3-large",
        n_features=20,
    )),
    ("clf", LogisticRegression()),
])

cross_val_score(pipe, texts, labels, cv=5)

Labels can be numeric (0/1) or strings ("positive"/"negative").

Multi-class

Use strategy="ovr" (one-vs-rest, default) or strategy="ovo" (one-vs-one):

# OvR: generates n_features hypotheses per class (k × n_features total)
vect = SupervisedTransformer(llm="gpt-4o", nli_model="...", n_features=10, strategy="ovr")

# OvO: generates n_features hypotheses per class pair (C(k,2) × n_features total)
vect = SupervisedTransformer(llm="gpt-4o", nli_model="...", n_features=10, strategy="ovo")

Interpreting features

After fitting, both transformers expose features_ (flat list of hypothesis strings). SupervisedTransformer also exposes feature_meta_, parallel to features_, which records which class pair each hypothesis came from.

vect = SupervisedTransformer(llm="gpt-4o", nli_model="...", n_features=5, strategy="ovr")
vect.fit(texts, labels)

for hypothesis, meta in zip(vect.features_, vect.feature_meta_):
    print(f"[{meta.positive} vs {meta.negative}]  {hypothesis}")
[cat vs rest]  This text describes feline behavior.
[cat vs rest]  This text mentions a cat or kitten.
[dog vs rest]  This text describes canine behavior.
[dog vs rest]  This text mentions a dog or puppy.
...

Combine with a linear model to get per-hypothesis coefficients:

from sklearn.linear_model import LogisticRegression
import numpy as np

X = vect.transform(texts)
clf = LogisticRegression().fit(X, labels)

for coef, hyp in sorted(zip(clf.coef_[0], vect.features_), key=lambda x: abs(x[0]), reverse=True):
    print(f"  {coef:+.3f}  {hyp}")

Custom LLM

For in-process inference, use LlamaCppClient backed by llama-cpp-python:

from llama_cpp import Llama
from semaxis import UnsupervisedTransformer
from semaxis import LlamaCppClient

llm = LlamaCppClient(Llama(model_path="path/to/model.gguf", n_ctx=4096))

vect = UnsupervisedTransformer(llm=llm, nli_model="cross-encoder/nli-deberta-v3-large")

Install the optional dependency with:

pip install "semaxis[llamacpp]"

Related Work


Citation

@software{semaxis2026,
  title  = {SemAxis: Interpretable NLI-based text features for scikit-learn},
  year   = {2026},
}

Download files

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

Source Distribution

semaxis-0.25.0.tar.gz (16.1 kB view details)

Uploaded Source

Built Distribution

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

semaxis-0.25.0-py3-none-any.whl (17.5 kB view details)

Uploaded Python 3

File details

Details for the file semaxis-0.25.0.tar.gz.

File metadata

  • Download URL: semaxis-0.25.0.tar.gz
  • Upload date:
  • Size: 16.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for semaxis-0.25.0.tar.gz
Algorithm Hash digest
SHA256 99c7df077f55dca7eb8bef14803b48d4fd3bcf4a44afb5163765c2db99a5dac7
MD5 58152521fe07979847fe64d762c937dd
BLAKE2b-256 183260af80bdb628413eec1f680cbc04b4b6334f7144e2d2d3f37d461b5807a8

See more details on using hashes here.

Provenance

The following attestation bundles were made for semaxis-0.25.0.tar.gz:

Publisher: release.yml on pillyshi/semaxis

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

File details

Details for the file semaxis-0.25.0-py3-none-any.whl.

File metadata

  • Download URL: semaxis-0.25.0-py3-none-any.whl
  • Upload date:
  • Size: 17.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for semaxis-0.25.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e565db017b619c8437c458f77c4fcb67c137ea86629a5723376c81b027672bf2
MD5 6f8dc8ee9134e618ded6cafeca2cad04
BLAKE2b-256 94831aee80e7b04ca88052bbb7b0c88c99140a2abf7e7fa602983db430ff329d

See more details on using hashes here.

Provenance

The following attestation bundles were made for semaxis-0.25.0-py3-none-any.whl:

Publisher: release.yml on pillyshi/semaxis

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

Release history Release notifications | RSS feed

This release

0.25.0 This release

2 files

0.24.0

2 files

0.23.0

2 files

0.21.0

2 files

0.20.0

2 files

0.19.0

2 files

0.18.0

2 files

0.17.0

2 files

0.16.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page