diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 504653b..0000000 --- a/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM maven:3.8.4-openjdk-17 AS maven_build -COPY pom.xml /tmp/pom.xml -COPY env.properties /tmp/env.properties -COPY src /tmp/src -WORKDIR /tmp/ - -RUN mvn -f /tmp/pom.xml clean package - -FROM openjdk:17 -EXPOSE 8080 - -CMD ls /tmp -COPY --from=maven_build /tmp/target/oracleai-0.0.1-SNAPSHOT.jar /app/oracleai-0.0.1-SNAPSHOT.jar -ENTRYPOINT ["java","-jar","/app/oracleai-0.0.1-SNAPSHOT.jar"] \ No newline at end of file diff --git a/java-ai/Dockerfile b/java-ai/Dockerfile new file mode 100644 index 0000000..5335edd --- /dev/null +++ b/java-ai/Dockerfile @@ -0,0 +1,5 @@ +FROM openjdk:17-alpine +#docker.io/library/openjdk:17-oracle + +ADD target/oracleai-0.0.1-SNAPSHOT.jar /usr/share/oracleai/oracleai-0.0.1-SNAPSHOT.jar +ENTRYPOINT ["java", "-jar", "/usr/share/oracleai/oracleai-0.0.1-SNAPSHOT.jar"] diff --git a/build.sh b/java-ai/build.sh similarity index 100% rename from build.sh rename to java-ai/build.sh diff --git a/java-ai/build0.sh b/java-ai/build0.sh new file mode 100755 index 0000000..3455a02 --- /dev/null +++ b/java-ai/build0.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +set -e + +IMAGE_NAME=podsofkon +#IMAGE_VERSION=latest +IMAGE_VERSION=sustainableaijava +#DOCKER_REGISTRY=us-ashburn-1.ocir.io/oradbclouducm/gd74087885 +DOCKER_REGISTRY=us-ashburn-1.ocir.io/oradbclouducm/podsofkon + +export IMAGE=${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_VERSION} +export IMAGE_VERSION=$IMAGE_VERSION + +mvn clean package + +#docker buildx build --platform linux/amd64,linux/arm64 -t $IMAGE . +podman build -t=$IMAGE . +#docker buildx build --platform=linux/amd64 -t=$IMAGE . + +#docker push --platform linux/amd64 "$IMAGE" +podman push "$IMAGE" diff --git a/build_and_run.sh b/java-ai/build_and_run.sh similarity index 100% rename from build_and_run.sh rename to java-ai/build_and_run.sh diff --git a/build_docker.sh b/java-ai/build_docker.sh similarity index 100% rename from build_docker.sh rename to java-ai/build_docker.sh diff --git a/env.properties b/java-ai/env.properties similarity index 100% rename from env.properties rename to java-ai/env.properties diff --git a/java-ai/k8s/createSecretFromWallet.sh b/java-ai/k8s/createSecretFromWallet.sh new file mode 100755 index 0000000..26cee25 --- /dev/null +++ b/java-ai/k8s/createSecretFromWallet.sh @@ -0,0 +1,22 @@ +#!/bin/bash +#simply copy this file to and run it from your wallet dir... +if kubectl apply -f - ; then + echo "secret applied for wallet." +else + echo "Error: Failure to create ragdb-wallet-secret." +fi <Oracle AI Demos - 3.44.2 + 3.52.1 @@ -32,10 +32,15 @@ json 20231013 + + commons-io + commons-io + 2.8.0 + com.oracle.cloud.spring spring-cloud-oci-starter - 1.0.0 + 1.3.0 com.oracle.oci.sdk diff --git a/run.sh b/java-ai/run.sh similarity index 100% rename from run.sh rename to java-ai/run.sh diff --git a/run_docker.sh b/java-ai/run_docker.sh similarity index 100% rename from run_docker.sh rename to java-ai/run_docker.sh diff --git a/src/main/java/oracleai/AIApplication.java b/java-ai/src/main/java/oracleai/AIApplication.java similarity index 62% rename from src/main/java/oracleai/AIApplication.java rename to java-ai/src/main/java/oracleai/AIApplication.java index 13a12c9..96ce305 100644 --- a/src/main/java/oracleai/AIApplication.java +++ b/java-ai/src/main/java/oracleai/AIApplication.java @@ -1,8 +1,10 @@ package oracleai; +import com.oracle.bmc.retrier.RetryConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; + @SpringBootApplication public class AIApplication { @@ -10,9 +12,12 @@ public class AIApplication { public static final String OBJECTSTORAGE_NAMESPACE = System.getenv("OBJECTSTORAGE_NAMESPACE"); public static final String OBJECTSTORAGE_BUCKETNAME = System.getenv("OBJECTSTORAGE_BUCKETNAME"); public static final String ORDS_ENDPOINT_URL = System.getenv("ORDS_ENDPOINT_URL"); + public static final String ORDS_OMLOPSENDPOINT_URL= System.getenv("ORDS_ENDPOINT_URL") + "/omlopsuser/"; public static final String OCI_VISION_SERVICE_ENDPOINT = System.getenv("OCI_VISION_SERVICE_ENDPOINT"); - public static final String OCI_SPEECH_SERVICE_ENDPOINT = System.getenv("OCI_SPEECH_SERVICE_ENDPOINT"); - public static final String OCI_GENAI_SERVICE_ENDPOINT = System.getenv("OCI_GENAI_SERVICE_ENDPOINT"); + public static final String OCICONFIG_FILE = System.getenv("OCICONFIG_FILE"); + public static final String OCICONFIG_PROFILE = System.getenv("OCICONFIG_PROFILE"); + public static final String DIGITAL_DOUBLES_IMAGES_ENDPOINT = System.getenv("DIGITAL_DOUBLES_IMAGES_ENDPOINT"); + public static final String THREEDEY = "msy_mykey"; static { System.out.println("AIApplication.static initializer COMPARTMENT_ID:" + COMPARTMENT_ID); @@ -21,8 +26,12 @@ public class AIApplication { System.out.println("AIApplication.static initializer ORDS_ENDPOINT_URL:" + ORDS_ENDPOINT_URL); System.out.println("AIApplication.static initializer OCI_VISION_SERVICE_ENDPOINT:" + OCI_VISION_SERVICE_ENDPOINT); } + public static void main(String[] args) { - SpringApplication.run(AIApplication.class, args); - } +// RetryConfiguration retryConfiguration = RetryConfiguration.builder() +// .terminationStrategy(RetryUtils.createExponentialBackoffStrategy(500, 5)) // Configure limits +// .build(); + SpringApplication.run(AIApplication.class, args); + } } diff --git a/src/main/java/oracleai/ExplainAndAdviseOnHealthTestResults.java b/java-ai/src/main/java/oracleai/ExplainAndAdviseOnHealthTestResults.java similarity index 86% rename from src/main/java/oracleai/ExplainAndAdviseOnHealthTestResults.java rename to java-ai/src/main/java/oracleai/ExplainAndAdviseOnHealthTestResults.java index 867649a..f07506f 100644 --- a/src/main/java/oracleai/ExplainAndAdviseOnHealthTestResults.java +++ b/java-ai/src/main/java/oracleai/ExplainAndAdviseOnHealthTestResults.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.oracle.bmc.aivision.model.ImageTextDetectionFeature; +import com.oracle.bmc.generativeaiinference.model.OnDemandServingMode; import oracleai.services.ORDSCalls; import oracleai.services.OracleGenAI; import oracleai.services.OracleObjectStore; @@ -43,8 +44,13 @@ public String analyzedoc(@RequestParam("file") MultipartFile multipartFile, } System.out.println(concatenatedText); System.out.println("analyzedoc fullText = " + concatenatedText); + OnDemandServingMode chatServingMode = OnDemandServingMode.builder() + .modelId("cohere.command-r-16k") + .build(); String explanationOfResults = - OracleGenAI.chat("explain these test results in simple terms, in less than 100 words, " + + OracleGenAI.builder().compartment(AIApplication.COMPARTMENT_ID) + .servingMode(chatServingMode) + .build().chat("explain these test results in simple terms, in less than 100 words, " + "and tell me what should I do to get better results: \"" + concatenatedText + "\""); System.out.println("ExplainAndAdviseOnHealthTestResults.analyzedoc explanationOfResults:" + explanationOfResults); model.addAttribute("results", "SUMMARY WITH ADVICE: " + explanationOfResults + diff --git a/src/main/java/oracleai/FaceRecognition.java b/java-ai/src/main/java/oracleai/FaceRecognition.java similarity index 100% rename from src/main/java/oracleai/FaceRecognition.java rename to java-ai/src/main/java/oracleai/FaceRecognition.java diff --git a/src/main/java/oracleai/GenerateAPictureStoryUsingOnlySpeech.java b/java-ai/src/main/java/oracleai/GenerateAPictureStoryUsingOnlySpeech.java similarity index 100% rename from src/main/java/oracleai/GenerateAPictureStoryUsingOnlySpeech.java rename to java-ai/src/main/java/oracleai/GenerateAPictureStoryUsingOnlySpeech.java diff --git a/src/main/java/oracleai/TextSearch.java b/java-ai/src/main/java/oracleai/TextSearch.java similarity index 100% rename from src/main/java/oracleai/TextSearch.java rename to java-ai/src/main/java/oracleai/TextSearch.java diff --git a/src/main/java/oracleai/UploadDownloadImage.java b/java-ai/src/main/java/oracleai/UploadDownloadImage.java similarity index 78% rename from src/main/java/oracleai/UploadDownloadImage.java rename to java-ai/src/main/java/oracleai/UploadDownloadImage.java index ba69c96..fd566a8 100644 --- a/src/main/java/oracleai/UploadDownloadImage.java +++ b/java-ai/src/main/java/oracleai/UploadDownloadImage.java @@ -1,15 +1,13 @@ package oracleai; - +import oracleai.digitaldouble.ImageStore; import oracleai.services.ORDSCalls; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; + @Controller @RequestMapping("/transferimage") public class UploadDownloadImage { @@ -23,8 +21,6 @@ public String uploadImage(@RequestParam("image") MultipartFile image, Model mode return "images"; } - - @GetMapping("/downloadimages") public String getImageStoreData(Model model) { ImageStore[] imageStores = ORDSCalls.getImageStoreData(); diff --git a/src/main/java/oracleai/WriteAStoryAboutAPictureAndGiveItsSentiments.java b/java-ai/src/main/java/oracleai/WriteAStoryAboutAPictureAndGiveItsSentiments.java similarity index 95% rename from src/main/java/oracleai/WriteAStoryAboutAPictureAndGiveItsSentiments.java rename to java-ai/src/main/java/oracleai/WriteAStoryAboutAPictureAndGiveItsSentiments.java index 99cc9a8..7e15d6c 100644 --- a/src/main/java/oracleai/WriteAStoryAboutAPictureAndGiveItsSentiments.java +++ b/java-ai/src/main/java/oracleai/WriteAStoryAboutAPictureAndGiveItsSentiments.java @@ -40,7 +40,7 @@ public String tellastory(@RequestParam("file") MultipartFile multipartFile, @Req "OBJECT_DETECTION", "TellAStory"); } - String generatedstory = OracleGenAI.chat("using strong negative and positive sentiments, " + + String generatedstory = OracleGenAI.builder().build().chat("using strong negative and positive sentiments, " + "write a story that is " + genopts + " and includes " + fullText ); model.addAttribute("results", "STORY: " + generatedstory + " --->SENTIMENT ANALYSIS: " + OracleLanguageAI.sentimentAnalysis(generatedstory) ); diff --git a/java-ai/src/main/java/oracleai/common/FileUploadExceptionAdvice.java b/java-ai/src/main/java/oracleai/common/FileUploadExceptionAdvice.java new file mode 100644 index 0000000..f164b7d --- /dev/null +++ b/java-ai/src/main/java/oracleai/common/FileUploadExceptionAdvice.java @@ -0,0 +1,16 @@ +package oracleai.common; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.multipart.MaxUploadSizeExceededException; + +@ControllerAdvice +public class FileUploadExceptionAdvice { + + @ExceptionHandler(MaxUploadSizeExceededException.class) + public ResponseEntity handleMaxSizeException(MaxUploadSizeExceededException exc) { + return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body("File too large!"); + } +} \ No newline at end of file diff --git a/java-ai/src/main/java/oracleai/digitaldouble/DigitalDoubleDownloadInfo.java b/java-ai/src/main/java/oracleai/digitaldouble/DigitalDoubleDownloadInfo.java new file mode 100644 index 0000000..1b90219 --- /dev/null +++ b/java-ai/src/main/java/oracleai/digitaldouble/DigitalDoubleDownloadInfo.java @@ -0,0 +1,103 @@ +package oracleai.digitaldouble; + +public class DigitalDoubleDownloadInfo { + + String email; + String modelUrl; + String modelGlbUrl; + String modelFbxUrl ; + String modelUsdzUrl ; + String thumbnailUrl; + String animatedVideoLocation; + String similarImageUrl; + + + + public DigitalDoubleDownloadInfo() { + + } + public DigitalDoubleDownloadInfo(String modelUrl, String modelGlbUrl, String modelFbxUrl, + String modelUsdzUrl, String thumbnailUrl) { + this.modelUrl = modelUrl; + this.modelGlbUrl = modelGlbUrl; + this.modelFbxUrl = modelFbxUrl; + this.modelUsdzUrl = modelUsdzUrl; + this.thumbnailUrl = thumbnailUrl; + } + + public DigitalDoubleDownloadInfo(String modelGlbUrl, String modelFbxUrl, String modelUsdzUrl, + String thumbnailUrl, String animatedVideoLocation, + String email, String similarImageUrl) { + this.modelGlbUrl = modelGlbUrl; + this.modelFbxUrl = modelFbxUrl; + this.modelUsdzUrl = modelUsdzUrl; + this.thumbnailUrl = thumbnailUrl; + this.animatedVideoLocation = animatedVideoLocation; + this.email = email; + this.similarImageUrl = similarImageUrl; + } + + public void setEmail(String email) { + this.email = email; + } + + public void setModelUrl(String modelUrl) { + this.modelUrl = modelUrl; + } + + public void setModelGlbUrl(String modelGlbUrl) { + this.modelGlbUrl = modelGlbUrl; + } + + public void setModelFbxUrl(String modelFbxUrl) { + this.modelFbxUrl = modelFbxUrl; + } + + public void setModelUsdzUrl(String modelUsdzUrl) { + this.modelUsdzUrl = modelUsdzUrl; + } + + public void setThumbnailUrl(String thumbnailUrl) { + this.thumbnailUrl = thumbnailUrl; + } + + public void setAnimatedVideoLocation(String animatedVideoLocation) { + this.animatedVideoLocation = animatedVideoLocation; + } + + public void setSimilarImageUrl(String similarImageUrl) { + this.similarImageUrl = similarImageUrl; + } + + public String getEmail() { + return email; + } + + public String getModelUrl() { + return modelUrl; + } + + public String getModelGlbUrl() { + return modelGlbUrl; + } + + public String getModelFbxUrl() { + return modelFbxUrl; + } + + public String getModelUsdzUrl() { + return modelUsdzUrl; + } + + public String getThumbnailUrl() { + return thumbnailUrl; + } + + public String getAnimatedVideoLocation() { + return animatedVideoLocation; + } + + public String getSimilarImageUrl() { + return similarImageUrl; + } +} diff --git a/java-ai/src/main/java/oracleai/digitaldouble/DigitalDoubleService.java b/java-ai/src/main/java/oracleai/digitaldouble/DigitalDoubleService.java new file mode 100644 index 0000000..f660a46 --- /dev/null +++ b/java-ai/src/main/java/oracleai/digitaldouble/DigitalDoubleService.java @@ -0,0 +1,39 @@ +package oracleai.digitaldouble; + +import oracleai.AIApplication; +import org.springframework.http.*; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.util.HashMap; +import java.util.Map; + +@Service +public class DigitalDoubleService { + + public void updateDigitalDoubleData(DigitalDoubleDownloadInfo info) { + String url = AIApplication.ORDS_OMLOPSENDPOINT_URL + "update_digital_double_data/"; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + Map requestBody = new HashMap<>(); + requestBody.put("p_participant_email", info.getEmail()); + requestBody.put("p_modelglburl_out", info.getModelGlbUrl()); + requestBody.put("p_modelfbxurl_out", info.modelFbxUrl); + requestBody.put("p_modelusdzurl_out", info.modelUsdzUrl); + requestBody.put("p_thumbnailurl_out", info.thumbnailUrl); + + HttpEntity> entity = new HttpEntity<>(requestBody, headers); + + ResponseEntity response = + new RestTemplate().exchange(url, HttpMethod.POST, entity, String.class); + + if (response.getStatusCode().is2xxSuccessful()) { + System.out.println("Request successful: " + response.getBody()); + } else { + System.err.println("Request failed with status code: " + response.getStatusCode()); + } + + } +} \ No newline at end of file diff --git a/java-ai/src/main/java/oracleai/digitaldouble/DigitalDoublesController.java b/java-ai/src/main/java/oracleai/digitaldouble/DigitalDoublesController.java new file mode 100644 index 0000000..2276965 --- /dev/null +++ b/java-ai/src/main/java/oracleai/digitaldouble/DigitalDoublesController.java @@ -0,0 +1,94 @@ +package oracleai.digitaldouble; + + +import oracleai.services.ORDSCalls; +import oracleai.services.OracleObjectStore; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; + +import org.springframework.http.MediaType; + +@Controller +@RequestMapping("/digitaldoubles") +public class DigitalDoublesController { + + private final ImageProcessor imageProcessor; + + @Autowired + public DigitalDoublesController(ImageProcessor imageProcessor) { + this.imageProcessor = imageProcessor; + } + private static final String DIRECTORY = "/tmp/images/"; + + @GetMapping("/uploadordownload") + public String digitaldouble(@RequestParam("action") String action, Model model) { + return action.equals("uploading") ? "digitaldoubleupload" : "digitaldoubledownload"; + } + + + @PostMapping("/uploadimageandvideo") + public String uploadimageandvideo( + @RequestParam("image") MultipartFile image, + @RequestParam("video") MultipartFile video, + @RequestParam("animstyle") String animstyle, + @RequestParam("animprompt") String animprompt, + @RequestParam("firstName") String firstName, + @RequestParam("lastName") String lastName, + @RequestParam("email") String email, + @RequestParam("company") String company, + @RequestParam("jobrole") String jobRole, + @RequestParam("tshirtsize") String tshirtSize, + @RequestParam("comments") String comments, + Model model) throws IOException { + + String commentsWithAnimStyleAndPrompt = animstyle + " " + animprompt + " " + comments; + System.out.println("image = " + image + ", video = " + video + ", animstyle = " + animstyle + + ", firstName = " + firstName + ", lastName = " + lastName + + ", email = " + email + ", company = " + company + + ", jobRole = " + jobRole + ", tshirtSize = " + tshirtSize + + ", comments = " + comments + ", model = " + model + + "\ncomments with animstyle and prompt = " + commentsWithAnimStyleAndPrompt); + ORDSCalls.insertDigitalDoubleData( + image, null, firstName, lastName, email, company, jobRole, tshirtSize, commentsWithAnimStyleAndPrompt); + + String fullVideoName =""; + if (!video.isEmpty()) { + fullVideoName = email + "_" + animstyle + "_" + video.getOriginalFilename(); + OracleObjectStore.sendToObjectStorage(fullVideoName, video.getInputStream()); + } + imageProcessor.handleImageUpload(email, image, fullVideoName); + + return "digitaldoubledownload"; + + } + + @GetMapping("/images/{filename:.+}") + public ResponseEntity getImage(@PathVariable String filename) throws IOException { + try { + File file = new File(DIRECTORY, filename); + byte[] fileContent = org.apache.commons.io.FileUtils.readFileToByteArray(file); + return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(fileContent); + } catch (IOException e) { + return ResponseEntity.notFound().build(); + } + } + + + @PostMapping("/downloaddigitaldouble") + public String downloaddigitaldouble(@RequestParam("email") String email, Model model) throws Exception { + model.addAttribute("fbxlink", ORDSCalls.getDigitalDoubleData(email)); + model.addAttribute("fbxtext", "FBX 3D Model"); + model.addAttribute("mp4link", ImageProcessor.objectStoreLocation + email + ".mp4"); + model.addAttribute("mp4text", "MP4 Animation"); + return "digitaldoubleresults"; + } + + +} diff --git a/java-ai/src/main/java/oracleai/digitaldouble/ImageProcessor.java b/java-ai/src/main/java/oracleai/digitaldouble/ImageProcessor.java new file mode 100644 index 0000000..2592dbb --- /dev/null +++ b/java-ai/src/main/java/oracleai/digitaldouble/ImageProcessor.java @@ -0,0 +1,108 @@ +package oracleai.digitaldouble; + +import oracleai.AIApplication; +import oracleai.services.ORDSCalls; +import org.apache.commons.io.FileUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +@Service +public class ImageProcessor { + + private static final String DIRECTORY = "/tmp/images/"; + private static final BlockingQueue queue = new LinkedBlockingQueue<>(); + + // Inject DigitalDoubleService to make REST call + private final DigitalDoubleService digitalDoubleService; + + @Autowired + public ImageProcessor(DigitalDoubleService digitalDoubleService) { + this.digitalDoubleService = digitalDoubleService; + new Thread(this::processQueue).start(); + } + + public String handleImageUpload(String email, MultipartFile image, String fullVideoName) throws IOException { + String imageFileNameWithEmailPrefix = ""; + if (image != null && !image.isEmpty()) { + FileUtils.forceMkdir(new File(DIRECTORY)); + imageFileNameWithEmailPrefix = email + "_" + image.getOriginalFilename(); + Path path = Paths.get(DIRECTORY + imageFileNameWithEmailPrefix); + image.transferTo(path); + } + queue.offer(new ImageTask(email, imageFileNameWithEmailPrefix, fullVideoName)); + return "Image is being processed"; + } + + public static String objectStoreLocation = + "https://" + AIApplication.OBJECTSTORAGE_NAMESPACE + ".compat.objectstorage.us-ashburn-1.oraclecloud.com/" + + AIApplication.OBJECTSTORAGE_BUCKETNAME + "/anim/"; + + private void processQueue() { + while (true) { + try { + ImageTask task = queue.take(); + DigitalDoubleDownloadInfo digitalDoubleDownloadInfo; + if (!task.getImageFileNameWithEmailPrefix().equals("")) { + digitalDoubleDownloadInfo = ORDSCalls.convertImageAndQueueResults( + AIApplication.DIGITAL_DOUBLES_IMAGES_ENDPOINT, + task.getImageFileNameWithEmailPrefix()); + } else { + digitalDoubleDownloadInfo = new DigitalDoubleDownloadInfo(); + } + + digitalDoubleDownloadInfo.animatedVideoLocation = objectStoreLocation + task.getFullVideoName(); + + // Call the method to update Digital Double data + digitalDoubleService.updateDigitalDoubleData( + new DigitalDoubleDownloadInfo( + digitalDoubleDownloadInfo.modelGlbUrl, + digitalDoubleDownloadInfo.modelFbxUrl, + digitalDoubleDownloadInfo.modelUsdzUrl, + digitalDoubleDownloadInfo.thumbnailUrl, + digitalDoubleDownloadInfo.animatedVideoLocation, + task.getEmail(), + "" // Similar image can be passed here if available + ) + ); + + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } catch (Exception e) { + System.err.println("Failed to process image for: " + e.getMessage()); + } + } + } + + private static class ImageTask { + private final String email; + private final String imageFileNameWithEmailPrefix; + private final String fullVideoName; + + public ImageTask(String email, String imageFileNameWithEmailPrefix, String fullVideoName) { + this.email = email; + this.imageFileNameWithEmailPrefix = imageFileNameWithEmailPrefix; + this.fullVideoName = fullVideoName; + } + + public String getEmail() { + return email; + } + + public String getImageFileNameWithEmailPrefix() { + return imageFileNameWithEmailPrefix; + } + + public String getFullVideoName() { + return fullVideoName; + } + } +} \ No newline at end of file diff --git a/src/main/java/oracleai/ImageStore.java b/java-ai/src/main/java/oracleai/digitaldouble/ImageStore.java similarity index 96% rename from src/main/java/oracleai/ImageStore.java rename to java-ai/src/main/java/oracleai/digitaldouble/ImageStore.java index 3107a10..e4fd2d2 100644 --- a/src/main/java/oracleai/ImageStore.java +++ b/java-ai/src/main/java/oracleai/digitaldouble/ImageStore.java @@ -1,4 +1,4 @@ -package oracleai; +package oracleai.digitaldouble; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/oracleai/ImageStoreWrapper.java b/java-ai/src/main/java/oracleai/digitaldouble/ImageStoreWrapper.java similarity index 91% rename from src/main/java/oracleai/ImageStoreWrapper.java rename to java-ai/src/main/java/oracleai/digitaldouble/ImageStoreWrapper.java index 5a1e3a6..29f230d 100644 --- a/src/main/java/oracleai/ImageStoreWrapper.java +++ b/java-ai/src/main/java/oracleai/digitaldouble/ImageStoreWrapper.java @@ -1,4 +1,4 @@ -package oracleai; +package oracleai.digitaldouble; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.util.List; diff --git a/java-ai/src/main/java/oracleai/services/AuthProvider.java b/java-ai/src/main/java/oracleai/services/AuthProvider.java new file mode 100644 index 0000000..995727d --- /dev/null +++ b/java-ai/src/main/java/oracleai/services/AuthProvider.java @@ -0,0 +1,23 @@ +package oracleai.services; + +import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider; +import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider; +import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider; +import oracleai.AIApplication; + +import java.io.IOException; + +public class AuthProvider { + + public static BasicAuthenticationDetailsProvider getAuthenticationDetailsProvider() throws IOException { + if (isRunningInOKE()) return InstancePrincipalsAuthenticationDetailsProvider.builder().build(); + else return new ConfigFileAuthenticationDetailsProvider( +// "~/.oci/config", "DEFAULT"); + AIApplication.OCICONFIG_FILE, AIApplication.OCICONFIG_PROFILE); + } + + private static boolean isRunningInOKE() { + return false; //System.getenv("OCI_RESOURCE_PRINCIPAL_VERSION") != null; + } + +} diff --git a/java-ai/src/main/java/oracleai/services/DigitalDoubleDataRequest.java b/java-ai/src/main/java/oracleai/services/DigitalDoubleDataRequest.java new file mode 100644 index 0000000..779c885 --- /dev/null +++ b/java-ai/src/main/java/oracleai/services/DigitalDoubleDataRequest.java @@ -0,0 +1,15 @@ +package oracleai.services; + +public class DigitalDoubleDataRequest { + public String p_participant_firstname; + public String p_participant_lastname; + public String p_participant_email; + public String p_participant_company; + public String p_participant_role; + public String p_participant_tshirt; + public String p_participant_comments; + public String p_id_image_in; // You can change this to byte[] for BLOB + public String p_image_in; // You can change this to byte[] for BLOB + public String p_video_in; // You can change this to byte[] for BLOB + +} \ No newline at end of file diff --git a/java-ai/src/main/java/oracleai/services/DigitalDoubleORDS.java b/java-ai/src/main/java/oracleai/services/DigitalDoubleORDS.java new file mode 100644 index 0000000..7910cb3 --- /dev/null +++ b/java-ai/src/main/java/oracleai/services/DigitalDoubleORDS.java @@ -0,0 +1,32 @@ +package oracleai.services; + +import oracleai.AIApplication; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +public class DigitalDoubleORDS { + + public void insertDigitalDoubleData(DigitalDoubleDataRequest request) { + String url = AIApplication.ORDS_OMLOPSENDPOINT_URL + "insert_digital_double_data/"; + + RestTemplate restTemplate = new RestTemplate(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity entity = new HttpEntity<>(request, headers); + + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.POST, + entity, + String.class + ); + + System.out.println(response.getBody()); + } +} \ No newline at end of file diff --git a/src/main/java/oracleai/services/ImageGeneration.java b/java-ai/src/main/java/oracleai/services/ImageGeneration.java similarity index 100% rename from src/main/java/oracleai/services/ImageGeneration.java rename to java-ai/src/main/java/oracleai/services/ImageGeneration.java diff --git a/java-ai/src/main/java/oracleai/services/ORDSCalls.java b/java-ai/src/main/java/oracleai/services/ORDSCalls.java new file mode 100644 index 0000000..f09ee99 --- /dev/null +++ b/java-ai/src/main/java/oracleai/services/ORDSCalls.java @@ -0,0 +1,233 @@ +package oracleai.services; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import oracleai.*; +import oracleai.digitaldouble.DigitalDoubleDownloadInfo; +import oracleai.digitaldouble.ImageStore; +import oracleai.digitaldouble.ImageStoreWrapper; +import org.springframework.http.*; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.util.UriComponentsBuilder; + + +import java.io.IOException; +import java.net.URI; +import java.net.URLEncoder; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +@Service +public class ORDSCalls { + + public static String callAnalyzeImageInline(String ordsEndpoint, String visionServiceIndpoint, + String compartmentOcid, MultipartFile imageFile) + throws Exception { + RestTemplate restTemplate = new RestTemplate(); + String base64ImageData = Base64.getEncoder().encodeToString(imageFile.getBytes()); + String jsonBody = String.format("{\"p_compartment_ocid\": \"%s\", \"p_endpoint\": \"%s\", \"p_image_data\": \"%s\"}", + compartmentOcid, visionServiceIndpoint, base64ImageData); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity requestEntity = new HttpEntity<>(jsonBody, headers); + ResponseEntity response = restTemplate.exchange(ordsEndpoint, HttpMethod.POST, requestEntity, String.class); + return response.getBody(); + } + + + //As written only supports one feature type per call + public static String analyzeImageInObjectStore( + String ordsEndpoint, String visionServiceEndpoint, String compartmentOcid, + String bucketName, String namespaceName, String objectName, String featureType, String label) { + System.out.println("ORDSCalls.analyzeImageInObjectStore"); + System.out.println("ordsEndpoint = " + ordsEndpoint + ", visionServiceEndpoint = " + visionServiceEndpoint + ", compartmentOcid = " + compartmentOcid + ", bucketName = " + bucketName + ", namespaceName = " + namespaceName + ", objectName = " + objectName + ", featureType = " + featureType + ", label = " + label); + RestTemplate restTemplate = new RestTemplate(); + String jsonPayload = String.format( + "{\"p_bucketname\": \"%s\", \"p_compartment_ocid\": \"%s\", \"p_endpoint\": \"%s\", " + + "\"p_namespacename\": \"%s\", \"p_objectname\": \"%s\", \"p_featuretype\": \"%s\", \"p_label\": \"%s\"}", + bucketName, compartmentOcid, visionServiceEndpoint, namespaceName, objectName, featureType, label); + System.out.println("ORDSCalls.analyzeImageInObjectStore jsonPayload:" + jsonPayload); + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity entity = new HttpEntity<>(jsonPayload, headers); + ResponseEntity response = restTemplate.exchange(ordsEndpoint, HttpMethod.POST, entity, String.class); + System.out.println("ORDSCalls.analyzeImageInObjectStore response.getBody():" + response.getBody()); + return response.getBody(); + } + + public static String executeTextSearchContains(String ordsEndpoint, String sql) { + String jsonPayload = String.format("{\"p_sql\": \"%s\"}", sql); + return callTextSearch(ordsEndpoint, jsonPayload); + } + + public static String executeTextSearchOR(String ordsEndpoint, String sql, String sql2) { + String jsonPayload = String.format("{\"p_sql\": \"%s\", \"p_sql\": \"%s\"}", sql, sql2); + return callTextSearch(ordsEndpoint, jsonPayload); + } + + private static String callTextSearch(String ordsEndpoint, String jsonPayload) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity entity = new HttpEntity<>(jsonPayload, headers); + ResponseEntity response = new RestTemplate().exchange(ordsEndpoint, HttpMethod.POST, entity, String.class); + System.out.println("ORDSCalls.analyzeImageInObjectStore response.getBody():" + response.getBody()); + return response.getBody(); + } + + public static ResponseEntity uploadImage(MultipartFile image) { + try { + String base64Image = Base64.getEncoder().encodeToString(image.getBytes()); + Map payload = new HashMap<>(); + payload.put("p_image_name", image.getOriginalFilename()); + payload.put("p_image", base64Image); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity> requestEntity = new HttpEntity<>(payload, headers); + RestTemplate restTemplate = new RestTemplate(); + String uploadUrl = AIApplication.ORDS_ENDPOINT_URL + "insert_image/"; + return restTemplate.exchange(uploadUrl, HttpMethod.POST, requestEntity, String.class); + } catch (Exception e) { + throw new RuntimeException("Failed to upload image", e); + } + } + + + public static ImageStore[] getImageStoreData() { + String url = AIApplication.ORDS_ENDPOINT_URL + "image_store/"; + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity response = restTemplate.getForEntity(url, ImageStoreWrapper.class); + ImageStoreWrapper wrapper = response.getBody(); + if (wrapper != null) { + for (ImageStore imageStore : wrapper.getItems()) { + System.out.println("Image Name: " + imageStore.getImageName()); + } + return wrapper.getItems().toArray(new ImageStore[0]); + } else { + return new ImageStore[0]; + } + } + + public static ImageStore[] make3Drequest() { + String url = AIApplication.ORDS_ENDPOINT_URL + "image_store/"; + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity response = restTemplate.getForEntity(url, ImageStoreWrapper.class); + ImageStoreWrapper wrapper = response.getBody(); + if (wrapper != null) { + for (ImageStore imageStore : wrapper.getItems()) { + System.out.println("Image Name: " + imageStore.getImageName()); + } + return wrapper.getItems().toArray(new ImageStore[0]); + } else { + return new ImageStore[0]; + } + } + + + public static DigitalDoubleDownloadInfo convertImageAndQueueResults( + String imageLocation, String fileName) { + String apiUrl = "https://api.meshy.ai/v1/image-to-3d"; + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("Authorization", "Bearer " + AIApplication.THREEDEY); + String requestJson = + "{\"image_url\": \"" + imageLocation + fileName + "\", " + + "\"enable_pbr\": true, \"surface_mode\": \"hard\"}"; + HttpEntity entity = new HttpEntity<>(requestJson, headers); + ResponseEntity response = restTemplate.postForEntity(apiUrl, entity, String.class); + ObjectMapper mapper = new ObjectMapper(); + try { + JsonNode root = mapper.readTree(response.getBody()); + String theResultString = root.path("result").asText(); + return pollApiUntilSuccess(fileName, theResultString); + } catch (IOException e) { + e.printStackTrace(); + return new DigitalDoubleDownloadInfo(); + } + } + + public static DigitalDoubleDownloadInfo pollApiUntilSuccess( + String fileName, String theResultString) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", "Bearer " + AIApplication.THREEDEY); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity entity = new HttpEntity<>(headers); + + ObjectMapper mapper = new ObjectMapper(); + while (true) { + try { + ResponseEntity response = + restTemplate.exchange( + "https://api.meshy.ai/v1/image-to-3d/" + theResultString, + HttpMethod.GET, entity, String.class); + JsonNode rootNode = mapper.readTree(response.getBody()); + String status = rootNode.path("status").asText(); + System.out.println(fileName + " status:" + status); + if ("SUCCEEDED".equals(status)) { + String modelUrl = rootNode.path("model_url").asText(); + String modelGlbUrl = rootNode.path("model_urls").path("glb").asText(); + String modelFbxUrl = rootNode.path("model_urls").path("fbx").asText(); + String modelUsdzUrl = rootNode.path("model_urls").path("usdz").asText(); + String thumbnailUrl = rootNode.path("thumbnail_url").asText(); + System.out.println("ORDSCalls.pollApiUntilSuccess modelFbxUrl:" + modelFbxUrl); + return new DigitalDoubleDownloadInfo( + modelUrl, modelGlbUrl, modelFbxUrl, modelUsdzUrl, thumbnailUrl); + } + Thread.sleep(5000); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static void insertDigitalDoubleData(MultipartFile image, MultipartFile video, + String firstName, String lastName, String email, + String company, String jobRole, String tshirtSize, + String comments) throws IOException { + DigitalDoubleORDS client = new DigitalDoubleORDS(); + DigitalDoubleDataRequest request = new DigitalDoubleDataRequest(); + request.p_participant_firstname = firstName; + request.p_participant_lastname = lastName; + request.p_participant_email = email; + request.p_participant_company = company; + request.p_participant_role = jobRole; + request.p_participant_tshirt = tshirtSize; + request.p_participant_comments = comments; +// request.p_id_image_in = idimage; + if (image != null) request.p_image_in = Base64.getEncoder().encodeToString(image.getBytes()); + if (video != null) request.p_video_in = Base64.getEncoder().encodeToString(video.getBytes()); + client.insertDigitalDoubleData(request); + System.out.println("ORDSCalls.insertDigitalDoubleData insert complete"); + } + + + public static String getDigitalDoubleData(String email) throws Exception { + System.out.println("DigitalDoubles.downloaddigitaldouble lookup email:" + email); +// String url = AIApplication.ORDS_OMLOPSENDPOINT_URL + "modelurls/geturls/" + email; + String baseUrl = AIApplication.ORDS_OMLOPSENDPOINT_URL + "/digitaldouble/fbxurl/" ; + URI uri = UriComponentsBuilder.fromHttpUrl(baseUrl) + .pathSegment(URLEncoder.encode(email, "UTF-8")) + .build(true).toUri(); + System.out.println("ORDSCalls.getDigitalDoubleData uri=" + uri); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity entity = new HttpEntity<>(headers); + ResponseEntity response = new RestTemplate().exchange(uri, HttpMethod.GET, entity, String.class); + if (response.getStatusCode().is2xxSuccessful()) { + String modelFbxUrl = response.getBody(); + System.out.println("MODELFBXURL_OUT: " + modelFbxUrl); + return modelFbxUrl; + } else { + System.err.println("Failed to retrieve FBX URL. Status code: " + response.getStatusCode()); + return null; + } + + } +} + diff --git a/java-ai/src/main/java/oracleai/services/OracleGenAI.java b/java-ai/src/main/java/oracleai/services/OracleGenAI.java new file mode 100644 index 0000000..d7a9cad --- /dev/null +++ b/java-ai/src/main/java/oracleai/services/OracleGenAI.java @@ -0,0 +1,214 @@ +package oracleai.services; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider; +import com.oracle.bmc.generativeaiinference.GenerativeAiInference; +import com.oracle.bmc.generativeaiinference.GenerativeAiInferenceClient; +import com.oracle.bmc.generativeaiinference.model.*; +import com.oracle.bmc.generativeaiinference.requests.ChatRequest; +import com.oracle.bmc.generativeaiinference.responses.ChatResponse; +import lombok.Builder; +import lombok.Getter; +import oracleai.AIApplication; + +/** + * OCI GenAI Chat + */ +public class OracleGenAI { + private final GenerativeAiInference client; + private final ServingMode servingMode; + private final String compartment; + private final String preambleOverride; + private final Double temperature; + private final Double frequencyPenalty; + private final Integer maxTokens; + private final Double presencePenalty; + private final Double topP; + private final Integer topK; + private final InferenceRequestType inferenceRequestType; + private List cohereChatMessages; + private List genericChatMessages; + + @Builder + public OracleGenAI(BasicAuthenticationDetailsProvider authProvider, + ServingMode servingMode, + String compartment, + String preambleOverride, + Double temperature, + Double frequencyPenalty, + Integer maxTokens, + Double presencePenalty, + Double topP, + Integer topK, + InferenceRequestType inferenceRequestType) throws Exception { + + + + this.client = GenerativeAiInferenceClient.builder() + .build(AuthProvider.getAuthenticationDetailsProvider()); + this.servingMode = servingMode; + this.compartment = compartment; + this.preambleOverride = preambleOverride; + + this.temperature = Objects.requireNonNullElse(temperature, 1.0); + this.frequencyPenalty = Objects.requireNonNullElse( + frequencyPenalty, + 0.0 + ); + this.maxTokens = Objects.requireNonNullElse(maxTokens, 600); + this.presencePenalty = Objects.requireNonNullElse( + presencePenalty, + 0.0 + ); + this.topP = Objects.requireNonNullElse(topP, 0.75); + this.inferenceRequestType = Objects.requireNonNullElse( + inferenceRequestType, + InferenceRequestType.COHERE + ); + this.topK = Objects.requireNonNullElseGet(topK, () -> { + if (this.inferenceRequestType == InferenceRequestType.COHERE) { + return 0; + } + return -1; + }); + } + + @Getter + public enum InferenceRequestType { + COHERE("COHERE"), + LLAMA("LLAMA"); + + private final String type; + + InferenceRequestType(String type) { + this.type = type; + } + } + + /** + * Chat using OCI GenAI. + * @param prompt Prompt text sent to OCI GenAI chat model. + * @return OCI GenAI ChatResponse + */ + public String chat1(String prompt) { + return "whateve"; + } + + public String chat(String prompt) { + ChatDetails chatDetails = ChatDetails.builder() +// .compartmentId(AIApplication.COMPARTMENT_ID) + .compartmentId(compartment) +// .servingMode(OnDemandServingMode.builder().build()) + .servingMode(servingMode) + .chatRequest(createChatRequest(prompt)) + .build(); + ChatRequest chatRequest = ChatRequest.builder() + .body$(chatDetails) + .build(); + ChatResponse response = client.chat(chatRequest); + saveChatHistory(response); + return extractText(response); + } + + /** + * Create a ChatRequest from a text prompt. Supports COHERE or LLAMA inference. + * @param prompt To create a ChatRequest from. + * @return A COHERE or LLAMA ChatRequest. + */ + private BaseChatRequest createChatRequest(String prompt) { + switch (inferenceRequestType) { + case COHERE: + return CohereChatRequest.builder() + .frequencyPenalty(frequencyPenalty) + .maxTokens(maxTokens) + .presencePenalty(presencePenalty) + .message(prompt) + .temperature(temperature) + .topP(topP) + .topK(topK) + .chatHistory(cohereChatMessages) + .preambleOverride(preambleOverride) + .build(); + case LLAMA: + List messages = genericChatMessages == null ? + new ArrayList<>() : + genericChatMessages.stream() + .map(ChatChoice::getMessage) + .collect(Collectors.toList()); + ChatContent content = TextContent.builder() + .text(prompt) + .build(); + List contents = new ArrayList<>(); + contents.add(content); + UserMessage message = UserMessage.builder() + .name("USER") + .content(contents) + .build(); + messages.add(message); + return GenericChatRequest.builder() + .messages(messages) + .frequencyPenalty(frequencyPenalty) + .temperature(temperature) + .maxTokens(maxTokens) + .presencePenalty(presencePenalty) + .topP(topP) + .topK(topK) + .build(); + } + + throw new IllegalArgumentException(String.format( + "Unknown request type %s", + inferenceRequestType + )); + } + + /** + * Save the current chat history to memory. + * @param chatResponse The latest chat response. + */ + private void saveChatHistory(ChatResponse chatResponse) { + BaseChatResponse bcr = chatResponse.getChatResult() + .getChatResponse(); + if (bcr instanceof CohereChatResponse resp) { + cohereChatMessages = resp.getChatHistory(); + } else if (bcr instanceof GenericChatResponse resp) { + genericChatMessages = resp.getChoices(); + } else { + throw new IllegalStateException(String.format( + "Unexpected chat response type: %s", + bcr.getClass().getName() + )); + } + } + + /** + * Extract text from an OCI GenAI ChatResponse. + * @param chatResponse The response to extract text from. + * @return The chat response text. + */ + private String extractText(ChatResponse chatResponse) { + BaseChatResponse bcr = chatResponse + .getChatResult() + .getChatResponse(); + if (bcr instanceof CohereChatResponse resp) { + return resp.getText(); + } else if (bcr instanceof GenericChatResponse resp) { + List choices = resp.getChoices(); + List contents = choices.get(choices.size() - 1) + .getMessage() + .getContent(); + ChatContent content = contents.get(contents.size() - 1); + if (content instanceof TextContent) { + return ((TextContent) content).getText(); + } + } + throw new IllegalStateException(String.format( + "Unexpected chat response type: %s", + bcr.getClass().getName() + )); + } +} \ No newline at end of file diff --git a/src/main/java/oracleai/services/OracleLanguageAI.java b/java-ai/src/main/java/oracleai/services/OracleLanguageAI.java similarity index 100% rename from src/main/java/oracleai/services/OracleLanguageAI.java rename to java-ai/src/main/java/oracleai/services/OracleLanguageAI.java diff --git a/src/main/java/oracleai/services/OracleObjectStore.java b/java-ai/src/main/java/oracleai/services/OracleObjectStore.java similarity index 84% rename from src/main/java/oracleai/services/OracleObjectStore.java rename to java-ai/src/main/java/oracleai/services/OracleObjectStore.java index d837d47..56049e7 100644 --- a/src/main/java/oracleai/services/OracleObjectStore.java +++ b/java-ai/src/main/java/oracleai/services/OracleObjectStore.java @@ -1,6 +1,6 @@ package oracleai.services; -import com.oracle.bmc.auth.AuthenticationDetailsProvider; +import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider; import com.oracle.bmc.objectstorage.ObjectStorageClient; import com.oracle.bmc.objectstorage.requests.GetObjectRequest; import com.oracle.bmc.objectstorage.requests.PutObjectRequest; @@ -9,6 +9,7 @@ import oracleai.AIApplication; import java.io.BufferedReader; +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; @@ -16,9 +17,9 @@ public class OracleObjectStore { - public static void sendToObjectStorage(String fileName, InputStream inputStreamForFile) throws Exception { - System.out.println("GenerateAPictureStoryUsingOnlySpeech.sendToObjectStorage fileToUpload:" + fileName); - AuthenticationDetailsProvider provider = AuthProvider.getAuthenticationDetailsProvider(); + public static void sendToObjectStorage(String fileName, InputStream inputStreamForFile) throws IOException { + System.out.println("sendToObjectStorage fileToUpload:" + fileName); + BasicAuthenticationDetailsProvider provider = AuthProvider.getAuthenticationDetailsProvider(); ObjectStorageClient client = ObjectStorageClient.builder().build(provider); PutObjectRequest putObjectRequest = PutObjectRequest.builder() .namespaceName(AIApplication.OBJECTSTORAGE_NAMESPACE) @@ -32,7 +33,7 @@ public static void sendToObjectStorage(String fileName, InputStream inputStreamF public static String getFromObjectStorage(String transcriptionJobId, String objectName) throws Exception { System.out.println("GenerateAPictureStoryUsingOnlySpeech.getFromObjectStorage objectName:" + objectName); - AuthenticationDetailsProvider provider = AuthProvider.getAuthenticationDetailsProvider(); + BasicAuthenticationDetailsProvider provider = AuthProvider.getAuthenticationDetailsProvider(); ObjectStorageClient client = ObjectStorageClient.builder().build(provider); GetObjectRequest putObjectRequest = GetObjectRequest.builder() .namespaceName(AIApplication.OBJECTSTORAGE_NAMESPACE) diff --git a/src/main/java/oracleai/services/OracleSpeechAI.java b/java-ai/src/main/java/oracleai/services/OracleSpeechAI.java similarity index 97% rename from src/main/java/oracleai/services/OracleSpeechAI.java rename to java-ai/src/main/java/oracleai/services/OracleSpeechAI.java index 751a7cf..0243b68 100644 --- a/src/main/java/oracleai/services/OracleSpeechAI.java +++ b/java-ai/src/main/java/oracleai/services/OracleSpeechAI.java @@ -7,7 +7,7 @@ import com.oracle.bmc.aispeech.requests.GetTranscriptionJobRequest; import com.oracle.bmc.aispeech.responses.CreateTranscriptionJobResponse; import com.oracle.bmc.aispeech.responses.GetTranscriptionJobResponse; -import com.oracle.bmc.auth.AuthenticationDetailsProvider; +import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider; import lombok.Getter; import lombok.Setter; import oracleai.AIApplication; @@ -20,7 +20,7 @@ public class OracleSpeechAI { public static String getTranscriptFromOCISpeech(String fileName) throws IOException, InterruptedException { - AuthenticationDetailsProvider provider = AuthProvider.getAuthenticationDetailsProvider(); + BasicAuthenticationDetailsProvider provider = AuthProvider.getAuthenticationDetailsProvider(); AIServiceSpeechClient client = AIServiceSpeechClient.builder().build(provider); CreateTranscriptionJobDetails createTranscriptionJobDetails = CreateTranscriptionJobDetails.builder() diff --git a/src/main/java/oracleai/services/OracleVisionAI.java b/java-ai/src/main/java/oracleai/services/OracleVisionAI.java similarity index 95% rename from src/main/java/oracleai/services/OracleVisionAI.java rename to java-ai/src/main/java/oracleai/services/OracleVisionAI.java index 12a1cdf..3146b6d 100644 --- a/src/main/java/oracleai/services/OracleVisionAI.java +++ b/java-ai/src/main/java/oracleai/services/OracleVisionAI.java @@ -7,7 +7,7 @@ import com.oracle.bmc.aivision.model.*; import com.oracle.bmc.aivision.requests.AnalyzeImageRequest; import com.oracle.bmc.aivision.responses.AnalyzeImageResponse; -import com.oracle.bmc.auth.AuthenticationDetailsProvider; +import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider; import lombok.Getter; import lombok.Setter; @@ -30,7 +30,7 @@ public class OracleVisionAI { * */ public static String processImage(byte[] bytes, ImageFeature feature) throws Exception { - AuthenticationDetailsProvider provider = AuthProvider.getAuthenticationDetailsProvider(); + BasicAuthenticationDetailsProvider provider = AuthProvider.getAuthenticationDetailsProvider(); AIServiceVisionClient aiServiceVisionClient = AIServiceVisionClient.builder().build(provider); List features = new ArrayList<>(); features.add(feature); diff --git a/src/main/resources/application.yaml b/java-ai/src/main/resources/application.yaml similarity index 80% rename from src/main/resources/application.yaml rename to java-ai/src/main/resources/application.yaml index 8821f7b..f0e4baf 100644 --- a/src/main/resources/application.yaml +++ b/java-ai/src/main/resources/application.yaml @@ -1,4 +1,13 @@ spring: + servlet: + multipart: + enabled: true + max-file-size: 200MB + max-request-size: 200MB + cloud: + oci: + config: + type: INSTANCE_PRINCIPAL datasource: # Example where a wallet is used (TNS_ADMIN is the location of the wallet). # Eg if using Oracle Cloud ADB (autonomous database) Always Free. @@ -17,3 +26,6 @@ spring: logging: level: org.springframework.web.cors: DEBUG +server: + tomcat: + max-swallow-size: 200MB \ No newline at end of file diff --git a/java-ai/src/main/resources/static/DDAdminUpload.html b/java-ai/src/main/resources/static/DDAdminUpload.html new file mode 100644 index 0000000..ebd636d --- /dev/null +++ b/java-ai/src/main/resources/static/DDAdminUpload.html @@ -0,0 +1,169 @@ + + + + + + Player Form + + + +
+

