"""Bounded API contract checks; retain complete requests and streamed responses.""" import argparse import json from pathlib import Path import time import urllib.request import urllib.error def main(): p = argparse.ArgumentParser() p.add_argument('--url', default='http://127.0.0.1:8036') p.add_argument('--model', default='candidate') p.add_argument('--out', type=Path, required=True) a = p.parse_args() results = [] def call(name, body, check, expected_status=200): payload = dict(model=a.model, max_tokens=512, temperature=0, seed=1201, chat_template_kwargs={'enable_thinking': False}) payload.update(body) started = time.perf_counter() record = dict(name=name, request=payload) request = urllib.request.Request(a.url+'/v1/chat/completions', data=json.dumps(payload).encode(), headers={'Content-Type':'application/json'}) try: with urllib.request.urlopen(request, timeout=120) as response: record['status'] = response.status if payload.get('stream'): chunks = [] done = False for line in response: if line.strip() == b'data: [DONE]': done = True elif line.startswith(b'data: '): chunks.append(dict(seconds=time.perf_counter()-started, data=json.loads(line[6:]))) record.update(chunks=chunks, done=done) else: record['response'] = json.load(response) except urllib.error.HTTPError as error: record.update(status=error.code, error=error.read().decode()) record['seconds'] = time.perf_counter()-started record['passed'] = record['status'] == expected_status and check(record) results.append(record) a.out.write_text(json.dumps(results, indent=2)) return record def content(record): return record['response']['choices'][0]['message'].get('content') or '' stream = call('stream-eos', dict(messages=[dict(role='user', content='Return only the word Mercury.')], stream=True, stream_options={'include_usage':True}), lambda r: r['done'] and ''.join(c['data']['choices'][0].get('delta',{}).get('content') or '' for c in r['chunks'] if c['data'].get('choices')).strip()=='Mercury' and any(c['data'].get('choices') and c['data']['choices'][0].get('finish_reason')=='stop' for c in r['chunks'])) call('multiturn', dict(messages=[dict(role='user',content='My project codename is Cedar. Reply OK.'), dict(role='assistant',content='OK'),dict(role='user',content='What is my project codename? Reply with the name only.')]), lambda r: content(r).strip()=='Cedar') notes = 'A workshop starts Tuesday at 10 AM and lasts two hours. ' call('supplied-facts', dict(messages=[dict(role='system',content='Use only supplied facts. Never invent people, locations, prices or contact details. Use [placeholders] for missing facts. Return a short draft only.'), dict(role='user',content='Write a one-sentence invitation using these notes: '+notes)]), lambda r: 'Tuesday' in content(r) and '10' in content(r) and ('two' in content(r) or '2' in content(r))) filler = 'The project stores local notes on disk. The settings can be reviewed. ' call('long-context-retrieval', dict(messages=[dict(role='user',content= filler*180+'\nThe access phrase for this exercise is amber-tulip-73.\n'+filler*180+ '\nReturn only the access phrase from the notes.')]), lambda r: content(r).strip()=='amber-tulip-73') # Exercise the configured limit, not just the advertised 128K upstream limit. lo,hi=180,400 while lo