sail / sail_scripts /agent /inference.py
muterornament's picture
Industrialize: Backup sovereign training pipeline
e5b79b7 verified
Raw
History Blame Contribute Delete
4.92 kB
import torch
import torch.nn.functional as F
import os
from model.config import ModelConfig
from model.transformer import GPT
from model.tokenizer import AdvancedTokenizer
class InferenceEngine:
def __init__(self, model_path='sail.pt'):
self.device = 'cuda' if torch.cuda.is_available() else 'cpu'
self.draft_model = None # Initialized if available
if not os.path.exists(model_path):
print(f"Warning: {model_path} not found. Agent will be uninitialized.")
self.model = None
return
print(f"Loading model from {model_path}...")
try:
checkpoint = torch.load(model_path, map_location=self.device, weights_only=False)
if isinstance(checkpoint, dict) and 'config' in checkpoint:
self.config = checkpoint['config']
self.config.device = self.device
self.tokenizer = AdvancedTokenizer(vocab_size=self.config.vocab_size)
if 'vocab' in checkpoint:
self.tokenizer.word_to_id = checkpoint['vocab']
self.tokenizer.id_to_word = {v: k for k, v in self.tokenizer.word_to_id.items()}
state_dict = checkpoint['model_state_dict']
# Strip _orig_mod. prefix if model was saved compiled
state_dict = {k.replace('_orig_mod.', ''): v for k, v in state_dict.items()}
self.model = GPT(self.config).to(self.device)
self.model.load_state_dict(state_dict)
else:
import pickle
with open('tokenizer.pkl', 'rb') as f:
self.tokenizer = pickle.load(f)
self.config = ModelConfig()
self.model = GPT(self.config).to(self.device)
self.model.load_state_dict(checkpoint)
self.model.eval()
print("Model loaded successfully.")
except Exception as e:
print(f"Error loading model: {e}")
self.model = None
def speculative_generate(self, idx, max_new_tokens, K=4):
"""
Speculative Decoding: Generate multiple tokens using a draft model,
then verify them in one pass with the big model.
"""
if self.draft_model is None:
return self.model.generate(idx, max_new_tokens)
generated = 0
while generated < max_new_tokens:
T = idx.shape[1]
draft_idx = idx.clone()
for _ in range(min(K, max_new_tokens - generated)):
logits, _ = self.draft_model(draft_idx)
next_token = torch.multinomial(F.softmax(logits[:, -1, :], dim=-1), 1)
draft_idx = torch.cat([draft_idx, next_token], dim=1)
# Big model verifies in one pass
full_logits, _ = self.model(draft_idx)
# Simple acceptance logic (simplified for agentic use)
idx = draft_idx
generated += K
if generated >= max_new_tokens: break
return idx
def chat(self, prompt, system_prompt="You are a smart, agentic AI assistant.", max_steps=3):
if not self.model: return "Error: Model not loaded."
from agent.tool_executor import parse_and_execute_tools
current_text = f"[SYSTEM] {system_prompt} [USER] {prompt} [THOUGHT]"
for step in range(max_steps):
token_ids = self.tokenizer.encode(current_text)
idx = torch.tensor(token_ids, dtype=torch.long).unsqueeze(0).to(self.device)
with torch.no_grad():
out_idx = self.speculative_generate(idx, max_new_tokens=256)
generated_text = self.tokenizer.decode(out_idx[0].tolist())
# Tool Use
tool_result = parse_and_execute_tools(generated_text)
if tool_result:
current_text = generated_text + " " + tool_result
continue
else:
# Self-Critique
if "[THOUGHT]" in generated_text and "error" in generated_text.lower():
current_text = generated_text + " [THOUGHT] I detected a potential error. I must correct it."
continue
return generated_text
return generated_text
def generate(self, prompt, max_new_tokens=200, **kwargs):
if not self.model: return "Model not loaded."
token_ids = self.tokenizer.encode(prompt)
idx = torch.tensor(token_ids, dtype=torch.long).unsqueeze(0).to(self.device)
with torch.no_grad():
out_idx = self.model.generate(idx, max_new_tokens, **kwargs)
return self.tokenizer.decode(out_idx[0].tolist())