001package com.box.sdk; 002 003import com.box.sdk.http.HttpMethod; 004import com.eclipsesource.json.Json; 005import com.eclipsesource.json.JsonArray; 006import com.eclipsesource.json.JsonObject; 007import java.net.URL; 008import java.util.List; 009 010 011public final class BoxAI { 012 013 /** 014 * Ask AI url. 015 */ 016 public static final URLTemplate SEND_AI_REQUEST_URL = new URLTemplate("ai/ask"); 017 /** 018 * Text gen AI url. 019 */ 020 public static final URLTemplate SEND_AI_TEXT_GEN_REQUEST_URL = new URLTemplate("ai/text_gen"); 021 /** 022 * AI agent default config url. 023 */ 024 public static final URLTemplate AI_AGENT_DEFAULT_CONFIG_URL = new URLTemplate("ai_agent_default"); 025 /** 026 * AI extract metadata freeform url. 027 */ 028 public static final URLTemplate EXTRACT_METADATA_FREEFORM_URL = new URLTemplate("ai/extract"); 029 /** 030 * AI extract metadata structured url. 031 */ 032 public static final URLTemplate EXTRACT_METADATA_STRUCTURED_URL = new URLTemplate("ai/extract_structured"); 033 034 private BoxAI() { 035 } 036 037 /** 038 * Sends an AI request to supported LLMs and returns an answer specifically focused 039 * on the user's question given the provided items. 040 * 041 * @param api the API connection to be used by the created user. 042 * @param prompt The prompt provided by the client to be answered by the LLM. 043 * @param items The items to be processed by the LLM, currently only files are supported. 044 * @param mode The mode specifies if this request is for a single or multiple items. 045 * @return The response from the AI. 046 */ 047 public static BoxAIResponse sendAIRequest(BoxAPIConnection api, String prompt, List<BoxAIItem> items, Mode mode) { 048 return sendAIRequest(api, prompt, items, mode, null, null, null); 049 } 050 051 /** 052 * Sends an AI request to supported LLMs and returns an answer specifically focused 053 * on the user's question given the provided items. 054 * 055 * @param api the API connection to be used by the created user. 056 * @param prompt The prompt provided by the client to be answered by the LLM. 057 * @param items The items to be processed by the LLM, currently only files are supported. 058 * @param mode The mode specifies if this request is for a single or multiple items. 059 * @param dialogueHistory The history of prompts and answers previously passed to the LLM. 060 * This provides additional context to the LLM in generating the response. 061 * @param agent The AI agent configuration to be used for the request. 062 * @param includeCitations Whether to include citations in the response. 063 * @return The response from the AI. 064 */ 065 public static BoxAIResponse sendAIRequest(BoxAPIConnection api, String prompt, List<BoxAIItem> items, Mode mode, 066 List<BoxAIDialogueEntry> dialogueHistory, BoxAIAgentAsk agent, 067 Boolean includeCitations) { 068 URL url = SEND_AI_REQUEST_URL.build(api.getBaseURL()); 069 JsonObject requestJSON = new JsonObject(); 070 requestJSON.add("mode", mode.toString()); 071 requestJSON.add("prompt", prompt); 072 073 JsonArray itemsJSON = new JsonArray(); 074 for (BoxAIItem item : items) { 075 itemsJSON.add(item.getJSONObject()); 076 } 077 requestJSON.add("items", itemsJSON); 078 079 if (dialogueHistory != null) { 080 JsonArray dialogueHistoryJSON = new JsonArray(); 081 for (BoxAIDialogueEntry dialogueEntry : dialogueHistory) { 082 dialogueHistoryJSON.add(dialogueEntry.getJSONObject()); 083 } 084 requestJSON.add("dialogue_history", dialogueHistoryJSON); 085 } 086 if (agent != null) { 087 requestJSON.add("ai_agent", agent.getJSONObject()); 088 } 089 if (includeCitations != null) { 090 requestJSON.add("include_citations", includeCitations); 091 } 092 093 BoxJSONRequest req = new BoxJSONRequest(api, url, HttpMethod.POST); 094 req.setBody(requestJSON.toString()); 095 096 try (BoxJSONResponse response = req.send()) { 097 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 098 return new BoxAIResponse(responseJSON); 099 } 100 } 101 102 /** 103 * Sends an AI request to supported LLMs and returns an answer specifically focused on the creation of new text. 104 * 105 * @param api the API connection to be used by the created user. 106 * @param prompt The prompt provided by the client to be answered by the LLM. 107 * @param items The items to be processed by the LLM, currently only files are supported. 108 * @return The response from the AI. 109 */ 110 public static BoxAIResponse sendAITextGenRequest(BoxAPIConnection api, String prompt, List<BoxAIItem> items) { 111 return sendAITextGenRequest(api, prompt, items, null); 112 } 113 114 /** 115 * Sends an AI request to supported LLMs and returns an answer specifically focused on the creation of new text. 116 * 117 * @param api the API connection to be used by the created user. 118 * @param prompt The prompt provided by the client to be answered by the LLM. 119 * @param items The items to be processed by the LLM, currently only files are supported. 120 * @param dialogueHistory The history of prompts and answers previously passed to the LLM. 121 * This provides additional context to the LLM in generating the response. 122 * @return The response from the AI. 123 */ 124 public static BoxAIResponse sendAITextGenRequest(BoxAPIConnection api, String prompt, List<BoxAIItem> items, 125 List<BoxAIDialogueEntry> dialogueHistory) { 126 return sendAITextGenRequest(api, prompt, items, dialogueHistory, null); 127 } 128 129 /** 130 * Sends an AI request to supported LLMs and returns an answer specifically focused on the creation of new text. 131 * 132 * @param api the API connection to be used by the created user. 133 * @param prompt The prompt provided by the client to be answered by the LLM. 134 * @param items The items to be processed by the LLM, currently only files are supported. 135 * @param dialogueHistory The history of prompts and answers previously passed to the LLM. 136 * This provides additional context to the LLM in generating the response. 137 * @param agent The AI agent configuration to be used for the request. 138 * @return The response from the AI. 139 */ 140 public static BoxAIResponse sendAITextGenRequest(BoxAPIConnection api, String prompt, List<BoxAIItem> items, 141 List<BoxAIDialogueEntry> dialogueHistory, 142 BoxAIAgentTextGen agent) { 143 URL url = SEND_AI_TEXT_GEN_REQUEST_URL.build(api.getBaseURL()); 144 JsonObject requestJSON = new JsonObject(); 145 requestJSON.add("prompt", prompt); 146 147 JsonArray itemsJSON = new JsonArray(); 148 for (BoxAIItem item : items) { 149 itemsJSON.add(item.getJSONObject()); 150 } 151 requestJSON.add("items", itemsJSON); 152 153 if (dialogueHistory != null) { 154 JsonArray dialogueHistoryJSON = new JsonArray(); 155 for (BoxAIDialogueEntry dialogueEntry : dialogueHistory) { 156 dialogueHistoryJSON.add(dialogueEntry.getJSONObject()); 157 } 158 requestJSON.add("dialogue_history", dialogueHistoryJSON); 159 } 160 161 if (agent != null) { 162 requestJSON.add("ai_agent", agent.getJSONObject()); 163 } 164 165 BoxJSONRequest req = new BoxJSONRequest(api, url, HttpMethod.POST); 166 req.setBody(requestJSON.toString()); 167 168 try (BoxJSONResponse response = req.send()) { 169 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 170 return new BoxAIResponse(responseJSON); 171 } 172 } 173 174 /** 175 * Get the default AI Agent use for the given mode. 176 * 177 * @param api The API connection to be used by the created user. 178 * @param mode The mode to filter the agent config to return. 179 * @return A successful response including the default agent configuration. 180 */ 181 public static BoxAIAgent getAiAgentDefaultConfig(BoxAPIConnection api, BoxAIAgent.Mode mode) { 182 return getAiAgentDefaultConfig(api, mode, null, null); 183 } 184 185 /** 186 * Get the default AI Agent use for the given mode. 187 * 188 * @param api The API connection to be used by the created user. 189 * @param mode The mode to filter the agent config to return. 190 * @param language The language to filter the agent config to return. 191 * @param model The model to filter the agent config to return. 192 * @return A successful response including the default agent configuration. 193 */ 194 public static BoxAIAgent getAiAgentDefaultConfig(BoxAPIConnection api, 195 BoxAIAgent.Mode mode, 196 String language, 197 String model) { 198 QueryStringBuilder builder = new QueryStringBuilder(); 199 builder.appendParam("mode", mode.toString()); 200 if (language != null) { 201 builder.appendParam("language", language); 202 } 203 if (model != null) { 204 builder.appendParam("model", model); 205 } 206 URL url = AI_AGENT_DEFAULT_CONFIG_URL.buildWithQuery(api.getBaseURL(), builder.toString()); 207 BoxAPIRequest req = new BoxAPIRequest(api, url, HttpMethod.GET); 208 try (BoxJSONResponse response = (BoxJSONResponse) req.send()) { 209 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 210 return BoxAIAgent.parse(responseJSON); 211 } 212 } 213 214 public enum Mode { 215 /** 216 * Multiple items 217 */ 218 MULTIPLE_ITEM_QA("multiple_item_qa"), 219 220 /** 221 * Single item 222 */ 223 SINGLE_ITEM_QA("single_item_qa"); 224 225 private final String mode; 226 227 Mode(String mode) { 228 this.mode = mode; 229 } 230 231 static BoxAI.Mode fromJSONValue(String jsonValue) { 232 if (jsonValue.equals("multiple_item_qa")) { 233 return BoxAI.Mode.MULTIPLE_ITEM_QA; 234 } else if (jsonValue.equals("single_item_qa")) { 235 return BoxAI.Mode.SINGLE_ITEM_QA; 236 } else { 237 System.out.print("Invalid AI mode."); 238 return null; 239 } 240 } 241 242 String toJSONValue() { 243 return this.mode; 244 } 245 246 public String toString() { 247 return this.mode; 248 } 249 } 250 251 /** 252 * Sends an AI request to supported Large Language Models (LLMs) and extracts metadata in form of key-value pairs. 253 * Freeform metadata extraction does not require any metadata template setup before sending the request. 254 * 255 * @param api the API connection to be used by the created user. 256 * @param prompt The prompt provided by the client to be answered by the LLM. 257 * @param items The items to be processed by the LLM, currently only files are supported. 258 * @return The response from the AI. 259 */ 260 public static BoxAIResponse extractMetadataFreeform(BoxAPIConnection api, 261 String prompt, 262 List<BoxAIItem> items) { 263 return extractMetadataFreeform(api, prompt, items, null); 264 } 265 266 /** 267 * Sends an AI request to supported Large Language Models (LLMs) and extracts metadata in form of key-value pairs. 268 * Freeform metadata extraction does not require any metadata template setup before sending the request. 269 * 270 * @param api the API connection to be used by the created user. 271 * @param prompt The prompt provided by the client to be answered by the LLM. 272 * @param items The items to be processed by the LLM, currently only files are supported. 273 * @param agent The AI agent configuration to be used for the request. 274 * @return The response from the AI. 275 */ 276 public static BoxAIResponse extractMetadataFreeform(BoxAPIConnection api, 277 String prompt, 278 List<BoxAIItem> items, 279 BoxAIAgentExtract agent) { 280 URL url = EXTRACT_METADATA_FREEFORM_URL.build(api.getBaseURL()); 281 282 JsonObject requestJSON = new JsonObject(); 283 JsonArray itemsJSON = new JsonArray(); 284 for (BoxAIItem item : items) { 285 itemsJSON.add(item.getJSONObject()); 286 } 287 requestJSON.add("items", itemsJSON); 288 requestJSON.add("prompt", prompt); 289 if (agent != null) { 290 requestJSON.add("ai_agent", agent.getJSONObject()); 291 } 292 293 BoxJSONRequest req = new BoxJSONRequest(api, url, HttpMethod.POST); 294 req.setBody(requestJSON.toString()); 295 296 try (BoxJSONResponse response = req.send()) { 297 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 298 return new BoxAIResponse(responseJSON); 299 } 300 } 301 302 /** 303 * Sends an AI request to supported Large Language Models (LLMs) and returns extracted metadata as a set of 304 * key-value pairs. For this request, you need to use an already defined metadata template or a define a 305 * schema yourself. 306 * 307 * @param api The API connection to be used by the created user. 308 * @param items The items to be processed by the LLM, currently only files are supported. 309 * @param template The metadata template to be used for the request. 310 * @return The response from the AI. 311 */ 312 public static BoxAIExtractStructuredResponse extractMetadataStructured(BoxAPIConnection api, List<BoxAIItem> items, 313 BoxAIExtractMetadataTemplate template) { 314 return extractMetadataStructured(api, items, template, null, null); 315 } 316 317 /** 318 * Sends an AI request to supported Large Language Models (LLMs) and returns extracted metadata as a set of 319 * key-value pairs. For this request, you need to use an already defined metadata template or a define a 320 * schema yourself. 321 * 322 * @param api The API connection to be used by the created user. 323 * @param items The items to be processed by the LLM, currently only files are supported. 324 * @param template The metadata template to be used for the request. 325 * @param agent The AI agent configuration to be used for the request. 326 * @return The response from the AI. 327 */ 328 public static BoxAIExtractStructuredResponse extractMetadataStructured(BoxAPIConnection api, List<BoxAIItem> items, 329 BoxAIExtractMetadataTemplate template, 330 BoxAIAgentExtractStructured agent) { 331 return extractMetadataStructured(api, items, template, null, agent); 332 } 333 334 /** 335 * Sends an AI request to supported Large Language Models (LLMs) and returns extracted metadata as a set of 336 * key-value pairs. For this request, you need to use an already defined metadata template or a define a 337 * schema yourself. 338 * 339 * @param api The API connection to be used by the created user. 340 * @param items The items to be processed by the LLM, currently only files are supported. 341 * @param fields The fields to be extracted from the items. 342 * @return The response from the AI. 343 */ 344 public static BoxAIExtractStructuredResponse extractMetadataStructured(BoxAPIConnection api, List<BoxAIItem> items, 345 List<BoxAIExtractField> fields) { 346 return extractMetadataStructured(api, items, null, fields, null); 347 } 348 349 /** 350 * Sends an AI request to supported Large Language Models (LLMs) and returns extracted metadata as a set of 351 * key-value pairs. For this request, you need to use an already defined metadata template or a define a 352 * schema yourself. 353 * 354 * @param api The API connection to be used by the created user. 355 * @param items The items to be processed by the LLM, currently only files are supported. 356 * @param fields The fields to be extracted from the items. 357 * @param agent The AI agent configuration to be used for the request. 358 * @return The response from the AI. 359 */ 360 public static BoxAIExtractStructuredResponse extractMetadataStructured(BoxAPIConnection api, List<BoxAIItem> items, 361 List<BoxAIExtractField> fields, 362 BoxAIAgentExtractStructured agent) { 363 return extractMetadataStructured(api, items, null, fields, agent); 364 } 365 366 /** 367 * Sends an AI request to supported Large Language Models (LLMs) and returns extracted metadata as a set of 368 * key-value pairs. For this request, you need to use an already defined metadata template or a define a 369 * schema yourself. 370 * 371 * @param api The API connection to be used by the created user. 372 * @param items The items to be processed by the LLM, currently only files are supported. 373 * @param template The metadata template to be used for the request. 374 * @param fields The fields to be extracted from the items. 375 * @param agent The AI agent configuration to be used for the request. 376 * @return The response from the AI. 377 */ 378 private static BoxAIExtractStructuredResponse extractMetadataStructured(BoxAPIConnection api, List<BoxAIItem> items, 379 BoxAIExtractMetadataTemplate template, 380 List<BoxAIExtractField> fields, 381 BoxAIAgentExtractStructured agent) { 382 URL url = EXTRACT_METADATA_STRUCTURED_URL.build(api.getBaseURL()); 383 384 JsonObject requestJSON = new JsonObject(); 385 JsonArray itemsJSON = new JsonArray(); 386 for (BoxAIItem item : items) { 387 itemsJSON.add(item.getJSONObject()); 388 } 389 requestJSON.add("items", itemsJSON); 390 391 if (template != null) { 392 requestJSON.add("metadata_template", template.getJSONObject()); 393 } 394 395 if (fields != null) { 396 JsonArray fieldsJSON = new JsonArray(); 397 for (BoxAIExtractField field : fields) { 398 fieldsJSON.add(field.getJSONObject()); 399 } 400 requestJSON.add("fields", fieldsJSON); 401 } 402 403 if (agent != null) { 404 requestJSON.add("ai_agent", agent.getJSONObject()); 405 } 406 407 BoxJSONRequest req = new BoxJSONRequest(api, url, HttpMethod.POST); 408 req.setBody(requestJSON.toString()); 409 410 try (BoxJSONResponse response = req.send()) { 411 return new BoxAIExtractStructuredResponse(response.getJSON()); 412 } 413 } 414}