Skip to main content

Discourse Cohesion Analysis Library Based on Centering Theory

Project description

Centering-Lgram

Discourse cohesion analysis based on Centering Theory (Grosz, Joshi, and Weinstein, 1983). Measures how entities and topics flow across sentences — pronouns, repetitions, entity continuity.

Note: Cohesion (bağdaşıklık) = surface grammatical/lexical links. Coherence (tutarlılık) = deeper semantic unity. Centering Theory models cohesion.


⚠️ What This Tool Does NOT Measure

  • Factual accuracy — a high cohesion score does NOT mean the content is correct
  • Hallucination — a fluent-sounding LLM output can still be completely false
  • Overall quality — cohesion is ONE dimension of text quality, not the whole picture

Correct positioning: Use centering-lgram as a complementary evaluator alongside faithfulness/accuracy checkers. It measures "how smoothly does this read?", not "is this correct?".

What we measure What we DON'T measure
Entity flow across sentences Factual correctness
Pronoun resolution quality Hallucination / faithfulness
Topic continuity / shifts Logical reasoning
Readability (Flesch) Relevance to prompt
Lexical repetition chains Domain accuracy

PyPI Python License Tests


Quick Start

pip install centering-lgram
python -m spacy download en_core_web_sm
from lgram import TextAnalyzer

ta = TextAnalyzer()
r = ta.analyze("AI helps doctors. It speeds up diagnosis. These tools save lives.")
print(r.overall_cohesion)  # 0.0-1.0 (exact value depends on the spaCy model)
print(r.quality)           # "high"

For best results, use the medium model:

ta = TextAnalyzer("en_core_web_md")

Genre Calibration

Empirically derived transition patterns. Method: Tukey's fence (p75 + 1.5×IQR).

Brown Corpus (1960s)

NLTK Brown: 1.1M words, 500 files, 15 categories. n=30/genre, HIGH confidence.

Genre Rough normal (p25–p75) Flag > (Tukey) Continue mean Conf.
Narrative 11.5% – 27.3% 51.0% 49.8% HIGH
Expository 16.7% – 33.3% 58.2% 29.2% HIGH
Essay 11.5% – 27.7% 52.0% 30.7% HIGH

Modern Corpus (2020s) — n=30/genre, HIGH confidence

Genre Rough normal (p25–p75) Flag > (Tukey) Continue mean Conf.
Narrative 0.0% – 25.0% 62.5% 25.0% HIGH
Expository 0.0% – 25.0% 62.5% 32.3% HIGH
Essay 0.0% – 25.0% 62.5% 20.3% HIGH

Note: Single-author corpus. Stylistic homogeneity may narrow distributions.

Cross-Validation: Wikipedia (multi-author, 2024)

n=12, MEDIUM confidence. Small sample — treat as observational, not conclusive.

Genre n Rough normal Flag > Continue Conf.
Expository (Wikipedia) 12 23.0% – 34.6% 52.0% 34.5% MEDIUM

Wikipedia's 52% flag threshold is broadly consistent with Brown's 58%. Direction is as expected (multi-author corpora cluster together, single-author is the outlier). However, at n=12 this is an observation, not a validated claim. Two caveats: (1) Wikipedia's strict editing guidelines may make it a distinct sub-genre, not representative of general 2020s expository writing. (2) The 6% gap could be measurement noise, temporal change, or genre artifact — the current data cannot distinguish between these explanations.

Findings

  1. Rough-Shift >50% is abnormal — all corpora agree. Flag thresholds: 51-63%.
  2. Wikipedia cross-validates the multi-author finding — Brown (58%) and Wikipedia (52%) cluster together, while the single-author corpus (63%) diverges. Consistent with the stylistic homogeneity hypothesis. However, n=12 precludes strong conclusions about temporal stability.
  3. Wikipedia is not "general 2020s writing" — its strict editing guidelines may constitute a distinct sub-genre. More diverse modern sources needed.

Calibration is reproducible: python -m lgram.brown_calibration

⚠️ Reliability note: Scores depend on the underlying embedding model. For production use, pick ONE model (recommended: en_core_web_md) and standardize on it. Compare texts only within the same genre — cross-genre comparison is meaningless because different genres have different natural transition patterns.


Core Concepts

Centering Theory tracks three discourse centers per utterance:

Center Notation Definition
Forward Centers Cf Entities ordered by grammatical salience
Backward Center Cb Entity linking to previous utterance
Preferred Center Cp Highest-ranked Cf

Five transition types between utterances:

Transition Rule Quality
Establish First utterance
Continue Cb(Ui) = Cb(Ui-1) = Cp(Ui) Best
Retain Cb(Ui) = Cb(Ui-1) ≠ Cp(Ui) Good
Smooth-Shift Cb(Ui) ≠ Cb(Ui-1) = Cp(Ui) OK
Rough-Shift Cb(Ui) ≠ Cb(Ui-1) ≠ Cp(Ui) Poor

API — TextAnalyzer (High-Level)

from lgram import TextAnalyzer

ta = TextAnalyzer()                    # default: en_core_web_sm
ta = TextAnalyzer("en_core_web_md")    # better vectors
ta = TextAnalyzer(use_sentence_transformers=True)  # best quality

Core Analysis

Method Description
analyze(text) Full analysis → TextReport (sentences, paragraphs, transitions, entities)
analyze_batch(texts, labels) Compare multiple texts with rankings
analyze_llm(response, prompt?) LLM output quality: high/medium/low + prompt comparison

Cohesion Metrics

