inspect-ai 0.3.70__py3-none-any.whl → 0.3.72__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- inspect_ai/_cli/eval.py +14 -8
- inspect_ai/_display/core/display.py +2 -0
- inspect_ai/_display/core/footer.py +13 -3
- inspect_ai/_display/plain/display.py +6 -2
- inspect_ai/_display/rich/display.py +19 -6
- inspect_ai/_display/textual/app.py +6 -1
- inspect_ai/_display/textual/display.py +4 -0
- inspect_ai/_display/textual/widgets/transcript.py +10 -6
- inspect_ai/_eval/task/run.py +5 -8
- inspect_ai/_util/content.py +20 -1
- inspect_ai/_util/transcript.py +10 -4
- inspect_ai/_util/working.py +4 -0
- inspect_ai/_view/www/App.css +6 -0
- inspect_ai/_view/www/dist/assets/index.css +115 -87
- inspect_ai/_view/www/dist/assets/index.js +5324 -2276
- inspect_ai/_view/www/eslint.config.mjs +24 -1
- inspect_ai/_view/www/log-schema.json +283 -20
- inspect_ai/_view/www/package.json +8 -3
- inspect_ai/_view/www/src/App.tsx +2 -2
- inspect_ai/_view/www/src/components/AnsiDisplay.tsx +4 -3
- inspect_ai/_view/www/src/components/Card.tsx +9 -8
- inspect_ai/_view/www/src/components/DownloadButton.tsx +2 -1
- inspect_ai/_view/www/src/components/EmptyPanel.tsx +2 -2
- inspect_ai/_view/www/src/components/ErrorPanel.tsx +4 -3
- inspect_ai/_view/www/src/components/ExpandablePanel.tsx +13 -5
- inspect_ai/_view/www/src/components/FindBand.tsx +3 -3
- inspect_ai/_view/www/src/components/HumanBaselineView.tsx +3 -3
- inspect_ai/_view/www/src/components/LabeledValue.tsx +5 -4
- inspect_ai/_view/www/src/components/LargeModal.tsx +18 -13
- inspect_ai/_view/www/src/components/{LightboxCarousel.css → LightboxCarousel.module.css} +22 -18
- inspect_ai/_view/www/src/components/LightboxCarousel.tsx +36 -27
- inspect_ai/_view/www/src/components/MessageBand.tsx +2 -1
- inspect_ai/_view/www/src/components/NavPills.tsx +9 -8
- inspect_ai/_view/www/src/components/ProgressBar.tsx +2 -1
- inspect_ai/_view/www/src/components/TabSet.tsx +21 -15
- inspect_ai/_view/www/src/index.tsx +2 -2
- inspect_ai/_view/www/src/metadata/MetaDataGrid.tsx +11 -9
- inspect_ai/_view/www/src/metadata/MetaDataView.tsx +3 -2
- inspect_ai/_view/www/src/metadata/MetadataGrid.module.css +1 -0
- inspect_ai/_view/www/src/metadata/RenderedContent.tsx +16 -0
- inspect_ai/_view/www/src/plan/DatasetDetailView.tsx +3 -2
- inspect_ai/_view/www/src/plan/DetailStep.tsx +2 -1
- inspect_ai/_view/www/src/plan/PlanCard.tsx +2 -5
- inspect_ai/_view/www/src/plan/PlanDetailView.tsx +6 -9
- inspect_ai/_view/www/src/plan/ScorerDetailView.tsx +2 -1
- inspect_ai/_view/www/src/plan/SolverDetailView.tsx +3 -3
- inspect_ai/_view/www/src/samples/InlineSampleDisplay.tsx +2 -2
- inspect_ai/_view/www/src/samples/SampleDialog.tsx +3 -3
- inspect_ai/_view/www/src/samples/SampleDisplay.tsx +2 -2
- inspect_ai/_view/www/src/samples/SampleSummaryView.tsx +2 -2
- inspect_ai/_view/www/src/samples/SamplesTools.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatMessage.tsx +3 -19
- inspect_ai/_view/www/src/samples/chat/ChatMessageRenderer.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatMessageRow.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatView.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatViewVirtualList.tsx +22 -7
- inspect_ai/_view/www/src/samples/chat/MessageContent.tsx +35 -6
- inspect_ai/_view/www/src/samples/chat/MessageContents.tsx +2 -2
- inspect_ai/_view/www/src/samples/chat/messages.ts +15 -2
- inspect_ai/_view/www/src/samples/chat/tools/ToolCallView.tsx +13 -4
- inspect_ai/_view/www/src/samples/chat/tools/ToolInput.module.css +2 -2
- inspect_ai/_view/www/src/samples/chat/tools/ToolInput.tsx +18 -19
- inspect_ai/_view/www/src/samples/chat/tools/ToolOutput.module.css +1 -1
- inspect_ai/_view/www/src/samples/chat/tools/ToolOutput.tsx +4 -3
- inspect_ai/_view/www/src/samples/chat/tools/ToolTitle.tsx +2 -2
- inspect_ai/_view/www/src/samples/error/FlatSampleErrorView.tsx +2 -3
- inspect_ai/_view/www/src/samples/error/SampleErrorView.tsx +3 -2
- inspect_ai/_view/www/src/samples/list/SampleFooter.tsx +2 -1
- inspect_ai/_view/www/src/samples/list/SampleHeader.tsx +2 -1
- inspect_ai/_view/www/src/samples/list/SampleList.tsx +57 -45
- inspect_ai/_view/www/src/samples/list/SampleRow.tsx +2 -1
- inspect_ai/_view/www/src/samples/list/SampleSeparator.tsx +2 -1
- inspect_ai/_view/www/src/samples/sample-tools/EpochFilter.tsx +2 -2
- inspect_ai/_view/www/src/samples/sample-tools/SelectScorer.tsx +4 -3
- inspect_ai/_view/www/src/samples/sample-tools/SortFilter.tsx +2 -5
- inspect_ai/_view/www/src/samples/sample-tools/sample-filter/SampleFilter.tsx +2 -2
- inspect_ai/_view/www/src/samples/scores/SampleScoreView.tsx +2 -1
- inspect_ai/_view/www/src/samples/scores/SampleScores.tsx +2 -2
- inspect_ai/_view/www/src/samples/transcript/ApprovalEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/ErrorEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/InfoEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/InputEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/LoggerEventView.module.css +4 -0
- inspect_ai/_view/www/src/samples/transcript/LoggerEventView.tsx +12 -2
- inspect_ai/_view/www/src/samples/transcript/ModelEventView.module.css +1 -1
- inspect_ai/_view/www/src/samples/transcript/ModelEventView.tsx +25 -28
- inspect_ai/_view/www/src/samples/transcript/SampleInitEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/SampleLimitEventView.tsx +5 -4
- inspect_ai/_view/www/src/samples/transcript/SampleTranscript.tsx +2 -2
- inspect_ai/_view/www/src/samples/transcript/SandboxEventView.tsx +8 -7
- inspect_ai/_view/www/src/samples/transcript/ScoreEventView.tsx +2 -2
- inspect_ai/_view/www/src/samples/transcript/StepEventView.tsx +3 -3
- inspect_ai/_view/www/src/samples/transcript/SubtaskEventView.tsx +18 -14
- inspect_ai/_view/www/src/samples/transcript/ToolEventView.tsx +5 -5
- inspect_ai/_view/www/src/samples/transcript/TranscriptView.tsx +34 -15
- inspect_ai/_view/www/src/samples/transcript/event/EventNav.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/event/EventNavs.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/event/EventRow.tsx +3 -2
- inspect_ai/_view/www/src/samples/transcript/event/EventSection.tsx +2 -2
- inspect_ai/_view/www/src/samples/transcript/event/EventTimingPanel.module.css +28 -0
- inspect_ai/_view/www/src/samples/transcript/event/EventTimingPanel.tsx +115 -0
- inspect_ai/_view/www/src/samples/transcript/event/utils.ts +29 -0
- inspect_ai/_view/www/src/samples/transcript/state/StateDiffView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/state/StateEventRenderers.tsx +3 -3
- inspect_ai/_view/www/src/samples/transcript/state/StateEventView.tsx +11 -8
- inspect_ai/_view/www/src/types/log.d.ts +129 -34
- inspect_ai/_view/www/src/usage/ModelTokenTable.tsx +6 -10
- inspect_ai/_view/www/src/usage/ModelUsagePanel.module.css +4 -0
- inspect_ai/_view/www/src/usage/ModelUsagePanel.tsx +32 -9
- inspect_ai/_view/www/src/usage/TokenTable.tsx +4 -6
- inspect_ai/_view/www/src/usage/UsageCard.tsx +2 -1
- inspect_ai/_view/www/src/utils/format.ts +1 -1
- inspect_ai/_view/www/src/utils/json.ts +24 -0
- inspect_ai/_view/www/src/workspace/WorkSpace.tsx +6 -5
- inspect_ai/_view/www/src/workspace/WorkSpaceView.tsx +9 -2
- inspect_ai/_view/www/src/workspace/error/TaskErrorPanel.tsx +2 -1
- inspect_ai/_view/www/src/workspace/navbar/Navbar.tsx +2 -1
- inspect_ai/_view/www/src/workspace/navbar/PrimaryBar.tsx +3 -3
- inspect_ai/_view/www/src/workspace/navbar/ResultsPanel.tsx +4 -3
- inspect_ai/_view/www/src/workspace/navbar/SecondaryBar.tsx +5 -4
- inspect_ai/_view/www/src/workspace/navbar/StatusPanel.tsx +5 -8
- inspect_ai/_view/www/src/workspace/sidebar/EvalStatus.tsx +5 -4
- inspect_ai/_view/www/src/workspace/sidebar/LogDirectoryTitleView.tsx +2 -1
- inspect_ai/_view/www/src/workspace/sidebar/Sidebar.tsx +2 -1
- inspect_ai/_view/www/src/workspace/sidebar/SidebarLogEntry.tsx +2 -2
- inspect_ai/_view/www/src/workspace/sidebar/SidebarScoreView.tsx +2 -1
- inspect_ai/_view/www/src/workspace/sidebar/SidebarScoresView.tsx +2 -2
- inspect_ai/_view/www/src/workspace/tabs/InfoTab.tsx +2 -2
- inspect_ai/_view/www/src/workspace/tabs/JsonTab.tsx +2 -5
- inspect_ai/_view/www/src/workspace/tabs/SamplesTab.tsx +12 -11
- inspect_ai/_view/www/yarn.lock +241 -5
- inspect_ai/log/_condense.py +3 -0
- inspect_ai/log/_recorders/eval.py +6 -1
- inspect_ai/log/_transcript.py +58 -1
- inspect_ai/model/__init__.py +2 -0
- inspect_ai/model/_call_tools.py +7 -0
- inspect_ai/model/_chat_message.py +22 -7
- inspect_ai/model/_conversation.py +10 -8
- inspect_ai/model/_generate_config.py +25 -4
- inspect_ai/model/_model.py +133 -57
- inspect_ai/model/_model_output.py +3 -0
- inspect_ai/model/_openai.py +106 -40
- inspect_ai/model/_providers/anthropic.py +281 -153
- inspect_ai/model/_providers/google.py +27 -8
- inspect_ai/model/_providers/groq.py +9 -4
- inspect_ai/model/_providers/openai.py +57 -4
- inspect_ai/model/_providers/openai_o1.py +10 -0
- inspect_ai/model/_providers/providers.py +1 -1
- inspect_ai/model/_reasoning.py +15 -2
- inspect_ai/scorer/_model.py +23 -19
- inspect_ai/solver/_human_agent/agent.py +14 -10
- inspect_ai/solver/_human_agent/commands/__init__.py +7 -3
- inspect_ai/solver/_human_agent/commands/submit.py +76 -30
- inspect_ai/tool/__init__.py +2 -0
- inspect_ai/tool/_tool.py +3 -1
- inspect_ai/tool/_tools/_computer/_common.py +117 -58
- inspect_ai/tool/_tools/_computer/_computer.py +80 -57
- inspect_ai/tool/_tools/_computer/_resources/image_home_dir/.config/Code/User/settings.json +7 -1
- inspect_ai/tool/_tools/_computer/_resources/image_home_dir/.config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml +91 -0
- inspect_ai/tool/_tools/_computer/_resources/tool/.pylintrc +8 -0
- inspect_ai/tool/_tools/_computer/_resources/tool/.vscode/settings.json +12 -0
- inspect_ai/tool/_tools/_computer/_resources/tool/_args.py +78 -0
- inspect_ai/tool/_tools/_computer/_resources/tool/_constants.py +20 -0
- inspect_ai/tool/_tools/_computer/_resources/tool/_run.py +1 -1
- inspect_ai/tool/_tools/_computer/_resources/tool/_x11_client.py +175 -113
- inspect_ai/tool/_tools/_computer/_resources/tool/computer_tool.py +76 -20
- inspect_ai/tool/_tools/_computer/_resources/tool/pyproject.toml +65 -0
- inspect_ai/tool/_tools/_computer/test_args.py +151 -0
- inspect_ai/tool/_tools/_web_browser/_resources/.pylintrc +8 -0
- inspect_ai/tool/_tools/_web_browser/_resources/.vscode/launch.json +24 -0
- inspect_ai/tool/_tools/_web_browser/_resources/.vscode/settings.json +25 -0
- inspect_ai/tool/_tools/_web_browser/_resources/Dockerfile +5 -6
- inspect_ai/tool/_tools/_web_browser/_resources/README.md +10 -11
- inspect_ai/tool/_tools/_web_browser/_resources/accessibility_tree.py +71 -0
- inspect_ai/tool/_tools/_web_browser/_resources/accessibility_tree_node.py +323 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/__init__.py +5 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/a11y.py +279 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/dom.py +9 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/dom_snapshot.py +293 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/page.py +94 -0
- inspect_ai/tool/_tools/_web_browser/_resources/constants.py +2 -0
- inspect_ai/tool/_tools/_web_browser/_resources/images/usage_diagram.svg +2 -0
- inspect_ai/tool/_tools/_web_browser/_resources/playwright_browser.py +50 -0
- inspect_ai/tool/_tools/_web_browser/_resources/playwright_crawler.py +31 -359
- inspect_ai/tool/_tools/_web_browser/_resources/playwright_page_crawler.py +280 -0
- inspect_ai/tool/_tools/_web_browser/_resources/pyproject.toml +65 -0
- inspect_ai/tool/_tools/_web_browser/_resources/rectangle.py +64 -0
- inspect_ai/tool/_tools/_web_browser/_resources/rpc_client_helpers.py +146 -0
- inspect_ai/tool/_tools/_web_browser/_resources/scale_factor.py +64 -0
- inspect_ai/tool/_tools/_web_browser/_resources/test_accessibility_tree_node.py +180 -0
- inspect_ai/tool/_tools/_web_browser/_resources/test_playwright_crawler.py +15 -9
- inspect_ai/tool/_tools/_web_browser/_resources/test_rectangle.py +15 -0
- inspect_ai/tool/_tools/_web_browser/_resources/test_web_client.py +44 -0
- inspect_ai/tool/_tools/_web_browser/_resources/web_browser_rpc_types.py +39 -0
- inspect_ai/tool/_tools/_web_browser/_resources/web_client.py +198 -48
- inspect_ai/tool/_tools/_web_browser/_resources/web_client_new_session.py +26 -25
- inspect_ai/tool/_tools/_web_browser/_resources/web_server.py +178 -39
- inspect_ai/tool/_tools/_web_browser/_web_browser.py +38 -19
- inspect_ai/util/__init__.py +2 -1
- inspect_ai/util/_display.py +12 -0
- inspect_ai/util/_sandbox/events.py +55 -21
- inspect_ai/util/_sandbox/self_check.py +131 -43
- inspect_ai/util/_subtask.py +11 -0
- {inspect_ai-0.3.70.dist-info → inspect_ai-0.3.72.dist-info}/METADATA +1 -1
- {inspect_ai-0.3.70.dist-info → inspect_ai-0.3.72.dist-info}/RECORD +209 -186
- {inspect_ai-0.3.70.dist-info → inspect_ai-0.3.72.dist-info}/WHEEL +1 -1
- inspect_ai/_view/www/src/components/VirtualList.module.css +0 -19
- inspect_ai/_view/www/src/components/VirtualList.tsx +0 -292
- inspect_ai/tool/_tools/_computer/_computer_split.py +0 -198
- inspect_ai/tool/_tools/_web_browser/_resources/accessibility_node.py +0 -312
- inspect_ai/tool/_tools/_web_browser/_resources/dm_env_servicer.py +0 -275
- inspect_ai/tool/_tools/_web_browser/_resources/images/usage_diagram.png +0 -0
- inspect_ai/tool/_tools/_web_browser/_resources/test_accessibility_node.py +0 -176
- inspect_ai/tool/_tools/_web_browser/_resources/test_dm_env_servicer.py +0 -135
- inspect_ai/tool/_tools/_web_browser/_resources/test_web_environment.py +0 -71
- inspect_ai/tool/_tools/_web_browser/_resources/web_environment.py +0 -184
- {inspect_ai-0.3.70.dist-info → inspect_ai-0.3.72.dist-info}/LICENSE +0 -0
- {inspect_ai-0.3.70.dist-info → inspect_ai-0.3.72.dist-info}/entry_points.txt +0 -0
- {inspect_ai-0.3.70.dist-info → inspect_ai-0.3.72.dist-info}/top_level.txt +0 -0
inspect_ai/model/_openai.py
CHANGED
@@ -27,11 +27,18 @@ from openai.types.chat.chat_completion_message_tool_call import Function
|
|
27
27
|
from openai.types.completion_usage import CompletionUsage
|
28
28
|
from openai.types.shared_params.function_definition import FunctionDefinition
|
29
29
|
|
30
|
-
from inspect_ai._util.content import
|
30
|
+
from inspect_ai._util.content import (
|
31
|
+
Content,
|
32
|
+
ContentAudio,
|
33
|
+
ContentImage,
|
34
|
+
ContentReasoning,
|
35
|
+
ContentText,
|
36
|
+
)
|
31
37
|
from inspect_ai._util.images import file_as_data_uri
|
32
38
|
from inspect_ai._util.url import is_http_url
|
33
39
|
from inspect_ai.model._call_tools import parse_tool_call
|
34
40
|
from inspect_ai.model._model_output import ChatCompletionChoice, Logprobs
|
41
|
+
from inspect_ai.model._reasoning import parse_content_with_reasoning
|
35
42
|
from inspect_ai.tool import ToolCall, ToolChoice, ToolFunction, ToolInfo
|
36
43
|
|
37
44
|
from ._chat_message import (
|
@@ -148,14 +155,14 @@ async def openai_chat_message(
|
|
148
155
|
if message.tool_calls:
|
149
156
|
return ChatCompletionAssistantMessageParam(
|
150
157
|
role=message.role,
|
151
|
-
content=message
|
158
|
+
content=openai_assistant_content(message),
|
152
159
|
tool_calls=[
|
153
160
|
openai_chat_tool_call_param(call) for call in message.tool_calls
|
154
161
|
],
|
155
162
|
)
|
156
163
|
else:
|
157
164
|
return ChatCompletionAssistantMessageParam(
|
158
|
-
role=message.role, content=message
|
165
|
+
role=message.role, content=openai_assistant_content(message)
|
159
166
|
)
|
160
167
|
elif message.role == "tool":
|
161
168
|
return ChatCompletionToolMessageParam(
|
@@ -175,16 +182,29 @@ async def openai_chat_messages(
|
|
175
182
|
return [await openai_chat_message(message, model) for message in messages]
|
176
183
|
|
177
184
|
|
185
|
+
def openai_assistant_content(message: ChatMessageAssistant) -> str:
|
186
|
+
if isinstance(message.content, str):
|
187
|
+
content = message.content
|
188
|
+
else:
|
189
|
+
content = ""
|
190
|
+
for c in message.content:
|
191
|
+
if c.type == "reasoning":
|
192
|
+
attribs = ""
|
193
|
+
if c.signature is not None:
|
194
|
+
attribs = f'{attribs} signature="{c.signature}"'
|
195
|
+
if c.redacted:
|
196
|
+
attribs = f'{attribs} redacted="true"'
|
197
|
+
content = f"{content}\n<think{attribs}>\n{c.reasoning}\n</think>\n"
|
198
|
+
elif c.type == "text":
|
199
|
+
content = f"{content}\n{c.text}"
|
200
|
+
return content
|
201
|
+
|
202
|
+
|
178
203
|
def openai_chat_choices(choices: list[ChatCompletionChoice]) -> list[Choice]:
|
179
204
|
oai_choices: list[Choice] = []
|
180
205
|
|
181
206
|
for index, choice in enumerate(choices):
|
182
|
-
|
183
|
-
content = choice.message.content
|
184
|
-
else:
|
185
|
-
content = "\n".join(
|
186
|
-
[c.text for c in choice.message.content if c.type == "text"]
|
187
|
-
)
|
207
|
+
content = openai_assistant_content(choice.message)
|
188
208
|
if choice.message.tool_calls:
|
189
209
|
tool_calls = [openai_chat_tool_call(tc) for tc in choice.message.tool_calls]
|
190
210
|
else:
|
@@ -274,35 +294,47 @@ def chat_messages_from_openai(
|
|
274
294
|
chat_messages: list[ChatMessage] = []
|
275
295
|
|
276
296
|
for message in messages:
|
297
|
+
content: str | list[Content] = []
|
277
298
|
if message["role"] == "system" or message["role"] == "developer":
|
278
299
|
sys_content = message["content"]
|
279
300
|
if isinstance(sys_content, str):
|
280
301
|
chat_messages.append(ChatMessageSystem(content=sys_content))
|
281
302
|
else:
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
)
|
303
|
+
content = []
|
304
|
+
for sc in sys_content:
|
305
|
+
content.extend(content_from_openai(sc))
|
306
|
+
chat_messages.append(ChatMessageSystem(content=content))
|
287
307
|
elif message["role"] == "user":
|
288
308
|
user_content = message["content"]
|
289
309
|
if isinstance(user_content, str):
|
290
310
|
chat_messages.append(ChatMessageUser(content=user_content))
|
291
311
|
else:
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
)
|
312
|
+
content = []
|
313
|
+
for uc in user_content:
|
314
|
+
content.extend(content_from_openai(uc))
|
315
|
+
chat_messages.append(ChatMessageUser(content=content))
|
297
316
|
elif message["role"] == "assistant":
|
298
317
|
# resolve content
|
299
|
-
asst_content = message
|
318
|
+
asst_content = message.get("content", None)
|
300
319
|
if isinstance(asst_content, str):
|
301
|
-
|
320
|
+
result = parse_content_with_reasoning(asst_content)
|
321
|
+
if result is not None:
|
322
|
+
content = [
|
323
|
+
ContentReasoning(
|
324
|
+
reasoning=result.reasoning,
|
325
|
+
signature=result.signature,
|
326
|
+
redacted=result.redacted,
|
327
|
+
),
|
328
|
+
ContentText(text=result.content),
|
329
|
+
]
|
330
|
+
else:
|
331
|
+
content = asst_content
|
302
332
|
elif asst_content is None:
|
303
333
|
content = message.get("refusal", None) or ""
|
304
334
|
else:
|
305
|
-
content = [
|
335
|
+
content = []
|
336
|
+
for ac in asst_content:
|
337
|
+
content.extend(content_from_openai(ac, parse_reasoning=True))
|
306
338
|
|
307
339
|
# resolve reasoning (OpenAI doesn't suport this however OpenAI-compatible
|
308
340
|
# interfaces e.g. DeepSeek do include this field so we pluck it out)
|
@@ -310,22 +342,25 @@ def chat_messages_from_openai(
|
|
310
342
|
"reasoning", None
|
311
343
|
)
|
312
344
|
if reasoning is not None:
|
313
|
-
|
345
|
+
if isinstance(content, str):
|
346
|
+
content = [ContentText(text=content)]
|
347
|
+
else:
|
348
|
+
content.insert(0, ContentReasoning(reasoning=str(reasoning)))
|
314
349
|
|
315
350
|
# return message
|
316
351
|
if "tool_calls" in message:
|
317
352
|
tool_calls: list[ToolCall] = []
|
318
|
-
for
|
319
|
-
tool_calls.append(tool_call_from_openai(
|
320
|
-
tool_names[
|
353
|
+
for call in message["tool_calls"]:
|
354
|
+
tool_calls.append(tool_call_from_openai(call))
|
355
|
+
tool_names[call["id"]] = call["function"]["name"]
|
321
356
|
|
322
357
|
else:
|
323
358
|
tool_calls = []
|
359
|
+
|
324
360
|
chat_messages.append(
|
325
361
|
ChatMessageAssistant(
|
326
362
|
content=content,
|
327
363
|
tool_calls=tool_calls or None,
|
328
|
-
reasoning=reasoning,
|
329
364
|
)
|
330
365
|
)
|
331
366
|
elif message["role"] == "tool":
|
@@ -333,7 +368,9 @@ def chat_messages_from_openai(
|
|
333
368
|
if isinstance(tool_content, str):
|
334
369
|
content = tool_content
|
335
370
|
else:
|
336
|
-
content = [
|
371
|
+
content = []
|
372
|
+
for tc in tool_content:
|
373
|
+
content.extend(content_from_openai(tc))
|
337
374
|
chat_messages.append(
|
338
375
|
ChatMessageTool(
|
339
376
|
content=content,
|
@@ -357,20 +394,40 @@ def tool_call_from_openai(tool_call: ChatCompletionMessageToolCallParam) -> Tool
|
|
357
394
|
|
358
395
|
def content_from_openai(
|
359
396
|
content: ChatCompletionContentPartParam | ChatCompletionContentPartRefusalParam,
|
360
|
-
|
397
|
+
parse_reasoning: bool = False,
|
398
|
+
) -> list[Content]:
|
361
399
|
if content["type"] == "text":
|
362
|
-
|
400
|
+
text = content["text"]
|
401
|
+
if parse_reasoning:
|
402
|
+
result = parse_content_with_reasoning(text)
|
403
|
+
if result:
|
404
|
+
return [
|
405
|
+
ContentReasoning(
|
406
|
+
reasoning=result.reasoning,
|
407
|
+
signature=result.signature,
|
408
|
+
redacted=result.redacted,
|
409
|
+
),
|
410
|
+
ContentText(text=result.content),
|
411
|
+
]
|
412
|
+
else:
|
413
|
+
return [ContentText(text=text)]
|
414
|
+
else:
|
415
|
+
return [ContentText(text=text)]
|
363
416
|
elif content["type"] == "image_url":
|
364
|
-
return
|
365
|
-
|
366
|
-
|
417
|
+
return [
|
418
|
+
ContentImage(
|
419
|
+
image=content["image_url"]["url"], detail=content["image_url"]["detail"]
|
420
|
+
)
|
421
|
+
]
|
367
422
|
elif content["type"] == "input_audio":
|
368
|
-
return
|
369
|
-
|
370
|
-
|
371
|
-
|
423
|
+
return [
|
424
|
+
ContentAudio(
|
425
|
+
audio=content["input_audio"]["data"],
|
426
|
+
format=content["input_audio"]["format"],
|
427
|
+
)
|
428
|
+
]
|
372
429
|
elif content["type"] == "refusal":
|
373
|
-
return ContentText(text=content["refusal"])
|
430
|
+
return [ContentText(text=content["refusal"])]
|
374
431
|
|
375
432
|
|
376
433
|
def chat_message_assistant_from_openai(
|
@@ -380,11 +437,20 @@ def chat_message_assistant_from_openai(
|
|
380
437
|
reasoning = getattr(message, "reasoning_content", None) or getattr(
|
381
438
|
message, "reasoning", None
|
382
439
|
)
|
440
|
+
|
441
|
+
msg_content = refusal or message.content or ""
|
442
|
+
if reasoning is not None:
|
443
|
+
content: str | list[Content] = [
|
444
|
+
ContentReasoning(reasoning=str(reasoning)),
|
445
|
+
ContentText(text=msg_content),
|
446
|
+
]
|
447
|
+
else:
|
448
|
+
content = msg_content
|
449
|
+
|
383
450
|
return ChatMessageAssistant(
|
384
|
-
content=
|
451
|
+
content=content,
|
385
452
|
source="generate",
|
386
453
|
tool_calls=chat_tool_calls_from_openai(message, tools),
|
387
|
-
reasoning=reasoning,
|
388
454
|
)
|
389
455
|
|
390
456
|
|