Skip to main content

nlp-components-library

Reusable inference, analysis and configuration components for NLP and LLM experiment pipelines, extracted from the multi-turn dice roll, UnBLEnD, decision-model psychometrics and human-disagreement projects so new experiments can be assembled from tested parts.

Package Components
config model registry with experiment presets, cultural macro regions, cue lexicons, questionnaire schema
inference reproducible chat rendering, verified model loading, exact next-token option probabilities, continuation log-likelihoods, persona questionnaires, logit lens, float32 reward scoring, OpenAI-compatible top-logprobs, vLLM batch chat
analysis entropies and divergences, history information, item scoring and aggregation, bootstrap and rank statistics, psychometric scales and reliability, rule-based question annotation
data, io, plotting item and persona loading, result files with provenance, figure helpers

Installation

uv add "nlp-components-library[hf]"      # or: pip install "nlp-components-library[hf]"

The core (config, analysis, data, io) needs only numpy, polars, pydantic and scipy. Extras add the heavier parts:

Extra Enables
hf local models: torch, transformers, accelerate, huggingface-hub
api APIScorer with an OpenAI-compatible client
vllm inference.vllm_chat (resolve it in its own environment; vLLM pins torch)
plot plotting with matplotlib and seaborn

Usage

Models

from nlp_components_library.config import models

for spec in models.resolve(["dice-core", "qwen3_14b"]):  # presets, keys or Hub ids
    if spec.fits(gpu_gb=48):
        print(spec.key, spec.hf_id, spec.bf16_gb)
print(models.table(models.resolve(["human-disagreement"])))

The same listing is available as nlp-components-library models dice-core and nlp-components-library presets.

Exact option probabilities

from nlp_components_library.inference import NextTokenScorer, build_chat

scorer = NextTokenScorer.from_pretrained("Qwen/Qwen3-8B", dtype="bfloat16")
chat = build_chat(
    "Roll a six-sided die. Return exactly one number from 1 to 6. Answer: "
)
(result,) = scorer.score([chat], options=("1", "2", "3", "4", "5", "6"))
result.probs  # raw probability of every option (all matching tokens summed)
result.option_mass  # share of the full distribution on the options
result.normalized()  # renormalised over the options
scorer.metadata()  # model revision, template hash, token ids, versions, ...

Every option sums the probability of all vocabulary tokens that decode to it ("4", " 4", "▁4", ...), normalised in float64 over the full vocabulary. Batches never pad (sequences are bucketed by length), so results do not depend on the batch size. APIScorer offers the same interface for OpenAI-compatible servers, where only the top-20 log-probabilities are known.

Logit lens and reward models

from nlp_components_library.config import models
from nlp_components_library.inference import (
    ChatTemplate,
    LogitLens,
    RewardScorer,
    build_chat,
    load_spec,
)

tokenizer, model = load_spec(models.BY_KEY["llama3_8b"])
lens = LogitLens(model, ChatTemplate(tokenizer), options=("A", "B", "C", "D"))
output = lens.score([build_chat(prompt) for prompt in prompts])
output.probs  # [item, layer, option]; output.predictions is the last layer
output.hidden_states

tokenizer, rm = load_spec(models.BY_KEY["skywork_qwen3_8b"])
RewardScorer(rm, ChatTemplate(tokenizer)).score_responses(prompt, ["A", "B", "C", "D"])

load_model/load_spec refuse checkpoints that would leave weights randomly initialised (e.g. a text-only class on a vision-language checkpoint).

Persona questionnaires

from nlp_components_library.config import Questionnaire
from nlp_components_library.data import sample_personas
from nlp_components_library.inference import (
    ChatTemplate,
    ContinuationScorer,
    QuestionnaireScorer,
)

segment = Questionnaire.from_json("instruments/big5.json").sole_segment
personas = sample_personas(
    "hf://datasets/nvidia/Nemotron-Personas-USA/data/train-*.parquet", 100
)
scorer = QuestionnaireScorer(
    ContinuationScorer(model, tokenizer),
    template=ChatTemplate(tokenizer),
    history_window=5,
)
responses = scorer.score(personas["persona"].to_list(), segment)

