#!/usr/bin/env node import {parseArgs} from 'node:util'; import {writeFileSync} from 'node:fs'; try { const {values:o}=parseArgs({options:{endpoint:{type:'string'},model:{type:'string'},hardware:{type:'string'},requests:{type:'string',default:'10'},warmup:{type:'string',default:'1'},prompt:{type:'string',default:'Explain the purpose of a benchmark in one sentence.'},out:{type:'string',default:'orbitriva-run.json'},name:{type:'string',default:'Inference benchmark'},'max-tokens':{type:'string',default:'128'},help:{type:'boolean'}}}); if(o.help){console.log('Usage: node benchmark.mjs --endpoint http://localhost:8000/v1 --model MODEL --hardware "Your hardware" [--requests 10] [--warmup 1] [--prompt TEXT] [--max-tokens 128] [--out run.json]\nOptional authentication: set MODEL_API_KEY in your local environment. Never upload it.');process.exit(0);} if(!o.endpoint||!o.model||!o.hardware)throw new Error('--endpoint, --model and --hardware are required. Use --help.'); const endpoint=new URL(o.endpoint);if(!['http:','https:'].includes(endpoint.protocol)||endpoint.username||endpoint.password||endpoint.search||endpoint.hash)throw new Error('Endpoint must be an HTTP(S) base URL without credentials, query or fragment.'); const requests=Number(o.requests),warmup=Number(o.warmup),maxTokens=Number(o['max-tokens']); if(!Number.isInteger(requests)||requests<1||requests>1000||!Number.isInteger(warmup)||warmup<0||warmup>100||!Number.isInteger(maxTokens)||maxTokens<1||maxTokens>32768)throw new Error('Requests: 1–1000. Warmup: 0–100. Max tokens: 1–32768.'); if(process.env.MODEL_API_KEY&&endpoint.protocol==='http:'&&!['localhost','127.0.0.1','[::1]'].includes(endpoint.hostname))throw new Error('Use HTTPS to send an API key to a remote endpoint.'); const samples=[];const url=endpoint.href.replace(/\/$/,'')+'/chat/completions'; for(let i=0;i=warmup){const outputTokens=result.usage?.completion_tokens;samples.push({latencyMs,...(Number.isSafeInteger(outputTokens)&&outputTokens>=0?{outputTokens}:{})});} console.error(`${i