From 5aa39751557c18dbe325005b220064012e9f51d3 Mon Sep 17 00:00:00 2001 From: Lahiru Madushanka Date: Wed, 29 May 2024 19:16:49 +0530 Subject: [PATCH 1/2] sample mediator sketch --- components/mediation/mediators/pom.xml | 1 + .../pom.xml | 73 +++++++++++++++++++ .../mediator/sampleAI/SampleAIMediator.java | 11 +++ .../sampleAI/SampleAIMediatorFactory.java | 21 ++++++ .../sampleAI/SampleAIMediatorSerializer.java | 17 +++++ ....apache.synapse.config.xml.MediatorFactory | 1 + ...ache.synapse.config.xml.MediatorSerializer | 1 + .../pom.xml | 7 ++ pom.xml | 5 ++ 9 files changed, 137 insertions(+) create mode 100644 components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/pom.xml create mode 100644 components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediator.java create mode 100644 components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorFactory.java create mode 100644 components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorSerializer.java create mode 100644 components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorFactory create mode 100644 components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorSerializer diff --git a/components/mediation/mediators/pom.xml b/components/mediation/mediators/pom.xml index 4c2eca448b..ec7af722a2 100644 --- a/components/mediation/mediators/pom.xml +++ b/components/mediation/mediators/pom.xml @@ -34,5 +34,6 @@ oauth-mediator/org.wso2.micro.integrator.mediator.oauth entitlement-mediator/org.wso2.micro.integrator.identity.entitlement.mediator dataservices-mediator/org.wso2.micro.integrator.mediator.dataservice + sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI diff --git a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/pom.xml b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/pom.xml new file mode 100644 index 0000000000..588119a549 --- /dev/null +++ b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/pom.xml @@ -0,0 +1,73 @@ + + + + + mediators + org.wso2.ei + 4.3.0-SNAPSHOT + ../../pom.xml + + + 4.0.0 + org.wso2.micro.integrator.mediator.sampleAI + bundle + WSO2 Carbon - sample AI Mediator + http://wso2.org + + + + org.apache.synapse + synapse-core + + + org.wso2.org.ops4j.pax.logging + pax-logging-api + + + org.wso2.ei + org.wso2.micro.integrator.core + + + org.apache.synapse + synapse-core + 4.0.0-wso2v110 + + + + + + + org.apache.felix + maven-bundle-plugin + + true + + + ${project.artifactId} + ${project.artifactId} + + org.wso2.micro.integrator.mediator.sampleAI.* + + + + synapse-core + + + + + + diff --git a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediator.java b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediator.java new file mode 100644 index 0000000000..bf215212c1 --- /dev/null +++ b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediator.java @@ -0,0 +1,11 @@ +package org.wso2.micro.integrator.mediator.sampleAI; + +import org.apache.synapse.mediators.AbstractMediator; +import org.apache.synapse.MessageContext; +public class SampleAIMediator extends AbstractMediator { + + public boolean mediate(MessageContext synCtx) { + System.out.println("SampleAI Mediator"); + return true; + } +} diff --git a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorFactory.java b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorFactory.java new file mode 100644 index 0000000000..c01437fa2b --- /dev/null +++ b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorFactory.java @@ -0,0 +1,21 @@ +package org.wso2.micro.integrator.mediator.sampleAI; + +import org.apache.axiom.om.OMElement; +import org.apache.synapse.Mediator; +import org.apache.synapse.config.xml.AbstractMediatorFactory; +import org.apache.synapse.config.xml.XMLConfigConstants; + +import javax.xml.namespace.QName; +import java.util.Properties; + +public class SampleAIMediatorFactory extends AbstractMediatorFactory { + @Override + protected Mediator createSpecificMediator(OMElement omElement, Properties properties) { + return new SampleAIMediator(); + } + + @Override + public QName getTagQName() { + return new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, "SampleAI"); + } +} diff --git a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorSerializer.java b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorSerializer.java new file mode 100644 index 0000000000..2ae3022879 --- /dev/null +++ b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorSerializer.java @@ -0,0 +1,17 @@ +package org.wso2.micro.integrator.mediator.sampleAI; + +import org.apache.axiom.om.OMElement; +import org.apache.synapse.Mediator; +import org.apache.synapse.config.xml.AbstractMediatorSerializer; + +public class SampleAIMediatorSerializer extends AbstractMediatorSerializer { + @Override + protected OMElement serializeSpecificMediator(Mediator mediator) { + return null; + } + + @Override + public String getMediatorClassName() { + return null; + } +} diff --git a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorFactory b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorFactory new file mode 100644 index 0000000000..6410b4a1d6 --- /dev/null +++ b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorFactory @@ -0,0 +1 @@ +org.wso2.micro.integrator.mediator.sampleAI.SampleAIMediatorFactory diff --git a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorSerializer b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorSerializer new file mode 100644 index 0000000000..7726bc4f40 --- /dev/null +++ b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorSerializer @@ -0,0 +1 @@ +org.wso2.micro.integrator.mediator.sampleAI.SampleAIMediatorSerializer diff --git a/features/mediation-features/builtin-mediators/org.wso2.micro.integrator.mediators.server.feature/pom.xml b/features/mediation-features/builtin-mediators/org.wso2.micro.integrator.mediators.server.feature/pom.xml index 179f499a89..175105eb76 100644 --- a/features/mediation-features/builtin-mediators/org.wso2.micro.integrator.mediators.server.feature/pom.xml +++ b/features/mediation-features/builtin-mediators/org.wso2.micro.integrator.mediators.server.feature/pom.xml @@ -33,6 +33,10 @@ This feature contains the bundles required for All mediator Back-ends + + org.wso2.ei + org.wso2.micro.integrator.mediator.sampleAI + org.wso2.ei org.wso2.carbon.mediator.cache @@ -84,6 +88,9 @@ org.wso2.ei:org.wso2.carbon.mediator.cache:${project.version} + + org.wso2.ei:org.wso2.micro.integrator.mediator.sampleAI:${project.version} + org.wso2.ei:org.wso2.micro.integrator.mediator.oauth:${project.version} diff --git a/pom.xml b/pom.xml index 22f8394f36..d9adbe27cd 100644 --- a/pom.xml +++ b/pom.xml @@ -176,6 +176,11 @@ org.wso2.carbon.mediator.cache ${project.version} + + org.wso2.ei + org.wso2.micro.integrator.mediator.sampleAI + ${project.version} + org.wso2.ei org.wso2.micro.integrator.registry From 75075ccac0cd87d7b7d9569309e17d36430f1d70 Mon Sep 17 00:00:00 2001 From: "Thushan D. Fernando" Date: Thu, 27 Jun 2024 07:07:24 +0530 Subject: [PATCH 2/2] Add the basic configuration of Intelligent Mediator --- .../pom.xml | 67 +++-- .../intelligent/IntelligentConstants.java | 39 +++ .../intelligent/IntelligentMediator.java | 251 ++++++++++++++++++ .../IntelligentMediatorFactory.java | 108 ++++++++ .../IntelligentMediatorSerializer.java | 34 +++ .../intelligent/util/RequestSchema.java | 34 +++ .../intelligent/util/ResponseSchema.java | 28 ++ ....apache.synapse.config.xml.MediatorFactory | 1 + ...ache.synapse.config.xml.MediatorSerializer | 1 + components/mediation/mediators/pom.xml | 2 +- .../mediator/sampleAI/SampleAIMediator.java | 11 - .../sampleAI/SampleAIMediatorFactory.java | 21 -- .../sampleAI/SampleAIMediatorSerializer.java | 17 -- ....apache.synapse.config.xml.MediatorFactory | 1 - ...ache.synapse.config.xml.MediatorSerializer | 1 - .../pom.xml | 4 +- pom.xml | 2 +- 17 files changed, 545 insertions(+), 77 deletions(-) rename components/mediation/mediators/{sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI => intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent}/pom.xml (50%) create mode 100644 components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentConstants.java create mode 100644 components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentMediator.java create mode 100644 components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentMediatorFactory.java create mode 100644 components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentMediatorSerializer.java create mode 100644 components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/util/RequestSchema.java create mode 100644 components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/util/ResponseSchema.java create mode 100644 components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorFactory create mode 100644 components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorSerializer delete mode 100644 components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediator.java delete mode 100644 components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorFactory.java delete mode 100644 components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorSerializer.java delete mode 100644 components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorFactory delete mode 100644 components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorSerializer diff --git a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/pom.xml b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/pom.xml similarity index 50% rename from components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/pom.xml rename to components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/pom.xml index 588119a549..74863b1738 100644 --- a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/pom.xml +++ b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/pom.xml @@ -1,20 +1,23 @@ - + ~ Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + ~ + ~ WSO2 LCC. licenses this file to you under the Apache License, + ~ Version 2.0 (the "License"); you may not use this file except + ~ in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, + ~ software distributed under the License is distributed on an + ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + ~ KIND, either express or implied. See the License for the + ~ specific language governing permissions and limitations + ~ under the License. + --> + mediators org.wso2.ei @@ -23,16 +26,12 @@ 4.0.0 - org.wso2.micro.integrator.mediator.sampleAI + org.wso2.micro.integrator.mediator.intelligent bundle - WSO2 Carbon - sample AI Mediator + WSO2 Carbon - Intelligent Mediator http://wso2.org - - org.apache.synapse - synapse-core - org.wso2.org.ops4j.pax.logging pax-logging-api @@ -46,6 +45,30 @@ synapse-core 4.0.0-wso2v110 + + + com.azure + azure-ai-openai + 1.0.0-beta.8 + + + com.google.code.gson + gson + 2.10.1 + + + + org.apache.felix + org.osgi.foundation + 1.0.0 + compile + + + io.grpc + grpc-core + 1.59.0 + compile + @@ -60,7 +83,7 @@ ${project.artifactId} ${project.artifactId} - org.wso2.micro.integrator.mediator.sampleAI.* + org.wso2.micro.integrator.mediator.intelligent.* diff --git a/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentConstants.java b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentConstants.java new file mode 100644 index 0000000000..56ee0add63 --- /dev/null +++ b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentConstants.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */package org.wso2.micro.integrator.mediator.intelligent; + +import org.apache.synapse.config.xml.XMLConfigConstants; +import javax.xml.namespace.QName; + +public class IntelligentConstants { + public static final QName INTELLIGENT_Q = new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, + IntelligentConstants.INTELLIGENT_LOCAL_NAME); + public static final String INTELLIGENT_LOCAL_NAME = "intelligent"; + + public static final QName PAYLOAD_Q = new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, "payload"); + + public static final String KEY_STRING = "key"; + public static final String MODEL_STRING = "model"; + public static final String ENDPOINT_STRING = "endpoint"; + public static final String RETRY_COUNT_STRING = "retry-count"; + public static final String PROMPT_STRING = "prompt"; + public static final String HEADERS_STRING = "headers"; + + public static final String MESSAGE_TYPE_STRING = "messageType"; + public static final String CONTENT_TYPE_STRING = "ContentType"; + public static final String JSON_CONTENT_TYPE = "application/json"; +} diff --git a/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentMediator.java b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentMediator.java new file mode 100644 index 0000000000..190a4a74a3 --- /dev/null +++ b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentMediator.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.micro.integrator.mediator.intelligent; + +import org.apache.axis2.AxisFault; +import org.apache.synapse.commons.json.JsonUtil; +import org.apache.synapse.core.axis2.Axis2MessageContext; +import org.apache.synapse.mediators.AbstractMediator; +import org.apache.synapse.MessageContext; + +import com.azure.ai.openai.OpenAIClient; +import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.ai.openai.models.*; +import com.azure.core.credential.AzureKeyCredential; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + +import org.wso2.micro.integrator.mediator.intelligent.util.RequestSchema; +import org.wso2.micro.integrator.mediator.intelligent.util.ResponseSchema; + +import java.util.ArrayList; +import java.util.List; + +/** + * This mediator will ask for a prompt from the user and is able to send the request to OpenAI with a + * JSON or XML payload within this mediator or in the message context. + */ +public class IntelligentMediator extends AbstractMediator { + + private String openaiKey = ""; + + private String openaiModel = "gpt-3.5-turbo"; + + private String openaiEndpoint = "https://api.openai.com/v1/chat/completions"; + + private String basePrompt = ""; + + private String retryPrompt = ""; + + private String prompt = ""; + + private String headers = ""; + + private String payload = ""; + + private String requestSchema; + + private String responseSchema; + + private int retryCount = 3; + + private int remainingRetries = 3; + + /** + * After reading the prompt from the user, this method will initialize the mediator. + */ + public void initialize() { + basePrompt = "You are a helpful assistant who do what I tell you. I will provide a request-schema and a " + + "response-schema. The task to do is available in the request-schema (task prop). The data you have " + + "to process is available in the request-schema (payload prop). Avoid xmlns attribute if data is " + + "given in xml format. When you're giving an answer, always use the response-schema. The processed " + + "data should be in the data prop. This processed data can be json, xml or text. It depends on the " + + "task. Set the dataType prop in response to 'json', 'xml' or 'text' depending on the processed " + + "data. And don't forget to set the status prop to 'success' or 'error' depending on the result of " + + "the task."; + + retryPrompt = "The response you provided is not in the given format in response-schema. Please provide a " + + "valid response."; + + RequestSchema request = new RequestSchema(prompt, payload, headers); + ResponseSchema response = new ResponseSchema(); + + Gson gsonBuilder = new GsonBuilder().setPrettyPrinting().create(); + requestSchema = gsonBuilder.toJson(request); + responseSchema = gsonBuilder.toJson(response); + } + + /** + * This method will convert a given string into JSON object. + * + * @param json The JSON data in string format. + * @return The JSON object. + */ + public JsonObject loadJsonData(String json) { + try { + return JsonParser.parseString(json).getAsJsonObject(); + } catch (JsonSyntaxException e) { + return null; + } + } + + /** + * This method will check whether the given response is in the correct format as per the response-schema. + * + * @param response The response from OpenAI. + * @return Whether the response is in the correct format. (true | false) + */ + public boolean isInvalidResponse(String response) { + JsonObject jsonNode = loadJsonData(response); + + if (jsonNode == null || jsonNode.get("data") == null) { + return true; + } + + if (jsonNode.get("dataType") != null) { + String type = jsonNode.get("dataType").getAsString(); + switch (type.toLowerCase()) { + case "json": + case "xml": + case "text": + return false; + default: + return true; + } + } + + return true; + } + + /** + * This method will send the request to OpenAI and get the response. If the response is not in the given format + * in response-schema, it will resend a request with the given response saying that the given response is not in + * the correct format. + * + * @param client The OpenAI client. + * @param response The given response from OpenAI (if any). + * @return The correct response from OpenAI. + */ + public List getResponses(OpenAIClient client, String response) { + String userMessage = "request-schema: \n" + requestSchema + "\nresponse-schema: \n" + responseSchema; + + List chatMessages = new ArrayList<>(); + chatMessages.add(new ChatRequestSystemMessage(basePrompt)); + chatMessages.add(new ChatRequestUserMessage(userMessage)); + + if (!response.isEmpty()) { + chatMessages.add(new ChatRequestAssistantMessage(response)); + chatMessages.add(new ChatRequestUserMessage(retryPrompt)); + } + + ChatCompletions chatCompletions = client.getChatCompletions( + openaiModel, + new ChatCompletionsOptions(chatMessages) + ); + remainingRetries--; + + return chatCompletions.getChoices(); + } + + public boolean mediate(MessageContext synCtx) { + + // TODO: This mediator only support for INLINE payload at the moment. + // Need to add support for other types like the `Enrich Mediator`. + // INLINE, PROPERTY, BODY, ENVELOPE, CUSTOM + + org.apache.axis2.context.MessageContext msgContext = ((Axis2MessageContext) synCtx).getAxis2MessageContext(); + + try { + OpenAIClientBuilder builder = new OpenAIClientBuilder() + .credential(new AzureKeyCredential(openaiKey)) + .endpoint(openaiEndpoint); + + OpenAIClient client = builder.buildClient(); + List chats = getResponses(client, ""); + + boolean noValidResponse = true; + String response = ""; + while (noValidResponse && remainingRetries > 0) { + for (ChatChoice chat : chats) { + response = chat.getMessage().getContent(); + if (!isInvalidResponse(response)) { + noValidResponse = false; + break; + } + } + if (noValidResponse) { + chats = getResponses(client, response); + } + } + + if (noValidResponse) { + JsonUtil.getNewJsonPayload( + msgContext, + "Failed to get a valid JSON response after " + retryCount + " attempts.", + true, + true + ); + } else { + JsonUtil.getNewJsonPayload( + msgContext, + String.valueOf(response), + true, + true + ); + } + msgContext.setProperty(IntelligentConstants.MESSAGE_TYPE_STRING, IntelligentConstants.JSON_CONTENT_TYPE); + msgContext.setProperty(IntelligentConstants.CONTENT_TYPE_STRING, IntelligentConstants.JSON_CONTENT_TYPE); + } catch (AxisFault e) { + handleException("JsonUtil error.", e, synCtx); + } + return true; + } + + public void setPrompt(String prompt) { + this.prompt = prompt; + } + + public void setHeaders(String headers) { + this.headers = headers; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + public void setOpenaiKey(String openaiKey) { + this.openaiKey = openaiKey; + } + + public void setOpenaiModel(String openaiModel) { + this.openaiModel = openaiModel; + } + + public void setOpenaiEndpoint(String openaiEndpoint) { + this.openaiEndpoint = openaiEndpoint; + } + + public void setRetryCount(int retryCount) { + this.retryCount = retryCount; + this.remainingRetries = retryCount; + } +} diff --git a/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentMediatorFactory.java b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentMediatorFactory.java new file mode 100644 index 0000000000..68f76bcb18 --- /dev/null +++ b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentMediatorFactory.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.micro.integrator.mediator.intelligent; + +import org.apache.axiom.om.OMAttribute; +import org.apache.axiom.om.OMElement; +import org.apache.synapse.Mediator; +import org.apache.synapse.config.xml.AbstractMediatorFactory; + +import javax.xml.namespace.QName; +import java.util.Properties; + +public class IntelligentMediatorFactory extends AbstractMediatorFactory { + private static final QName ATT_KEY = new QName(IntelligentConstants.KEY_STRING); + private static final QName ATT_MODEL = new QName(IntelligentConstants.MODEL_STRING); + private static final QName ATT_ENDPOINT = new QName(IntelligentConstants.ENDPOINT_STRING); + private static final QName ATT_RETRY_COUNT = new QName(IntelligentConstants.RETRY_COUNT_STRING); + private static final QName ATT_PROMPT = new QName(IntelligentConstants.PROMPT_STRING); + private static final QName ATT_HEADERS = new QName(IntelligentConstants.HEADERS_STRING); + private static final QName PAYLOAD_Q = IntelligentConstants.PAYLOAD_Q; + + @Override + protected Mediator createSpecificMediator(OMElement omElement, Properties properties) { + if (!IntelligentConstants.INTELLIGENT_Q.equals(omElement.getQName())) { + handleException("Unable to create the intelligent mediator. Unexpected element as the intelligent mediator configuration"); + } + + IntelligentMediator intelligentMediator = new IntelligentMediator(); + String key, model, endpoint, prompt, headers; + int retryCount; + + // TODO: Key should be encrypted and decrypted during the process + OMAttribute keyAttr = omElement.getAttribute(ATT_KEY); + if (keyAttr != null && keyAttr.getAttributeValue() != null) { + key = keyAttr.getAttributeValue(); + intelligentMediator.setOpenaiKey(key); + } else { + handleException("OpenAI key is required for the intelligent mediator"); + } + + OMAttribute taskAttr = omElement.getAttribute(ATT_PROMPT); + if (taskAttr != null && taskAttr.getAttributeValue() != null) { + prompt = taskAttr.getAttributeValue(); + intelligentMediator.setPrompt(prompt); + } else { + handleException("Prompt attribute is required for the intelligent mediator"); + } + + OMElement payloadElem = omElement.getFirstChildWithName(PAYLOAD_Q); + if (payloadElem == null) { + handleException("Payload element of Intelligent Mediator is required"); + } else { + if (payloadElem.getFirstElement() != null) { + intelligentMediator.setPayload(payloadElem.getFirstElement().toString()); + } else { + intelligentMediator.setPayload(payloadElem.getText()); + } + } + + OMAttribute modelAttr = omElement.getAttribute(ATT_MODEL); + if (modelAttr != null && modelAttr.getAttributeValue() != null) { + model = modelAttr.getAttributeValue(); + intelligentMediator.setOpenaiModel(model); + } + + OMAttribute endpointAttr = omElement.getAttribute(ATT_ENDPOINT); + if (endpointAttr != null && endpointAttr.getAttributeValue() != null) { + endpoint = endpointAttr.getAttributeValue(); + intelligentMediator.setOpenaiEndpoint(endpoint); + } + + OMAttribute retryCountAttr = omElement.getAttribute(ATT_RETRY_COUNT); + if (retryCountAttr != null && retryCountAttr.getAttributeValue() != null) { + retryCount = Integer.parseInt(retryCountAttr.getAttributeValue()); + intelligentMediator.setRetryCount(retryCount); + } + + OMAttribute headersAttr = omElement.getAttribute(ATT_HEADERS); + if (headersAttr != null && headersAttr.getAttributeValue() != null) { + headers = headersAttr.getAttributeValue(); + intelligentMediator.setHeaders(headers); + } + + intelligentMediator.initialize(); + + return intelligentMediator; + } + + @Override + public QName getTagQName() { + return IntelligentConstants.INTELLIGENT_Q; + } +} diff --git a/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentMediatorSerializer.java b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentMediatorSerializer.java new file mode 100644 index 0000000000..173aa56252 --- /dev/null +++ b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/IntelligentMediatorSerializer.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.micro.integrator.mediator.intelligent; + +import org.apache.axiom.om.OMElement; +import org.apache.synapse.Mediator; +import org.apache.synapse.config.xml.AbstractMediatorSerializer; + +public class IntelligentMediatorSerializer extends AbstractMediatorSerializer { + @Override + protected OMElement serializeSpecificMediator(Mediator mediator) { + return null; + } + + @Override + public String getMediatorClassName() { + return null; + } +} diff --git a/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/util/RequestSchema.java b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/util/RequestSchema.java new file mode 100644 index 0000000000..79d35fbafb --- /dev/null +++ b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/util/RequestSchema.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.micro.integrator.mediator.intelligent.util; + +/** + * A template class for sending the request to OpenAI. + */ +@SuppressWarnings({"unused", "FieldCanBeLocal"}) +public class RequestSchema { + private final String prompt; + private final String payload; + private final String headers; + + public RequestSchema(String prompt, String payload, String headers) { + this.prompt = prompt; + this.payload = payload; + this.headers = headers; + } +} diff --git a/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/util/ResponseSchema.java b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/util/ResponseSchema.java new file mode 100644 index 0000000000..11de80f508 --- /dev/null +++ b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/java/org/wso2/micro/integrator/mediator/intelligent/util/ResponseSchema.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.micro.integrator.mediator.intelligent.util; + +/** + * A template class for receiving the response from OpenAI. + */ +@SuppressWarnings("unused") +public class ResponseSchema { + private final String data = ""; + private final String status = ""; + private final String dataType = ""; +} diff --git a/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorFactory b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorFactory new file mode 100644 index 0000000000..10b30d36b4 --- /dev/null +++ b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorFactory @@ -0,0 +1 @@ +org.wso2.micro.integrator.mediator.intelligent.IntelligentMediatorFactory diff --git a/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorSerializer b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorSerializer new file mode 100644 index 0000000000..418e0db8a7 --- /dev/null +++ b/components/mediation/mediators/intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorSerializer @@ -0,0 +1 @@ +org.wso2.micro.integrator.mediator.intelligent.IntelligentMediatorSerializer diff --git a/components/mediation/mediators/pom.xml b/components/mediation/mediators/pom.xml index ec7af722a2..12d4628d1d 100644 --- a/components/mediation/mediators/pom.xml +++ b/components/mediation/mediators/pom.xml @@ -34,6 +34,6 @@ oauth-mediator/org.wso2.micro.integrator.mediator.oauth entitlement-mediator/org.wso2.micro.integrator.identity.entitlement.mediator dataservices-mediator/org.wso2.micro.integrator.mediator.dataservice - sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI + intelligent-mediator/org.wso2.micro.integrator.mediator.intelligent diff --git a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediator.java b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediator.java deleted file mode 100644 index bf215212c1..0000000000 --- a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediator.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.wso2.micro.integrator.mediator.sampleAI; - -import org.apache.synapse.mediators.AbstractMediator; -import org.apache.synapse.MessageContext; -public class SampleAIMediator extends AbstractMediator { - - public boolean mediate(MessageContext synCtx) { - System.out.println("SampleAI Mediator"); - return true; - } -} diff --git a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorFactory.java b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorFactory.java deleted file mode 100644 index c01437fa2b..0000000000 --- a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.wso2.micro.integrator.mediator.sampleAI; - -import org.apache.axiom.om.OMElement; -import org.apache.synapse.Mediator; -import org.apache.synapse.config.xml.AbstractMediatorFactory; -import org.apache.synapse.config.xml.XMLConfigConstants; - -import javax.xml.namespace.QName; -import java.util.Properties; - -public class SampleAIMediatorFactory extends AbstractMediatorFactory { - @Override - protected Mediator createSpecificMediator(OMElement omElement, Properties properties) { - return new SampleAIMediator(); - } - - @Override - public QName getTagQName() { - return new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, "SampleAI"); - } -} diff --git a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorSerializer.java b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorSerializer.java deleted file mode 100644 index 2ae3022879..0000000000 --- a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/java/org/wso2/micro/integrator/mediator/sampleAI/SampleAIMediatorSerializer.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.wso2.micro.integrator.mediator.sampleAI; - -import org.apache.axiom.om.OMElement; -import org.apache.synapse.Mediator; -import org.apache.synapse.config.xml.AbstractMediatorSerializer; - -public class SampleAIMediatorSerializer extends AbstractMediatorSerializer { - @Override - protected OMElement serializeSpecificMediator(Mediator mediator) { - return null; - } - - @Override - public String getMediatorClassName() { - return null; - } -} diff --git a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorFactory b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorFactory deleted file mode 100644 index 6410b4a1d6..0000000000 --- a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorFactory +++ /dev/null @@ -1 +0,0 @@ -org.wso2.micro.integrator.mediator.sampleAI.SampleAIMediatorFactory diff --git a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorSerializer b/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorSerializer deleted file mode 100644 index 7726bc4f40..0000000000 --- a/components/mediation/mediators/sampleAI-mediator/org.wso2.micro.integrator.mediator.sampleAI/src/main/resources/META-INF/services/org.apache.synapse.config.xml.MediatorSerializer +++ /dev/null @@ -1 +0,0 @@ -org.wso2.micro.integrator.mediator.sampleAI.SampleAIMediatorSerializer diff --git a/features/mediation-features/builtin-mediators/org.wso2.micro.integrator.mediators.server.feature/pom.xml b/features/mediation-features/builtin-mediators/org.wso2.micro.integrator.mediators.server.feature/pom.xml index 175105eb76..9f41623790 100644 --- a/features/mediation-features/builtin-mediators/org.wso2.micro.integrator.mediators.server.feature/pom.xml +++ b/features/mediation-features/builtin-mediators/org.wso2.micro.integrator.mediators.server.feature/pom.xml @@ -35,7 +35,7 @@ org.wso2.ei - org.wso2.micro.integrator.mediator.sampleAI + org.wso2.micro.integrator.mediator.intelligent org.wso2.ei @@ -89,7 +89,7 @@ org.wso2.ei:org.wso2.carbon.mediator.cache:${project.version} - org.wso2.ei:org.wso2.micro.integrator.mediator.sampleAI:${project.version} + org.wso2.ei:org.wso2.micro.integrator.mediator.intelligent:${project.version} org.wso2.ei:org.wso2.micro.integrator.mediator.oauth:${project.version} diff --git a/pom.xml b/pom.xml index d9adbe27cd..838beeb110 100644 --- a/pom.xml +++ b/pom.xml @@ -178,7 +178,7 @@ org.wso2.ei - org.wso2.micro.integrator.mediator.sampleAI + org.wso2.micro.integrator.mediator.intelligent ${project.version}