KeelCore Professional: rough draft in, professional writing out

Base model  |  Technical report  |  GitHub  |  License  |  Contact


KeelCore-750M-Professional

KeelCore-750M-Professional is a LoRA adapter for KeelCore-750M that rewrites rough text into clear, professional writing. It fixes spelling and grammar, adjusts tone and wording, and keeps the meaning. It is a 73 MB file, not a full model: it needs the frozen base model to run.

  • Task: professional rewriting of English text (messages, emails, notes, short documents)
  • Size: rank-16 LoRA, 18.29M trainable parameters (2.43% of the base)
  • Runs: on CPU or GPU with PyTorch, or in a browser through ONNX Runtime Web
  • Terms of use: KeelCore License, Version 1.0 (see License)
  • Author: Saravanan A R

Model Information

Description

You give the adapter a piece of text and it returns the same message written professionally. The base model is an encoder–decoder, so it reads the whole input first and can copy names, URLs and other exact text straight into the output. The adapter teaches it the rewriting task. It is not a chat model and it does not answer questions or follow instructions in the text. It only rewrites the text it is given.

Examples

These come from the final adapter, run with the default settings described under Usage.

Input Output
hi john, i wanted to ask you if you have time tomorow for a quick call Hi John,

I wanted to ask if you have any time tomorrow to make a quick call.
sorry for late reply, i was busy in another project Apologies for the delayed response. I was occupied with another project.
Your invoice is still pending since two weeks, pay it soon. Your invoice has been pending for two weeks; please pay it promptly.
we found a vulnerabilty in the login page and fixed it yesterday We identified a vulnerability in the login page and resolved it yesterday.
i hereby confirm that all the informations provided are true I hereby confirm that all the provided information is accurate.
pls check the doc here https://docs.google.com/document/d/1AbC_xYz-99/edit?usp=sharing and tell me ur thoughts Please review the document at this link: https://docs.google.com/document/d/1AbC_xYz-99/edit?usp=sharing and share your thoughts.
Update the config in /etc/app/prod.yaml and restart the service by 10:30. Update the configuration in /etc/app/prod.yaml and restart the service by 10:30.

Inputs and outputs

Direction Description
Input Plain English text. The code adds the frame <style:professional> <text_to_rewrite> … </text_to_rewrite> </s> for you.
Output The rewritten text, up to 384 new tokens with the default settings.

Intended use

  • Cleaning up drafts: chat messages, emails, status updates, tickets and notes.
  • A rewriting step inside an application, on device or in a browser, where the text should not leave the user's machine.
  • A starting point for researchers who study small adapters on a shared base model.

Out of scope. Text where every character must survive unchanged (legal clauses, code, configuration, financial figures) unless a person checks the result. Languages other than English. Long documents without splitting them first. Generating text from scratch.

Usage

The adapter file is in a KeelCore format (adapter.safetensors with adapter_config.json), not the PEFT format, and it is loaded by the code in the KeelCore GitHub repository. It checks a fingerprint of the base weights and refuses to load onto any base other than KeelCore-750M.

git clone https://github.com/saravanan-a-r/KeelCore
pip install torch safetensors sentencepiece pyyaml huggingface_hub
huggingface-cli login      # needed while these repositories are private
import sys
from huggingface_hub import snapshot_download

sys.path.insert(0, "KeelCore/SFT_adapter_rephrase")
from src.inference import RephraseAdapter

# The base needs only these four files; the ONNX folder is not required.
base = snapshot_download(
    "KeelCore/KeelCore-750M",
    allow_patterns=["config.json", "model.safetensors", "spm.model", "token_map.json"],
)
adapter = snapshot_download("KeelCore/KeelCore-750M-Professional", ignore_patterns=["onnx/*"])  # PyTorch files only

rephraser = RephraseAdapter.load(adapter, base_checkpoint=base, tokenizer_dir=base, device="cpu")  # or "cuda"
print(rephraser.rephrase(["hey team, the client call is moved to 3pm tmrw, pls update ur calendars"]))

rephrase() takes a list of texts and returns a list of rewrites. The base loads in float32 (about 3 GB of memory).

Decoding. The defaults are greedy decoding, a ban on repeating any 3-token sequence, and at most 384 new tokens. The tokenizer writes every digit as its own token, so the ban would force numbers to change (50000 becomes 5000). The default therefore exempts the ten digit tokens from the ban. If you write your own decoding loop, keep that exemption.