Please provide image and/or video and some basic info...

+
+ + + + + + + + +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/static/DownloadImages.html b/java-ai/src/main/resources/static/DownloadImages.html similarity index 90% rename from src/main/resources/static/DownloadImages.html rename to java-ai/src/main/resources/static/DownloadImages.html index 084bb3f..b9c5a58 100644 --- a/src/main/resources/static/DownloadImages.html +++ b/java-ai/src/main/resources/static/DownloadImages.html @@ -5,7 +5,7 @@ Upload Image -

Upload Image

+

Download Images

diff --git a/src/main/resources/static/FaceRecognition.html b/java-ai/src/main/resources/static/FaceRecognition.html similarity index 100% rename from src/main/resources/static/FaceRecognition.html rename to java-ai/src/main/resources/static/FaceRecognition.html diff --git a/src/main/resources/static/ObjectDetectionGenAIAndSentimentAnalysis.html b/java-ai/src/main/resources/static/ObjectDetectionGenAIAndSentimentAnalysis.html similarity index 100% rename from src/main/resources/static/ObjectDetectionGenAIAndSentimentAnalysis.html rename to java-ai/src/main/resources/static/ObjectDetectionGenAIAndSentimentAnalysis.html diff --git a/src/main/resources/static/SpeechTranscriptionAndImageGeneration.html b/java-ai/src/main/resources/static/SpeechTranscriptionAndImageGeneration.html similarity index 100% rename from src/main/resources/static/SpeechTranscriptionAndImageGeneration.html rename to java-ai/src/main/resources/static/SpeechTranscriptionAndImageGeneration.html diff --git a/src/main/resources/static/TextDetectionAndSummarization.html b/java-ai/src/main/resources/static/TextDetectionAndSummarization.html similarity index 100% rename from src/main/resources/static/TextDetectionAndSummarization.html rename to java-ai/src/main/resources/static/TextDetectionAndSummarization.html diff --git a/src/main/resources/static/TextSearch.html b/java-ai/src/main/resources/static/TextSearch.html similarity index 100% rename from src/main/resources/static/TextSearch.html rename to java-ai/src/main/resources/static/TextSearch.html diff --git a/java-ai/src/main/resources/static/UploadForDigitalDoubles.html b/java-ai/src/main/resources/static/UploadForDigitalDoubles.html new file mode 100644 index 0000000..843ff17 --- /dev/null +++ b/java-ai/src/main/resources/static/UploadForDigitalDoubles.html @@ -0,0 +1,61 @@ + + + + + + Player Selection + + + +
+

