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=FalseunlessChatTemplate(..., thinking=True). - Pinned date. Templates that stamp today's date get
config.DEFAULT_TEMPLATE_DATE(2026-10-26); passdate=Nonefor the real date. The dice-roll runs useddatetime.date(2024, 7, 26). - Provenance.
io.write_resultsstores 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.
-
Once: on PyPI (and TestPyPI) add a trusted publisher for this repository with workflow
publish.ymland environmentpypi(testpypi), and create both environments in the GitHub repository settings. -
Optional dry run: start the Publish workflow manually; it runs CI, builds and uploads to TestPyPI.
-
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 buildand publishes withuv 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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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.