vader-parity 0.1.0

VADER sentiment scoring with exact output parity against Python vaderSentiment 3.3.2. Algorithm and lexicons by Hutto and Gilbert (ICWSM-14).
Documentation
  • Coverage
  • 100%
    9 out of 9 items documented2 out of 5 items with examples
  • Size
  • Source code size: 792.9 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 367.5 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 3s Average build duration of successful builds.
  • all releases: 3s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • hey-jj/vader-parity
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • hey-jj

vader-parity

VADER sentiment scoring for Rust, with exact output parity against Python vaderSentiment 3.3.2.

polarity_scores returns four numbers per text: neg, neu, pos, and compound. Each equals the value the Python package returns for the same text, at that package's published precision: three decimals for the proportions, four for the compound. The whole rule set ships. That covers lexicon scoring, booster and dampener modifiers with the casing increment, negation with the "least" special case, contrastive "but" reweighting, exclamation and question mark emphasis, the special-case idioms, emoji translation, and the alpha-15 normalization to compound, all over the reference's own data files, vendored byte for byte from the 3.3.2 sdist.

Parity is the tested contract. The 177 frozen oracle vectors in tests/vectors/frozen.tsv were captured from the pinned Python package before implementation, and tests/vectors.rs replays them on every cargo test with zero tolerated divergence. Before a release, a differential harness scores a 63,471-sentence corpus against the live pinned package under the same zero-divergence bar, and on that corpus the pre-rounding compound is bit-identical to the oracle's. Casing is part of the pin: str.isupper() and str.lower() are answered from data/casing_tables.tsv, recorded from CPython 3.14.6 with Unicode data 16.0.0, and a sweep test checks every codepoint against the recorded behavior, so the scores cannot drift when the Rust standard library moves to a newer Unicode version than the reference interpreter's.

[dependencies]
vader-parity = "0.1.0"

Use

use vader_parity::SentimentIntensityAnalyzer;

let analyzer = SentimentIntensityAnalyzer::new();
let scores = analyzer.polarity_scores("VADER is smart, handsome, and funny.");
assert_eq!(scores.neg, 0.0);
assert_eq!(scores.neu, 0.254);
assert_eq!(scores.pos, 0.746);
assert_eq!(scores.compound, 0.8316);

polarity_scores is total: every &str returns scores, and text with nothing scoreable is neutral, exactly as the reference scores it (is? returns a compound of 0.0 and a neu of 1.0, and the doctest on polarity_scores asserts both). Construction parses the vendored lexicons once, about 11,000 data lines, so build one analyzer and score many texts. Each call is one bounded linear pass, and a doctest in the crate docs pins that by scoring 10,000 sentences on one analyzer inside a fixed budget.

Replacing qsv_vader_sentiment_analysis

This crate replaces the qsv_vader_sentiment_analysis / vader-sentimental / vader_sentiment family, whose scoring defects reverse the sign of compound on ordinary sentences. Migration is the dependency line plus the return shape: where those crates hand back a map or struct, read scores.compound, scores.neg, scores.neu, scores.pos here. Scores change on migration wherever the incumbent was wrong, which is the point. Two before/after examples, both pinned as regression tests named defect_m1_* and defect_m2_* in tests/vectors.rs:

Text Reference and this crate qsv_vader_sentiment_analysis
he is at least smart +0.4019 -0.3089
these are the shittiest of times -0.6597 positive: "shittiest" matched "the shit" (+3.0) by substring

Scope

  • English only: the reference is English-only and so is its lexicon.
  • Scoring engine only: sentence splitting, CSV integration, and custom lexicons are out of scope (custom lexicons are the first candidate for a minor release).
  • Reference version 3.3.2 exactly: a reference upgrade would be a minor release with a re-frozen corpus.
  • std only, with zero runtime dependencies.

Requirements

Rust 1.81.0 or later. The manifest declares rust-version = "1.81.0", and a CI job builds the library and runs the doctests on that exact toolchain.

Attribution

VADER is the work of C.J. Hutto and E.E. Gilbert: the algorithm design, the sentiment lexicon vader_lexicon.txt, and the emoji lexicon emoji_utf8_lexicon.txt, published under the MIT license, copyright C.J. Hutto. The idiom and booster tables in data/rules_tables.tsv are transcribed from the reference source, and the two lexicon files are byte-identical copies from the vaderSentiment 3.3.2 sdist. data/PROVENANCE records the sha256 digest of the sdist and of every vendored file, and tests/provenance.rs enforces them. The Rust implementation and the test suite are this crate's own work.

If you use VADER, cite:

Hutto, C.J. & Gilbert, E.E. (2014). VADER: A Parsimonious Rule-based Model for Sentiment Analysis of Social Media Text. Eighth International Conference on Weblogs and Social Media (ICWSM-14). Ann Arbor, MI, June 2014.

License

The crate's own code is licensed under either of Apache License, Version 2.0 or the MIT license at your option.

The vendored data files in data/ remain under the VADER authors' MIT license regardless of which arm you pick for the code. That composition works because MIT's obligation is notice preservation, and the crate ships data/LICENSE-VADER in every archive. The manifest's SPDX expression states exactly that: (MIT OR Apache-2.0) AND MIT.

Unless you state otherwise, any contribution you intentionally submit for inclusion in this crate, as defined in the Apache-2.0 license, is dual licensed as above, with no additional terms or conditions.