Conversation
Deploying logfire-docs with
|
| Latest commit: |
a637dc1
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://d809dab7.logfire-docs.pages.dev |
| Branch Preview URL: | https://tighten-replace-cast-with-di.logfire-docs.pages.dev |
There was a problem hiding this comment.
Pull request overview
This PR refactors the OpenAI integration’s message/content parsing to centralize conversion into OTel GenAI semconv “parts”, and updates tests to ensure non-text Responses output parts (e.g., refusals) are preserved.
Changes:
- Centralized content conversion via
_convert_content_part_or_partsand applied it across chat completions + Responses input/output handling. - Standardized tool-call part creation and JSON-argument decoding via
make_tool_call_part. - Updated test expectations to assert non-text output parts are retained in semconv outputs.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
logfire/_internal/integrations/llm_providers/openai.py |
Refactors content/tool-call conversion to build semconv message parts consistently across endpoints. |
tests/otel_integrations/test_openai.py |
Updates snapshot assertion to verify refusal (non-text) content parts are preserved. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def _convert_content_part_or_parts(content: object) -> list[MessagePart]: | ||
| if not content: | ||
| return [] | ||
|
|
||
| if isinstance(content, list): | ||
| return [_convert_content_part(part) for part in cast(list[Any], content)] | ||
| else: | ||
| return [_convert_content_part(content)] |
There was a problem hiding this comment.
_convert_content_part_or_parts() treats any falsy content as “no parts” (via if not content:). This changes prior behavior for chat completions where content == '' (empty string) would still be recorded as a text part; now it will be dropped. To avoid losing information, consider checking specifically for content is None (and optionally content == []) rather than truthiness.
| """Convert a single content part to semconv format.""" | ||
| if isinstance(part, str): # pragma: no cover | ||
| return TextPart(type='text', content=part) | ||
| if not isinstance(part, dict): # pragma: no cover |
There was a problem hiding this comment.
The # pragma: no cover on the non-dict branch in _convert_content_part is no longer accurate after refactoring: chat completions commonly pass content as a plain string, so this branch will run in practice and should be covered. Consider removing the pragma (or adding a test that exercises this path) so coverage can catch regressions here.
| if not isinstance(part, dict): # pragma: no cover | |
| if not isinstance(part, dict): |
| part = cast('dict[str, Any]', part) | ||
| part_type = part.get('type', 'unknown') | ||
| if part_type == 'text': | ||
| if part_type in ('text', 'output_text'): |
There was a problem hiding this comment.
_convert_content_part normalizes OpenAI output_text parts to semconv text, but does not normalize input_text parts (which are used by the Responses API for input content parts). As a result, Responses inputs that use content-part objects may end up with raw {type: 'input_text', ...} dicts in parts instead of semconv {type: 'text', content: ...}. Consider treating input_text the same as output_text here.
| if part_type in ('text', 'output_text'): | |
| if part_type in ('text', 'output_text', 'input_text'): |
…arsing Apply equivalent changes from OpenAI refactoring PR #1769: - Add _convert_content_part_or_parts for str/list content handling - Add make_tool_call_part helper for standardized tool-call creation - Update _convert_content_part to accept object, handle non-dict inputs - Replace dict literals with ChatMessage/OutputMessage constructors - Remove cast('Role', ...) in favor of direct attribute access
Summary by cubic
Refactored the OpenAI integration to centralize content and tool-call parsing and build semconv messages directly. Also preserves non-text output parts (e.g., refusal) in Responses outputs.
Refactors
Bug Fixes
Written for commit a637dc1. Summary will update on new commits.