Which are you doing?...

+
+
+ + +
+
+
+ + + diff --git a/src/main/resources/static/UploadImage.html b/java-ai/src/main/resources/static/UploadImage.html similarity index 100% rename from src/main/resources/static/UploadImage.html rename to java-ai/src/main/resources/static/UploadImage.html diff --git a/src/main/resources/static/VideoAnalysis.html b/java-ai/src/main/resources/static/VideoAnalysis.html similarity index 100% rename from src/main/resources/static/VideoAnalysis.html rename to java-ai/src/main/resources/static/VideoAnalysis.html diff --git a/src/main/resources/static/audio/invaded.m4a b/java-ai/src/main/resources/static/audio/invaded.m4a similarity index 100% rename from src/main/resources/static/audio/invaded.m4a rename to java-ai/src/main/resources/static/audio/invaded.m4a diff --git a/src/main/resources/static/audio/paradise.m4a b/java-ai/src/main/resources/static/audio/paradise.m4a similarity index 100% rename from src/main/resources/static/audio/paradise.m4a rename to java-ai/src/main/resources/static/audio/paradise.m4a diff --git a/src/main/resources/static/audio/shipwrecked.m4a b/java-ai/src/main/resources/static/audio/shipwrecked.m4a similarity index 100% rename from src/main/resources/static/audio/shipwrecked.m4a rename to java-ai/src/main/resources/static/audio/shipwrecked.m4a diff --git a/java-ai/src/main/resources/static/digitaldouble_QRCode.png b/java-ai/src/main/resources/static/digitaldouble_QRCode.png new file mode 100644 index 0000000..bd2e8eb Binary files /dev/null and b/java-ai/src/main/resources/static/digitaldouble_QRCode.png differ diff --git a/src/main/resources/static/images/bloodsugarreport.jpeg b/java-ai/src/main/resources/static/images/bloodsugarreport.jpeg similarity index 100% rename from src/main/resources/static/images/bloodsugarreport.jpeg rename to java-ai/src/main/resources/static/images/bloodsugarreport.jpeg diff --git a/src/main/resources/static/images/faces.png b/java-ai/src/main/resources/static/images/faces.png similarity index 100% rename from src/main/resources/static/images/faces.png rename to java-ai/src/main/resources/static/images/faces.png diff --git a/src/main/resources/static/images/objectdetectiontestimage.jpg b/java-ai/src/main/resources/static/images/objectdetectiontestimage.jpg similarity index 100% rename from src/main/resources/static/images/objectdetectiontestimage.jpg rename to java-ai/src/main/resources/static/images/objectdetectiontestimage.jpg diff --git a/src/main/resources/static/index.html b/java-ai/src/main/resources/static/index.html similarity index 100% rename from src/main/resources/static/index.html rename to java-ai/src/main/resources/static/index.html diff --git a/src/main/resources/static/sidebar.html b/java-ai/src/main/resources/static/sidebar.html similarity index 92% rename from src/main/resources/static/sidebar.html rename to java-ai/src/main/resources/static/sidebar.html index d5b8559..5383890 100644 --- a/src/main/resources/static/sidebar.html +++ b/java-ai/src/main/resources/static/sidebar.html @@ -4,7 +4,7 @@ Face Recognition
Database Text Search and DBMS_SEARCH
Upload Image
-Download Images
+Download Images
Video Analysis (coming soon)
Speech Transcription And Translation (coming soon)
Realtime Speech Transcription (coming soon)
diff --git a/java-ai/src/main/resources/templates/digitaldoubledownload.html b/java-ai/src/main/resources/templates/digitaldoubledownload.html new file mode 100644 index 0000000..fd45d2f --- /dev/null +++ b/java-ai/src/main/resources/templates/digitaldoubledownload.html @@ -0,0 +1,82 @@ + + + + + + Player Form + + + +
+

