#!/usr/bin/env python3 """Export visible assistant replies for the fixed EP1 cohort (no reasoning/headers/tools).""" import hashlib, json, pathlib ROOT=pathlib.Path(__file__).resolve().parents[1] SNAPSHOTS=['exp-20260915-ep1-f005-docker.json','exp-20260918-ep1-f005-glm-probe1200.json'] def visible_reply(path): response=json.loads(path.read_text()) body=response.get('body') chunks=[] if isinstance(body,dict):chunks=[body] elif isinstance(body,str): for line in body.splitlines(): if not line.startswith('data: '):continue try:chunks.append(json.loads(line[6:])) except json.JSONDecodeError:continue if not chunks: try:chunks=[json.loads(body)] except json.JSONDecodeError:pass text=[];has_tools=False for chunk in chunks: for choice in chunk.get('choices',[]): delta=choice.get('delta',choice.get('message',{})) if isinstance(delta.get('content'),str):text.append(delta['content']) has_tools=has_tools or bool(delta.get('tool_calls')) return ''.join(text),has_tools def main(): runs=[]; excluded_titles=[] for name in SNAPSHOTS: for row in json.loads((ROOT/'data/experiments'/name).read_text())['runs']: if row['task']!='ep1-f005':continue messages=[] for p in sorted((ROOT/'data/runs'/row['run_id']/'turns').glob('*.response.json')): text,tools=visible_reply(p) try: title=json.loads(text) except (json.JSONDecodeError,TypeError): title=None if isinstance(title,dict) and set(title)=={'title'} and isinstance(title['title'],str): excluded_titles.append({'source':str(p.relative_to(ROOT)),'sourceSha256':hashlib.sha256(p.read_bytes()).hexdigest()}) continue if text.strip():messages.append({'source':str(p.relative_to(ROOT)),'sourceSha256':hashlib.sha256(p.read_bytes()).hexdigest(),'text':text,'hasToolCalls':tools}) assert messages, row['run_id'] runs.append({'id':row['run_id'],'model':row['model'],'attempt':row['attempt'],'budget':row['params']['timeout_s'],'messages':messages}) assert len(runs)==20 out=ROOT/'site/evidence/ep1-reference/answer-corpus.json' out.write_text(json.dumps({'scope':'Visible assistant content only. No reasoning_content, request headers, tool arguments or tool outputs. Fixed 20-run cohort. Excludes auxiliary JSON-only title replies.','excludedAuxiliaryTitles':excluded_titles,'runs':runs},ensure_ascii=False,indent=2)+'\n') print(json.dumps({'runs':len(runs),'excludedAuxiliaryTitles':len(excluded_titles),'visibleMessages':sum(len(r['messages']) for r in runs)})) if __name__=='__main__':main()