1- """上传 JSONL 批量任务,等待完成并核对任务、输出与会话回复 。
1+ """上传 JSONL 批量任务,等待完成并打印任务状态与输出 。
22
33运行:python -m examples.forward.batch
44"""
1010
1111import httpx
1212
13- from examples .common .live import Run , choose_model , marker , name , run_cli , wait_reply
13+ from examples .common .live import Run , choose_model , name , run_cli
1414from qca import Forward
1515
1616from ._cleanup import finish_session
@@ -34,12 +34,12 @@ def run(client: Forward, context: Run) -> None:
3434 )
3535 template_id = context .track ("template" , template .id , lambda : client .templates .archive (template .id ))
3636
37- expected , custom_id = marker (), name ("task" )
37+ custom_id = name ("task" )
3838 data = {
3939 "custom_id" : custom_id ,
4040 "template_id" : template_id ,
4141 "identity_id" : identity_id ,
42- "body" : {"input" : "Reply with exactly " + expected },
42+ "body" : {"input" : "请用一句话打个招呼。" },
4343 }
4444 input_file = client .files .upload (
4545 file = ("input.jsonl" , (json .dumps (data ) + "\n " ).encode ()), purpose = "session_resource"
@@ -60,60 +60,32 @@ def cleanup_batch() -> None:
6060 while current .status not in terminal :
6161 context .pause ()
6262 current = client .batches .retrieve (batch .id )
63- if not current .output_file_id :
64- if current .request_counts and current .request_counts .total == 0 :
65- return
66- raise AssertionError ("Batch has no output for session cleanup" )
67- rows = batch_rows (client , batch .id )
68- if (
69- len (rows ) != 1
70- or rows [0 ].get ("custom_id" ) != custom_id
71- or rows [0 ].get ("identity_id" ) != identity_id
72- or rows [0 ].get ("template_id" ) != template_id
73- ):
74- raise AssertionError ("Batch cleanup output does not match this run" )
75- if rows [0 ].get ("session_id" ):
76- finish_session (client , context , rows [0 ]["session_id" ])
63+ if current .output_file_id :
64+ for row in batch_rows (client , batch .id ):
65+ if row .get ("session_id" ):
66+ finish_session (client , context , row ["session_id" ])
7767
7868 context .track ("batch" , batch .id , cleanup_batch )
7969 while batch .status not in terminal :
8070 context .pause ()
8171 batch = client .batches .retrieve (batch .id )
82- if (
83- batch .status != "completed"
84- or not batch .request_counts
85- or batch .request_counts .completed != 1
86- or batch .request_counts .failed != 0
87- or not batch .output_file_id
88- ):
89- raise AssertionError ("Batch did not complete exactly one successful task" )
72+ context .output ("batch_status" , batch .status )
73+ if batch .request_counts :
74+ context .output (
75+ "request_counts" ,
76+ {"completed" : batch .request_counts .completed , "failed" : batch .request_counts .failed },
77+ )
9078 tasks = client .batches .tasks .list (batch .id )
91- if len (tasks .data ) != 1 or tasks .data [0 ].custom_id != custom_id :
92- raise AssertionError ("Batch task did not round trip" )
93- rows = batch_rows (client , batch .id )
94- if len (rows ) != 1 :
95- raise AssertionError ("Expected one Batch output row" )
96- row = rows [0 ]
97- context .output ("batch_output" , row )
98- if (
99- row .get ("custom_id" ) != custom_id
100- or row .get ("identity_id" ) != identity_id
101- or row .get ("template_id" ) != template_id
102- or row .get ("status" ) != "completed"
103- or row .get ("error" )
104- or not row .get ("session_id" )
105- ):
106- raise AssertionError ("Batch output ownership or status mismatch" )
107- if expected not in json .dumps (row .get ("response" )):
108- raise AssertionError ("Batch response does not contain expected output" )
109- wait_reply (client .sessions .events , context , row ["session_id" ]).verify ([expected ])
79+ context .output ("tasks" , [task .custom_id for task in tasks .data ])
80+ if batch .output_file_id :
81+ context .output ("batch_output" , batch_rows (client , batch .id ))
11082
11183
11284def batch_rows (client : Forward , batch_id : str ) -> list [dict [str , Any ]]:
11385 link = client .batches .retrieve_output (batch_id )
11486 url = httpx .URL (link .url )
11587 if url .scheme not in ("http" , "https" ) or not url .host or url .userinfo :
116- raise AssertionError ("Invalid Batch output URL" )
88+ raise RuntimeError ("Invalid Batch output URL" )
11789 # A separate HTTP client prevents API credentials from reaching storage.
11890 with httpx .Client (timeout = 30 , follow_redirects = True ) as download :
11991 with download .stream ("GET" , url ) as response :
@@ -122,7 +94,7 @@ def batch_rows(client: Forward, batch_id: str) -> list[dict[str, Any]]:
12294 for chunk in response .iter_bytes ():
12395 content .extend (chunk )
12496 if len (content ) > 4 * 1024 * 1024 :
125- raise AssertionError ("Batch output exceeds the example's 4 MiB limit" )
97+ raise RuntimeError ("Batch output exceeds the example's 4 MiB limit" )
12698 return [json .loads (line ) for line in content .splitlines () if line .strip ()]
12799
128100
0 commit comments