Skip to content

Conversation

@tsaiggo
Copy link
Contributor

@tsaiggo tsaiggo commented Oct 29, 2025

Linked issue: #286

Purpose of change

This PR adds support for the Azure AI chat model as a foundational model for the agent.

Tests

I added one test to verify this change, but I ran into some issues while running the test cases:

  1. When I tried to run the AgentWithOllamaExample, the output stream didn't produce any data. Consequently, the same thing happened when I tested my new AgentWithAzureAIExample. My assumption is that this isn't related to the chat model implementation itself, but is more likely a higher-level issue (perhaps in the core agent logic or streaming setup).
  2. Because of this, I switched to a different test case, ReActAgentExample. I modified it locally to use my Azure AI implementation, and it worked perfectly. However, I did not commit this change, as my PR should not introduce breaking changes to existing examples.
  3. Finally, since this PR integrates a cloud-hosted model, I cannot check in my personal endpoint or API key. Therefore, I created the new AgentWithAzureAIExample and leveraged the MockChatModel (from AgentWithResource) to add mock tests. The "happy path" for this mock test passes successfully.

API

No

Documentation

Yes, exactly. It's because we now offer more model options.

@wenjin272
Copy link
Collaborator

Hi, @tsaiggo, thanks for your work. I will take a look today.

I verified the question of ollama test you mentioned, it is generated after we minor refactor the OllamaChatModelConnection in #279 but forgot to adapt the ollama integration test. I fix it in #291.

Copy link
Collaborator

@wenjin272 wenjin272 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, @tsaiggo, thanks for your contribution. I left some minor comments.

this.prompt = descriptor.getArgument("prompt");
this.tools = (java.util.List<String>) descriptor.getArgument("tools");
this.key = descriptor.getArgument("key");
this.endpoint = descriptor.getArgument("endpoint");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

key and endpoint should be the arguments of AzureAIChatModelConnection. Different AzureAIChatModelSetup can share the same AzureAIChatModelConnection.

java.util.Map<String, Object> params = new java.util.HashMap<>();
params.put("model", model);
params.put("prompt", prompt);
params.put("tools", tools);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Base class BaseChatModelSetup will process the prompt and tools directly, no need to pass them as parameters here.

case USER:
return new ChatRequestUserMessage(content);
case ASSISTANT:
return new ChatRequestAssistantMessage(content);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, only the content of ChatRequestAssistantMessage is set, but no toolCalls are set.

case ASSISTANT:
return new ChatRequestAssistantMessage(content);
case TOOL:
return new ChatRequestToolMessage(content);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, the content will be set as toolCallId of ChatRequestToolMessage, so we should pass the function call id generated by Azure llm.

ChatRequestToolMessage msg =
                        new ChatRequestToolMessage(
                                (String) message.getExtraArgs().get("externalId"));
msg.setContent(content);
return msg;

and the externalId should be set in convertToAgentsTools:

private List<Map<String, Object>> convertToAgentsTools(
            List<ChatCompletionsToolCall> azureToolCalls) {
    ...
            final Map<String, Object> call =
                    Map.of(
                            "id", functionCall.getId(),
                            "original_id", functionCall.getId(),
                            "type", "function",
                            "function",
                                    Map.of(
                                            "name", functionCall.getFunction().getName(),
                                            "arguments",
                                                    functionCall.getFunction().getArguments()));
            toolCalls.add(call);
    ...
}

@tsaiggo
Copy link
Contributor Author

tsaiggo commented Oct 31, 2025

pushed new changes, please re-review this PR, thx @wenjin272
btw, there might be something wrong with the python-related test case, can you help retry the failed job? I have no access to do this

Copy link
Collaborator

@wenjin272 wenjin272 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, @tsaiggo, thanks for your update. LGTM, only one comment.

The failed test case in CI is caused by the request time out of ollama chat model. I fixed it also in pr #291, you can rebase main branch after it is merged.

super(descriptor, getResource);
}

// For any other specific parameters, please refer to ChatCompletionsOptions @Override
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @Override annotation is commented out.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, good catch! 😂 Blame it on the late-night brain fog. Will fix it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolved

@tsaiggo
Copy link
Contributor Author

tsaiggo commented Nov 3, 2025

Looks like the issue of python-related test case has been self-recovered.
lease let me know if you have any further comments or feedback—even nitpicks are welcome. If not, is this PR good to go? @wenjin272

@wenjin272
Copy link
Collaborator

Hi, @tsaiggo, this pr looks good to me.

Since merging a PR requires apache committer privileges, @xintongsong could you take a look at this pr at your convenience?

Copy link
Contributor

@xintongsong xintongsong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tsaiggo, thanks for your contribution.

The PR overall looks good. I just have one minor comment.

Additionally, I think this new support for Azure chat model needs to be documented. We can either do that in this PR, or create a separate issue for it.

examples/pom.xml Outdated
<groupId>org.apache.flink</groupId>
<artifactId>flink-agents-integrations-chat-models-azureai</artifactId>
<version>${project.version}</version>
</dependency>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this dependency in examples/ ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to keep documentation updates in a separate PR

Copy link
Contributor Author

@tsaiggo tsaiggo Nov 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added the azureaichatmodel to the examples module because I intended it to be our first example of a cloud-hosted model. My original plan was to add specific use cases for cloud-hosted models, but I haven't come up with any good ideas for that yet, so it's temporarily on hold. If you think this addition should be removed for now, I'm happy to take care of that. @xintongsong

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think the dependency should be introduced only when it's needed. Thanks for addressing my comments.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, I just created #305 for the documentation work.

Copy link
Contributor

@xintongsong xintongsong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Merging.

@xintongsong xintongsong merged commit d8f2eea into apache:main Nov 5, 2025
11 checks passed
@Sxnan Sxnan added priority/major Default priority of the PR or issue. fixVersion/0.2.0 The feature or bug should be implemented/fixed in the 0.2.0 version. doc-not-needed Your PR changes do not impact docs labels Nov 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

doc-not-needed Your PR changes do not impact docs fixVersion/0.2.0 The feature or bug should be implemented/fixed in the 0.2.0 version. priority/major Default priority of the PR or issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants