Letterweave-1.0-E2B / inference.py
magnus919's picture
Publish Letterweave owner-authorized release with provenance, benchmark and usage documentation
4405d34 verified
Raw History Blame Contribute Delete
2.82 kB
"""Classify one subject/body JSON record using Letterweave's evaluated contract."""
import argparse
import json
import math
from pathlib import Path
def main():
parser=argparse.ArgumentParser(description=__doc__)
parser.add_argument('--checkpoint', default='Groktopus/Letterweave-1.0-E2B')
parser.add_argument('--revision', help='Pin a published model commit for reproducibility')
parser.add_argument('--email', type=Path, required=True, help='UTF-8 JSON file with subject and body strings')
args=parser.parse_args()
state=json.loads(args.email.read_text())
if set(state)!={'subject','body'} or not all(isinstance(v,str) for v in state.values()):
raise ValueError('Expected exactly subject and body strings')
if len(state['subject'])+len(state['body'])>32768:
raise ValueError('Input exceeds the bounded CLI character cap')
import unsloth # Patch before transformers or torch model loading.
import torch
from huggingface_hub import snapshot_download
from unsloth import FastDecisionModel
from unsloth.models.clef import encode_record
if not torch.cuda.is_available():
raise RuntimeError('This release was qualified on CUDA, not CPU inference')
folder=Path(args.checkpoint)
if not folder.is_dir():
folder=Path(snapshot_download(args.checkpoint,revision=args.revision))
model,tokenizer=FastDecisionModel.from_pretrained(str(folder),max_seq_length=2048,load_in_4bit=True,dtype=torch.bfloat16,offload_embedding=False)
if not all(p.device.type=='cuda' for p in model.parameters()):
raise RuntimeError('GPU-resident configuration required; CPU fallback is not qualified')
questions=json.loads((folder/'questions.json').read_text())
mapping=json.loads((folder/'label-map.json').read_text())
text_tokenizer=getattr(tokenizer,'tokenizer',tokenizer)
record=encode_record(text_tokenizer,{'state':state,'questions':questions},max_length=16384)
if len(record.input_ids)>2048 or len(record.questions)!=7:
raise ValueError('Complete input exceeds the evaluated 2048-token, seven-question contract')
FastDecisionModel.for_inference(model)
answers=FastDecisionModel.predict(model,tokenizer,state,questions)
if set(answers)!=set(mapping.values()):
raise ValueError('Unexpected answer IDs')
probabilities={label:float(answers[qid]['noul']) for label,qid in mapping.items()}
if not all(math.isfinite(p) and 0<=p<=1 for p in probabilities.values()):
raise ValueError('Invalid purpose probability')
print(json.dumps({'labels':[label for label,p in probabilities.items() if p>.5],'probabilities':probabilities,'threshold':0.5,'threshold_policy':'strictly_greater_than','input_tokens':len(record.input_ids)},ensure_ascii=False))
if __name__=='__main__':
main()