'Mon','MONDAY'=>'Mon','TUE'=>'Tue','TUES'=>'Tue','TUESDAY'=>'Tue','WED'=>'Wed','WEDNESDAY'=>'Wed', 'THU'=>'Thu','THUR'=>'Thu','THURS'=>'Thu','THURSDAY'=>'Thu','FRI'=>'Fri','FRIDAY'=>'Fri', 'SAT'=>'Sat','SATURDAY'=>'Sat','SUN'=>'Sun','SUNDAY'=>'Sun']; $ORDER = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']; function rd_canon(array $list): array { global $DAYS, $ORDER; $set = []; foreach ($list as $d) { $k = strtoupper(trim((string)$d)); if (isset($DAYS[$k])) $set[$DAYS[$k]] = 1; } $out = []; foreach ($ORDER as $d) if (isset($set[$d])) $out[] = $d; return $out; } function openai_rundays(string $model, string $trainNo): array { $instructions = "You report Indian Railways train running days. Use web search to verify. " . "Reply with ONLY a JSON object (no prose, no code fences): " . '{"run_days":["Mon","Tue",...],"confidence":"high|medium|low","source":""}. ' . "run_days = weekday(s) the train departs origin. If not certain, set confidence low and run_days []. Never guess."; $body = json_encode([ 'model' => $model, 'tools' => [['type' => 'web_search']], 'instructions' => $instructions, 'input' => "Train number $trainNo — what days of the week does it currently run? Verify by searching.", ]); $ch = curl_init('https://api.openai.com/v1/responses'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . OPENAI_API_KEY], CURLOPT_POSTFIELDS => $body, CURLOPT_RETURNTRANSFER => true, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 50, // return before nginx's ~60s, fail gracefully CURLOPT_SSL_VERIFYPEER => true, ]); $raw = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $cerr = curl_error($ch); curl_close($ch); if ($raw === false) return ['err' => 'Call failed/timed out: ' . $cerr]; if ($code !== 200) return ['err' => "HTTP $code: " . substr((string)$raw, 0, 200)]; $resp = json_decode($raw, true); $text = ''; if (isset($resp['output_text'])) { $text = $resp['output_text']; } elseif (isset($resp['output']) && is_array($resp['output'])) { foreach ($resp['output'] as $item) { if (($item['type'] ?? '') === 'message' && !empty($item['content'])) { foreach ($item['content'] as $c) if (($c['type'] ?? '') === 'output_text') $text .= $c['text'] ?? ''; } } } $text = trim(preg_replace('/^```(json)?|```$/m', '', (string)$text)); $json = json_decode($text, true); if (!is_array($json)) return ['err' => 'Unparseable reply: ' . substr($text, 0, 160)]; return ['days' => $json['run_days'] ?? [], 'conf' => (string)($json['confidence'] ?? '?'), 'src' => (string)($json['source'] ?? '')]; } $haveKey = defined('OPENAI_API_KEY') && OPENAI_API_KEY; /* ---- AJAX: test exactly one train, return JSON ---- */ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'one') { csrf_check(); header('Content-Type: application/json'); if (!$haveKey) { echo json_encode(['err' => 'OPENAI_API_KEY not set in app/secrets.php']); exit; } $tn = preg_replace('/\D/', '', (string)($_POST['train'] ?? '')); $model = trim((string)($_POST['model'] ?? '')) ?: $MODEL_DEFAULT; $exp = trim((string)($_POST['exp'] ?? '')); if ($tn === '') { echo json_encode(['err' => 'no train number']); exit; } $r = openai_rundays($model, $tn); if (isset($r['err'])) { echo json_encode(['err' => $r['err']]); exit; } $got = rd_canon($r['days']); $match = $exp === '' ? null : ($got === rd_canon(explode(',', $exp))); echo json_encode(['got' => $got, 'match' => $match, 'conf' => $r['conf'], 'src' => $r['src']]); exit; } $seed = "12244: Mon,Wed,Thu,Fri,Sat,Sun\n15607: Wed\n12512: Tue,Wed,Sun"; $page_title = 'AI running-days test'; require APP_DIR . '/header.php'; ?> ← Admin

AI running-days test

Asks OpenAI (with web search) for each train's running days and checks it against your verified answer. Trains are tested one at a time. One miss means the model isn't reliable enough.

Add your key to app/secrets.php: define('OPENAI_API_KEY', 'sk-...');
One line per train as number: Mon,Wed,Sun. Leave the days off to just see what the model returns. Verify the days in the free irctc1 playground first so the answer key is correct. Each train is one paid API call.
gpt-5.5 is strongest but slow; if rows time out, try gpt-5.4-mini.