Pull the amount, sender, reference and date out of mobile-money and bank SMS, then decide in one pass whether it is genuine, which account it belongs to and whether anyone needs to look at it.
Across Africa, a payment often exists only as a text message: an MTN MoMo confirmation, an M-Pesa receipt, a bank alert forwarded as a screenshot. Lenders, merchants and bookkeeping apps need those numbers in a database, and every provider words its messages differently.
Fake alerts are written to look exactly like the real ones. Parsing the text is not enough; something has to judge whether the message should be trusted before the goods leave the counter.
MIST-Extract-1.0 fills a template with recipient, amount, fee, reference and date, from the text or a screenshot. On held-out documents it reads dates at 0.979, amounts at 0.984 and currencies at 0.975 field accuracy.
MIST-Extract-1.0Pass the message and the extracted fields to PurpleMIST-Flash-1.0 with your questions, for example: is this a genuine provider message, which ledger does it belong to, how urgent is a review. It answers every question in one pass, in English and eight African languages.
PurpleMIST-Flash-1.0Both models return calibrated confidences, so a payment can be booked automatically only when the fields and the verdict are all confident, and held for a person otherwise.
The Olaverse SDK wraps the models with sane defaults. If you would rather not add a dependency, the second tab is the same pipeline in plain transformers.
import os, sys
from huggingface_hub import hf_hub_download, snapshot_download
path = snapshot_download("olaverse/MIST-Extract-1.0")
sys.path.insert(0, path)
from mist_extract import Extractor
repo = "olaverse/PurpleMIST-Flash-1.0"
sys.path.insert(0, os.path.dirname(hf_hub_download(repo, "purplemist.py")))
from purplemist import Decider
x = Extractor.from_pretrained(path, device="cuda")
d = Decider.from_pretrained(repo, device="cuda")
TEMPLATE = {"sender": "verbatim-string", "amount": "number", "currency": "string",
"reference": "verbatim-string", "date": "date"}
QUESTIONS = {
"genuine": {"type": "noul", "instructions": "This is a genuine payment notification from a bank or mobile-money provider."},
"review": {"type": "noul", "instructions": "A person should check this before goods or credit are released."},
}
def handle(sms):
fields = x.extract(TEMPLATE, text=sms, instructions="Dates are day/month/year.")
verdict = d.decide({"message": sms, "extracted": fields["data"]}, QUESTIONS)
return fields["data"], verdictEvery figure on this page comes from the published model cards. Download the weights and check us.
Fill a JSON template from a photo, a scan or plain text, with a calibrated confidence on every field. Built for African documents and currencies, in English and African languages.
/ Decisions · FrontierRoute, flag and score tickets, chats and records with calibrated probabilities, in English and eight African languages, from one self-hosted model instead of a chain of LLM calls.
The weights are open, so you can build it yourself this afternoon. If you would rather we tuned it to your domain, evaluated it properly, and handed it over, tell us what you are working on.