Please enter your email to retrieve links to your digital doubles

+
+ +
+ + +
+
+ +
+
+
+ + \ No newline at end of file diff --git a/java-ai/src/main/resources/templates/digitaldoubleresults.html b/java-ai/src/main/resources/templates/digitaldoubleresults.html new file mode 100644 index 0000000..48c50ba --- /dev/null +++ b/java-ai/src/main/resources/templates/digitaldoubleresults.html @@ -0,0 +1,90 @@ + + + + + + Player Form + + + +
+

Your Digital Doubles For Download......

+

*Note that links will not be active until assets are ready for download.

+

*Updates on status will be emailed nightly.

+

*Animations are MP4 format and 3D models are FBX format which can be opened in some browsers, free online sites, and 3d software.

+ + + +
+ + \ No newline at end of file diff --git a/java-ai/src/main/resources/templates/digitaldoubleupload.html b/java-ai/src/main/resources/templates/digitaldoubleupload.html new file mode 100644 index 0000000..3f8e588 --- /dev/null +++ b/java-ai/src/main/resources/templates/digitaldoubleupload.html @@ -0,0 +1,150 @@ + + + + + + Player Form + + + +
+

Please provide image and/or video and some basic info...

+
+ + + + + + + + +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/images.html b/java-ai/src/main/resources/templates/images.html similarity index 100% rename from src/main/resources/templates/images.html rename to java-ai/src/main/resources/templates/images.html diff --git a/src/main/resources/templates/resultspage.html b/java-ai/src/main/resources/templates/resultspage.html similarity index 100% rename from src/main/resources/templates/resultspage.html rename to java-ai/src/main/resources/templates/resultspage.html diff --git a/src/main/resources/templates/resultswithimages.html b/java-ai/src/main/resources/templates/resultswithimages.html similarity index 100% rename from src/main/resources/templates/resultswithimages.html rename to java-ai/src/main/resources/templates/resultswithimages.html diff --git a/java-ai/src/main/resources/templates/resultswithlinkpage.html b/java-ai/src/main/resources/templates/resultswithlinkpage.html new file mode 100644 index 0000000..c2d5b69 --- /dev/null +++ b/java-ai/src/main/resources/templates/resultswithlinkpage.html @@ -0,0 +1,35 @@ + + + + + Oracle AI + + + + + + +
+