Download only what you need. Both formats are in this repository, in separate places, so you never have to fetch both. For PyTorch, use ignore_patterns=["onnx/*"] as above (73 MB). For the browser or ONNX Runtime, use snapshot_download("KeelCore/KeelCore-750M-Professional", allow_patterns=["onnx/*"]) (73 MB), or request the two .onnx_adapter files directly by URL. The base model follows the same rule: its ONNX export lives in onnx/int8/ and is not downloaded by the PyTorch snippet.

In the browser. onnx/ holds this adapter converted to ONNX Runtime adapter files. They load on the int8 ONNX export in the base repository (onnx/int8/) through ONNX Runtime's LoraAdapter support (activeLoraAdapters run option). The base graphs, tokenizer and model.json are in onnx/int8/ of the base repository; model.json points to onnx/adapter.json here, which lists the two adapter files with their hashes and the base they fit. The EchoMeBetter extension in the GitHub repository is a working example.

Repository contents

File Size Description
adapter.safetensors 73 MB LoRA weights (fp32) and the learned embeddings of the three frame tokens
adapter_config.json 2 KB LoRA settings, frame tokens and the fingerprint of the base it needs
onnx/encoder.onnx_adapter, onnx/decoder.onnx_adapter 37 MB each The same adapter for the ONNX export of the base (encoder and decoder graphs)
onnx/adapter.json 1 KB The adapter's manifest for ONNX runners: style token, the two files with sizes and SHA-256 hashes, and the base it needs
training_curves.png, banner.png Images used on this page
LICENSE KeelCore License, Version 1.0

Adapter details

Base model KeelCore-750M, pretraining step 90,000 (weights unchanged)
Method LoRA with rank-stabilized scaling, rank 16, alpha 8 (scale 2.0), dropout 0.05
Where Every linear layer of the encoder and decoder: self-attention, cross-attention (q, k, v, o) and feed-forward (gate, up, down), 432 LoRA pairs
Also trained Embeddings of the three frame tokens <style:professional>, <text_to_rewrite>, </text_to_rewrite>
Trainable parameters 18,287,616

Training

The adapter was trained on about 2.37 million professional-rewrite examples for 2 passes (148,090 optimizer steps), with 20,000 further examples held out for evaluation. The base weights stayed frozen.

Setting Value
Effective batch size 32 examples
Learning rate 3e-4, 100 warm-up steps, cosine decay to 3e-5
Optimizer AdamW, no weight decay, gradient clipping at 1.0
Precision bfloat16
Loss Token-level cross-entropy, no label smoothing
Model selection Lowest held-out loss (the final step; the loss was still falling)

No optimizer step was skipped for non-finite values. Gradients were clipped on 3.5% of steps.

Evaluation

Training results

Training loss, held-out loss and SARI over 148,090 steps

Held-out loss kept falling to the last step, so it shows no sign of overfitting. Training loss steps down at the start of the second pass (step 74,045) because the model sees the examples again; the held-out loss does not step, which is the sign that matters.

Held-out results

20,000 held-out examples for loss and accuracy; the first 500 of them for generation metrics. The held-out set comes from the same source as the training data, so it is more favorable than text from a new source. The "reference" column scores the held-out examples' own target rewrites with the same metrics.

Metric No adapter This adapter Reference rewrites
Held-out loss ↓ 2.468 0.428
Perplexity ↓ 11.80 1.535
Token accuracy 70.9% 87.0%
Stops correctly (EOS accuracy) 89.4% 99.7%
Calibration error (ECE) ↓ 0.235 0.006
SARI ↑ 45.8 67.8
chrF vs the reference rewrite ↑ 59.2 72.6
chrF vs the input 97.5 68.5 63.5
Output length ÷ input length 1.00 1.07 1.09
Output identical to the input 52.8% 0.2% 0%
Protected spans kept (numbers, URLs, emails, @mentions, code) 95.2% 87.4% 90.7%
Words not in the input 1.3% 23.4% 28.8%
Repetition loops 1.0% 1.2% 5.0%
Ends with a proper stop 97.6% 97.8% 100%
Passes every quality check at once 93.0% 86.0% 85.8%

How to read this:

  • "No adapter" is the base model with the adapter switched off. It does not rewrite: more than half of its outputs are the input copied back. That is why its "meaning kept" score (chrF vs the input) is high and its "passes every check" score looks good. Neither shows rewriting quality, so compare SARI and the loss.
  • SARI scores a rewrite by what it adds, keeps and removes compared with the reference. The adapter goes from 45.8 to 67.8.
  • "Passes every quality check" requires, at once: non-empty, properly stopped, no loop, every protected span kept exactly, output at most 1.6x the input length, and chrF vs the input of at least 35. On this bar the adapter matches the reference rewrites (86.0% against 85.8%).
  • Protected spans kept is the weak number: 12.6% of outputs changed at least one number, URL, email, mention or code span. See Limitations.

