sentikit
A sentiment analysis library that goes beyond lexicon tools like VADER and TextBlob by actually fixing their known failure modes instead of just adding more words to a dictionary.
Why not just use VADER?
| Problem | VADER / TextBlob | sentikit |
|---|---|---|
| Negation scope | Fixed 3-4 token window | Real dependency-parse scope (spaCy), or clause-bounded fallback |
| Contrastive discourse ("but", "however") | Averages both clauses | Detects the marker, upweights the post-marker clause |
| Idioms ("break a leg", "a nightmare") | Scores each word literally | Phrase-level lookup, scored as a unit, excluded from word-level pass |
| Aspect-based sentiment | Not supported | Optional transformer stage: per-aspect sentiment, not one blended score |
| Sarcasm | Not supported | Optional transformer gate that dampens/inverts the score by confidence, not a hard flip |
| Implicit / contextual sentiment | Word-lookup only | Optional transformer backbone blended with the rule-based score |
Honest scope note: sarcasm and fully implicit sentiment (no sentiment words at all) are open research problems. sentikit ships best-effort modules for these with documented confidence handling — it does not claim to solve them outright.
Install
pip install sentikit # lite mode only, zero heavy deps
pip install sentikit[parse] # + spaCy for accurate negation scope
pip install sentikit[transformers] # + transformer sentiment/sarcasm/ABSA
pip install sentikit[all] # everything
python -m spacy download en_core_web_sm # needed if you installed [parse]
Lite mode works completely offline with zero downloads. Full mode downloads models from HuggingFace on first use of that feature (not at import time).
Usage
Lite mode (default) — fast, offline, no downloads
from sentikit import Analyzer
sa = Analyzer() # mode="lite" by default
r = sa.analyze("I do not think this movie was particularly good")
print(r.compound, r.label) # -0.356 negative
print(r.negation_applied) # True — correctly scoped "not ... good"
# despite them being far apart
r = sa.analyze("The food was great, but the service was awful")
print(r.label) # negative — post-"but" clause dominates
r = sa.analyze("This laptop is a nightmare to work with")
print(r.idioms_matched) # ['a nightmare']
Full mode — adds transformer sentiment, sarcasm gate, ABSA
sa = Analyzer(mode="full")
result = sa.analyze(
"The battery life is terrible but the camera is excellent",
aspects=True,
)
print(result.label) # blended rule + transformer score
for a in result.aspects:
print(a["aspect"], a["sentiment"], a["confidence"])
# battery life negative 0.91
# the camera positive 0.94
result = sa.analyze("Oh great, another Monday", sarcasm=True)
print(result.sarcasm_probability, result.sarcasm_adjusted, result.label)
Architecture
text
├─ idiom phrase matching (masks matched spans before word-level scoring)
├─ tokenize
├─ negation scope (spaCy dependency parse, or clause-bounded regex fallback)
├─ contrastive discourse split ("but"/"however"/...) + asymmetric reweighting
├─ lexicon lookup + intensifier scaling
└─ [full mode only]
├─ transformer sentiment backbone (blended with rule-based score)
├─ sarcasm gate (confidence-weighted dampen/invert, not a hard switch)
└─ aspect extraction (noun chunks) + per-aspect transformer classification
Each module (negation.py, contrast.py, idioms.py, sarcasm.py,
aspect.py) is independently testable and swappable — this is intentionally
a pipeline of small fit-for-purpose components, not one model trying to do
everything.
What's still unsolved / roadmap
- Conditionals ("it would be amazing if it worked") — not yet detected; currently scores the embedded positive word at face value.
- Rhetorical questions — not yet detected as a distinct category.
- Quoted/reported speech attribution (whose opinion is it?) — not handled.
- Word sense disambiguation ("sick" as slang vs. illness) — lexicon uses a single fixed value per word; a WSD stage would help here.
- Idiom coverage — the bundled idiom lexicon (
data/idioms.json) is a small starter set (~30 entries); swap in a larger corpus (e.g. MAGPIE) for production use.
Development
pip install -e .[dev,all]
pytest tests/
Metadata
Release files for sentikit 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 |
|---|---|---|---|---|
| sentikit-0.1.0.tar.gz | 53.8 kB | Without provenance | Details for sentikit-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| sentikit-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for sentikit-0.1.0-py3-none-any.whl |
Total release size: 104.8 kB
Release files / sentikit-0.1.0.tar.gz
| Download URL | sentikit-0.1.0.tar.gz |
|---|---|
| Size | 53.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
282fad768a574318b395df9396d57a19309673a04db71fa2beaa03cb67fa6a57
|
|
BLAKE2b-256 checksum How to use checksums |
119c159ec45c6b37c9788306d3adc644c63089365f2f9e3d38515e32de885061
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / sentikit-0.1.0-py3-none-any.whl
| Download URL | sentikit-0.1.0-py3-none-any.whl |
|---|---|
| Size | 51.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c0e94ade672a81f51c2f24665adaa0681e4c5b50fbab5d85f686441276985770
|
|
BLAKE2b-256 checksum How to use checksums |
eae2ed26ef794a1ee011d41deae6e44309bcddff46ef9c622930857fbd47fa86
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Security for sentikit 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.