weiqingy opened a new issue, #936:
URL: https://github.com/apache/flink-agents/issues/936

   ### Background
   
   The OpenAI-family chat model connections (OpenAI and Azure OpenAI, both 
languages) converge on a shared message conversion helper. Comparing the two 
implementations, the non-happy-path branches diverge in three places. All three 
predate any current work, and all three are invisible on the happy path, which 
is why they have survived.
   
   Native structured output makes the first two materially more reachable. With 
`strict: true` a model refuses rather than emitting non-conforming JSON, so the 
refusal branch stops being an edge case and becomes the primary non-happy path.
   
   ### 1. A refusal is preserved in Java and dropped in Python
   
   Java, `OpenAIChatCompletionsUtils.convertFromOpenAIMessage` 
(`integrations/chat-models/openai/src/main/java/org/apache/flink/agents/integrations/chatmodels/openai/OpenAIChatCompletionsUtils.java:113`):
   
   ```java
   String content = message.content().orElse("");
   ChatMessage response = ChatMessage.assistant(content);
   
   message.refusal().ifPresent(refusal -> 
response.getExtraArgs().put("refusal", refusal));
   ```
   
   Python, `convert_from_openai_message` 
(`python/flink_agents/integrations/chat_models/openai/openai_utils.py:217`):
   
   ```python
   return ChatMessage(
       role=MessageRole(message.role),
       content=message.content or "",
       tool_calls=tool_calls,
       extra_args=extra_args,
   )
   ```
   
   There is no refusal handling on the Python side. `grep -rn "refusal" 
python/flink_agents/` returns zero hits across the whole tree, and `git log 
-S"refusal" -- python/flink_agents/` returns no commit, so the field has never 
been read there.
   
   When a provider refuses, `content` is empty on both sides. A Java caller can 
recover the reason from `extraArgs["refusal"]`. A Python caller receives an 
empty assistant message with the reason discarded, and has no way to 
distinguish a refusal from a genuinely empty completion.
   
   ### 2. `finish_reason` is never inspected in either language
   
   `grep -rni "finishReason\|finish_reason"` returns zero hits in both 
`integrations/chat-models/openai/src/main/java/` and 
`python/flink_agents/integrations/chat_models/`.
   
   A completion truncated by a token limit therefore returns as ordinary 
partial content, with nothing indicating it is incomplete. Under structured 
output this is the more damaging case of the two, because truncated JSON fails 
to parse downstream with an error that points at the parser rather than at the 
truncation.
   
   Unlike case 1 this one is symmetric, so it is a behavior question rather 
than a parity question: should a truncated completion raise, or surface the 
reason to the caller and let them decide?
   
   ### 3. Provider errors are wrapped in Java and raw in Python
   
   Java wraps non-argument exceptions from the call in 
`RuntimeException("Failed to call ... API.", e)`. The corresponding Python 
paths have no `try`/`except`, so an SDK exception, including a provider 400, 
propagates to the caller unchanged.
   
   Neither behavior is obviously wrong on its own. The divergence is the issue, 
since a caller writing against both languages sees different failure types for 
the same provider condition.
   
   ### Proposed handling
   
   Case 1 is a clear parity fix with an established reference implementation, 
and is small and self-contained: mirror the Java behavior in the Python 
converter and cover it with a test on both sides. Worth doing on its own.
   
   Cases 2 and 3 are design questions rather than mechanical fixes, and I would 
rather not fold them into the same change. Raising them here so the decision is 
recorded in one place.
   
   I'm willing to submit a PR for case 1, and happy to take 2 and 3 as 
follow-ups once there is a decision on the intended behavior.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to