Hand-written checks

To look at specific failure modes we ran the final adapter, with the default decoding, on small hand-written sets. None of their 199 inputs appears in the training data (checked by exact match). They are in the GitHub repository under SFT_adapter_rephrase/eval_sets/professional/. They are small checks, not a benchmark. We did not run other rewriting models on them.

Check Result
Misspelled words (129 words, 31 sentences) 114 corrected (88%)
Exact text that must survive (64 sentences, 138 items) 123 kept (89%)
Repetition and junk inputs (24) No runaway loops; see Limitations for two bad cases

Items that must survive, by kind:

Kept every time Not always kept
URLs 8/8, names 13/13, product names 8/8, plain numbers 15/15, long numbers 6/6, phone numbers 4/4, acronyms 11/11, paths 2/2, @mentions 3/3, units 3/3 dates 7/10, versions 4/6, code and config 8/11, IDs 5/6, emails 3/4, currency 2/3, security terms 6/8, lists 5/6, quoted speech 0/1

Limitations

  • Numbers, dates, versions and code can change. Real outputs from the final adapter:

    Input Output
    i'll be on leave from 23rd dec to 2nd jan, back on 3rd I will be on leave from December 2nd to January 2rd, returning on January 3rd.
    set MAX_RETRIES=5 and TIMEOUT_MS=30000 in the .env file Set MAX_RETRIES to 5 and TIMEOUT_MS to 30000 in the .env file.
    upgrade node from 18.17.1 to 20.11.0 and python 3.9 to 3.12 Upgrade node from 18.17.1 to 20.11.0 and change Python 3.9 to 3 12
    send invoice to accounts_payable@zentech.example and cc j.smith@zentech.example asap …cc j.smith@zentechnology.example as soon as possible.
    commit a3f9c21 broke the prod, revert it Commit a3f9c21 broke the product; please revert it.
    ur booking ref is PNR 6E-QX7Z9K, flight 6E 2134 at gate B12 …flight 6e 2134 at gate B12.

    Always compare dates, amounts, versions, identifiers and addresses against the original before you send or publish a rewrite.

  • Slang and shorthand. Common ones (pls, ur, asap) are expanded, but others are not understood: tmrw came back as TMRW, and acct as ATC in one example.

  • It can add words. About 23% of output words are not in the input, because it rewrites. On meaningless or repetitive input it may invent text: a long run of a characters came back followed by "Thank you for your attention to this matter", and ten repeats of "see" became "Please review the following".

  • Quotes and tone words. Quoted speech is sometimes reworded, and a rewrite can be more formal than you want.

  • English only, and tuned for short to medium messages. The model accepts up to 2,048 tokens, but the code does not split long text, so split long documents yourself and rewrite them in parts.

  • Output length. Rewrites are on average about 7% longer than the input, and about 1 in 4 is shorter.

  • No factual checking. The adapter does not know whether the text is true. It can make a claim sound more confident than the writer meant.

Ethical considerations and risks

A rewriter can make careless or misleading text sound polished. Do not use it to impersonate someone or to disguise the origin of content, and have a person review anything legal, medical, financial or safety-related. The license limits who may use the model and where (see below).

Benefits

A small download (73 MB on top of the base), local inference with no text sent to a server, and a result that you can compare with your original on the same screen.

License

KeelCore-750M-Professional is released under the KeelCore License, Version 1.0 (Personal and Research Use). The license file controls; this section is a summary. The license covers the model and its adapters.

  • Individuals may use KeelCore, at no cost, for their own writing (including writing for their own job or studies) and for noncommercial research, only through the official EchoMeBetter browser extension.
  • Research publications that use KeelCore must cite it (see Citation).
  • Commercial use, use by or for an organization, any use outside the official extension, and purchase of the model require a separate written agreement with the copyright holder (see Contact).
  • The names "KeelCore" and "EchoMeBetter" are used by the copyright holder for this project; the license gives no right to use them.

Downloading the files from this repository does not grant any right beyond the license. Attributions for the base model are in the NOTICE file of KeelCore-750M.

Citation

@software{keelcore2026,
  author = {Saravanan A R},
  title  = {KeelCore: A 752M Encoder-Decoder Base Model for LoRA Adapters},
  year   = {2026},
  url    = {https://github.com/saravanan-a-r/KeelCore}
}

Contact

For commercial licensing, collaboration or anything else:

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for KeelCore/KeelCore-750M-Professional

Adapter
(1)
this model