Skip to content

Commit 4cdef35

Browse files
committed
fix(inference): unpack structured records per sample, not all-or-nothing
infer_data_job() only splits the prediction / extra_records columns when EVERY sample is a structured record: if all(_is_structured_record(data_all[x]) for x in data['index']): But a sample that exhausts its retries comes back from BaseAPI.generate as a plain string (`return self.fail_msg if answer in ['', None] else answer`), while a successful one returns {"prediction": ..., "extra_records": ...}. A single failed sample therefore makes all(...) False, and every successful record in the run is stringified into its own dict repr - the extra_records column is never created, and the prediction column holds "{'prediction': ..., 'extra_records': {...}}" for downstream scoring. Unpack each sample on its own via a shared helper, and gate on any(...) so that a run with no structured records at all still takes the old path. Fully homogeneous runs (all structured, none structured) are unchanged. The SPLIT_THINK branch had the same all-or-nothing gate and is fixed too; there the corruption is worse, because split_thinking() then cuts the dict repr at '</think>' and leaves the tail glued to the answer. Fixes #1665
1 parent 5a91183 commit 4cdef35

1 file changed

Lines changed: 26 additions & 6 deletions

File tree

vlmeval/inference.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,26 @@ def _is_structured_record(v):
206206
return isinstance(v, dict) and 'prediction' in v and 'extra_records' in v
207207

208208

209+
def _unpack_structured_records(data_all, indices):
210+
"""Split per-sample results into prediction / extra_records columns.
211+
212+
A sample whose retries are exhausted comes back from `BaseAPI.generate` as
213+
a plain string rather than a structured record, so a single run can mix
214+
both shapes. Unpack each sample on its own instead of letting one string
215+
discard the structured output of every other sample.
216+
"""
217+
predictions, extra_records = [], []
218+
for x in indices:
219+
value = data_all[x]
220+
if _is_structured_record(value):
221+
predictions.append(value['prediction'])
222+
extra_records.append(value['extra_records'])
223+
else:
224+
predictions.append(str(value))
225+
extra_records.append({})
226+
return predictions, extra_records
227+
228+
209229
# A wrapper for infer_data, do the pre & post processing
210230
def infer_data_job(
211231
model, work_dir, model_name, dataset, verbose=False, api_nproc=4, retry_failed=True, use_vllm=False
@@ -245,9 +265,8 @@ def infer_data_job(
245265
for x in data['index']:
246266
assert x in data_all
247267
if os.getenv('SPLIT_THINK', False):
248-
if all(_is_structured_record(data_all[x]) for x in data['index']):
249-
prediction = [data_all[x]['prediction'] for x in data['index']]
250-
extra_records = [data_all[x]['extra_records'] for x in data['index']]
268+
if any(_is_structured_record(data_all[x]) for x in data['index']):
269+
prediction, extra_records = _unpack_structured_records(data_all, data['index'])
251270
data['extra_records'] = extra_records
252271
else:
253272
prediction = [str(data_all[x]) for x in data['index']]
@@ -274,9 +293,10 @@ def split_thinking(s):
274293
else:
275294
# data['prediction'] = [str(data_all[x]) for x in data['index']]
276295
# Add for agent evaluation
277-
if all(_is_structured_record(data_all[x]) for x in data['index']):
278-
data['prediction'] = [data_all[x]['prediction'] for x in data['index']]
279-
data['extra_records'] = [data_all[x]['extra_records'] for x in data['index']]
296+
if any(_is_structured_record(data_all[x]) for x in data['index']):
297+
predictions, extra_records = _unpack_structured_records(data_all, data['index'])
298+
data['prediction'] = predictions
299+
data['extra_records'] = extra_records
280300
else:
281301
data['prediction'] = [str(data_all[x]) for x in data['index']]
282302
if 'image' in data:

0 commit comments

Comments
 (0)