A working local grammar-correction engine with a CLI and loopback JSON API. GECToR handles small edits; Phi-4 Mini runs only for detected residual problems. Rewrites are reviewable suggestions by default.
The environment and model assets are installed. From the project folder:
./.venv/Scripts/python.exe -m dot "She go to school."
./.venv/Scripts/python.exe -m dot --interactive
./.venv/Scripts/python.exe -m dot --input-file sample.txt
Interactive mode keeps GECToR loaded. Enter one sentence per line; Ctrl+C exits.
Outputs are JSON. Use --no-rewrite for GECToR only. Ollama must be running with
phi4-mini:latest installed for the optional rewrite step. Choose another installed
model with --rewrite-model NAME.
{"original":"She go to school.","corrected":"She goes to school.","status":"corrected","suggestion":null,"rewrite_called":false,"reasons":[]}
Results also include residual_error_probability. This is an uncalibrated detector
score, not the probability that the sentence is fully correct.
Requires Git and an existing Python with pip. Run:
powershell -ExecutionPolicy Bypass -File scripts/setup.ps1
Setup creates a project-local Python 3.11 environment, installs the locked CPU
dependencies, and downloads approximately 1 GB of model assets. It verifies assets
against model-assets.lock.json and can be rerun. Weights, environments and caches
are excluded from Git. Only setup requires internet access; GECToR inference
resolves local paths with Hugging Face offline mode enabled.
Ollama is installed separately. On this machine, Phi-4 Mini was already installed.
Sentence data goes only to 127.0.0.1:11434, with environment proxies disabled.
./.venv/Scripts/python.exe -m dot --serve 8765
In another terminal:
Invoke-RestMethod http://127.0.0.1:8765/health
Invoke-RestMethod -Method Post -Uri http://127.0.0.1:8765/correct -ContentType 'application/json' -Body '{"text":"I has two brother."}'
The server binds only to loopback, processes requests serially, rejects foreign
browser origins, and does not log text. /health reports that GECToR is loaded;
it does not guarantee Ollama availability. There is no graphical interface yet.
dont becomes don't) outside URLs and code. Split documents conservatively.JSON results include normalized, candidate acceptance/rejection details, and
edits / suggestion_edits with original character offsets. Documents also include
segments; segment edit offsets are relative to that segment, while top-level edit
offsets address the entire original. Separator whitespace and line endings survive.
Candidate acceptance means it passed these guards, not that correctness is proven.
Edit triage now flags regular lexical past-tense changes without a time cue,
plural-to-singular changes, and singular-to-plural changes immediately after a
determiner or possessive for review. Each candidate includes edit_decisions.
When a full candidate is rejected, independent allowlisted spelling and case fixes
can still be retained. Articles and related phrase edits are not detached from
their context; they still require whole-candidate validation.
A small explicit typo list supplements residual detection, including
contriubuting. This is not a dictionary spellchecker: unknown words and names
are not automatically flagged. Literal URLs, email addresses and code are skipped.
Names, pronouns, numeric values, common spelled-out numbers, negation, modal verbs, URLs and code spans are protected heuristically. Auxiliary tense substitutions without a past-time cue are rejected. Moving existing phrases is permitted for suggestions under a separate budget.
--apply-rewrite opts into automatically applying rewrites that also pass the
stricter automatic edit budget. Larger phrase movements remain suggestions even
with this option enabled.
| Status | Meaning |
|---|---|
unchanged | No accepted edit; not a certification of correctness. |
corrected | GECToR edits accepted. |
review | Residual issue, rejected edit, unsupported input, or suggestion to review. |
rewritten | An opted-in rewrite passed the automatic guards. |
unavailable | GECToR inference failed; original retained. |
python -m unittest discover -s tests -v
$env:DOT_TEST_MODELS='1'
./.venv/Scripts/python.exe -m unittest discover -s tests -v
./.venv/Scripts/python.exe scripts/evaluate.py
All 62 tests passed with the actual GECToR model enabled, including the reported negation regression, a longer clause, and paragraph line-ending preservation. Without the opt-in, five real-model tests are skipped.
The prior candidate-routing revision's 48-case development comparison produced (these numbers predate the newer edit-triage policy):
dont example now retains negation without invoking fallback.One other exact-match miss is grammatical: “Please explain to me the problem.” The fixed reference expected a different word order. References were not changed to inflate the result. This tiny set was used during development, so these numbers are not a general accuracy estimate. See evaluation notes and current comparison. The original 28-case results remain historical records, not results for the current implementation.
./.venv/Scripts/python.exe -m dot --engine t5-direct "She go to school."
./.venv/Scripts/python.exe -m dot --engine t5-direct --interactive
./.venv/Scripts/python.exe -m dot --engine t5-direct --input-file sample.txt
This is a different execution path, not another fallback layer: the installed
Unbabel T5-small runs on every sentence, followed only by existing content/edit
guards. No GECToR model, residual detector, likelihood verifier, or Ollama call is
used. It also supports --serve PORT. The same specialist setup below installs
its assets if needed; there are no additional downloads on this machine.
Read suggestion for a passing candidate. corrected deliberately retains the
original because this experiment is manual-review-only; --apply-rewrite is not
supported. rewrite_called: false means no fallback was called, not that T5 was
skipped. candidates records T5's output and rejection reason. A null residual
probability is expected. These lightweight guards cannot prove grammatical
completeness or meaning equivalence. Unchanged output is not a correctness verdict.
The default --engine pipeline remains unchanged. The reserved 20 user sentences
are not used to tune or compare this experiment.
The default remains GECToR plus selective Phi. To install and try the pinned, approximately 242 MB T5 specialist (already installed on this machine):
./.venv/Scripts/python.exe scripts/download_specialist.py
./.venv/Scripts/python.exe -m dot --fallback t5 "She go to school."
./.venv/Scripts/python.exe -m dot --source-verifier t5 "Its a known fact that there coming to the party tonigh"
./.venv/Scripts/python.exe scripts/compare.py
Fresh setup also accepts -Specialist. Asset hashes are pinned in
specialist-assets.lock.json. The experimental verifier compares candidate versus
copying-source likelihood; it is not a calibrated semantic check. The T5 fallback
is sentence-only; unlike Phi it does not use neighboring context. Comparison needs
both the specialist assets and Ollama and writes evaluation/v2-comparison.json.
A bounded model-selection experiment now compares
the current pipeline with raw local models, including an optional CPU-only,
grammar-trained FLAN-T5 Base checkpoint. This does not change DOT's default.
The user's 20 new examples are reserved separately in
evaluation/heldout-user-001.json, excluded from development comparisons.
This version is deliberately conservative. Documents are limited to 16,000 characters and 40 sentence spans. Each sentence is limited to 240 surface tokens and 6,000 characters; GECToR also enforces a 384-subword limit. Oversized sentences are not silently truncated. Sentence splitting is heuristic, not a full linguistic parser. Spacing inside a corrected sentence may change.
Neither the detector nor these guards prove semantic equivalence. They can miss wrong-word errors, unnamed subject/object swaps, and tense changes outside the covered auxiliary cases. They can also reject legitimate edits. Heavily broken or ambiguous inputs need review; silently accepting the model output is not reliable.
Before widening automatic correction, collect representative user sentences with human-reviewed minimal corrections, then evaluate a held-out set for harmful edits, missed errors, clean-text preservation, rewrite rate and latency. The likely next addition is a calibrated residual-error classifier and stronger semantic checking, not a larger model rewriting every sentence.
A working local grammar-correction engine with a CLI and loopback JSON API. GECToR handles small edits; Phi-4 Mini runs only for detected residual problems. Rewrites are reviewable suggestions by default.
The environment and model assets are installed. From the project folder:
./.venv/Scripts/python.exe -m dot "She go to school."
./.venv/Scripts/python.exe -m dot --interactive
./.venv/Scripts/python.exe -m dot --input-file sample.txt
Interactive mode keeps GECToR loaded. Enter one sentence per line; Ctrl+C exits.
Outputs are JSON. Use --no-rewrite for GECToR only. Ollama must be running with
phi4-mini:latest installed for the optional rewrite step. Choose another installed
model with --rewrite-model NAME.
{"original":"She go to school.","corrected":"She goes to school.","status":"corrected","suggestion":null,"rewrite_called":false,"reasons":[]}
Results also include residual_error_probability. This is an uncalibrated detector
score, not the probability that the sentence is fully correct.
Requires Git and an existing Python with pip. Run:
powershell -ExecutionPolicy Bypass -File scripts/setup.ps1
Setup creates a project-local Python 3.11 environment, installs the locked CPU
dependencies, and downloads approximately 1 GB of model assets. It verifies assets
against model-assets.lock.json and can be rerun. Weights, environments and caches
are excluded from Git. Only setup requires internet access; GECToR inference
resolves local paths with Hugging Face offline mode enabled.
Ollama is installed separately. On this machine, Phi-4 Mini was already installed.
Sentence data goes only to 127.0.0.1:11434, with environment proxies disabled.
./.venv/Scripts/python.exe -m dot --serve 8765
In another terminal:
Invoke-RestMethod http://127.0.0.1:8765/health
Invoke-RestMethod -Method Post -Uri http://127.0.0.1:8765/correct -ContentType 'application/json' -Body '{"text":"I has two brother."}'
The server binds only to loopback, processes requests serially, rejects foreign
browser origins, and does not log text. /health reports that GECToR is loaded;
it does not guarantee Ollama availability. There is no graphical interface yet.
dont becomes don't) outside URLs and code. Split documents conservatively.JSON results include normalized, candidate acceptance/rejection details, and
edits / suggestion_edits with original character offsets. Documents also include
segments; segment edit offsets are relative to that segment, while top-level edit
offsets address the entire original. Separator whitespace and line endings survive.
Candidate acceptance means it passed these guards, not that correctness is proven.
Edit triage now flags regular lexical past-tense changes without a time cue,
plural-to-singular changes, and singular-to-plural changes immediately after a
determiner or possessive for review. Each candidate includes edit_decisions.
When a full candidate is rejected, independent allowlisted spelling and case fixes
can still be retained. Articles and related phrase edits are not detached from
their context; they still require whole-candidate validation.
A small explicit typo list supplements residual detection, including
contriubuting. This is not a dictionary spellchecker: unknown words and names
are not automatically flagged. Literal URLs, email addresses and code are skipped.
Names, pronouns, numeric values, common spelled-out numbers, negation, modal verbs, URLs and code spans are protected heuristically. Auxiliary tense substitutions without a past-time cue are rejected. Moving existing phrases is permitted for suggestions under a separate budget.
--apply-rewrite opts into automatically applying rewrites that also pass the
stricter automatic edit budget. Larger phrase movements remain suggestions even
with this option enabled.
| Status | Meaning |
|---|---|
unchanged | No accepted edit; not a certification of correctness. |
corrected | GECToR edits accepted. |
review | Residual issue, rejected edit, unsupported input, or suggestion to review. |
rewritten | An opted-in rewrite passed the automatic guards. |
unavailable | GECToR inference failed; original retained. |
python -m unittest discover -s tests -v
$env:DOT_TEST_MODELS='1'
./.venv/Scripts/python.exe -m unittest discover -s tests -v
./.venv/Scripts/python.exe scripts/evaluate.py
All 62 tests passed with the actual GECToR model enabled, including the reported negation regression, a longer clause, and paragraph line-ending preservation. Without the opt-in, five real-model tests are skipped.
The prior candidate-routing revision's 48-case development comparison produced (these numbers predate the newer edit-triage policy):
dont example now retains negation without invoking fallback.One other exact-match miss is grammatical: “Please explain to me the problem.” The fixed reference expected a different word order. References were not changed to inflate the result. This tiny set was used during development, so these numbers are not a general accuracy estimate. See evaluation notes and current comparison. The original 28-case results remain historical records, not results for the current implementation.
./.venv/Scripts/python.exe -m dot --engine t5-direct "She go to school."
./.venv/Scripts/python.exe -m dot --engine t5-direct --interactive
./.venv/Scripts/python.exe -m dot --engine t5-direct --input-file sample.txt
This is a different execution path, not another fallback layer: the installed
Unbabel T5-small runs on every sentence, followed only by existing content/edit
guards. No GECToR model, residual detector, likelihood verifier, or Ollama call is
used. It also supports --serve PORT. The same specialist setup below installs
its assets if needed; there are no additional downloads on this machine.
Read suggestion for a passing candidate. corrected deliberately retains the
original because this experiment is manual-review-only; --apply-rewrite is not
supported. rewrite_called: false means no fallback was called, not that T5 was
skipped. candidates records T5's output and rejection reason. A null residual
probability is expected. These lightweight guards cannot prove grammatical
completeness or meaning equivalence. Unchanged output is not a correctness verdict.
The default --engine pipeline remains unchanged. The reserved 20 user sentences
are not used to tune or compare this experiment.
The default remains GECToR plus selective Phi. To install and try the pinned, approximately 242 MB T5 specialist (already installed on this machine):
./.venv/Scripts/python.exe scripts/download_specialist.py
./.venv/Scripts/python.exe -m dot --fallback t5 "She go to school."
./.venv/Scripts/python.exe -m dot --source-verifier t5 "Its a known fact that there coming to the party tonigh"
./.venv/Scripts/python.exe scripts/compare.py
Fresh setup also accepts -Specialist. Asset hashes are pinned in
specialist-assets.lock.json. The experimental verifier compares candidate versus
copying-source likelihood; it is not a calibrated semantic check. The T5 fallback
is sentence-only; unlike Phi it does not use neighboring context. Comparison needs
both the specialist assets and Ollama and writes evaluation/v2-comparison.json.
A bounded model-selection experiment now compares
the current pipeline with raw local models, including an optional CPU-only,
grammar-trained FLAN-T5 Base checkpoint. This does not change DOT's default.
The user's 20 new examples are reserved separately in
evaluation/heldout-user-001.json, excluded from development comparisons.
This version is deliberately conservative. Documents are limited to 16,000 characters and 40 sentence spans. Each sentence is limited to 240 surface tokens and 6,000 characters; GECToR also enforces a 384-subword limit. Oversized sentences are not silently truncated. Sentence splitting is heuristic, not a full linguistic parser. Spacing inside a corrected sentence may change.
Neither the detector nor these guards prove semantic equivalence. They can miss wrong-word errors, unnamed subject/object swaps, and tense changes outside the covered auxiliary cases. They can also reject legitimate edits. Heavily broken or ambiguous inputs need review; silently accepting the model output is not reliable.
Before widening automatic correction, collect representative user sentences with human-reviewed minimal corrections, then evaluate a held-out set for harmful edits, missed errors, clean-text preservation, rewrite rate and latency. The likely next addition is a calibrated residual-error classifier and stronger semantic checking, not a larger model rewriting every sentence.