Skip to content

Malformed chat responses abort the run in the text-generation and QA codegens #8486

Description

@PG1204

What happened?

(Description corrected after review of #8617 - see the note at the end.)

TextGenCodegen.parsePython extracts the chat response with no guard at all:

return body["choices"][0]["message"]["content"]

QaRankingCodegen.parsePython guards only on key presence, at three sites:

if "choices" in body:
    return body["choices"][0]["message"]["content"]

Neither validates what choices actually contains, so unusual-but-valid responses put non-string values into the result column:

  • {"choices": [{"message": {"content": null}}]} → Python None is written to the cell
  • {"choices": [{"message": {"content": 42}}]} → the number is written to the cell
  • {"choices": [{"message": {"content": [{"type": "text", "text": "hi"}]}}]} → the raw list is written to the cell, rather than the text. Some OpenAI-compatible providers return content in this parts form.

Shapes that raise: an empty choices list, a missing message or content, a non-dict choices, are already handled: _parse_response wraps the branch in except (KeyError, IndexError, TypeError) and falls back to json.dumps(body). So this is not a crash, and the run is never aborted. The gap is that the extraction trusts the shape it is given and can emit a non-string cell value, where the native hf-inference paths beside it degrade cleanly via body.get("answer", json.dumps(body)).

This path is reachable in practice: of the top 100 models by downloads, 45 for text-generation, 37 for question-answering and 72 for sentence-similarity have a live third-party provider, so the chat branch does execute for these tasks.

The equivalent sites in ImageTaskCodegen were raised in review by @Ma77Ball on #7920; these remaining ones are in code merged earlier (#7798) and were left out of that PR to keep the diff focused.

How to reproduce?

Run the operator with text-generation (or any of the QA/ranking tasks) against a model whose cheapest provider is a third-party chat provider, and have that provider return a 200 whose message.content is null, numeric, or a list of parts. The result column receives that value as-is instead of text.

Version/Branch

1.4.0-incubating-SNAPSHOT (main)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions