File size: 2,496 Bytes
8efdc48 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | """Local runtime for separately trained Ares and Xiphos checkpoints.
Neither role executes a tool. Xiphos returns a reviewable proposal only.
"""
from dataclasses import dataclass
from pathlib import Path
import re, torch
from .config import AresConfig
from .model import AresTransformer
from .tokenizer import ByteBPETokenizer
@dataclass
class LoadedModel:
model: AresTransformer
tokenizer: ByteBPETokenizer
device: str
trained: bool
checkpoint: str
def load_model(checkpoint, tokenizer_path, device=None, expected_role=None):
device=device or ('cuda' if torch.cuda.is_available() else 'cpu')
tok=ByteBPETokenizer.load(tokenizer_path)
ckpt=torch.load(checkpoint,map_location=device,weights_only=False)
if expected_role and ckpt.get('role') not in (None, expected_role):
raise ValueError(f'Checkpoint role {ckpt.get("role")!r} cannot be loaded as {expected_role!r}')
model=AresTransformer(AresConfig(**ckpt['config'])).to(device)
model.load_state_dict(ckpt['model']); model.eval()
return LoadedModel(model,tok,device,bool(ckpt.get('training_complete',False)),str(checkpoint))
def respond(role, loaded, message, max_new=160):
if not loaded.trained:
return f'{role} is installed but its checkpoint is not trained yet. Train and evaluate it before using its output.'
# Role headers are data boundaries, not a security boundary; server never executes generated text.
prompt=f'<system>You are {role}. ' + ('Answer the user directly and helpfully.' if role=='Ares' else 'Draft a concise, non-executable implementation plan for user review.') + f'</system><user>{message}</user><assistant>'
ids=torch.tensor([loaded.tokenizer.encode(prompt,add_bos=True)],device=loaded.device)
if ids.size(1)>loaded.model.config.max_seq_len-1: ids=ids[:,-loaded.model.config.max_seq_len+1:]
out=loaded.model.generate(ids,max_new=max_new,temperature=.7)[0].tolist()
answer=loaded.tokenizer.decode(out[len(ids[0]):])
# Strip control tokens if a model emits them; never parse a response as commands.
return re.sub(r'<[^>]+>','',answer).strip()
def proposed_plan(xiphos, request):
"""Return model text in a plan envelope. Approval/execution is deliberately separate."""
return {'status':'proposed','executable':False,'request':request,'proposal':respond('Xiphos',xiphos,request),'required_review':['scope and files','data licences/privacy','resource estimate','tests and rollback','exact allowlisted commands']}
|