Skip to main content

Generate and classify text from user-defined (positive, negative) example pairs

Project description

pntx

pntx is a Python library that turns a handful of user-supplied (positive, negative) text pairs into:

  1. Generation — synthesize new text on either side of the pair.
  2. Classification — label arbitrary text as positive or negative.

The meaning of "positive" and "negative" is entirely up to you. It doesn't have to be sentiment — it can be formal/casual, policy-compliant/violating, or any other contrast you define with examples. pntx never interprets the pairs; it only uses them as few-shot and scoring material.

from pntx import PNTX

model = PNTX(backend="llama", model_path="model.gguf")

pairs = [
    ("The movie was fantastic", "The movie was boring"),
    ("Support was quick and helpful", "Support was slow and unhelpful"),
]
model.fit(pairs)

# Generation
texts = model.generate(
    n=20,
    side="positive",
    temperature=1.0,
    dedup=True,          # filter near-duplicates (of each other and of the seed pairs)
    verify=True,         # self-classify and reject anything that doesn't match `side`
    min_confidence=0.8,  # confidence threshold used by verify
)

# Classification
result = model.classify("The staff were incredibly friendly")
result.label        # "positive" | "negative"
result.confidence   # float in [0.0, 1.0]
result == "positive"  # True

results = model.classify_batch(texts)  # batched, not a naive per-item loop

Installation

pntx uses uv for package management.

uv add pntx              # core (zero dependencies)
uv add "pntx[llama]"     # + llama.cpp in-process backend
uv add "pntx[anthropic]" # + Anthropic API backend
uv add "pntx[embeddings]" # + semantic similarity for selectors

The core package has no runtime dependencies. Each backend/feature lives behind its own extra, and using one without installing it raises a clear ImportError with the install command to run.

Backends

pntx runs models two ways:

  • LlamaCppBackend (pntx[llama]) — runs a GGUF model in-process via llama-cpp-python. This is the primary, most-tuned backend: classification uses token log-probabilities directly (score_choices), and batched classification reuses the shared few-shot prefix's KV cache across every item instead of re-evaluating it per item.
  • AnthropicBackend (pntx[anthropic]) — calls the Anthropic Messages API. Since that API doesn't expose log-probabilities, classification asks the model to name the label and parses it out of the response instead (confidence is then a fixed convention value, not a calibrated probability). Batched classification runs requests concurrently (asyncio + a semaphore), not in a sequential loop.
model = PNTX(backend="llama", model_path="model.gguf")
model = PNTX(backend="anthropic", model="claude-...")

# or pass a backend instance directly, e.g. for dependency injection in tests
from pntx.backends.llama import LlamaCppBackend
model = PNTX(backend=LlamaCppBackend(model_path="model.gguf"))

Selecting exemplars

When there are more fitted pairs than comfortably fit in a prompt, a Selector decides which ones to use:

  • RandomSelector (default) — a uniform random subset.
  • NearestSelector — picks pairs whose text is most similar to the text being classified; dynamic, per-query selection.
  • DiversitySelector — greedily picks a maximally diverse subset.

Both NearestSelector and DiversitySelector take a similarity_fn. It defaults to a dependency-free character n-gram similarity (pntx.dedup.similarity); pass pntx.embeddings.cosine_similarity_fn() (requires pntx[embeddings]) for semantic similarity instead:

from pntx import PNTX
from pntx.selection import NearestSelector

model = PNTX(backend="llama", model_path="model.gguf", selector=NearestSelector())

Development

uv sync                          # install dev dependencies
uv run pytest                    # unit tests (integration tests are skipped by default)
uv run ruff check .
uv run mypy src tests

Integration tests that hit a real model or API are opt-in:

PNTX_LLAMA_MODEL_PATH=/path/to/model.gguf uv run pytest tests/integration
ANTHROPIC_API_KEY=... uv run pytest tests/integration/test_anthropic_backend.py

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

pntx-0.1.0.tar.gz (13.8 kB view details)

Uploaded Source

Built Distribution

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

pntx-0.1.0-py3-none-any.whl (19.1 kB view details)

Uploaded Python 3

File details

Details for the file pntx-0.1.0.tar.gz.

File metadata

  • Download URL: pntx-0.1.0.tar.gz
  • Upload date:
  • Size: 13.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for pntx-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d673de3541171296faf948154aef3eefcec1fd95081f66ea603038b1e985fd08
MD5 847a19c4e3d4c42a69e58f96173d7eee
BLAKE2b-256 cbd00fda697eb7e568823a0e8981e13fc4d2b02520b4a3370dbd12658b0c1de2

See more details on using hashes here.

File details

Details for the file pntx-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pntx-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 19.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for pntx-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 21ae2f8e12ba9bbbd41dee1028c586ce7aedb0a415faeedaa48822be9228e209
MD5 91539b0051771155ae05bda2235fb695
BLAKE2b-256 829dee75191b83762537c060e42ae20477298204404721ad8bbd33eeb14c2e1d

See more details on using hashes here.

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