Labs

+
+
+
+ +
+

Develop with Oracle AI Services and Oracle Database

+
+ + + +
+ + + diff --git a/java-ai/src/main/resources/templates/successful.html b/java-ai/src/main/resources/templates/successful.html new file mode 100644 index 0000000..beb4273 --- /dev/null +++ b/java-ai/src/main/resources/templates/successful.html @@ -0,0 +1,80 @@ + + + + + + Player Form + + + +
+ +

Thank You!

+ +
+ + \ No newline at end of file diff --git a/python-realtimespeech-selectai/requirements.txt b/python-realtimespeech-selectai/requirements.txt index 1478884..8c2c591 100644 --- a/python-realtimespeech-selectai/requirements.txt +++ b/python-realtimespeech-selectai/requirements.txt @@ -4,4 +4,14 @@ PyAudio>=0.2.14 websockets==11.0.3; python_version >= "3.7" websockets==9.1; python_version == "3.6" aiohttp -oracledb \ No newline at end of file +oracledb +certifi==2024.8.30 +cffi==1.17.1 +circuitbreaker==2.0.0 +cryptography==42.0.8 +oci==2.135.1 +pycparser==2.22 +pyOpenSSL==24.2.1 +python-dateutil==2.9.0.post0 +pytz==2024.2 +six==1.16.0 \ No newline at end of file diff --git a/python-realtimespeech-selectai/src/STTSelectAITTS.py b/python-realtimespeech-selectai/src/STTSelectAITTS.py new file mode 100644 index 0000000..ffc3701 --- /dev/null +++ b/python-realtimespeech-selectai/src/STTSelectAITTS.py @@ -0,0 +1,421 @@ +import asyncio +import getpass +import os +import json +import pyaudio +import requests +import time +from datetime import datetime +import oracledb +from datetime import datetime +import oci +from oci.config import from_file +from oci.auth.signers.security_token_signer import SecurityTokenSigner +from oci.ai_speech_realtime import ( + RealtimeClient, + RealtimeClientListener, + RealtimeParameters, +) +from aiohttp import web + +from oci.ai_speech import AIServiceSpeechClient +from oci.ai_speech.models import SynthesizeSpeechDetails + +latest_thetime = None +latest_question = None +latest_answer = None +compartment_id = os.getenv('COMPARTMENT_ID') +print(f"compartment_id: {compartment_id}") + +connection = oracledb.connect( + user="user", + password="userpw", + dsn="yourdb_high", + config_dir=r"C:\locationofyourwallet", + wallet_location=r"C:\locationofyourwallet", + wallet_password="walletpw" +) +print(f"Successfully connected to Oracle Database Connection: {connection}") + +queue = asyncio.Queue() + +SAMPLE_RATE = 16000 +FORMAT = pyaudio.paInt16 +CHANNELS = 1 +BUFFER_DURATION_MS = 96 +FRAMES_PER_BUFFER = int(SAMPLE_RATE * BUFFER_DURATION_MS / 1000) + +cummulativeResult = "" +isSelect = False +last_result_time = None + +def audio_callback(in_data, frame_count, time_info, status): + queue.put_nowait(in_data) + return (None, pyaudio.paContinue) + +p = pyaudio.PyAudio() + +stream = p.open( + format=FORMAT, + channels=CHANNELS, + rate=SAMPLE_RATE, + input=True, + frames_per_buffer=FRAMES_PER_BUFFER, + stream_callback=audio_callback, +) + +stream.start_stream() +config = from_file() +isInsertResults = False + +async def send_audio(client): + while True: + data = await queue.get() + await client.send_data(data) + +class SpeechListener(RealtimeClientListener): + def on_result(self, result): + global cummulativeResult, isSelect, last_result_time + if result["transcriptions"][0]["isFinal"]: + transcription = result['transcriptions'][0]['transcription'] + cummulativeResult += transcription + print(f"Received final results: {transcription}") + print(f"Current cummulative result: {cummulativeResult}") + if cummulativeResult.lower().startswith("hey db"): + cummulativeResult = cummulativeResult[len("hey db"):].strip() + isSelect = True + elif cummulativeResult.lower().startswith("hey deebee"): + cummulativeResult = cummulativeResult[len("hey deebee"):].strip() + isSelect = True + elif cummulativeResult.lower().startswith("they deebee"): + cummulativeResult = cummulativeResult[len("they deebee"):].strip() + isSelect = True + elif cummulativeResult.lower().startswith("adb"): + cummulativeResult = cummulativeResult[len("adb"):].strip() + isSelect = True + elif cummulativeResult.lower().startswith("a db"): + cummulativeResult = cummulativeResult[len("a db"):].strip() + isSelect = True + else: + cummulativeResult = "" + last_result_time = asyncio.get_event_loop().time() + else: + print(f"Received partial results: {result['transcriptions'][0]['transcription']}") + + def on_ack_message(self, ackmessage): + return super().on_ack_message(ackmessage) + + def on_connect(self): + return super().on_connect() + + def on_connect_message(self, connectmessage): + print(f"connectmessage: {connectmessage}") + return super().on_connect_message(connectmessage) + + def on_network_event(self, ackmessage): + return super().on_network_event(ackmessage) + + def on_error(self, exception): + print(f"An error occurred: {exception}") + +async def check_idle(): + global last_result_time, isSelect + while True: + if isSelect and last_result_time and (asyncio.get_event_loop().time() - last_result_time > 2): + executeSelectAI() + isSelect = False + await asyncio.sleep(1) + +def executeSelectAI(): + global cummulativeResult, isInsertResults, latest_thetime, latest_question, latest_answer + print(f"executeSelectAI called cummulative result: {cummulativeResult}") + + contains_logic = [ + {"containsWord": "reset", "latestQuestion": "reset", "latestAnswer": "reset"} + ] + + # BEGIN + # DBMS_CLOUD_AI.CREATE_PROFILE( + # profile_name= > 'OCWPODS_PROFILE', + # attributes = > + # '{"provider": "openai", + # "credential_name": "OPENAI_CRED", + # "model": "gpt-4", + # "object_list": [{"owner": "MOVIESTREAM", "name": "OCWPODS"}]}' + # ); + # END; + # / + + # https: // blogs.oracle.com / datawarehousing / post / how - to - help - ai - models - generate - better - natural - language - queries - in -autonomous - database + # COMMENT ON TABLE OCWPODS IS 'Contains pod short name, products, title, abstract, pod name, points of contact, location, and other keywords'; + # COMMENT ON COLUMN OCWPODS.PODSHORTNAME IS 'the short name of the pod'; + # COMMENT ON COLUMN OCWPODS.PRODUCTS IS 'abstract describing the pod'; + # COMMENT ON COLUMN OCWPODS.TITLE IS 'the title the pod'; + # COMMENT ON COLUMN OCWPODS.ABSTRACT IS 'abstract describing the pod'; + # COMMENT ON COLUMN OCWPODS.PODNAME IS 'the name of the pod'; + # COMMENT ON COLUMN OCWPODS.POCS IS 'the people at the pod'; + # COMMENT ON COLUMN OCWPODS.LOCATION IS 'the location of the pod'; + # COMMENT ON COLUMN OCWPODS.OTHERKEYWORDS IS 'other keywords describing the pod that can be searched on'; + + # profile_name => 'openai_gpt35', + promptSuffix = " . In a single word, tell me the most appropriate PODSHORTNAME" + # promptSuffix = "" + # query = """SELECT DBMS_CLOUD_AI.GENERATE( + # prompt => :prompt || :promptSuffix, + # profile_name => 'OCWPODS_PROFILE', + # action => 'narrate') + # FROM dual""" + query = """SELECT DBMS_CLOUD_AI.GENERATE( + prompt => :prompt, + profile_name => 'openai_gpt35', + action => 'chat') + FROM dual""" + + try: + with connection.cursor() as cursor: + try: + if handleContainsLogic(cummulativeResult.lower(), contains_logic): + print(f"executeSelectAI handled directly with cummulative result: {cummulativeResult}") + else: + start_time = time.time() + # cursor.execute(query, {'prompt': cummulativeResult, 'promptSuffix': promptSuffix}) + cursor.execute(query, {'prompt': cummulativeResult}) + result = cursor.fetchone() + if result and isinstance(result[0], oracledb.LOB): + text_result = result[0].read() + print(f"isinstance LOB text_result: {text_result}") + end_time = time.time() + elapsed_time = end_time - start_time + print(f"Query execution time: {elapsed_time:.4f} seconds") + + latest_thetime = datetime.now() + latest_question = cummulativeResult + latest_answer = text_result[:3000] + else: + print(f"!isinstance LOB result: {result}") + except Exception as query_error: + print(f"An error occurred during query execution: {query_error}") + latest_thetime = datetime.now() + latest_question = "default" + latest_answer = "default" + + cummulativeResult = "" + + if isInsertResults: + insert_query = """ + INSERT INTO selectai_data (thetime, question, answer) + VALUES (:thetime, :question, :answer) + """ + cursor.execute(insert_query, { + 'thetime': latest_thetime, + 'question': latest_question, + 'answer': latest_answer + }) + connection.commit() + print("Insert successful.") + + # setting up OCI config file and speech client + config = oci.config.from_file("~/.oci/config", "DEFAULT") + speech_client = AIServiceSpeechClient(config) + + print(f"latest_question: {latest_question}") + print(f"latest_answer: {latest_answer}") + + + text_to_speech = SynthesizeSpeechDetails( + text=f" {latest_answer}", + is_stream_enabled=True, + # voice_id="en-US-Standard-B", # Example: Set the voice to "Standard B" (change to any available voice) + # compartment_id=, # Ensure you fill this with your OCI compartment ID + # configuration=, # Optional: Add speech synthesis configuration if needed + # audio_config=, # Optional: Add audio output configuration if needed + ) + + start_time = time.time() + # Call the service to synthesize speech + response = speech_client.synthesize_speech(synthesize_speech_details=text_to_speech) + end_time = time.time() + elapsed_time = end_time - start_time + print(f"TTS execution time: {elapsed_time:.4f} seconds") + + # Save the synthesized speech output to a file + with open("TTSoutput.wav", "wb") as audio_file: + audio_file.write(response.data.content) + + print("Speech synthesis completed and saved as output.wav") + + + + + # + # + # # Define the URL and headers + # url = 'http://localhost:8011/A2F/Player/GetRootPath' + # headers = { + # 'accept': 'application/json', + # 'Content-Type': 'application/json' + # } + # + # # Define the JSON payload for the request + # payload = { + # "a2f_player": "/World/audio2face/Player" + # } + # + # # Make the POST request + # response = requests.post(url, json=payload, headers=headers) + # + # # Check if the request was successful + # if response.status_code == 200: + # print("GetRootPath call successful.") + # print("Response:", response.json()) # Print the JSON response + # else: + # print(f"Failed to get root path: {response.status_code}, {response.text}") + + # 2. SetRootPath + start_time = time.time() + url = 'http://localhost:8011/A2F/Player/SetRootPath' + headers = { + 'accept': 'application/json', + 'Content-Type': 'application/json' + } + payload = { + "a2f_player": "/World/audio2face/Player", + "dir_path": "C:/Users/paulp/src/github.com/paulparkinson/oracle-ai-for-sustainable-dev" + } + response = requests.post(url, json=payload, headers=headers) + if response.status_code == 200: + print("SetRootPath call successful.") + print("Response:", response.json()) # Print the JSON response + else: + print(f"Failed to set root path: {response.status_code}, {response.text}") + + print("Speech synthesis completed SetRootPath") + end_time = time.time() + elapsed_time = end_time - start_time + print(f"SetRootPath execution time: {elapsed_time:.4f} seconds") + + + + # 2. Set Track + start_time = time.time() + set_track_url = 'http://localhost:8011/A2F/Player/SetTrack' + set_track_data = { + "a2f_player": "/World/audio2face/Player", + "file_name": "TTSoutput.wav", # Use the path of the generated audio file + "time_range": [0, -1] + } + set_track_response = requests.post(set_track_url, json=set_track_data, headers={ + 'accept': 'application/json', + 'Content-Type': 'application/json' + }) + if set_track_response.status_code == 200: + print("Track set successfully.") + end_time = time.time() + elapsed_time = end_time - start_time + print(f"SetTrack execution time: {elapsed_time:.4f} seconds") + else: + print(f"Failed to set track: {set_track_response.status_code}, {set_track_response.text}") + + + # 3. Play Track + start_time = time.time() + play_track_url = 'http://localhost:8011/A2F/Player/Play' + play_track_data = { + "a2f_player": "/World/audio2face/Player" + } + play_response = requests.post(play_track_url, json=play_track_data, headers={ + 'accept': 'application/json', + 'Content-Type': 'application/json' + }) + if play_response.status_code == 200: + print("Track started playing.") + else: + print(f"Failed to play track: {play_response.status_code}, {play_response.text}") + + print(" TTSoutput.wav sent to a2f") + end_time = time.time() + elapsed_time = end_time - start_time + print(f"Play execution time: {elapsed_time:.4f} seconds") + + except Exception as e: + print(f"An error occurred: {e}") + + cummulativeResult = "" + +def handleContainsLogic(cummulative_result, logic_array): + global latest_thetime, latest_question, latest_answer + + for item in logic_array: + if item["containsWord"] in cummulative_result: + latest_thetime = datetime.now() + latest_question = item["latestQuestion"] + latest_answer = item["latestAnswer"] + # print("item containsWord: " + item["containsWord"]) + return True + return False + +async def handle_request(request): + global latest_thetime, latest_question, latest_answer + data = { + "thetime": latest_thetime.isoformat() if latest_thetime else None, + "question": latest_question, + "answer": latest_answer + } + return web.json_response(data) + +async def connect_with_retry(client, max_retries=5, initial_delay=2): + delay = initial_delay + for attempt in range(max_retries): + try: + await client.connect() + print("Connection successful.") + break # Exit the loop if the connection is successful + except Exception as e: + print(f"Attempt {attempt + 1} failed with error: {e}") + if attempt < max_retries - 1: + print(f"Retrying in {delay} seconds...") + await asyncio.sleep(delay) + delay *= 2 # Exponential backoff + else: + print("Max retries reached. Exiting.") + +if __name__ == "__main__": + realtime_speech_parameters = RealtimeParameters() + realtime_speech_parameters.language_code = "en-US" + realtime_speech_parameters.model_domain = ( + realtime_speech_parameters.MODEL_DOMAIN_GENERIC + ) + realtime_speech_parameters.partial_silence_threshold_in_ms = 0 + realtime_speech_parameters.final_silence_threshold_in_ms = 2000 + realtime_speech_parameters.should_ignore_invalid_customizations = False + realtime_speech_parameters.stabilize_partial_results = ( + realtime_speech_parameters.STABILIZE_PARTIAL_RESULTS_NONE + ) + + realtime_speech_url = "wss://realtime.aiservice.us-phoenix-1.oci.oraclecloud.com" + client = RealtimeClient( + config=config, + realtime_speech_parameters=realtime_speech_parameters, + listener=SpeechListener(), + service_endpoint=realtime_speech_url, + signer=None, + compartment_id=compartment_id, + ) + + loop = asyncio.get_event_loop() + loop.create_task(send_audio(client)) + loop.create_task(check_idle()) + + app = web.Application() + app.router.add_get('/selectai_data', handle_request) + runner = web.AppRunner(app) + loop.run_until_complete(runner.setup()) + site = web.TCPSite(runner, 'localhost', 8080) + loop.run_until_complete(site.start()) + + loop.run_until_complete(connect_with_retry(client)) + + if stream.is_active(): + stream.close() + + print("Closed") diff --git a/sql/digital_doubles.sql b/sql/digital_doubles.sql new file mode 100644 index 0000000..d5dd20d --- /dev/null +++ b/sql/digital_doubles.sql @@ -0,0 +1,205 @@ +CREATE TABLE digital_double_data ( + id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + participant_firstname VARCHAR2(100), + participant_lastname VARCHAR2(100), + participant_email VARCHAR2(100) NOT NULL, + participant_company VARCHAR2(100), + participant_role VARCHAR2(100), + participant_tshirt VARCHAR2(100), + participant_comments VARCHAR2(200), + id_image_in BLOB, + image_in BLOB, + video_in BLOB, + modelglburl_out VARCHAR2(1000), + modelfbxurl_out VARCHAR2(1000), + modelusdzurl_out VARCHAR2(1000), + thumbnailurl_out VARCHAR2(1000), + videourl_out BLOB, + video_out BLOB, + similar_image_out BLOB +); +/ + + +CREATE OR REPLACE PROCEDURE insert_digital_double_data ( + p_participant_firstname IN VARCHAR2, + p_participant_lastname IN VARCHAR2, + p_participant_email IN VARCHAR2, + p_participant_company IN VARCHAR2, + p_participant_role IN VARCHAR2, + p_participant_tshirt IN VARCHAR2, + p_participant_comments IN VARCHAR2, + p_id_image_in IN BLOB, + p_image_in IN BLOB, + p_video_in IN BLOB +) IS +BEGIN + INSERT INTO digital_double_data ( + participant_firstname, + participant_lastname, + participant_email, + participant_company, + participant_role, + participant_tshirt, + participant_comments, + id_image_in, + image_in, + video_in + ) + VALUES ( + p_participant_firstname, + p_participant_lastname, + p_participant_email, + p_participant_company, + p_participant_role, + p_participant_tshirt, + p_participant_comments, + p_id_image_in, + p_image_in, + p_video_in + ); +END insert_digital_double_data; +/ + +CREATE OR REPLACE PROCEDURE update_digital_double_data ( + p_participant_email IN VARCHAR2, + p_modelglburl_out IN VARCHAR2, + p_modelfbxurl_out IN VARCHAR2, + p_modelusdzurl_out IN VARCHAR2, + p_thumbnailurl_out IN VARCHAR2, + p_videourl_out IN BLOB, + p_video_out IN BLOB, + p_similar_image_out IN BLOB +) IS +BEGIN + UPDATE digital_double_data + SET modelglburl_out = p_modelglburl_out, + modelfbxurl_out = p_modelfbxurl_out, + modelusdzurl_out = p_modelusdzurl_out, + thumbnailurl_out = p_thumbnailurl_out, + videourl_out = p_videourl_out, + video_out = p_video_out, + similar_image_out = p_similar_image_out + WHERE participant_email = p_participant_email; +END update_digital_double_data; +/ + +CREATE OR REPLACE PROCEDURE get_digital_double_data ( + p_participant_email IN VARCHAR2, + p_participant_firstname OUT VARCHAR2, + p_participant_lastname OUT VARCHAR2, + p_participant_company OUT VARCHAR2, + p_participant_role OUT VARCHAR2, + p_participant_tshirt OUT VARCHAR2, + p_participant_comments OUT VARCHAR2, + p_id_image_in OUT BLOB, + p_image_in OUT BLOB, + p_video_in OUT BLOB, + p_modelglburl_out OUT VARCHAR2, + p_modelfbxurl_out OUT VARCHAR2, + p_modelusdzurl_out OUT VARCHAR2, + p_thumbnailurl_out OUT VARCHAR2, + p_videourl_out OUT BLOB, + p_video_out OUT BLOB, + p_similar_image_out OUT BLOB +) IS +BEGIN + SELECT participant_firstname, participant_lastname, participant_company, + participant_role, participant_tshirt, participant_comments, + id_image_in, image_in, video_in, + modelglburl_out, modelfbxurl_out, modelusdzurl_out, + thumbnailurl_out, videourl_out, video_out, similar_image_out + INTO p_participant_firstname, p_participant_lastname, p_participant_company, + p_participant_role, p_participant_tshirt, p_participant_comments, + p_id_image_in, p_image_in, p_video_in, + p_modelglburl_out, p_modelfbxurl_out, p_modelusdzurl_out, + p_thumbnailurl_out, p_videourl_out, p_video_out, p_similar_image_out + FROM digital_double_data + WHERE participant_email = p_participant_email; +END get_digital_double_data; +/ + + + +--ORDS... + + +BEGIN + ORDS.ENABLE_OBJECT( + P_ENABLED => TRUE, + P_SCHEMA => 'OMLOPSUSER', + P_OBJECT => 'INSERT_DIGITAL_DOUBLE_DATA', + P_OBJECT_TYPE => 'PROCEDURE', + P_OBJECT_ALIAS => 'insert_digital_double_data', + P_AUTO_REST_AUTH => FALSE + ); + COMMIT; +END; +/ + +BEGIN + ORDS.ENABLE_OBJECT( + P_ENABLED => TRUE, + P_SCHEMA => 'OMLOPSUSER', + P_OBJECT => 'GET_DIGITAL_DOUBLE_DATA', + P_OBJECT_TYPE => 'PROCEDURE', + P_OBJECT_ALIAS => 'get_digital_double_data', + P_AUTO_REST_AUTH => FALSE + ); + COMMIT; +END; +/ + +BEGIN + ORDS.ENABLE_OBJECT( + P_ENABLED => TRUE, + P_SCHEMA => 'OMLOPSUSER', + P_OBJECT => 'UPDATE_DIGITAL_DOUBLE_DATA', + P_OBJECT_TYPE => 'PROCEDURE', + P_OBJECT_ALIAS => 'update_digital_double_data', + P_AUTO_REST_AUTH => FALSE + ); + COMMIT; +END; +/ + +--query to just get the 3d urls... + +CREATE OR REPLACE FUNCTION get_model_urls (p_participant_email IN VARCHAR2) + RETURN SYS_REFCURSOR +AS + l_cursor SYS_REFCURSOR; +BEGIN + OPEN l_cursor FOR + SELECT MODELGLBURL_OUT, + MODELFBXURL_OUT, + MODELUSDZURL_OUT, + THUMBNAILURL_OUT + FROM DIGITAL_DOUBLE_DATA + WHERE PARTICIPANT_EMAIL = p_participant_email; + + RETURN l_cursor; +END get_model_urls; +/ + + + +BEGIN + ORDS.DEFINE_SERVICE( + p_module_name => 'ModelURLsService', + p_base_path => 'modelurls/', + p_pattern => 'geturls/:email', + p_method => 'GET', + p_source_type => ORDS.SOURCE_TYPE_PLSQL, + p_source => 'DECLARE + l_cursor SYS_REFCURSOR; + BEGIN + l_cursor := get_model_urls(:email); + ORDS.DEFINE_SERVICE_REF_CURSOR(p_cursor => l_cursor); + END;' + ); +END; +/ + + + diff --git a/sql/mlops.sql b/sql/mlops.sql new file mode 100644 index 0000000..24bbc7a --- /dev/null +++ b/sql/mlops.sql @@ -0,0 +1,36 @@ +-- USER SQL +CREATE USER OMLOPSUSER IDENTIFIED BY Welcome12345; + +-- ADD ROLES +GRANT CONNECT TO OMLOPSUSER; +GRANT CONSOLE_DEVELOPER TO OMLOPSUSER; +GRANT DWROLE TO OMLOPSUSER; +GRANT GRAPH_DEVELOPER TO OMLOPSUSER; +GRANT OML_DEVELOPER TO OMLOPSUSER; +GRANT RESOURCE TO OMLOPSUSER; +ALTER USER OMLOPSUSER DEFAULT ROLE CONSOLE_DEVELOPER,DWROLE,GRAPH_DEVELOPER,OML_DEVELOPER; + +-- REST ENABLE +BEGIN + ORDS_ADMIN.ENABLE_SCHEMA( + p_enabled => TRUE, + p_schema => 'OMLOPSUSER', + p_url_mapping_type => 'BASE_PATH', + p_url_mapping_pattern => 'omlopsuser', + p_auto_rest_auth=> TRUE + ); + -- ENABLE DATA SHARING + C##ADP$SERVICE.DBMS_SHARE.ENABLE_SCHEMA( + SCHEMA_NAME => 'OMLOPSUSER', + ENABLED => TRUE + ); + commit; +END; +/ + +-- ENABLE GRAPH +ALTER USER OMLOPSUSER GRANT CONNECT THROUGH GRAPH$PROXY_USER; + +-- ENABLE OML +ALTER USER OMLOPSUSER GRANT CONNECT THROUGH OML$PROXY; + diff --git a/src/main/java/oracleai/services/AuthProvider.java b/src/main/java/oracleai/services/AuthProvider.java deleted file mode 100644 index cde4005..0000000 --- a/src/main/java/oracleai/services/AuthProvider.java +++ /dev/null @@ -1,15 +0,0 @@ -package oracleai.services; - -import com.oracle.bmc.auth.AuthenticationDetailsProvider; -import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider; - -import java.io.IOException; - -public class AuthProvider { - - public static AuthenticationDetailsProvider getAuthenticationDetailsProvider() throws IOException { - return new ConfigFileAuthenticationDetailsProvider( - System.getenv("OCICONFIG_FILE"), System.getenv("OCICONFIG_PROFILE")); - // InstancePrincipalsAuthenticationDetailsProvider.builder().build(); - } -} diff --git a/src/main/java/oracleai/services/ORDSCalls.java b/src/main/java/oracleai/services/ORDSCalls.java deleted file mode 100644 index 16ebc59..0000000 --- a/src/main/java/oracleai/services/ORDSCalls.java +++ /dev/null @@ -1,107 +0,0 @@ -package oracleai.services; - -import oracleai.AIApplication; -import oracleai.ImageStore; -import oracleai.ImageStoreWrapper; -import org.jetbrains.annotations.Nullable; -import org.springframework.http.*; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.multipart.MultipartFile; - -import java.util.Base64; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -@Service -public class ORDSCalls { - - public static String callAnalyzeImageInline(String ordsEndpoint, String visionServiceIndpoint, - String compartmentOcid, MultipartFile imageFile) - throws Exception { - RestTemplate restTemplate = new RestTemplate(); - String base64ImageData = Base64.getEncoder().encodeToString(imageFile.getBytes()); - String jsonBody = String.format("{\"p_compartment_ocid\": \"%s\", \"p_endpoint\": \"%s\", \"p_image_data\": \"%s\"}", - compartmentOcid, visionServiceIndpoint, base64ImageData); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity requestEntity = new HttpEntity<>(jsonBody, headers); - ResponseEntity response = restTemplate.exchange(ordsEndpoint, HttpMethod.POST, requestEntity, String.class); - return response.getBody(); - } - - - //As written only supports one feature type per call - public static String analyzeImageInObjectStore( - String ordsEndpoint, String visionServiceEndpoint, String compartmentOcid, - String bucketName, String namespaceName, String objectName, String featureType, String label) { - System.out.println("ORDSCalls.analyzeImageInObjectStore"); - System.out.println("ordsEndpoint = " + ordsEndpoint + ", visionServiceEndpoint = " + visionServiceEndpoint + ", compartmentOcid = " + compartmentOcid + ", bucketName = " + bucketName + ", namespaceName = " + namespaceName + ", objectName = " + objectName + ", featureType = " + featureType + ", label = " + label); - RestTemplate restTemplate = new RestTemplate(); - String jsonPayload = String.format( - "{\"p_bucketname\": \"%s\", \"p_compartment_ocid\": \"%s\", \"p_endpoint\": \"%s\", " + - "\"p_namespacename\": \"%s\", \"p_objectname\": \"%s\", \"p_featuretype\": \"%s\", \"p_label\": \"%s\"}", - bucketName, compartmentOcid, visionServiceEndpoint, namespaceName, objectName, featureType, label); - System.out.println("ORDSCalls.analyzeImageInObjectStore jsonPayload:" + jsonPayload); - HttpHeaders headers = new HttpHeaders(); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity entity = new HttpEntity<>(jsonPayload, headers); - ResponseEntity response = restTemplate.exchange(ordsEndpoint, HttpMethod.POST, entity, String.class); - System.out.println("ORDSCalls.analyzeImageInObjectStore response.getBody():" + response.getBody()); - return response.getBody(); - } - public static String executeTextSearchContains(String ordsEndpoint, String sql) { - String jsonPayload = String.format( "{\"p_sql\": \"%s\"}", sql); - return callTextSearch(ordsEndpoint, jsonPayload); - } - public static String executeTextSearchOR(String ordsEndpoint, String sql, String sql2) { - String jsonPayload = String.format( "{\"p_sql\": \"%s\", \"p_sql\": \"%s\"}", sql, sql2); - return callTextSearch(ordsEndpoint, jsonPayload); - } - - @Nullable - private static String callTextSearch(String ordsEndpoint, String jsonPayload) { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity entity = new HttpEntity<>(jsonPayload, headers); - ResponseEntity response = new RestTemplate().exchange(ordsEndpoint, HttpMethod.POST, entity, String.class); - System.out.println("ORDSCalls.analyzeImageInObjectStore response.getBody():" + response.getBody()); - return response.getBody(); - } - - public static ResponseEntity uploadImage(MultipartFile image) { - try { - String base64Image = Base64.getEncoder().encodeToString(image.getBytes()); - Map payload = new HashMap<>(); - payload.put("p_image_name", image.getOriginalFilename()); - payload.put("p_image", base64Image); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity> requestEntity = new HttpEntity<>(payload, headers); - RestTemplate restTemplate = new RestTemplate(); - String uploadUrl = AIApplication.ORDS_ENDPOINT_URL + "insert_image/"; - return restTemplate.exchange(uploadUrl, HttpMethod.POST, requestEntity, String.class); - } catch (Exception e) { - throw new RuntimeException("Failed to upload image", e); - } - } - - - public static ImageStore[] getImageStoreData() { - String url = AIApplication.ORDS_ENDPOINT_URL + "image_store/"; - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity response = restTemplate.getForEntity(url, ImageStoreWrapper.class); - ImageStoreWrapper wrapper = response.getBody(); - if (wrapper != null) { - for (ImageStore imageStore : wrapper.getItems()) { - System.out.println("Image Name: " + imageStore.getImageName()); - } - return wrapper.getItems().toArray(new ImageStore[0]); - } else { - return new ImageStore[0]; - } - } -} - diff --git a/src/main/java/oracleai/services/OracleGenAI.java b/src/main/java/oracleai/services/OracleGenAI.java deleted file mode 100644 index 533358d..0000000 --- a/src/main/java/oracleai/services/OracleGenAI.java +++ /dev/null @@ -1,63 +0,0 @@ -package oracleai.services; - -import com.oracle.bmc.ClientConfiguration; -import com.oracle.bmc.ConfigFileReader; -import com.oracle.bmc.Region; -import com.oracle.bmc.auth.AuthenticationDetailsProvider; -import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider; -import com.oracle.bmc.retrier.RetryConfiguration; -import com.oracle.bmc.ClientConfiguration; -import com.oracle.bmc.ConfigFileReader; -import com.oracle.bmc.Region; -import com.oracle.bmc.auth.AuthenticationDetailsProvider; -import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider; -import com.oracle.bmc.generativeaiinference.GenerativeAiInferenceClient; -import com.oracle.bmc.generativeaiinference.model.CohereLlmInferenceRequest; -import com.oracle.bmc.generativeaiinference.model.GenerateTextDetails; -import com.oracle.bmc.generativeaiinference.model.OnDemandServingMode; -import com.oracle.bmc.generativeaiinference.requests.GenerateTextRequest; -import com.oracle.bmc.generativeaiinference.responses.GenerateTextResponse; -import com.oracle.bmc.generativeaiinference.responses.GenerateTextResponse; - - -import oracleai.AIApplication; - -import java.util.Arrays; -import java.util.List; - -public class OracleGenAI { - - public static String chat(String textcontent) throws Exception { - return new OracleGenAI().doChat(textcontent); - } - - public String doChat(String textcontent) throws Exception { - final GenerativeAiInferenceClient generativeAiInferenceClient = - new GenerativeAiInferenceClient(AuthProvider.getAuthenticationDetailsProvider()); - // generativeAiInferenceClient.setEndpoint(ENDPOINT); - generativeAiInferenceClient.setRegion(Region.US_CHICAGO_1); - CohereLlmInferenceRequest cohereLlmInferenceRequest = - CohereLlmInferenceRequest.builder() - .prompt(textcontent) - .maxTokens(600) - .temperature(0.75) - .frequencyPenalty(1.0) - .topP(0.7) - .isStream(false) // SDK doesn't support streaming responses, feature is under development - .isEcho(true) - .build(); - GenerateTextDetails generateTextDetails = GenerateTextDetails.builder() - .servingMode(OnDemandServingMode.builder().modelId("cohere.command").build()) // "cohere.command-light" is also available to use - // .servingMode(DedicatedServingMode.builder().endpointId("custom-model-endpoint").build()) // for custom model from Dedicated AI Cluster - .compartmentId(AIApplication.COMPARTMENT_ID) - .inferenceRequest(cohereLlmInferenceRequest) - .build(); - GenerateTextRequest generateTextRequest = GenerateTextRequest.builder() - .generateTextDetails(generateTextDetails) - .build(); - GenerateTextResponse generateTextResponse = generativeAiInferenceClient.generateText(generateTextRequest); - System.out.println(generateTextResponse.toString()); - return generateTextResponse.toString(); - } - -} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 85598b6..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1,11 +0,0 @@ -OCICONFIG_FILE=~/.oci/config -OCICONFIG_PROFILE=DEFAULT -COMPARTMENT_ID="ocid1.compartment.oc1..mycompartmentvalue" -OBJECTSTORAGE_NAMESPACE="myobjectstorenamespacename" -OBJECTSTORAGE_BUCKETNAME="myobjectstorebucketname" -ORDS_ENDPOINT_URL="https://myordsendpointurl" -ORDS_ENDPOINT_URL="https://rddainsuh6u1okc-aidatabaseworkshop.adb.us-ashburn-1.oraclecloudapps.com/ords/aiuser/_sdw/" -OCI_VISION_SERVICE_ENDPOINT="https://vision.aiservice.myregion.oci.oraclecloud.com" -OCI_SPEECH_SERVICE_ENDPOINT="https://speech.aiservice.myregion.oci.oraclecloud.com" -OCI_GENAI_SERVICE_ENDPOINT="https://inference.generativeai.us-chicago-1.oci.oraclecloud.com" -