|
7 | 7 | import com.fasterxml.jackson.core.JsonProcessingException; |
8 | 8 | import com.fasterxml.jackson.databind.JsonNode; |
9 | 9 | import com.fasterxml.jackson.databind.ObjectMapper; |
| 10 | +import com.microsoft.semantickernel.exceptions.SKException; |
| 11 | +import com.microsoft.semantickernel.orchestration.responseformat.ResponseSchemaGenerator; |
10 | 12 | import com.microsoft.semantickernel.semanticfunctions.InputVariable; |
11 | 13 | import com.microsoft.semantickernel.semanticfunctions.KernelFunctionMetadata; |
| 14 | +import org.apache.commons.lang3.StringUtils; |
12 | 15 | import java.util.ArrayList; |
13 | 16 | import java.util.Collections; |
14 | 17 | import java.util.HashMap; |
15 | 18 | import java.util.List; |
16 | 19 | import java.util.Locale; |
17 | 20 | import java.util.Map; |
| 21 | +import java.util.Objects; |
| 22 | +import java.util.concurrent.ConcurrentHashMap; |
18 | 23 | import java.util.stream.Collectors; |
19 | 24 | import javax.annotation.Nonnull; |
20 | 25 | import javax.annotation.Nullable; |
21 | 26 |
|
22 | 27 | class OpenAIFunction { |
| 28 | + private static final ConcurrentHashMap<String, String> SCHEMA_CACHE = new ConcurrentHashMap<>(); |
23 | 29 |
|
24 | 30 | private final String pluginName; |
25 | 31 | private final String name; |
@@ -159,14 +165,17 @@ private static String getSchemaForFunctionParameter(@Nullable InputVariable para |
159 | 165 | entries.add("\"type\":\"" + type + "\""); |
160 | 166 |
|
161 | 167 | // Add description if present |
| 168 | + String description =null; |
162 | 169 | if (parameter != null && parameter.getDescription() != null && !parameter.getDescription() |
163 | 170 | .isEmpty()) { |
164 | | - String description = parameter.getDescription(); |
| 171 | + description = parameter.getDescription(); |
165 | 172 | description = description.replaceAll("\\r?\\n|\\r", ""); |
166 | 173 | description = description.replace("\"", "\\\""); |
167 | | - |
168 | | - description = String.format("\"description\":\"%s\"", description); |
169 | | - entries.add(description); |
| 174 | + entries.add(String.format("\"description\":\"%s\"", description)); |
| 175 | + } |
| 176 | + // If custom type, generate schema |
| 177 | + if("object".equalsIgnoreCase(type)) { |
| 178 | + return getObjectSchema(parameter.getType(), description); |
170 | 179 | } |
171 | 180 |
|
172 | 181 | // Add enum options if parameter is an enum |
@@ -219,4 +228,24 @@ private static String getJavaTypeToOpenAiFunctionType(String javaType) { |
219 | 228 | return "object"; |
220 | 229 | } |
221 | 230 | } |
| 231 | + |
| 232 | + private static String getObjectSchema(String type, String description){ |
| 233 | + String schema= ""; |
| 234 | + try { |
| 235 | + if(SCHEMA_CACHE.containsKey(type)) { |
| 236 | + schema= SCHEMA_CACHE.get(type); |
| 237 | + } else { |
| 238 | + Class<?> clazz = Class.forName(type); |
| 239 | + schema = ResponseSchemaGenerator.jacksonGenerator().generateSchema(clazz); |
| 240 | + SCHEMA_CACHE.put(type, schema); |
| 241 | + } |
| 242 | + } catch (ClassNotFoundException | SKException ignored) { |
| 243 | + |
| 244 | + } |
| 245 | + Map<String, Object> properties = BinaryData.fromString(schema).toObject(Map.class); |
| 246 | + if(StringUtils.isNotBlank(description)) { |
| 247 | + properties.put("description", description); |
| 248 | + } |
| 249 | + return BinaryData.fromObject(properties).toString(); |
| 250 | + } |
222 | 251 | } |
0 commit comments