|
| 1 | +package com.modzy.sdk.samples; |
| 2 | + |
| 3 | +import com.fasterxml.jackson.databind.JsonNode; |
| 4 | +import com.modzy.sdk.ModzyClient; |
| 5 | +import com.modzy.sdk.dto.EmbeddedData; |
| 6 | +import com.modzy.sdk.exception.ApiException; |
| 7 | +import com.modzy.sdk.model.Job; |
| 8 | +import com.modzy.sdk.model.JobInput; |
| 9 | +import com.modzy.sdk.model.JobInputStream; |
| 10 | +import com.modzy.sdk.model.JobOutput; |
| 11 | +import com.modzy.sdk.model.JobStatus; |
| 12 | +import com.modzy.sdk.model.Model; |
| 13 | +import com.modzy.sdk.model.ModelInput; |
| 14 | +import com.modzy.sdk.model.ModelOutput; |
| 15 | +import com.modzy.sdk.model.ModelVersion; |
| 16 | +import io.github.cdimascio.dotenv.Dotenv; |
| 17 | +import org.apache.commons.io.IOUtils; |
| 18 | + |
| 19 | +import java.io.ByteArrayInputStream; |
| 20 | +import java.io.File; |
| 21 | +import java.io.FileInputStream; |
| 22 | +import java.io.IOException; |
| 23 | +import java.io.InputStream; |
| 24 | +import java.util.HashMap; |
| 25 | +import java.util.Iterator; |
| 26 | +import java.util.Map; |
| 27 | + |
| 28 | +public class JobFileInputSample { |
| 29 | + |
| 30 | + public static void main(String[] args) throws ApiException, IOException { |
| 31 | + |
| 32 | + // The system admin can provide the right base API URL, the API key can be downloaded from your profile page on Modzy. |
| 33 | + // You can config those params as is described in the readme file (as environment variables, or by using the .env file), |
| 34 | + // or you can just update the BASE_URL and API_KEY vars on this sample code (not recommended for production environments). |
| 35 | + |
| 36 | + Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); |
| 37 | + |
| 38 | + // The MODZY_BASE_URL should point to the API services route, it may be different from the Modzy page URL. |
| 39 | + // (ie: https://modzy.example.com/api). |
| 40 | + String baseURL = dotenv.get("MODZY_BASE_URL"); |
| 41 | + // The MODZY_API_KEY is your own personal API key. It is composed by a public part, a dot character and a private part |
| 42 | + // (ie: AzQBJ3h4B1z60xNmhAJF.uQyQh8putLIRDi1nOldh). |
| 43 | + String apiKey = dotenv.get("MODZY_API_KEY"); |
| 44 | + |
| 45 | + // Client initialization |
| 46 | + // Initialize the ApiClient instance with the BASE_URL and the API_KEY to store those arguments |
| 47 | + // for the following API calls. |
| 48 | + ModzyClient modzyClient = new ModzyClient(baseURL,apiKey); |
| 49 | + |
| 50 | + // Create a Job with a embedded input, wait, and retrieve results |
| 51 | + |
| 52 | + // Get the model object: |
| 53 | + // If you already know the model identifier (i.e.: you get from the URL of the model details page or the input sample), |
| 54 | + // you can skip this step, if you don't you can find the model identifier by using its name as follows: |
| 55 | + Model model = modzyClient.getModelByName("Multi-Language OCR"); |
| 56 | + // Or if you already know the model id and want to know more about the model, you can use this instead: |
| 57 | + // Model model = modzyClient.getModel("c60c8dbd79"); |
| 58 | + // You can find more information about how to query the models on the ModelSamples.java file |
| 59 | + |
| 60 | + // The model identifier is under the identifier property. You can take a look at the other properties under Model class |
| 61 | + // Or just log the model identifier, and potencially the latest version |
| 62 | + System.out.println(String.format("The model identifier is %s and the latest version is %s", model.getIdentifier(), model.getLatestVersion())); |
| 63 | + |
| 64 | + // Get the model version object: |
| 65 | + // If you already know the model version and the input key(s) of the model version you can skip this step. Also, you can |
| 66 | + // use the following code block to know about the inputs keys, and skip the call on future job submissions. |
| 67 | + ModelVersion modelVersion = modzyClient.getModelVersion(model.getIdentifier(), model.getLatestVersion() ); |
| 68 | + // The info stored in modelVersion provides insights about the amount of time that the model can spend processing, |
| 69 | + // the inputs, and output keys of the model. |
| 70 | + System.out.println(String.format("The model version is %s", modelVersion)); |
| 71 | + System.out.println(String.format(" timeouts: status %sms, run %sms ",modelVersion.getTimeout().getStatus(), modelVersion.getTimeout().getRun())); |
| 72 | + System.out.println(" inputs:"); |
| 73 | + for( ModelInput input : modelVersion.getInputs() ){ |
| 74 | + System.out.println( |
| 75 | + String.format(" key %s, type %s, description: %s", input.getName(), input.getAcceptedMediaTypes(), input.getDescription()) |
| 76 | + ); |
| 77 | + } |
| 78 | + System.out.println(" outputs:"); |
| 79 | + for( ModelOutput output : modelVersion.getOutputs() ){ |
| 80 | + System.out.println( |
| 81 | + String.format(" key %s, type %s, description: %s", output.getName(), output.getMediaType(), output.getDescription()) |
| 82 | + ); |
| 83 | + } |
| 84 | + |
| 85 | + // Send the job: |
| 86 | + // A file input will be submitted individually, so this method is best for large or multiple input files |
| 87 | + // You can use as a drop-in replacement instead of embedded inputs |
| 88 | + |
| 89 | + //byte[] imageBytes = IOUtils.toByteArray( JobAwsInputSample.class.getClassLoader().getResourceAsStream("samples/image.png") ); |
| 90 | + //byte[] configBytes = IOUtils.toByteArray( JobAwsInputSample.class.getClassLoader().getResourceAsStream("samples/config.json") ); |
| 91 | + |
| 92 | + String imagePath = "src/main/resources/samples/image.png"; |
| 93 | + String configPath = "src/main/resources/samples/config.json"; |
| 94 | + |
| 95 | + // With the info about the model (identifier), the model version (version string, input/output keys), you are ready to |
| 96 | + // submit the job. Just prepare the source object: |
| 97 | + JobInput<InputStream> jobInput = new JobInputStream(modelVersion); |
| 98 | + Map<String,InputStream> mapSource = new HashMap<>(); |
| 99 | + mapSource.put("input", new FileInputStream( imagePath )); |
| 100 | + mapSource.put("config.json", new FileInputStream( configPath ) ); |
| 101 | + jobInput.addSource("source-key", mapSource); |
| 102 | + // An inference job groups input data that you send to a model. You can send any amount of inputs to |
| 103 | + // process and you can identify and refer to a specific input by the key that you assign, for example we can add: |
| 104 | + mapSource = new HashMap<>(); |
| 105 | + mapSource.put("input", new FileInputStream( imagePath ) ); |
| 106 | + mapSource.put("config.json", new FileInputStream( configPath ) ); |
| 107 | + jobInput.addSource("second-key", mapSource); |
| 108 | + // You don't need to load all the inputs from files, just convert from bytes as follows: |
| 109 | + byte[] configBytes = "{\"languages\": [\"spa\"]}".getBytes(); |
| 110 | + mapSource = new HashMap<>(); |
| 111 | + mapSource.put("input", new FileInputStream( imagePath ) ); |
| 112 | + mapSource.put("config.json", new ByteArrayInputStream(configBytes)); |
| 113 | + jobInput.addSource("another-key", mapSource); |
| 114 | + //If you send a wrong input key, the model fails to process the input. |
| 115 | + mapSource = new HashMap<>(); |
| 116 | + mapSource.put("a.wrong.key", new FileInputStream( imagePath )); |
| 117 | + mapSource.put("config.json", new FileInputStream( configPath )); |
| 118 | + jobInput.addSource("wrong-key", mapSource); |
| 119 | + // If you send a correct input key, but some wrong values, the model fails to process the input. |
| 120 | + mapSource = new HashMap<>(); |
| 121 | + mapSource.put("input", new FileInputStream( configPath )); |
| 122 | + mapSource.put("config.json", new FileInputStream( imagePath )); |
| 123 | + jobInput.addSource("wrong-values", mapSource); |
| 124 | + |
| 125 | + // When you have all your inputs ready, you can use our helper method to submit the job as follows: |
| 126 | + Job job = modzyClient.submitJob(model, modelVersion, jobInput); |
| 127 | + // Modzy creates the job and queue for processing. The job object contains all the info that you need to keep track |
| 128 | + // of the process, the most important being the job_identifier and the job status. |
| 129 | + System.out.println(String.format("job: %s", job)); |
| 130 | + // The job moves to SUBMITTED, meaning that Modzy acknowledged the job and sent it to the queue to be processed. |
| 131 | + // We provide a helper method to hold until the job finishes processing. Its a good practice to set a max timeout |
| 132 | + // if you're doing a test (ie: 2*status+run). in any case, it will hold until the job |
| 133 | + // finishes and moves to COMPLETED, CANCELED, or TIMEOUT. |
| 134 | + job = modzyClient.blockUntilComplete(job, null); |
| 135 | + |
| 136 | + // Get the results: |
| 137 | + // Check the status of the job. Jobs may be canceled or can reach a timeout. |
| 138 | + if( JobStatus.COMPLETED.equals( job.getStatus() ) ){ |
| 139 | + // A completed job means that all the inputs were processed by the model. Check the results for each |
| 140 | + // input key provided in the source map to see the model output. |
| 141 | + JobOutput<JsonNode> result = modzyClient.getResult(job); |
| 142 | + // The result object has some useful info: |
| 143 | + System.out.println( |
| 144 | + String.format("Result: finished: %s, total: %s, completed: %s, failed: %s", |
| 145 | + result.getFinished(), result.getTotal(), result.getCompleted(), result.getFailed() |
| 146 | + ) |
| 147 | + ); |
| 148 | + // Notice that we are iterating thought the same keys of the input sources |
| 149 | + for( String key : jobInput.getSources().keySet() ){ |
| 150 | + // The result object has the individual results of each job input. In this case the output key is called |
| 151 | + // results.json, so we can get that specific model result as follows: |
| 152 | + if( result.getResults().containsKey(key) ){ |
| 153 | + JsonNode modelResult = result.getResults().get(key).get("results.json"); |
| 154 | + // The output for this model comes in a JSON format, so we can directly log the model results: |
| 155 | + System.out.print(String.format(" %s: ", key)); |
| 156 | + Map.Entry<String, JsonNode> field; |
| 157 | + String textValue; |
| 158 | + for (Iterator<Map.Entry<String, JsonNode>> it = modelResult.fields(); it.hasNext(); ) { |
| 159 | + field = it.next(); |
| 160 | + textValue = field.getValue().asText().replace('\n', ' '); |
| 161 | + System.out.print( String.format(" %s: %s", field.getKey(), textValue) ); |
| 162 | + } |
| 163 | + System.out.println(); |
| 164 | + } |
| 165 | + else{ |
| 166 | + // If the model raises an error, we can get the specific error message: |
| 167 | + System.err.println(String.format(" %s: failure: %s", key, result.getFailures().get(key))); |
| 168 | + } |
| 169 | + } |
| 170 | + } |
| 171 | + else{ |
| 172 | + System.err.println(String.format("processing failed: %s", job)); |
| 173 | + } |
| 174 | + |
| 175 | + } |
| 176 | + |
| 177 | +} |
0 commit comments