Each statement is scored by the log-likelihood of every response option; the most likely answers of the last history_window statements are shown with the next one, and personas beyond max_context_tokens are truncated.

Scoring, aggregation and statistics

from nlp_components_library.analysis import (
    aggregate,
    bootstrap_ci,
    kruskal,
    score_probabilities,
)
from nlp_components_library.config import macro_region_map
from nlp_components_library.data import load_items

items = load_items(
    "blend.json", ("A", "B", "C", "D"), annotations={"macro_region": macro_region_map()}
)
scores = score_probabilities(
    items, probs, ("A", "B", "C", "D"), lens=lens_table, model="llama3_8b"
)
aggregate(
    scores, ["model", "macro_region"]
)  # accuracy, question accuracy, certainty, ...
bootstrap_ci(scores["correct"].to_numpy())
kruskal(scores["p_gold"], scores["macro_region"])

Psychometrics

from nlp_components_library.analysis import psychometrics

choices, probabilities = psychometrics.response_tables(
    [response.probabilities for response in responses], segment
)
scales = psychometrics.scale_scores(choices, segment)
psychometrics.reliability(choices, segment)  # Cronbach's alpha per dimension
psychometrics.run_r_analysis("omega", choices, segment, "reports/omega.csv")  # needs R

Reproducibility defaults

  • Thinking off. Templates receive enable_thinking=False unless ChatTemplate(..., thinking=True).
  • Pinned date. Templates that stamp today's date get config.DEFAULT_TEMPLATE_DATE (2026-10-26); pass date=None for the real date. The dice-roll runs used datetime.date(2024, 7, 26).
  • Provenance. io.write_results stores a CSV with a JSON sidecar (creation time, library version and your metadata, e.g. scorer.metadata()).

Development

uv sync --extra hf --extra api --extra plot
uv run pytest                 # tiny random models are built offline
uv run pytest -m "not slow"   # without the model tests
uv run ruff check && uv run ruff format --check && uv run mypy

The lock file resolves vllm in its own fork. Upgrading everything at once (uv lock --upgrade) can pull the hf fork down to vLLM's torch pin; upgrade packages selectively (uv lock --upgrade-package transformers) instead.

Releasing

Publishing uses PyPI trusted publishing from .github/workflows/publish.yml.

  1. Once: on PyPI (and TestPyPI) add a trusted publisher for this repository with workflow publish.yml and environment pypi (testpypi), and create both environments in the GitHub repository settings.

  2. Optional dry run: start the Publish workflow manually; it runs CI, builds and uploads to TestPyPI.

  3. Release:

    uv version --bump minor            # or patch / major
    git commit -am "Release $(uv version --short)"
    git tag "v$(uv version --short)"
    git push origin main --tags
    

    The tag runs CI, checks that it matches the package version, builds with uv build and publishes with uv publish.

Metadata

Release files for nlp-components-library 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nlp-components-library 0.1.0
File Size Uploaded Provenance Actions
nlp_components_library-0.1.0.tar.gz 43.7 kB Without provenance Details for nlp_components_library-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for nlp-components-library 0.1.0
File Interpreter ABI Platform Actions
nlp_components_library-0.1.0-py3-none-any.whl Python 3 none any Details for nlp_components_library-0.1.0-py3-none-any.whl

Total release size: 102.8 kB

Release files / nlp_components_library-0.1.0.tar.gz

Download URL nlp_components_library-0.1.0.tar.gz
Size 43.7 kB
Tags Source
SHA-256 checksum
How to use checksums
290bd4c1fa3584ab4f572b6ae0b231419a4e4a7f3b117588a4ceba6c43469905
BLAKE2b-256 checksum
How to use checksums
872b69db581a42a1c7baaa03702f17ae5cb9e21a496eaa2990ae83bc324c03a6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.6.16

Release files / nlp_components_library-0.1.0-py3-none-any.whl

Download URL nlp_components_library-0.1.0-py3-none-any.whl
Size 59.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
490df317430821de15edeb3f74e3bb597611b0615ed2f000566ff68c0091a26c
BLAKE2b-256 checksum
How to use checksums
8b33412fa4c7e520e3289916c8a93395f8f539753d130575024a2ebbaa504996
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.6.16

Security for nlp-components-library 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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