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