Skip to content

Commit 07a9a12

Browse files
Successfully displaying code interpreter images
1 parent 5732d1c commit 07a9a12

File tree

3 files changed

+53
-4
lines changed

3 files changed

+53
-4
lines changed

routers/chat.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,13 @@ async def handle_assistant_stream(
170170
async with stream_manager as event_handler:
171171
event: AssistantStreamEvent
172172
async for event in event_handler:
173+
# Debug logging for all events
174+
logger.debug(f"SSE Event Type: {type(event).__name__}")
175+
logger.debug(f"SSE Event Data: {event.data}")
176+
173177
if isinstance(event, ThreadMessageCreated):
174178
step_id = event.data.id
179+
logger.debug(f"Message Created - Step ID: {step_id}")
175180

176181
yield sse_format(
177182
"messageCreated",
@@ -192,6 +197,7 @@ async def handle_assistant_stream(
192197

193198
if isinstance(event, ThreadRunStepCreated) and event.data.type == "tool_calls":
194199
step_id = event.data.id
200+
logger.debug(f"Tool Call Created - Step ID: {step_id}")
195201

196202
yield sse_format(
197203
f"toolCallCreated",
@@ -207,6 +213,7 @@ async def handle_assistant_stream(
207213
if tool_calls:
208214
# TODO: Support parallel function calling
209215
tool_call = tool_calls[0]
216+
logger.debug(f"Tool Call Delta - Type: {tool_call.type}")
210217

211218
# Handle function tool call
212219
if tool_call.type == "function":
@@ -224,27 +231,33 @@ async def handle_assistant_stream(
224231
# Handle code interpreter tool calls
225232
elif tool_call.type == "code_interpreter":
226233
if tool_call.code_interpreter and tool_call.code_interpreter.input:
234+
logger.debug(f"Code Interpreter Input: {tool_call.code_interpreter.input}")
227235
yield sse_format(
228236
f"toolDelta{step_id}",
229237
str(tool_call.code_interpreter.input)
230238
)
231239
if tool_call.code_interpreter and tool_call.code_interpreter.outputs:
232240
for output in tool_call.code_interpreter.outputs:
241+
logger.debug(f"Code Interpreter Output Type: {output.type}")
233242
if output.type == "logs" and output.logs:
234243
yield sse_format(
235244
f"toolDelta{step_id}",
236245
str(output.logs)
237246
)
238247
elif output.type == "image" and output.image and output.image.file_id:
248+
logger.debug(f"Image Output - File ID: {output.image.file_id}")
249+
# Create the image HTML on the backend
250+
image_html = f'<img src="/assistants/{assistant_id}/messages/{thread_id}/files/{output.image.file_id}/content" class="code-interpreter-image">'
239251
yield sse_format(
240252
f"toolDelta{step_id}",
241-
str(output.image.file_id)
253+
image_html
242254
)
243255

244256
# If the assistant run requires an action (a tool call), break and handle it
245257
if isinstance(event, ThreadRunRequiresAction):
246258
required_action = event.data.required_action
247259
run_requires_action_event = event
260+
logger.debug("Run Requires Action Event")
248261
if required_action and required_action.submit_tool_outputs:
249262
break
250263

@@ -349,3 +362,28 @@ async def event_generator() -> AsyncGenerator[str, None]:
349362
"Connection": "keep-alive",
350363
}
351364
)
365+
366+
# Route to serve image files from OpenAI API
367+
@router.get("/files/{file_id}/content")
368+
async def get_file_content(
369+
file_id: str,
370+
client: AsyncOpenAI = Depends(lambda: AsyncOpenAI())
371+
) -> StreamingResponse:
372+
"""
373+
Streams file content from OpenAI API.
374+
This route is used to serve images and other files generated by the code interpreter.
375+
"""
376+
try:
377+
# Get the file content from OpenAI
378+
file_content = await client.files.content(file_id)
379+
file_bytes = file_content.read() # Remove await since read() returns bytes directly
380+
381+
# Return the file content as a streaming response
382+
# Note: In a production environment, you might want to add caching
383+
return StreamingResponse(
384+
content=iter([file_bytes]),
385+
media_type="image/png" # You might want to make this dynamic based on file type
386+
)
387+
except Exception as e:
388+
logger.error(f"Error getting file content: {e}")
389+
raise HTTPException(status_code=500, detail=str(e))

static/styles.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,3 +567,12 @@ pre {
567567
.reports {
568568
flex: 1;
569569
}
570+
571+
/* Code Interpreter Image Styles */
572+
.code-interpreter-image {
573+
max-width: 100%;
574+
height: auto;
575+
margin: 1rem 0;
576+
border-radius: 0.5rem;
577+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
578+
}

templates/components/assistant-run.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
<div class="assistant-run" hx-swap="beforeend"
33
hx-ext="sse"
44
sse-connect="/assistants/{{ assistant_id }}/messages/{{ thread_id }}/receive"
5-
sse-swap="messageCreated,toolCallCreated,toolOutput"
6-
sse-close="endStream">
7-
</div>
5+
sse-swap="messageCreated,toolCallCreated,toolOutput,codeInterpreterOutput"
6+
sse-close="endStream"
7+
data-assistant-id="{{ assistant_id }}"
8+
data-thread-id="{{ thread_id }}">
9+
</div>

0 commit comments

Comments
 (0)