routing-agent / main.py
Ugas's picture
Upload routing agent adapters and source code
975dbdd verified
Raw History Blame Contribute Delete
4.32 kB
#!/usr/bin/env python3
import os
import sys
import argparse
import csv
import torch
ROOT = os.path.dirname(__file__)
def build_dataset_from_csv(csv_path):
dataset = []
with open(csv_path, newline='', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
q = row.get('question') or row.get('Question')
lbl = row.get('label') or row.get('Label')
if q is None or lbl is None:
continue
try:
lbl = int(lbl)
except Exception:
continue
dataset.append({'question': q, 'label': lbl})
return dataset
class EmbedderWrapper:
"""Wrap a SentenceTransformer instance to ensure tensors are on `device`.
The wrapper exposes `encode(texts, convert_to_tensor=True, **kwargs)` same as
the SentenceTransformer API and will move returned torch.Tensor to the device.
"""
def __init__(self, embedder, device):
self.embedder = embedder
self.device = device
def encode(self, texts, convert_to_tensor=True, **kwargs):
emb = self.embedder.encode(texts, convert_to_tensor=convert_to_tensor, **kwargs)
# Move tensor outputs to device (if it's a torch.Tensor)
if convert_to_tensor and hasattr(emb, 'to'):
try:
emb = emb.to(self.device)
except Exception:
pass
return emb
def main():
parser = argparse.ArgumentParser(description='Run SFT training for RouterNetwork')
parser.add_argument('--csv', default='processed_dataset.csv', help='Path to CSV dataset')
parser.add_argument('--model_name', default='all-MiniLM-L6-v2', help='SentenceTransformer model name')
parser.add_argument('--epochs', type=int, default=5)
parser.add_argument('--lr', type=float, default=1e-3)
parser.add_argument('--checkpoint', default='router_checkpoint.pt', help='Checkpoint output path')
parser.add_argument('--device', default=None, help='Device to use (cpu or cuda). Auto-detect if unset')
args = parser.parse_args()
# Ensure routing_agent directory is importable such that its modules' imports work
routing_agent_path = os.path.join(ROOT, 'routing_agent')
if routing_agent_path not in sys.path:
sys.path.insert(0, routing_agent_path)
# Import modules from routing_agent (sft_trainer expects to import model as a top-level module)
try:
import sft_trainer
import model as model_mod
except Exception as e:
print('Failed importing routing_agent modules:', e)
sys.exit(1)
# Device selection
if args.device:
device = torch.device(args.device)
else:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# Build dataset
csv_path = os.path.join(ROOT, args.csv) if not os.path.isabs(args.csv) else args.csv
if not os.path.exists(csv_path):
print('Dataset CSV not found at', csv_path)
sys.exit(1)
dataset = build_dataset_from_csv(csv_path)
if len(dataset) == 0:
print('No valid rows found in dataset. Exiting.')
sys.exit(1)
# Initialize embedder
try:
from sentence_transformers import SentenceTransformer
except Exception as e:
print('sentence-transformers not installed or failed to import:', e)
sys.exit(1)
embedder = SentenceTransformer(args.model_name)
embedder_wrapper = EmbedderWrapper(embedder, device)
# Infer embedding dim and instantiate model from the same module sft_trainer expects
try:
embed_dim = embedder.get_sentence_embedding_dimension()
except Exception:
# fallback to common dim
embed_dim = 384
model = model_mod.RouterNetwork(embedding_dim=embed_dim, num_classes=3).to(device)
# Run SFT training
print(f"Starting SFT training on device={device} with model={args.model_name} | epochs={args.epochs} | lr={args.lr}")
sft_trainer.train_sft(model, embedder_wrapper, dataset, epochs=args.epochs, lr=args.lr)
# Save checkpoint
try:
torch.save(model.state_dict(), args.checkpoint)
print('Saved checkpoint to', args.checkpoint)
except Exception as e:
print('Failed to save checkpoint:', e)
if __name__ == '__main__':
main()