You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by we...@apache.org on 2026/08/20 07:57:45 UTC
(flink-agents) branch main updated: [integration][ollama] Tolerate tool schemas without a 'required' key (#1026)
This is an automated email from the ASF dual-hosted git repository.
wenjin272 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/flink-agents.git
The following commit(s) were added to refs/heads/main by this push:
new a6213bdb [integration][ollama] Tolerate tool schemas without a 'required' key (#1026)
a6213bdb is described below
commit a6213bdb7f991544877ab77e00ddf865e9c9d633
Author: Edson <11...@users.noreply.github.com>
AuthorDate: Thu Aug 20 03:57:39 2026 -0400
[integration][ollama] Tolerate tool schemas without a 'required' key (#1026)
---
.../ollama/OllamaChatModelConnection.java | 8 +-
.../ollama/OllamaChatModelConnectionTest.java | 104 +++++++++++++++++++++
2 files changed, 110 insertions(+), 2 deletions(-)
diff --git a/integrations/chat-models/ollama/src/main/java/org/apache/flink/agents/integrations/chatmodels/ollama/OllamaChatModelConnection.java b/integrations/chat-models/ollama/src/main/java/org/apache/flink/agents/integrations/chatmodels/ollama/OllamaChatModelConnection.java
index de6f946f..e86f1277 100644
--- a/integrations/chat-models/ollama/src/main/java/org/apache/flink/agents/integrations/chatmodels/ollama/OllamaChatModelConnection.java
+++ b/integrations/chat-models/ollama/src/main/java/org/apache/flink/agents/integrations/chatmodels/ollama/OllamaChatModelConnection.java
@@ -106,8 +106,9 @@ public class OllamaChatModelConnection extends BaseChatModelConnection {
* @return List of Ollama compatible tool specifications
* @throws RuntimeException if schema parsing or conversion fails
*/
+ // Package-visible for unit testing of the schema conversion.
@SuppressWarnings("unchecked")
- private List<Tools.Tool> convertToOllamaTools(List<Tool> tools) {
+ List<Tools.Tool> convertToOllamaTools(List<Tool> tools) {
final ObjectMapper mapper = new ObjectMapper();
final List<Tools.Tool> ollamaTools = new ArrayList<>();
try {
@@ -118,7 +119,10 @@ public class OllamaChatModelConnection extends BaseChatModelConnection {
final Map<String, Map<String, String>> properties =
(Map<String, Map<String, String>>) schema.get("properties");
- final List<String> required = (List<String>) schema.get("required");
+ // "required" is optional in JSON Schema, and SchemaUtils only emits it when at
+ // least one parameter is required — treat a missing list as empty (#1014).
+ final List<String> required =
+ (List<String>) schema.getOrDefault("required", Collections.emptyList());
Map<String, Tools.Property> propertiesMap = new HashMap<>();
diff --git a/integrations/chat-models/ollama/src/test/java/org/apache/flink/agents/integrations/chatmodels/ollama/OllamaChatModelConnectionTest.java b/integrations/chat-models/ollama/src/test/java/org/apache/flink/agents/integrations/chatmodels/ollama/OllamaChatModelConnectionTest.java
new file mode 100644
index 00000000..06570c29
--- /dev/null
+++ b/integrations/chat-models/ollama/src/test/java/org/apache/flink/agents/integrations/chatmodels/ollama/OllamaChatModelConnectionTest.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.flink.agents.integrations.chatmodels.ollama;
+
+import io.github.ollama4j.tools.Tools;
+import org.apache.flink.agents.api.resource.ResourceContext;
+import org.apache.flink.agents.api.resource.ResourceDescriptor;
+import org.apache.flink.agents.api.tools.Tool;
+import org.apache.flink.agents.api.tools.ToolMetadata;
+import org.apache.flink.agents.api.tools.ToolParameters;
+import org.apache.flink.agents.api.tools.ToolResponse;
+import org.apache.flink.agents.api.tools.ToolType;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Unit tests for {@link OllamaChatModelConnection}'s tool-schema conversion — no network access.
+ */
+class OllamaChatModelConnectionTest {
+
+ private static final ResourceContext NOOP = ResourceContext.fromGetResource((a, b) -> null);
+
+ private static OllamaChatModelConnection connection() {
+ ResourceDescriptor desc =
+ ResourceDescriptor.Builder.newBuilder(OllamaChatModelConnection.class.getName())
+ .addInitialArgument("endpoint", "http://localhost:11434")
+ .build();
+ return new OllamaChatModelConnection(desc, NOOP);
+ }
+
+ /** Minimal tool carrying only metadata; never invoked in these tests. */
+ private static final class SchemaOnlyTool extends Tool {
+ SchemaOnlyTool(String inputSchema) {
+ super(new ToolMetadata("add", "Add two numbers.", inputSchema));
+ }
+
+ @Override
+ public ToolType getToolType() {
+ return ToolType.FUNCTION;
+ }
+
+ @Override
+ public ToolResponse call(ToolParameters parameters) {
+ throw new UnsupportedOperationException("not invoked in this test");
+ }
+ }
+
+ @Test
+ @DisplayName("A schema without a 'required' key converts with every property optional")
+ void testSchemaWithoutRequiredKey() {
+ // SchemaUtils only emits "required" when at least one parameter is required, so an
+ // all-optional @Tool produces exactly this shape (#1014).
+ String schema =
+ "{\"type\":\"object\",\"properties\":{"
+ + "\"a\":{\"type\":\"integer\"},\"b\":{\"type\":\"integer\"}}}";
+
+ List<Tools.Tool> converted =
+ connection().convertToOllamaTools(List.of(new SchemaOnlyTool(schema)));
+
+ assertThat(converted).hasSize(1);
+ Tools.Tool tool = converted.get(0);
+ assertThat(tool.getToolSpec().getParameters().getProperties())
+ .containsOnlyKeys("a", "b")
+ .allSatisfy((name, property) -> assertThat(property.isRequired()).isFalse());
+ }
+
+ @Test
+ @DisplayName("A schema with a 'required' key still marks the listed parameters required")
+ void testSchemaWithRequiredKey() {
+ String schema =
+ "{\"type\":\"object\",\"properties\":{"
+ + "\"a\":{\"type\":\"integer\"},\"b\":{\"type\":\"integer\"}},"
+ + "\"required\":[\"a\"]}";
+
+ List<Tools.Tool> converted =
+ connection().convertToOllamaTools(List.of(new SchemaOnlyTool(schema)));
+
+ assertThat(converted).hasSize(1);
+ Tools.Tool tool = converted.get(0);
+ assertThat(tool.getToolSpec().getParameters().getProperties().get("a").isRequired())
+ .isTrue();
+ assertThat(tool.getToolSpec().getParameters().getProperties().get("b").isRequired())
+ .isFalse();
+ }
+}