← All work

NenoDoc Lexicon by Neno Technologies

Archive indexers fix grammar and style without a name, date or figure changing

In NenoDoc Lexicon, Neno Technologies' knowledge workspace, writing help for English and French archive notes never rewrites the whole text. A rules engine finds errors, the model resolves only unclear spans, and approved names, places and acronyms are locked first.

Government, Legal & DefenseArchive knowledge workspaceBuilt from zero

Lexicon Ask AI: query list with Answer/Grounding tabs and source PDF panel (red QA boxes)

The challenge

Indexers wanted grammar, paraphrase and quality help in English and French, but a model that rewrites text can silently change a name, a date or a figure in a government record.

What we did

Approved terms are masked first, a rules engine detects errors, only spelling and grammar spans go to a self-hosted model, and edits apply span by span with the facts checked afterward.

The outcome

Indexers get writing help that leaves approved names, numbers and attributions untouched in both languages, verified by the client on its own test documents.

Protected
Approved names, numbers and attributions
Tools
Grammar, paraphrase, standards, structure my notes
Languages
English and French, accents kept
Models
Self-hosted, no outside AI service

The starting point

NenoDoc Lexicon is Neno Technologies' knowledge workspace for archive indexers: they process government records, extract people, places, organizations and acronyms, and write notes and briefs. It runs in English and French on self-hosted models.

What had to change

Indexers wanted grammar, paraphrase and quality help, but a model that rewrites text can silently change a name, a date or a figure. In archive work that is worse than no help at all.

What could not break

  • Approved names, places, organizations and acronyms never change
  • Numbers, dates and attributions come back exactly as written
  • French accents survive every step
  • No outside AI service, since the rules engine and models run on the client's own host
  • Standards checks name the approved rule they apply

The calls we made

We decided the model should never be trusted with the whole text, only with the parts a rules engine could not settle on its own.

  1. 01

    Rules detect, the model resolves spans

    Self-hosted LanguageTool finds the errors. Punctuation, spacing and capitalization fixes apply directly. Spelling and grammar issues go to the model, which sees only the words around each flag and returns an edit for that span alone.

    Ruled out

    Letting the model regenerate the whole passage and hoping the facts survive.

  2. 02

    The registry becomes the dictionary

    Only terms an organization has approved, never pending or rejected ones, are masked first. At the client's request we went further and loaded the registry as a custom dictionary in English and French, so neither the rules nor the model can change those names.

    Ruled out

    Relying on prompts to tell the model which names to leave alone.

  3. 03

    Pin the facts, then verify

    Paraphrase is the riskiest task because the model writes new text, so it pins named entities, numbers and attributions at generation and checks them again afterward, catching a changed fact before the indexer sees it.

    Ruled out

    Trusting the output because it reads well.

  4. 04

    A small model for edits, a larger one for reasoning

    Grammar and paraphrase run on a small self-hosted model and reasoning on a larger one, sharing one GPU with OCR and embeddings.

    Ruled out

    Sending every writing task to the largest model.

  5. 05

    Every rule traceable

    Standards and quality checks cite the approved rule by title and version, and an organization with no approved rules is told there is nothing to check against. Approval roles are split so a reviewer reads the source before deciding.

    Ruled out

    A generic compliant label, or a score nobody can trace to an approved rule.

How the system fits together

writeapprove termstextdictionarymasked textflagged errorsambiguous spansproposed editsclear fixesverified editsArchive indexersWrite notes andbriefs in EN or FRReviewersApprove terms, readthe source firstNotes anddraftsLanguage chosen witha selectorApprovalregistryPeople, places,…Registry maskLocks approved termsbefore checksConfidence routerClear fixes apply,unclear spans…Fidelity checkNames, numbers,…LanguageToolSelf-hosted rulesengine, detectsSelf-hostedmodelsSmall for spans,larger for reasoningSpan editsApplied in place,facts unchanged
PeopleData storeBuilt by DaticsOutside serviceAI modelApproved terms are masked before any check, the model only resolves ambiguous spans, and only verified span edits reach the text, all on the client's own GPU host.

What we built

01

Entity extraction with approval

People, places, organizations and acronyms extracted from documents, including acronyms from definition paragraphs, and approved by reviewers into a registry.

02

Grammar and paraphrase

Span level grammar fixes and constrained paraphrase in English and French, with the language set by an explicit selector rather than guessed, and French accents and elisions preserved.

03

Standards and structure

Quality checks against the organization's approved rules that cite the rule title and version, and a structure my notes tool that keeps every number and year as written.

04

Review workflow

Split approval roles so a reviewer reads the source before deciding, inside a workspace with four roles and an admin for each organization.

How it works

Choose

The indexer picks a tool and the language, English or French.

Mask

Approved registry terms in the text are locked before any check runs.

Detect

The rules engine flags grammar and style issues, and clear fixes apply directly.

Resolve

Only ambiguous spans go to the model, which proposes an edit for that span alone.

Verify

Edits apply span by span, and names, numbers and attributions are checked against the original.

A closer look

A grammar check on a French noteSample data
{
  "tool": "grammar",
  "language": "fr",
  "locked_terms": ["Office des Archives Foncières", "OAF", "A. Laurent"],
  "edits": [
    {
      "span": "les dossiers  transférés",
      "replacement": "les dossiers transférés",
      "resolved_by": "rules, spacing"
    },
    {
      "span": "Le directeur et son adjoint a signé",
      "replacement": "Le directeur et son adjoint ont signé",
      "resolved_by": "model, grammar span"
    }
  ],
  "fidelity": {
    "names": "unchanged",
    "numbers": "unchanged",
    "attributions": "unchanged"
  }
}

What changed

Indexers get grammar, paraphrase and quality help that leaves approved names, numbers and attributions untouched, in English and French. The client checked each round on its own test documents, and the same registry also protects terms in the workspace's answers.

Under the hood

Datics role
Product built by Datics
Grammar engine
Self-hosted LanguageTool for detection, with a smaller self-hosted model for spans and a larger one for reasoning, served through vLLM.
Registry
Approved people, places, organizations and acronyms in PostgreSQL, loaded as a custom dictionary in English and French and shared with retrieval.
Deployment
Docker Compose on the client's own AWS GPU host with vLLM, and no outside AI service.

Data and retrieval

PostgreSQLpgvector

Cloud and infrastructure

Docker Compose

Apps and APIs

ReactFastAPI

Also in the stack

LanguageToolvLLMQwen

How it shipped

  1. First writing tools

    Grammar checking moved to self-hosted LanguageTool at the client's request, inside the rebuilt workspace's writing assistant.

  2. Redesign

    We proposed the mask, detect, route and apply design with the registry as a dictionary in both languages, and the client approved it with its change requests.

  3. QA fixes

    QA confirmed fixes to entity typing and acronym extraction, and that structure my notes no longer changed numbers or years.

  4. Client verification

    The client's test rounds checked that approved terms stayed protected, figures came back as written and paraphrase kept its facts, and each finding was fixed and rechecked.

Redesigned with the client

We proposed the detect, route and apply design, and the client approved its change requests, including the registry dictionary and split approval roles.

Every question answered plainly

When the client asked how the registry, the routing and the language selector worked, we answered each in plain terms before the next test round.

Tested on their documents

The client checked each round on its own test documents, and every finding was fixed and rechecked.

What this unlocked

Next is closing the open registry items, such as terms that exist only in the registry, so answers and writing tools obey one approved list everywhere.

Have a product with the same kind of constraints?

Tell us what already exists and what you want it to do. We will tell you what it takes.

Book a 30-minute Product Review