Text Generation
Transformers
Safetensors
English
llama
astheral
instruct
qlora
conversational
text-generation-inference
Instructions to use SEE7/Astheral with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use SEE7/Astheral with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="SEE7/Astheral") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("SEE7/Astheral") model = AutoModelForCausalLM.from_pretrained("SEE7/Astheral", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use SEE7/Astheral with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "SEE7/Astheral" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "SEE7/Astheral", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/SEE7/Astheral
- SGLang
How to use SEE7/Astheral with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "SEE7/Astheral" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "SEE7/Astheral", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "SEE7/Astheral" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "SEE7/Astheral", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use SEE7/Astheral with Docker Model Runner:
docker model run hf.co/SEE7/Astheral
File size: 10,259 Bytes
c9089df | 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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | # /// script
# dependencies = ["torch==2.8.0", "transformers==4.56.2", "peft==0.17.1", "accelerate==1.10.1", "huggingface_hub==0.34.4", "bitsandbytes==0.47.0", "safetensors==0.6.2"]
# ///
"""Budget-bounded V3 training with paired, disjoint evaluation and reload gate."""
import os, json, random, time, re, gc, hashlib, traceback
from pathlib import Path
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, Trainer, TrainingArguments, TrainerCallback, set_seed
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training, PeftModel
from huggingface_hub import HfApi, hf_hub_download
REPO='SEE7/Astheral'; REV='37adef9b3917e4a3de0bb77f0db71089b7b82202'
OUT=Path('/tmp/astheral-v3'); OUT.mkdir(exist_ok=True)
api=HfApi(); started=time.monotonic(); set_seed(20261113); rng=random.Random(20261113)
assert torch.cuda.is_available() and 'A10G' in torch.cuda.get_device_name(0)
branch='v3-expanded-20261113'
api.create_branch(REPO,branch=branch,revision=REV,exist_ok=True)
settings=json.loads(Path(hf_hub_download(REPO,'settings.json',revision=REV)).read_text())
tok=AutoTokenizer.from_pretrained(REPO,revision=REV); tok.pad_token_id=128004
report={'status':'preparing','parent_revision':REV,'hardware':torch.cuda.get_device_name(0),'job_timeout_seconds':5400,'listed_usd_per_hour':1.0,'training_seed':20261113}
def publish():
report['elapsed_seconds']=round(time.monotonic()-started,2)
(OUT/'v3_report.json').write_text(json.dumps(report,indent=2))
api.upload_folder(repo_id=REPO,folder_path=OUT,revision=branch,path_in_repo='v3-results',ignore_patterns=['merged/**'],commit_message='Record measured V3 training and evaluation artifacts')
def sample(a,b,c,kind):
if kind==0:return f'Return only the integer: {a} + {b} - {c}.',str(a+b-c),'integer'
if kind==1:return f'A crate has {a} red and {b} blue beads. Remove {c} red beads. Return only the total beads remaining.',str(a+b-c),'integer'
if kind==2:return f'Return only valid JSON with keys "item" and "count": item=part_{a}, count={b}.',{'item':f'part_{a}','count':b},'json'
if kind==3:return f'Return only one CSV value row, no header: name=Item{a}; quantity={b}; code=K{c}.',f'Item{a},{b},K{c}','exact'
if kind==4:return f'Copy exactly, no other text: Key_{a}-B{b}_C{c}',f'Key_{a}-B{b}_C{c}','exact'
return f'Write only a Python function named solve(x) that returns x * {b} + {c}.',f'x * {b} + {c}','code'
def grade(case,text):
expected=case['expected']; kind=case['kind']; text=text.strip()
try:
if kind=='json':return json.loads(text)==expected
if kind=='integer':return re.fullmatch(r'-?\d+',text) is not None and int(text)==int(expected)
if kind=='exact':return text==expected
# Parse and evaluate a tiny arithmetic-only AST; never execute model-generated code.
import ast
clean=re.sub(r'^```(?:python)?\s*|\s*```$','',text).strip();tree=ast.parse(clean)
if len(tree.body)!=1 or not isinstance(tree.body[0],ast.FunctionDef):return False
fn=tree.body[0]
if fn.name!='solve' or len(fn.args.args)!=1 or fn.args.args[0].arg!='x' or len(fn.body)!=1 or not isinstance(fn.body[0],ast.Return):return False
def calc(n,x):
if isinstance(n,ast.Constant) and isinstance(n.value,(int,float)):return n.value
if isinstance(n,ast.Name) and n.id=='x':return x
if isinstance(n,ast.BinOp) and isinstance(n.op,(ast.Add,ast.Sub,ast.Mult)):
a,b=calc(n.left,x),calc(n.right,x)
return a+b if isinstance(n.op,ast.Add) else a-b if isinstance(n.op,ast.Sub) else a*b
raise ValueError('Unsupported expression')
match=re.fullmatch(r'x \* (\d+) \+ (\d+)',expected);b,c=map(int,match.groups())
return all(calc(fn.body[0].value,x)==x*b+c for x in [-5,0,1,7,100])
except Exception:return False
tests=[]
for i in range(60):
# Evaluation numbers are outside the synthetic training ranges.
a,b,c=701+i*3,91+i,31+i%17;p,e,k=sample(a,b,c,i%6)
tests.append({'id':f'heldout_{i:02}','prompt':p,'expected':e,'kind':k})
train=[]
for i in range(900):
a,b,c=rng.randint(100,500),rng.randint(10,80),rng.randint(1,29)
p,e,k=sample(a,b,c,i%6)
answer=json.dumps(e) if k=='json' else 'def solve(x):\n return '+e if k=='code' else str(e)
train.append({'messages':[{'role':'user','content':p},{'role':'assistant','content':answer}]})
retained=[json.loads(s) for s in Path(hf_hub_download(REPO,'train.jsonl',revision=REV)).read_text().splitlines()]
rng.shuffle(retained);train+=retained[:900];rng.shuffle(train)
assert not {x['prompt'] for x in tests} & {m['content'] for row in train for m in row['messages'] if m['role']=='user'}
(OUT/'heldout_cases.json').write_text(json.dumps(tests,indent=2));(OUT/'training.jsonl').write_text('\n'.join(json.dumps(x) for x in train)+'\n')
(OUT/'train_v3.py').write_text(Path(__file__).read_text())
q=BitsAndBytesConfig(load_in_4bit=True,bnb_4bit_quant_type='nf4',bnb_4bit_use_double_quant=True,bnb_4bit_compute_dtype=torch.bfloat16)
model=AutoModelForCausalLM.from_pretrained(REPO,revision=REV,quantization_config=q,device_map={'':'cuda:0'},torch_dtype=torch.bfloat16,attn_implementation='sdpa')
@torch.inference_mode()
def evaluate(label):
model.eval(); rows=[]
for i,case in enumerate(tests):
inputs=tok.apply_chat_template([{'role':'system','content':settings['system']},{'role':'user','content':case['prompt']}],tokenize=True,add_generation_prompt=True,return_dict=True,return_tensors='pt').to('cuda')
out=model.generate(**inputs,max_new_tokens=96,do_sample=False,pad_token_id=128004,eos_token_id=128009)
text=tok.decode(out[0,inputs['input_ids'].shape[1]:],skip_special_tokens=True)
rows.append({**case,'output':text,'pass':grade(case,text),'tokens':int(out.shape[1]-inputs['input_ids'].shape[1])})
print('EVAL',label,i,rows[-1]['pass'],flush=True)
(OUT/(label+'_outputs.json')).write_text(json.dumps(rows,indent=2))
return rows
try:
baseline=evaluate('v2_quantized'); report['baseline_passed']=sum(r['pass'] for r in baseline);publish()
model=prepare_model_for_kbit_training(model,use_gradient_checkpointing=True)
model=get_peft_model(model,LoraConfig(r=32,lora_alpha=64,lora_dropout=0.05,target_modules=['q_proj','k_proj','v_proj','o_proj','gate_proj','up_proj','down_proj'],task_type='CAUSAL_LM'))
model.config.use_cache=False;encoded=[]
for row in train:
messages=row['messages']; prefix=tok.apply_chat_template(messages[:-1],tokenize=True,add_generation_prompt=True)
full=tok.apply_chat_template(messages,tokenize=True,add_generation_prompt=False)
if len(full)<=512 and full[:len(prefix)]==prefix:encoded.append({'input_ids':full,'labels':[-100]*len(prefix)+full[len(prefix):]})
def collate(rows):
length=max(len(r['input_ids']) for r in rows)
return {k:torch.tensor([r[k]+[pad]*(length-len(r[k])) for r in rows]) for k,pad in [('input_ids',128004),('labels',-100)]}|{'attention_mask':torch.tensor([[1]*len(r['input_ids'])+[0]*(length-len(r['input_ids'])) for r in rows])}
class Budget(TrainerCallback):
def on_step_end(self,args,state,control,**kwargs):
if time.monotonic()-started>2400:control.should_training_stop=True
return control
args=TrainingArguments(output_dir='/tmp/v3-checkpoints',max_steps=360,per_device_train_batch_size=1,gradient_accumulation_steps=4,learning_rate=5e-6,warmup_ratio=0.05,bf16=True,gradient_checkpointing=True,gradient_checkpointing_kwargs={'use_reentrant':False},optim='paged_adamw_8bit',save_strategy='no',logging_steps=10,report_to='none',remove_unused_columns=False,seed=20261113)
trainer=Trainer(model=model,args=args,train_dataset=encoded,data_collator=collate,callbacks=[Budget()])
report.update(status='training',training_examples=len(encoded),trainable_parameters=sum(p.numel() for p in model.parameters() if p.requires_grad));publish()
result=trainer.train();report['training']=result.metrics;report['optimizer_steps']=trainer.state.global_step
adapter=OUT/'adapter';model.save_pretrained(adapter,safe_serialization=True);tok.save_pretrained(adapter)
model.config.use_cache=True;model.gradient_checkpointing_disable();candidate=evaluate('v3_quantized')
report['candidate_passed']=sum(r['pass'] for r in candidate);report['status']='trained';publish()
del trainer,model;gc.collect();torch.cuda.empty_cache()
model=AutoModelForCausalLM.from_pretrained(REPO,revision=REV,torch_dtype=torch.bfloat16,device_map={'':'cuda:0'},attn_implementation='sdpa')
model=PeftModel.from_pretrained(model,adapter).merge_and_unload(safe_merge=True)
model.config.astheral_version='3';merged=OUT/'merged';model.save_pretrained(merged,safe_serialization=True,max_shard_size='4GB');tok.save_pretrained(merged)
del model;gc.collect();torch.cuda.empty_cache()
model=AutoModelForCausalLM.from_pretrained(merged,torch_dtype=torch.bfloat16,device_map={'':'cuda:0'},attn_implementation='sdpa')
reloaded=evaluate('v3_reloaded');report['reloaded_passed']=sum(r['pass'] for r in reloaded)
groups={kind:{'baseline':sum(r['pass'] for r in baseline if r['kind']==kind),'candidate':sum(r['pass'] for r in reloaded if r['kind']==kind),'total':sum(r['kind']==kind for r in tests)} for kind in {x['kind'] for x in tests}}
report['groups']=groups;report['quality_gate_passed']=report['reloaded_passed']>report['baseline_passed'] and all(v['candidate']>=v['baseline'] for v in groups.values())
report['status']='complete';report['peak_gpu_bytes']=torch.cuda.max_memory_allocated();publish()
# Save the actual trained weights to the isolated candidate branch even on a failed gate.
api.upload_folder(repo_id=REPO,folder_path=merged,revision=branch,commit_message='Save reloaded V3 candidate weights; see measured quality gate in v3-results')
if report['quality_gate_passed']:
api.create_tag(REPO,tag='v3-expanded-candidate',revision=api.model_info(REPO,revision=branch).sha,exist_ok=True)
print('V3_COMPLETE',json.dumps(report),flush=True)
except Exception:
report['status']='failed';report['error']=traceback.format_exc();publish();raise
|