From 69f0742e05d06d3c4336b96ebc159373003ff58a Mon Sep 17 00:00:00 2001 From: alexb-palisaderesearch <189858354+alexb-palisaderesearch@users.noreply.github.com> Date: Sat, 8 Mar 2025 12:41:00 +0200 Subject: [PATCH] Fix KeyError "type" for untagged content encoding (#1439) * Update CHANGELOG.md * Fix KeyError "type" for untagged content encoding * Minify diff --------- Co-authored-by: jjallaire --- CHANGELOG.md | 1 + src/inspect_ai/model/_openai.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21a8c6d7f..6f6b857d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Improved async implementation using AnyIO (can now optionally run Trio rather than asyncio as the [async backend](https://inspect.ai-safety-institute.org.uk/parallelism.html#async-backends)). - Agent Bridge: Correct handling for `tool_choice` option. - Model API: `ChatMessage` now includes an `id` field (defaults to auto-generated uuid). +- OpenAI: More flexible parsing of content parts (some providers omit the "type" field); support for "reasoning" content parts. - Mistral: Update to new Mistral API (v1.5.1 of `mistralai` is now required). - Logging: Inspect no longer sets the global log level nor does it allow its own messages to propagate to the global handler (eliminating the possiblity of duplicate display). This should improve compatibility with applications that have their own custom logging configured. - Tasks: For filesystem based tasks, no longer switch to the task file's directory during execution (directory switching still occurs during task loading). Specify `@task(chdir=True)` to preserve the previous behavior. diff --git a/src/inspect_ai/model/_openai.py b/src/inspect_ai/model/_openai.py index 0084d6196..a94a63c71 100644 --- a/src/inspect_ai/model/_openai.py +++ b/src/inspect_ai/model/_openai.py @@ -396,6 +396,9 @@ def content_from_openai( content: ChatCompletionContentPartParam | ChatCompletionContentPartRefusalParam, parse_reasoning: bool = False, ) -> list[Content]: + # Some providers omit the type tag and use "object-with-a-single-field" encoding + if "type" not in content and len(content) == 1: + content["type"] = list(content.keys())[0] if content["type"] == "text": text = content["text"] if parse_reasoning: @@ -413,6 +416,8 @@ def content_from_openai( return [ContentText(text=text)] else: return [ContentText(text=text)] + elif content["type"] == "reasoning": + return [ContentReasoning(reasoning=content["reasoning"])] elif content["type"] == "image_url": return [ ContentImage(