Method Source Description
entity_grid_score(text) Barzilay & Lapata 2005 Entity role persistence (S/O/X/-) across sentences
lexical_chain_score(text) Halliday & Hasan 1976 Noun repetition + similarity chains
build_cohesion_graph(text) Graph-based Sentence adjacency graph (density, centrality, communities)
cohesion_trend(text) Sliding window Cohesion change across text (improving/declining/stable)
cohesion_heatmap(text) Matrix N×N sentence similarity with weak pair detection
combined_score(text) Hybrid Cohesion × 0.6 + Readability × 0.4

Segmentation & Quality

Method Description
texttile_segments(text) Hearst 1994 topic segmentation
hybrid_boundaries(text) Centering + TextTiling intersection (high confidence)
suggest_improvements(text) Find weak points + fix suggestions
annotate_weak_points(text) Mark <<<WEAK>>> at cohesion breaks
diff_cohesion(original, revised) Compare two versions
readability_score(text) Flesch Reading Ease + statistics

Export

Method Output
to_dict(report) JSON-serializable dict
to_json(report) JSON string
to_summary(report) Human-readable report

API — EnhancedCenteringTheory (Low-Level)

from lgram import EnhancedCenteringTheory
import spacy

nlp = spacy.load("en_core_web_sm")
ct = EnhancedCenteringTheory(nlp)

state = ct.analyze_utterance("John went to the store.")
ct.update_discourse("He bought milk.")

result = ct.evaluate_cohesion(["John went.", "He bought milk.", "The store was busy."])

Key methods: compute_forward_centers, compute_backward_center, determine_transition, extract_clauses, detect_boundaries, validate_sequence, visualize, compare_texts, stream_start/feed/flush, save/load, reset.


CLI

centering-lgram analyze --text "John went to the store. He bought milk."
centering-lgram clauses --text "She left because she was tired."
centering-lgram full --text "John left. He was tired because he worked late."
centering-lgram score --text "Alice met Bob. She greeted him."
centering-lgram info
centering-lgram version

How It Works

Salience Ranking

Cf ordered by: grammatical role (S=4 > O=3 > other=2 > poss=1) + POS (PRON=3 > PROPN=2 > NOUN=1) + position + entity type (PERSON/ORG/GPE bonus) + pronoun antecedent bonus.

Backward Center (5-level cascade)

  1. Possessive scan — "his"/"her" → matched person entity
  2. Direct match — entity appears in both Cf lists
  3. Pronoun resolution — gender-aware (he→male, she→female)
  4. Coreference — entity type matching + vector similarity fallback
  5. Compound plural — multiple persons → "they"

Gender-Aware Pronoun Resolution

120+ name gender map (English + Turkish) + title detection (Mr/Mrs) + suffix heuristics. Male pronoun "he" does NOT match female entity "Alice".

Clause Detection

Dependency parse: main, conj, advcl, ccomp, acl, relcl. Separator tokens (commas, conjunctions) assigned to following clause.


Architecture

lgram/
  __init__.py              # Package exports
  analyzer.py        924   # TextAnalyzer (17 methods)
  benchmark.py       290   # CohesionBenchmark (4 tests)
  cli.py             238   # 6 CLI commands
  core.py              7   # Re-export hub
  utils.py            20   # Logging
  models/
    __init__.py         7   # Sub-package exports
    centering_theory.py 1122 # Core engine
tests/
  test_lgram.py       209   # 15 core tests
  test_edges.py       312   # 34 edge case tests
docs/
  RESEARCH.md                # Literature survey
  IMPLEMENTATION_PLAN.md     # Implementation plan

Dependencies: spacy>=3.4.0 only. Optional: sentence-transformers for MiniLM.


Use Cases

Domain Application
LLM Evaluation Cohesion scoring for GPT/Claude/Llama output
Education Essay scoring, writing assistant feedback — CAEAS EFL essay feedback tool
Linguistics Discourse analysis research
Content Quality Blog/news fluency audits
Translation Cross-language cohesion comparison
Dialogue Conversation flow naturalness
Forensics Statement consistency analysis

License

MIT — see LICENSE. Copyright (c) 2025 Ilker Atagun.

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

centering_lgram-2.3.1.tar.gz (134.3 kB view details)

Uploaded Source

Built Distribution

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

centering_lgram-2.3.1-py3-none-any.whl (131.5 kB view details)

Uploaded Python 3

File details

Details for the file centering_lgram-2.3.1.tar.gz.

File metadata

  • Download URL: centering_lgram-2.3.1.tar.gz
  • Upload date:
  • Size: 134.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for centering_lgram-2.3.1.tar.gz
Algorithm Hash digest
SHA256 4220196311abaf71f30ef7ef2d3d34c0ae986489788a756b162082bdb40e95f5
MD5 ba178eb6b23cd87d8ad886a9d8162e94
BLAKE2b-256 23a30917aee336a28a3ec455ca72b9aea6be769f9c157faa31e97d6d2df9b184

See more details on using hashes here.

File details

Details for the file centering_lgram-2.3.1-py3-none-any.whl.

File metadata

  • Download URL: centering_lgram-2.3.1-py3-none-any.whl
  • Upload date:
  • Size: 131.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for centering_lgram-2.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9b24a765ce5236ff8c72905b6947c5653b561730451429832aa274878b30d8e8
MD5 7ac692b02cb5023078bcf742f562ac3e
BLAKE2b-256 09b8873d986778ca8b7de8dc4d21f0b80ee2ded1ecd058fe60fc1a78b760fb57

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