From 10b4bce96766edd107a40f045ff24255228a20c5 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Thu, 31 Oct 2024 16:48:52 +0100 Subject: [PATCH 1/2] Revert "Introducing a facade API : (#53)" This reverts commit b3b6794544ffd56b42b98ce3b7530ac55c361b8c. --- .gitignore | 2 +- examples/glassfish-car-booking/pom.xml | 8 +- .../io/jefrajames/booking/BookingService.java | 4 +- .../io/jefrajames/booking/ChatAiService.java | 6 +- .../io/jefrajames/booking/FraudAiService.java | 9 +- .../helidon-car-booking-portable-ext/pom.xml | 12 +- .../io/jefrajames/booking/ChatAiService.java | 5 +- .../io/jefrajames/booking/FraudAiService.java | 13 +- examples/helidon-car-booking/pom.xml | 12 +- .../io/jefrajames/booking/BookingService.java | 3 +- .../io/jefrajames/booking/ChatAiService.java | 5 +- .../io/jefrajames/booking/FraudAiService.java | 9 +- examples/liberty-car-booking/README.md | 4 +- examples/liberty-car-booking/pom.xml | 330 ++++++---- .../io/jefrajames/booking/ChatAiService.java | 6 +- .../io/jefrajames/booking/FraudAiService.java | 8 +- examples/quarkus-car-booking/pom.xml | 8 +- .../io/jefrajames/booking/BookingService.java | 3 +- .../io/jefrajames/booking/ChatAiService.java | 5 +- .../io/jefrajames/booking/FraudAiService.java | 9 +- mp-ai-api/pom.xml | 20 - .../eclipse/microprofile/ai/llm/MemoryId.java | 20 - .../eclipse/microprofile/ai/llm/Moderate.java | 24 - .../org/eclipse/microprofile/ai/llm/P.java | 32 - .../microprofile/ai/llm/StructuredPrompt.java | 32 - .../microprofile/ai/llm/SystemMessage.java | 62 -- .../microprofile/ai/llm/TokenStream.java | 59 -- .../ai/llm/TokenStreamAdapter.java | 14 - .../org/eclipse/microprofile/ai/llm/Tool.java | 36 -- .../microprofile/ai/llm/ToolMemoryId.java | 19 - .../microprofile/ai/llm/UserMessage.java | 63 -- .../eclipse/microprofile/ai/llm/UserName.java | 18 - .../org/eclipse/microprofile/ai/llm/V.java | 42 -- pom.xml | 129 ++-- .../pom.xml | 4 + ...in4JAIServiceBuildCompatibleExtension.java | 3 +- .../smallrye/llm/core/MyDummyAIService.java | 8 +- .../MyDummyApplicationScopedAIService.java | 2 +- .../pom.xml | 2 + smallrye-llm-langchain4j-core/pom.xml | 4 - .../llm/aiservice/CommonAIServiceCreator.java | 2 +- .../SmallRyeAiServiceTokenStream.java | 89 --- .../services/SmallRyeLang4JAiServices.java | 612 ------------------ .../SmallRyeLang4JchainAiServicesFactory.java | 23 - .../SmallRyeStructuredPromptFactory.java | 82 --- .../services/ToolSpecifications.java | 279 -------- .../smallrye/llm/spi}/RegisterAIService.java | 2 +- ....prompt.structured.StructuredPromptFactory | 1 - ...langchain4j.spi.services.AiServicesFactory | 1 - .../pom.xml | 1 + ...LangChain4JAIServicePortableExtension.java | 2 +- .../smallrye/llm/core/MyDummyAIService.java | 8 +- .../MyDummyApplicationScopedAIService.java | 2 +- 53 files changed, 334 insertions(+), 1824 deletions(-) delete mode 100644 mp-ai-api/pom.xml delete mode 100644 mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/MemoryId.java delete mode 100644 mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/Moderate.java delete mode 100644 mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/P.java delete mode 100644 mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/StructuredPrompt.java delete mode 100644 mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/SystemMessage.java delete mode 100644 mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/TokenStream.java delete mode 100644 mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/TokenStreamAdapter.java delete mode 100644 mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/Tool.java delete mode 100644 mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/ToolMemoryId.java delete mode 100644 mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/UserMessage.java delete mode 100644 mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/UserName.java delete mode 100644 mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/V.java delete mode 100644 smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeAiServiceTokenStream.java delete mode 100644 smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeLang4JAiServices.java delete mode 100644 smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeLang4JchainAiServicesFactory.java delete mode 100644 smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeStructuredPromptFactory.java delete mode 100644 smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/ToolSpecifications.java rename {mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm => smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/spi}/RegisterAIService.java (95%) delete mode 100644 smallrye-llm-langchain4j-core/src/main/resources/META-INF/services/dev.langchain4j.spi.prompt.structured.StructuredPromptFactory delete mode 100644 smallrye-llm-langchain4j-core/src/main/resources/META-INF/services/dev.langchain4j.spi.services.AiServicesFactory diff --git a/.gitignore b/.gitignore index 3d5de90..7879fe1 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,7 @@ buildNumber.properties .project # JDT-specific (Eclipse Java Development Tools) .classpath -nb-configuration.xml + .idea diff --git a/examples/glassfish-car-booking/pom.xml b/examples/glassfish-car-booking/pom.xml index 9373056..1dc46e0 100644 --- a/examples/glassfish-car-booking/pom.xml +++ b/examples/glassfish-car-booking/pom.xml @@ -25,13 +25,10 @@ ${jakarta.jakartaee-api.version} provided - - io.smallrye.llm - mp-ai-api - io.smallrye.llm smallrye-llm-langchain4j-portable-extension + 1.0.0-SNAPSHOT jakarta.enterprise @@ -69,6 +66,7 @@ dev.langchain4j langchain4j + ${dev.langchain4j.version} dev.langchain4j @@ -90,7 +88,7 @@ org.slf4j slf4j-jdk14 runtime - 2.0.16 + 2.0.9 diff --git a/examples/glassfish-car-booking/src/main/java/io/jefrajames/booking/BookingService.java b/examples/glassfish-car-booking/src/main/java/io/jefrajames/booking/BookingService.java index 3e38e4c..4ee5ff5 100644 --- a/examples/glassfish-car-booking/src/main/java/io/jefrajames/booking/BookingService.java +++ b/examples/glassfish-car-booking/src/main/java/io/jefrajames/booking/BookingService.java @@ -6,9 +6,9 @@ import java.util.Map; import java.util.stream.Collectors; -import org.eclipse.microprofile.ai.llm.Tool; - import jakarta.enterprise.context.ApplicationScoped; + +import dev.langchain4j.agent.tool.Tool; import lombok.extern.java.Log; @ApplicationScoped diff --git a/examples/glassfish-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java b/examples/glassfish-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java index 594b8f1..d35c5c3 100644 --- a/examples/glassfish-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java +++ b/examples/glassfish-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java @@ -1,7 +1,9 @@ package io.jefrajames.booking; -import org.eclipse.microprofile.ai.llm.RegisterAIService; -import org.eclipse.microprofile.ai.llm.SystemMessage; +import dev.langchain4j.service.SystemMessage; +import io.smallrye.llm.spi.RegisterAIService; + +import java.time.temporal.ChronoUnit; @SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService(tools = BookingService.class, chatMemoryMaxMessages = 10, chatLanguageModelName = "chat-model") diff --git a/examples/glassfish-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java b/examples/glassfish-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java index 021bf3c..68488de 100644 --- a/examples/glassfish-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java +++ b/examples/glassfish-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java @@ -1,12 +1,13 @@ package io.jefrajames.booking; -import org.eclipse.microprofile.ai.llm.RegisterAIService; -import org.eclipse.microprofile.ai.llm.SystemMessage; -import org.eclipse.microprofile.ai.llm.UserMessage; -import org.eclipse.microprofile.ai.llm.V; +import dev.langchain4j.service.SystemMessage; +import dev.langchain4j.service.UserMessage; +import dev.langchain4j.service.V; +import io.smallrye.llm.spi.RegisterAIService; @SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService(chatMemoryMaxMessages = 5, + chatLanguageModelName = "chat-model") public interface FraudAiService { diff --git a/examples/helidon-car-booking-portable-ext/pom.xml b/examples/helidon-car-booking-portable-ext/pom.xml index afe82b9..b9a2307 100644 --- a/examples/helidon-car-booking-portable-ext/pom.xml +++ b/examples/helidon-car-booking-portable-ext/pom.xml @@ -11,8 +11,8 @@ SmallRye LLM Examples: Helidon Car Booking Portable Extension - 4.0.7 io.helidon.Main + 0.34.0 @@ -20,14 +20,14 @@ io.helidon helidon-bom - ${version.io.helidon} + 4.0.7 pom import io.helidon helidon-dependencies - ${version.io.helidon} + 4.0.7 pom import @@ -35,17 +35,15 @@ - - io.smallrye.llm - mp-ai-api - io.smallrye.llm smallrye-llm-langchain4j-portable-extension + 1.0.0-SNAPSHOT io.smallrye.llm smallrye-llm-langchain4j-config-mpconfig + 1.0.0-SNAPSHOT diff --git a/examples/helidon-car-booking-portable-ext/src/main/java/io/jefrajames/booking/ChatAiService.java b/examples/helidon-car-booking-portable-ext/src/main/java/io/jefrajames/booking/ChatAiService.java index 407ee89..143dd93 100644 --- a/examples/helidon-car-booking-portable-ext/src/main/java/io/jefrajames/booking/ChatAiService.java +++ b/examples/helidon-car-booking-portable-ext/src/main/java/io/jefrajames/booking/ChatAiService.java @@ -2,12 +2,13 @@ import java.time.temporal.ChronoUnit; -import org.eclipse.microprofile.ai.llm.RegisterAIService; -import org.eclipse.microprofile.ai.llm.SystemMessage; import org.eclipse.microprofile.faulttolerance.Fallback; import org.eclipse.microprofile.faulttolerance.Retry; import org.eclipse.microprofile.faulttolerance.Timeout; +import dev.langchain4j.service.SystemMessage; +import io.smallrye.llm.spi.RegisterAIService; + @SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService(tools = BookingService.class, chatMemoryMaxMessages = 10, chatLanguageModelName = "chat-model") public interface ChatAiService { diff --git a/examples/helidon-car-booking-portable-ext/src/main/java/io/jefrajames/booking/FraudAiService.java b/examples/helidon-car-booking-portable-ext/src/main/java/io/jefrajames/booking/FraudAiService.java index a22deaa..185b006 100644 --- a/examples/helidon-car-booking-portable-ext/src/main/java/io/jefrajames/booking/FraudAiService.java +++ b/examples/helidon-car-booking-portable-ext/src/main/java/io/jefrajames/booking/FraudAiService.java @@ -2,16 +2,19 @@ import java.time.temporal.ChronoUnit; -import org.eclipse.microprofile.ai.llm.RegisterAIService; -import org.eclipse.microprofile.ai.llm.SystemMessage; -import org.eclipse.microprofile.ai.llm.UserMessage; -import org.eclipse.microprofile.ai.llm.V; import org.eclipse.microprofile.faulttolerance.Fallback; import org.eclipse.microprofile.faulttolerance.Retry; import org.eclipse.microprofile.faulttolerance.Timeout; +import dev.langchain4j.service.SystemMessage; +import dev.langchain4j.service.UserMessage; +import dev.langchain4j.service.V; +import io.smallrye.llm.spi.RegisterAIService; + @SuppressWarnings("CdiManagedBeanInconsistencyInspection") -@RegisterAIService(chatMemoryMaxMessages = 5, chatLanguageModelName = "chat-model") +@RegisterAIService(chatMemoryMaxMessages = 5, + + chatLanguageModelName = "chat-model") public interface FraudAiService { @SystemMessage(""" diff --git a/examples/helidon-car-booking/pom.xml b/examples/helidon-car-booking/pom.xml index 2b42388..47ee4b0 100644 --- a/examples/helidon-car-booking/pom.xml +++ b/examples/helidon-car-booking/pom.xml @@ -11,8 +11,8 @@ SmallRye LLM Examples: Helidon Car Booking - 4.0.7 io.helidon.Main + 0.34.0 @@ -20,14 +20,14 @@ io.helidon helidon-bom - ${version.io.helidon} + 4.0.7 pom import io.helidon helidon-dependencies - ${version.io.helidon} + 4.0.7 pom import @@ -35,17 +35,15 @@ - - io.smallrye.llm - mp-ai-api - io.smallrye.llm smallrye-llm-langchain4j-buildcompatible-extension + 1.0.0-SNAPSHOT io.smallrye.llm smallrye-llm-langchain4j-config-mpconfig + 1.0.0-SNAPSHOT diff --git a/examples/helidon-car-booking/src/main/java/io/jefrajames/booking/BookingService.java b/examples/helidon-car-booking/src/main/java/io/jefrajames/booking/BookingService.java index 8704807..4ee5ff5 100644 --- a/examples/helidon-car-booking/src/main/java/io/jefrajames/booking/BookingService.java +++ b/examples/helidon-car-booking/src/main/java/io/jefrajames/booking/BookingService.java @@ -8,8 +8,7 @@ import jakarta.enterprise.context.ApplicationScoped; -import org.eclipse.microprofile.ai.llm.Tool; - +import dev.langchain4j.agent.tool.Tool; import lombok.extern.java.Log; @ApplicationScoped diff --git a/examples/helidon-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java b/examples/helidon-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java index 407ee89..143dd93 100644 --- a/examples/helidon-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java +++ b/examples/helidon-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java @@ -2,12 +2,13 @@ import java.time.temporal.ChronoUnit; -import org.eclipse.microprofile.ai.llm.RegisterAIService; -import org.eclipse.microprofile.ai.llm.SystemMessage; import org.eclipse.microprofile.faulttolerance.Fallback; import org.eclipse.microprofile.faulttolerance.Retry; import org.eclipse.microprofile.faulttolerance.Timeout; +import dev.langchain4j.service.SystemMessage; +import io.smallrye.llm.spi.RegisterAIService; + @SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService(tools = BookingService.class, chatMemoryMaxMessages = 10, chatLanguageModelName = "chat-model") public interface ChatAiService { diff --git a/examples/helidon-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java b/examples/helidon-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java index a16e425..185b006 100644 --- a/examples/helidon-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java +++ b/examples/helidon-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java @@ -2,14 +2,15 @@ import java.time.temporal.ChronoUnit; -import org.eclipse.microprofile.ai.llm.RegisterAIService; -import org.eclipse.microprofile.ai.llm.SystemMessage; -import org.eclipse.microprofile.ai.llm.UserMessage; -import org.eclipse.microprofile.ai.llm.V; import org.eclipse.microprofile.faulttolerance.Fallback; import org.eclipse.microprofile.faulttolerance.Retry; import org.eclipse.microprofile.faulttolerance.Timeout; +import dev.langchain4j.service.SystemMessage; +import dev.langchain4j.service.UserMessage; +import dev.langchain4j.service.V; +import io.smallrye.llm.spi.RegisterAIService; + @SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService(chatMemoryMaxMessages = 5, diff --git a/examples/liberty-car-booking/README.md b/examples/liberty-car-booking/README.md index 7eb643f..92561c7 100644 --- a/examples/liberty-car-booking/README.md +++ b/examples/liberty-car-booking/README.md @@ -10,7 +10,7 @@ These are the steps to run this service. ## Application requirements: - JDK 17 and higher - Maven 3.9.9 and higher -- LangChain4j 0.35.0 or higher. +- LangChain4j 0.33.0 or higher. - Testing against GPT 3.5 and 4.0 on a dedicated Azure instance (to be customized in your context). Then you can access the application through the browser of your choice. @@ -39,7 +39,7 @@ To package the application in JVM mode run: `mvn package`. ## Configuration -All configuration is centralized in `microprofile-config.properties` (found is `resources\META-INF` folder) and can be redefined using environment variables. +All configuration is centralized in `microprofile-config.properties`(found is `resources\META-INF` folder) and can be redefined using environment variables. ## Running the application diff --git a/examples/liberty-car-booking/pom.xml b/examples/liberty-car-booking/pom.xml index 3d4b008..89923cd 100644 --- a/examples/liberty-car-booking/pom.xml +++ b/examples/liberty-car-booking/pom.xml @@ -1,120 +1,175 @@ - 4.0.0 - - io.smallrye.llm.examples - examples - 1.0.0-SNAPSHOT - ../pom.xml - + 4.0.0 + + io.smallrye.llm.examples + examples + 1.0.0-SNAPSHOT + - liberty-car-booking - war - SmallRye LLM Examples: Liberty Car Booking + liberty-car-booking + war + SmallRye LLM Examples: Liberty Car Booking - - - Buhake Sindi - +2 - - PROJECT LEAD - - - + + + Buhake Sindi + +2 + + PROJECT LEAD + + + - - UTF-8 - UTF-8 - 10.0.0 - 6.1 - 3.4.0 - - - ${project.build.directory}/liberty/wlp/usr/shared/resources/lib/ - + + UTF-8 + UTF-8 + 10.0.0 + 6.1 + 3.13.0 + 3.4.0 + 0.34.0 + + ${project.build.directory}/liberty/wlp/usr/shared/resources/lib/ + - - - - - jakarta.platform - jakarta.jakartaee-api - ${jakartaee-api.version} - provided - + + + + + jakarta.platform + jakarta.jakartaee-api + ${jakartaee-api.version} + provided + + + + org.eclipse.microprofile + microprofile + ${microprofile-api.version} + pom + provided + + + - - org.eclipse.microprofile - microprofile - ${microprofile-api.version} - pom - provided - + + io.smallrye.llm + smallrye-llm-langchain4j-config-mpconfig + 1.0.0-SNAPSHOT + - - dev.langchain4j - langchain4j-hugging-face - ${dev.langchain4j.version} - + + io.smallrye.llm + smallrye-llm-langchain4j-portable-extension + 1.0.0-SNAPSHOT + + + + + dev.langchain4j + langchain4j + ${dev.langchain4j.version} + + + + dev.langchain4j + langchain4j-hugging-face + ${dev.langchain4j.version} + - - - dev.langchain4j - langchain4j-azure-open-ai - ${dev.langchain4j.version} - + + + dev.langchain4j + langchain4j-azure-open-ai + ${dev.langchain4j.version} + - - dev.langchain4j - langchain4j-open-ai - ${dev.langchain4j.version} - + + dev.langchain4j + langchain4j-open-ai + ${dev.langchain4j.version} + - - dev.langchain4j - langchain4j-embeddings-all-minilm-l6-v2 - ${dev.langchain4j.version} - + + dev.langchain4j + langchain4j-embeddings-all-minilm-l6-v2 + ${dev.langchain4j.version} + - - - ai.djl.huggingface - tokenizers - 0.30.0 - + + + ai.djl.huggingface + tokenizers + 0.30.0 + - - - org.slf4j - slf4j-jdk14 - runtime - 2.0.9 - - - + + + org.slf4j + slf4j-jdk14 + runtime + 2.0.9 + + + - - - org.eclipse.microprofile - microprofile - pom - - - io.smallrye.llm - mp-ai-api - + + + + + org.eclipse.microprofile + microprofile + pom + io.smallrye.llm smallrye-llm-langchain4j-config-mpconfig - - io.smallrye.llm - smallrye-llm-langchain4j-portable-extension - - + + io.smallrye.llm + smallrye-llm-langchain4j-portable-extension + + + + + + org.projectlombok lombok @@ -134,10 +189,10 @@ - - dev.langchain4j - langchain4j-azure-open-ai - + + dev.langchain4j + langchain4j-azure-open-ai + dev.langchain4j @@ -150,10 +205,10 @@ - - ai.djl.huggingface - tokenizers - + + ai.djl.huggingface + tokenizers + @@ -161,38 +216,43 @@ slf4j-jdk14 runtime - + - - ${project.artifactId} - - - - - io.openliberty.tools - liberty-maven-plugin - 3.10.3 - - - ${project.build.finalName} - ${project.basedir}/docs-for-rag - - - - - + + ${project.artifactId} + + + + + io.openliberty.tools + liberty-maven-plugin + 3.10.3 + + + ${project.build.finalName} + ${project.basedir}/docs-for-rag + + + + + - - - io.openliberty.tools - liberty-maven-plugin - + + + org.apache.maven.plugins + maven-compiler-plugin + + + + io.openliberty.tools + liberty-maven-plugin + - - org.apache.maven.plugins - maven-war-plugin - ${war-plugin.version} - - - + + org.apache.maven.plugins + maven-war-plugin + ${war-plugin.version} + + + \ No newline at end of file diff --git a/examples/liberty-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java b/examples/liberty-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java index 6bdb4e6..bc6892f 100644 --- a/examples/liberty-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java +++ b/examples/liberty-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java @@ -2,12 +2,13 @@ import java.time.temporal.ChronoUnit; -import org.eclipse.microprofile.ai.llm.RegisterAIService; -import org.eclipse.microprofile.ai.llm.SystemMessage; import org.eclipse.microprofile.faulttolerance.Fallback; import org.eclipse.microprofile.faulttolerance.Retry; import org.eclipse.microprofile.faulttolerance.Timeout; +import dev.langchain4j.service.SystemMessage; +import io.smallrye.llm.spi.RegisterAIService; + //@SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService(tools = BookingService.class, chatMemoryMaxMessages = 10) public interface ChatAiService { @@ -37,4 +38,5 @@ default String chatFallback(String question) { "Sorry, I am not able to answer your request %s at the moment. Please try again later.", question); } + } diff --git a/examples/liberty-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java b/examples/liberty-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java index 0376b0e..68488de 100644 --- a/examples/liberty-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java +++ b/examples/liberty-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java @@ -1,9 +1,9 @@ package io.jefrajames.booking; -import org.eclipse.microprofile.ai.llm.RegisterAIService; -import org.eclipse.microprofile.ai.llm.SystemMessage; -import org.eclipse.microprofile.ai.llm.UserMessage; -import org.eclipse.microprofile.ai.llm.V; +import dev.langchain4j.service.SystemMessage; +import dev.langchain4j.service.UserMessage; +import dev.langchain4j.service.V; +import io.smallrye.llm.spi.RegisterAIService; @SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService(chatMemoryMaxMessages = 5, diff --git a/examples/quarkus-car-booking/pom.xml b/examples/quarkus-car-booking/pom.xml index c300926..54a9889 100644 --- a/examples/quarkus-car-booking/pom.xml +++ b/examples/quarkus-car-booking/pom.xml @@ -5,7 +5,6 @@ examples io.smallrye.llm.examples 1.0.0-SNAPSHOT - ../pom.xml quarkus-car-booking @@ -35,17 +34,15 @@ - - io.smallrye.llm - mp-ai-api - io.smallrye.llm smallrye-llm-langchain4j-buildcompatible-extension + 1.0.0-SNAPSHOT io.smallrye.llm smallrye-llm-langchain4j-config-mpconfig + 1.0.0-SNAPSHOT org.projectlombok @@ -56,6 +53,7 @@ dev.langchain4j langchain4j + ${dev.langchain4j.version} dev.langchain4j diff --git a/examples/quarkus-car-booking/src/main/java/io/jefrajames/booking/BookingService.java b/examples/quarkus-car-booking/src/main/java/io/jefrajames/booking/BookingService.java index 8704807..4ee5ff5 100644 --- a/examples/quarkus-car-booking/src/main/java/io/jefrajames/booking/BookingService.java +++ b/examples/quarkus-car-booking/src/main/java/io/jefrajames/booking/BookingService.java @@ -8,8 +8,7 @@ import jakarta.enterprise.context.ApplicationScoped; -import org.eclipse.microprofile.ai.llm.Tool; - +import dev.langchain4j.agent.tool.Tool; import lombok.extern.java.Log; @ApplicationScoped diff --git a/examples/quarkus-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java b/examples/quarkus-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java index 7ddaa0b..7e00c9b 100644 --- a/examples/quarkus-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java +++ b/examples/quarkus-car-booking/src/main/java/io/jefrajames/booking/ChatAiService.java @@ -2,12 +2,13 @@ import java.time.temporal.ChronoUnit; -import org.eclipse.microprofile.ai.llm.RegisterAIService; -import org.eclipse.microprofile.ai.llm.SystemMessage; import org.eclipse.microprofile.faulttolerance.Fallback; import org.eclipse.microprofile.faulttolerance.Retry; import org.eclipse.microprofile.faulttolerance.Timeout; +import dev.langchain4j.service.SystemMessage; +import io.smallrye.llm.spi.RegisterAIService; + @SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService(tools = BookingService.class, chatMemoryMaxMessages = 10) public interface ChatAiService { diff --git a/examples/quarkus-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java b/examples/quarkus-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java index 143b440..61fdeef 100644 --- a/examples/quarkus-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java +++ b/examples/quarkus-car-booking/src/main/java/io/jefrajames/booking/FraudAiService.java @@ -2,14 +2,15 @@ import java.time.temporal.ChronoUnit; -import org.eclipse.microprofile.ai.llm.RegisterAIService; -import org.eclipse.microprofile.ai.llm.SystemMessage; -import org.eclipse.microprofile.ai.llm.UserMessage; -import org.eclipse.microprofile.ai.llm.V; import org.eclipse.microprofile.faulttolerance.Fallback; import org.eclipse.microprofile.faulttolerance.Retry; import org.eclipse.microprofile.faulttolerance.Timeout; +import dev.langchain4j.service.SystemMessage; +import dev.langchain4j.service.UserMessage; +import dev.langchain4j.service.V; +import io.smallrye.llm.spi.RegisterAIService; + @SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService(chatMemoryMaxMessages = 5) public interface FraudAiService { diff --git a/mp-ai-api/pom.xml b/mp-ai-api/pom.xml deleted file mode 100644 index 4ba2ccd..0000000 --- a/mp-ai-api/pom.xml +++ /dev/null @@ -1,20 +0,0 @@ - - 4.0.0 - - io.smallrye.llm - smallrye-llm-parent - 1.0.0-SNAPSHOT - ../pom.xml - - mp-ai-api - - - - jakarta.enterprise - jakarta.enterprise.cdi-api - provided - - - \ No newline at end of file diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/MemoryId.java b/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/MemoryId.java deleted file mode 100644 index f1cbea5..0000000 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/MemoryId.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.eclipse.microprofile.ai.llm; - -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * The value of a method parameter annotated with @MemoryId will be used to find the memory belonging to that user/conversation. - * A parameter annotated with @MemoryId can be of any type, provided it has properly implemented equals() and hashCode() - * methods. - */ -@Documented -@Retention(RUNTIME) -@Target(PARAMETER) -public @interface MemoryId { - -} diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/Moderate.java b/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/Moderate.java deleted file mode 100644 index 58628a5..0000000 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/Moderate.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.eclipse.microprofile.ai.llm; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * When a method in the AI Service is annotated with @Moderate, each invocation of this method will call not only the LLM, - * but also the moderation model (which must be provided during the construction of the AI Service) in parallel. - * This ensures that no malicious content is supplied by the user. - * Before the method returns an answer from the LLM, it will wait until the moderation model returns a result. - * If the moderation model flags the content, a ModerationException will be thrown. - * There is also an option to moderate user input *before* sending it to the LLM. If you require this functionality, - * please open an issue. - */ -@Documented -@Retention(RUNTIME) -@Target(METHOD) -public @interface Moderate { - -} diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/P.java b/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/P.java deleted file mode 100644 index c261d1c..0000000 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/P.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.eclipse.microprofile.ai.llm; - -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Parameter of a Tool - */ -@Documented -@Retention(RUNTIME) -@Target({ PARAMETER }) -public @interface P { - - /** - * Description of a parameter - * - * @return the description of a parameter - */ - String value(); - - /** - * Whether the parameter is required - * - * @return true if the parameter is required, false otherwise - * Default is true. - */ - boolean required() default true; -} diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/StructuredPrompt.java b/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/StructuredPrompt.java deleted file mode 100644 index 4c0d469..0000000 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/StructuredPrompt.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.eclipse.microprofile.ai.llm; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Represents a structured prompt. - */ -@Documented -@Retention(RUNTIME) -@Target(TYPE) -public @interface StructuredPrompt { - - /** - * Prompt template can be defined in one line or multiple lines. - * If the template is defined in multiple lines, the lines will be joined with a delimiter defined below. - * - * @return the prompt template lines. - */ - String[] value(); - - /** - * The delimiter to join the lines of the prompt template. - * - * @return the delimiter. - */ - String delimiter() default "\n"; -} diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/SystemMessage.java b/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/SystemMessage.java deleted file mode 100644 index 1f050c3..0000000 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/SystemMessage.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.eclipse.microprofile.ai.llm; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Specifies either a complete system message (prompt) or a system message template to be used each time an AI service is - * invoked. - *
- * An example: - * - *
- * interface Assistant {
- *
- *     {@code @SystemMessage}("You are a helpful assistant")
- *     String chat(String userMessage);
- * }
- * 
- * - * The system message can contain template variables, - * which will be resolved with values from method parameters annotated with @{@link V}. - *
- * An example: - * - *
- * interface Assistant {
- *
- *     {@code @SystemMessage}("You are a {{characteristic}} assistant")
- *     String chat(@UserMessage String userMessage, @V("characteristic") String characteristic);
- * }
- * 
- * - * @see UserMessage - */ -@Documented -@Retention(RUNTIME) -@Target({ TYPE, METHOD }) -public @interface SystemMessage { - - /** - * Prompt template can be defined in one line or multiple lines. - * If the template is defined in multiple lines, the lines will be joined with a delimiter defined below. - */ - String[] value() default ""; - - String delimiter() default "\n"; - - /** - * The resource from which to read the prompt template. - * If no resource is specified, the prompt template is taken from {@link #value()}. - * If the resource is not found, an {@link IllegalConfigurationException} is thrown. - *

- * The resource will be read by calling {@link Class#getResourceAsStream(String)} - * on the AI Service class (interface). - */ - String fromResource() default ""; -} diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/TokenStream.java b/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/TokenStream.java deleted file mode 100644 index 76e9713..0000000 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/TokenStream.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.eclipse.microprofile.ai.llm; - -import java.util.function.Consumer; - -/** - * Represents a token stream from language model to which you can subscribe and receive updates - * when a new token is available, when language model finishes streaming, or when an error occurs during streaming. - * It is intended to be used as a return type in AI Service. - */ -public interface TokenStream { - - /** - * The provided consumer will be invoked when/if contents have been retrieved using {@link RetrievalAugmentor}. - *

- * The invocation happens before any call is made to the language model. - * - * @param contentHandler lambda that consumes all retrieved contents - * @return token stream instance used to configure or start stream processing - */ - // TokenStream onRetrieved(Consumer> contentHandler); - - /** - * The provided consumer will be invoked every time a new token from a language model is available. - * - * @param tokenHandler lambda that consumes tokens of the response - * @return token stream instance used to configure or start stream processing - */ - TokenStream onNext(Consumer tokenHandler); - - /** - * The provided consumer will be invoked when a language model finishes streaming a response. - * - * @param completionHandler lambda that will be invoked when language model finishes streaming - * @return token stream instance used to configure or start stream processing - */ - // TokenStream onComplete(Consumer> completionHandler); - - /** - * The provided consumer will be invoked when an error occurs during streaming. - * - * @param errorHandler lambda that will be invoked when an error occurs - * @return token stream instance used to configure or start stream processing - */ - TokenStream onError(Consumer errorHandler); - - /** - * All errors during streaming will be ignored (but will be logged with a WARN log level). - * - * @return token stream instance used to configure or start stream processing - */ - TokenStream ignoreErrors(); - - /** - * Completes the current token stream building and starts processing. - *

- * Will send a request to LLM and start response streaming. - */ - void start(); -} diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/TokenStreamAdapter.java b/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/TokenStreamAdapter.java deleted file mode 100644 index fd7a70b..0000000 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/TokenStreamAdapter.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.eclipse.microprofile.ai.llm; - -import java.lang.reflect.Type; - -/** - * @author Buhake Sindi - * @since 11 October 2024 - */ -public interface TokenStreamAdapter { - - boolean canAdaptTokenStreamTo(Type type); - - Object adapt(TokenStream tokenStream); -} diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/Tool.java b/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/Tool.java deleted file mode 100644 index 8655b33..0000000 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/Tool.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.eclipse.microprofile.ai.llm; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Java methods annotated with {@code @Tool} are considered tools/functions that language model can execute/call. - * Tool/function calling LLM capability (e.g., see OpenAI - * function calling documentation) - * is used under the hood. - * If LLM decides to call the tool, the arguments are automatically parsed and injected as method arguments. - */ -@Documented -@Retention(RUNTIME) -@Target(METHOD) -public @interface Tool { - - /** - * Name of the tool. If not provided, method name will be used. - * - * @return name of the tool. - */ - String name() default ""; - - /** - * Description of the tool. - * It should be clear and descriptive to allow language model to understand the tool's purpose and its intended use. - * - * @return description of the tool. - */ - String[] value() default ""; -} diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/ToolMemoryId.java b/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/ToolMemoryId.java deleted file mode 100644 index af46700..0000000 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/ToolMemoryId.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.eclipse.microprofile.ai.llm; - -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * If a {@link Tool} method parameter is annotated with this annotation, - * memory id (parameter annotated with @MemoryId in AI Service) will be injected automatically. - */ -@Documented -@Retention(RUNTIME) -@Target(PARAMETER) -public @interface ToolMemoryId { - -} diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/UserMessage.java b/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/UserMessage.java deleted file mode 100644 index 172d081..0000000 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/UserMessage.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.eclipse.microprofile.ai.llm; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Specifies either a complete user message or a user message template to be used each time an AI service is invoked. - * The user message can contain template variables, - * which will be resolved with values from method parameters annotated with @{@link V}. - *
- * An example: - * - *

- * interface Assistant {
- *
- *     {@code @UserMessage}("Say hello to {{name}}")
- *     String greet(@V("name") String name);
- * }
- * 
- * - * {@code @UserMessage} can also be used with method parameters: - * - *
- * interface Assistant {
- *
- *     {@code @SystemMessage}("You are a {{characteristic}} assistant")
- *     String chat(@UserMessage String userMessage, @V("characteristic") String characteristic);
- * }
- * 
- * - * In this case {@code String userMessage} can contain unresolved template variables (e.g. "{{characteristic}}"), - * which will be resolved using the values of method parameters annotated with @{@link V}. - * - * @see SystemMessage - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, PARAMETER }) -public @interface UserMessage { - - /** - * Prompt template can be defined in one line or multiple lines. - * If the template is defined in multiple lines, the lines will be joined with a delimiter defined below. - */ - String[] value() default ""; - - String delimiter() default "\n"; - - /** - * The resource from which to read the prompt template. - * If no resource is specified, the prompt template is taken from {@link #value()}. - * If the resource is not found, an {@link IllegalConfigurationException} is thrown. - *

- * The resource will be read by calling {@link Class#getResourceAsStream(String)} - * on the AI Service class (interface). - */ - String fromResource() default ""; -} diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/UserName.java b/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/UserName.java deleted file mode 100644 index 4e93838..0000000 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/UserName.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.eclipse.microprofile.ai.llm; - -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * The value of a method parameter annotated with @UserName will be injected into the field 'name' of a UserMessage. - */ -@Documented -@Retention(RUNTIME) -@Target(PARAMETER) -public @interface UserName { - -} diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/V.java b/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/V.java deleted file mode 100644 index 4110a4a..0000000 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/V.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.eclipse.microprofile.ai.llm; - -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * When a parameter of a method in an AI Service is annotated with {@code @V}, - * it becomes a prompt template variable. Its value will be injected into prompt templates defined - * via @{@link UserMessage}, @{@link SystemMessage}. - *

- * Example: - * - *

- * {@code @UserMessage("Hello, my name is {{name}}. I am {{age}} years old.")}
- * String chat(@V("name") String name, @V("age") int age);
- * 
- *

- * Example: - * - *

- * {@code @UserMessage("Hello, my name is {{name}}. I am {{age}} years old.")}
- * String chat(@V String name, @V int age);
- * 
- *

- * - * @see UserMessage - * @see SystemMessage - */ -@Documented -@Retention(RUNTIME) -@Target(PARAMETER) -public @interface V { - - /** - * Name of a variable (placeholder) in a prompt template. - */ - String value(); -} diff --git a/pom.xml b/pom.xml index 1b24b2d..881e44b 100644 --- a/pom.xml +++ b/pom.xml @@ -1,20 +1,20 @@ + ~ Copyright 2017 Red Hat, Inc. + ~ + ~ Licensed 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. + --> 4.0.0 @@ -42,9 +42,14 @@ 4.0.0.Final 5.1.3.Final 3.5.3.Final - 0.35.0 + 0.34.0 + + 17 + 17 + ${maven.compiler.target} + ${maven.compiler.source} 17 - ${maven.compiler.release} + SmallRye LLM @@ -74,7 +79,6 @@ smallrye-llm-langchain4j-buildcompatible-extension smallrye-llm-langchain4j-core smallrye-llm-langchain4j-config-mpconfig - mp-ai-api @@ -91,43 +95,15 @@ import pom - - org.jboss.logging - jboss-logging - ${version.org.jboss.logging} - - - dev.langchain4j - langchain4j - ${dev.langchain4j.version} - + - io.smallrye.llm - mp-ai-api - ${project.version} - - - io.smallrye.llm - smallrye-llm-langchain4j-buildcompatible-extension - ${project.version} - - - io.smallrye.llm - smallrye-llm-langchain4j-config-mpconfig - ${project.version} - - - io.smallrye.llm - smallrye-llm-langchain4j-core - ${project.version} - - - io.smallrye.llm - smallrye-llm-langchain4j-portable-extension - ${project.version} + io.smallrye.testing + smallrye-testing-bom + ${version.smallrye.testing} + import + pom - jakarta.enterprise jakarta.enterprise.cdi-api @@ -140,49 +116,44 @@ ${version.weld} runtime + + org.jboss.weld + weld-junit5 + ${weld-junit5.version} + test + org.jboss.weld.se weld-se-core ${version.weld} runtime - - - - io.smallrye.testing - smallrye-testing-bom - ${version.smallrye.testing} - import - pom - - org.jboss.weld - weld-junit5 - ${weld-junit5.version} - test + org.jboss.logging + jboss-logging + ${version.org.jboss.logging} - io.smallrye.config - smallrye-config - 3.8.1 - test + dev.langchain4j + langchain4j + ${dev.langchain4j.version} - - - - org.apache.maven.plugins - maven-compiler-plugin - + + + + org.apache.maven.plugins + maven-compiler-plugin + - - org.apache.maven.plugins - maven-surefire-plugin - + + org.apache.maven.plugins + maven-surefire-plugin + - + diff --git a/smallrye-llm-langchain4j-buildcompatible-extension/pom.xml b/smallrye-llm-langchain4j-buildcompatible-extension/pom.xml index 33a17bb..bb24078 100644 --- a/smallrye-llm-langchain4j-buildcompatible-extension/pom.xml +++ b/smallrye-llm-langchain4j-buildcompatible-extension/pom.xml @@ -15,6 +15,7 @@ org.jacoco jacoco-maven-plugin + 0.8.12 @@ -62,17 +63,20 @@ io.smallrye.llm smallrye-llm-langchain4j-core + ${project.version} io.smallrye.llm smallrye-llm-langchain4j-config-mpconfig + ${project.version} test io.smallrye.config smallrye-config + 3.8.1 test diff --git a/smallrye-llm-langchain4j-buildcompatible-extension/src/main/java/io/smallrye/llm/aiservice/Langchain4JAIServiceBuildCompatibleExtension.java b/smallrye-llm-langchain4j-buildcompatible-extension/src/main/java/io/smallrye/llm/aiservice/Langchain4JAIServiceBuildCompatibleExtension.java index 24c6d90..2cdbeb2 100644 --- a/smallrye-llm-langchain4j-buildcompatible-extension/src/main/java/io/smallrye/llm/aiservice/Langchain4JAIServiceBuildCompatibleExtension.java +++ b/smallrye-llm-langchain4j-buildcompatible-extension/src/main/java/io/smallrye/llm/aiservice/Langchain4JAIServiceBuildCompatibleExtension.java @@ -20,9 +20,10 @@ import jakarta.enterprise.lang.model.types.ClassType; import jakarta.inject.Named; -import org.eclipse.microprofile.ai.llm.RegisterAIService; import org.jboss.logging.Logger; +import io.smallrye.llm.spi.RegisterAIService; + public class Langchain4JAIServiceBuildCompatibleExtension implements BuildCompatibleExtension { private static final Logger LOGGER = Logger.getLogger(Langchain4JAIServiceBuildCompatibleExtension.class); private static final Set> detectedAIServicesDeclaredInterfaces = new HashSet<>(); diff --git a/smallrye-llm-langchain4j-buildcompatible-extension/src/test/java/io/smallrye/llm/core/MyDummyAIService.java b/smallrye-llm-langchain4j-buildcompatible-extension/src/test/java/io/smallrye/llm/core/MyDummyAIService.java index 5d656c1..fb87b1f 100644 --- a/smallrye-llm-langchain4j-buildcompatible-extension/src/test/java/io/smallrye/llm/core/MyDummyAIService.java +++ b/smallrye-llm-langchain4j-buildcompatible-extension/src/test/java/io/smallrye/llm/core/MyDummyAIService.java @@ -1,9 +1,9 @@ package io.smallrye.llm.core; -import org.eclipse.microprofile.ai.llm.RegisterAIService; -import org.eclipse.microprofile.ai.llm.SystemMessage; -import org.eclipse.microprofile.ai.llm.UserMessage; -import org.eclipse.microprofile.ai.llm.V; +import dev.langchain4j.service.SystemMessage; +import dev.langchain4j.service.UserMessage; +import dev.langchain4j.service.V; +import io.smallrye.llm.spi.RegisterAIService; @SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService diff --git a/smallrye-llm-langchain4j-buildcompatible-extension/src/test/java/io/smallrye/llm/core/MyDummyApplicationScopedAIService.java b/smallrye-llm-langchain4j-buildcompatible-extension/src/test/java/io/smallrye/llm/core/MyDummyApplicationScopedAIService.java index c86cf42..81deb7e 100644 --- a/smallrye-llm-langchain4j-buildcompatible-extension/src/test/java/io/smallrye/llm/core/MyDummyApplicationScopedAIService.java +++ b/smallrye-llm-langchain4j-buildcompatible-extension/src/test/java/io/smallrye/llm/core/MyDummyApplicationScopedAIService.java @@ -2,7 +2,7 @@ import jakarta.enterprise.context.ApplicationScoped; -import org.eclipse.microprofile.ai.llm.RegisterAIService; +import io.smallrye.llm.spi.RegisterAIService; @SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService(scope = ApplicationScoped.class) diff --git a/smallrye-llm-langchain4j-config-mpconfig/pom.xml b/smallrye-llm-langchain4j-config-mpconfig/pom.xml index 9c60d2c..d80a581 100644 --- a/smallrye-llm-langchain4j-config-mpconfig/pom.xml +++ b/smallrye-llm-langchain4j-config-mpconfig/pom.xml @@ -14,6 +14,7 @@ io.smallrye.config smallrye-config + 3.8.1 test @@ -24,6 +25,7 @@ io.smallrye.llm smallrye-llm-langchain4j-core + ${project.version} diff --git a/smallrye-llm-langchain4j-core/pom.xml b/smallrye-llm-langchain4j-core/pom.xml index aac899e..aee9cb2 100644 --- a/smallrye-llm-langchain4j-core/pom.xml +++ b/smallrye-llm-langchain4j-core/pom.xml @@ -11,10 +11,6 @@ SmallRye LLM: LangChain4j Core - - io.smallrye.llm - mp-ai-api - org.jboss.logging jboss-logging diff --git a/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/aiservice/CommonAIServiceCreator.java b/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/aiservice/CommonAIServiceCreator.java index a2a4faf..35546d9 100644 --- a/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/aiservice/CommonAIServiceCreator.java +++ b/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/aiservice/CommonAIServiceCreator.java @@ -7,13 +7,13 @@ import jakarta.enterprise.inject.Instance; import jakarta.enterprise.inject.literal.NamedLiteral; -import org.eclipse.microprofile.ai.llm.RegisterAIService; import org.jboss.logging.Logger; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.rag.content.retriever.ContentRetriever; import dev.langchain4j.service.AiServices; import io.smallrye.llm.core.langchain4j.core.config.spi.ChatMemoryFactoryProvider; +import io.smallrye.llm.spi.RegisterAIService; public class CommonAIServiceCreator { diff --git a/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeAiServiceTokenStream.java b/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeAiServiceTokenStream.java deleted file mode 100644 index 775d9dc..0000000 --- a/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeAiServiceTokenStream.java +++ /dev/null @@ -1,89 +0,0 @@ -package io.smallrye.llm.core.langchain4j.services; - -import java.util.function.Consumer; - -import org.eclipse.microprofile.ai.llm.TokenStream; - -/** - * @author Buhake Sindi - * @since 10 October 2024 - */ -public class SmallRyeAiServiceTokenStream implements TokenStream { - - private dev.langchain4j.service.TokenStream delegateTokenStream; - - /** - * @param delegateTokenStream - */ - public SmallRyeAiServiceTokenStream(dev.langchain4j.service.TokenStream delegateTokenStream) { - super(); - this.delegateTokenStream = delegateTokenStream; - } - - // /* (non-Javadoc) - // * @see io.smallrye.llm.service.TokenStream#onRetrieved(java.util.function.Consumer) - // */ - // @Override - // public TokenStream onRetrieved(Consumer> contentHandler) { - // // TODO Auto-generated method stub - // delegateTokenStream.onRetrieved(contentHandler); - // return this; - // } - - /* - * (non-Javadoc) - * - * @see io.smallrye.llm.service.TokenStream#onNext(java.util.function.Consumer) - */ - @Override - public TokenStream onNext(Consumer tokenHandler) { - // TODO Auto-generated method stub - delegateTokenStream.onNext(tokenHandler); - return this; - } - - // /* (non-Javadoc) - // * @see io.smallrye.llm.service.TokenStream#onComplete(java.util.function.Consumer) - // */ - // @Override - // public TokenStream onComplete(Consumer> completionHandler) { - // // TODO Auto-generated method stub - // delegateTokenStream.onComplete(completionHandler); - // return this; - // } - - /* - * (non-Javadoc) - * - * @see io.smallrye.llm.service.TokenStream#onError(java.util.function.Consumer) - */ - @Override - public TokenStream onError(Consumer errorHandler) { - // TODO Auto-generated method stub - delegateTokenStream.onError(errorHandler); - return this; - } - - /* - * (non-Javadoc) - * - * @see io.smallrye.llm.service.TokenStream#ignoreErrors() - */ - @Override - public TokenStream ignoreErrors() { - // TODO Auto-generated method stub - delegateTokenStream.ignoreErrors(); - return this; - } - - /* - * (non-Javadoc) - * - * @see io.smallrye.llm.service.TokenStream#start() - */ - @Override - public void start() { - // TODO Auto-generated method stub - delegateTokenStream.start(); - } -} diff --git a/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeLang4JAiServices.java b/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeLang4JAiServices.java deleted file mode 100644 index b4296c2..0000000 --- a/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeLang4JAiServices.java +++ /dev/null @@ -1,612 +0,0 @@ -package io.smallrye.llm.core.langchain4j.services; - -import static dev.langchain4j.exception.IllegalConfigurationException.illegalConfiguration; -import static dev.langchain4j.internal.Exceptions.illegalArgument; -import static dev.langchain4j.internal.Exceptions.runtime; -import static dev.langchain4j.internal.Utils.isNotNullOrBlank; -import static dev.langchain4j.model.chat.Capability.RESPONSE_FORMAT_JSON_SCHEMA; -import static dev.langchain4j.model.chat.request.ResponseFormatType.JSON; -import static dev.langchain4j.service.TypeUtils.typeHasRawClass; -import static dev.langchain4j.service.output.JsonSchemas.jsonSchemaFrom; -import static dev.langchain4j.spi.ServiceHelper.loadFactories; - -import java.io.InputStream; -import java.lang.reflect.Array; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; -import java.lang.reflect.Proxy; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Scanner; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import org.eclipse.microprofile.ai.llm.MemoryId; -import org.eclipse.microprofile.ai.llm.Moderate; -import org.eclipse.microprofile.ai.llm.StructuredPrompt; -import org.eclipse.microprofile.ai.llm.TokenStream; -import org.eclipse.microprofile.ai.llm.TokenStreamAdapter; -import org.eclipse.microprofile.ai.llm.Tool; -import org.eclipse.microprofile.ai.llm.UserName; -import org.eclipse.microprofile.ai.llm.V; -import org.jboss.logging.Logger; - -import dev.langchain4j.agent.tool.ToolExecutionRequest; -import dev.langchain4j.agent.tool.ToolSpecification; -import dev.langchain4j.data.message.AiMessage; -import dev.langchain4j.data.message.ChatMessage; -import dev.langchain4j.data.message.SystemMessage; -import dev.langchain4j.data.message.ToolExecutionResultMessage; -import dev.langchain4j.data.message.UserMessage; -import dev.langchain4j.memory.ChatMemory; -import dev.langchain4j.model.chat.request.ChatRequest; -import dev.langchain4j.model.chat.request.ResponseFormat; -import dev.langchain4j.model.chat.request.json.JsonSchema; -import dev.langchain4j.model.chat.response.ChatResponse; -import dev.langchain4j.model.input.Prompt; -import dev.langchain4j.model.input.PromptTemplate; -import dev.langchain4j.model.input.structured.StructuredPromptProcessor; -import dev.langchain4j.model.moderation.Moderation; -import dev.langchain4j.model.output.Response; -import dev.langchain4j.model.output.TokenUsage; -import dev.langchain4j.rag.AugmentationRequest; -import dev.langchain4j.rag.AugmentationResult; -import dev.langchain4j.rag.query.Metadata; -import dev.langchain4j.service.AiServiceContext; -import dev.langchain4j.service.AiServiceTokenStream; -import dev.langchain4j.service.AiServices; -import dev.langchain4j.service.Result; -import dev.langchain4j.service.TypeUtils; -import dev.langchain4j.service.output.ServiceOutputParser; -import dev.langchain4j.service.tool.DefaultToolExecutor; -import dev.langchain4j.service.tool.ToolExecution; -import dev.langchain4j.service.tool.ToolExecutor; -import dev.langchain4j.service.tool.ToolProviderRequest; -import dev.langchain4j.service.tool.ToolProviderResult; - -/** - * @author Buhake Sindi - * @since 10 October 2024 - */ -public class SmallRyeLang4JAiServices extends AiServices { - - private static final Logger LOGGER = Logger.getLogger(SmallRyeLang4JAiServices.class); - - private final ServiceOutputParser serviceOutputParser = new ServiceOutputParser(); - private final Collection tokenStreamAdapters = loadFactories(TokenStreamAdapter.class); - private static final int MAX_SEQUENTIAL_TOOL_EXECUTIONS = 10; - - /** - * @param context - */ - public SmallRyeLang4JAiServices(AiServiceContext context) { - super(context); - //TODO Auto-generated constructor stub - } - - /* - * (non-Javadoc) - * - * @see dev.langchain4j.service.AiServices#tools(java.util.List) - */ - @Override - public AiServices tools(List objectsWithTools) { - // TODO Auto-generated method stub - if (objectsWithTools != null) { - if (context.toolSpecifications == null) { - context.toolSpecifications = new ArrayList<>(); - } - if (context.toolExecutors == null) { - context.toolExecutors = new HashMap<>(); - } - - for (Object objectWithTool : objectsWithTools) { - if (objectWithTool instanceof Class) { - throw illegalConfiguration("Tool '%s' must be an object, not a class", objectWithTool); - } - - for (Method method : objectWithTool.getClass().getDeclaredMethods()) { - if (method.isAnnotationPresent(Tool.class)) { - ToolSpecification toolSpecification = ToolSpecifications.toolSpecificationFrom(method); - context.toolSpecifications.add(toolSpecification); - context.toolExecutors.put(toolSpecification.name(), new DefaultToolExecutor(objectWithTool, method)); - } - } - } - - return super.tools(objectsWithTools); - } - - return this; - } - - @SuppressWarnings("unchecked") - @Override - public T build() { - // TODO Auto-generated method stub - performBasicValidation(); - - for (Method method : context.aiServiceClass.getMethods()) { - if (method.isAnnotationPresent(Moderate.class) && context.moderationModel == null) { - throw illegalConfiguration("The @Moderate annotation is present, but the moderationModel is not set up. " + - "Please ensure a valid moderationModel is configured before using the @Moderate annotation."); - } - if (method.getReturnType() == Result.class || - method.getReturnType() == List.class || - method.getReturnType() == Set.class) { - TypeUtils.validateReturnTypesAreProperlyParametrized(method.getName(), method.getGenericReturnType()); - } - } - - Object proxyInstance = Proxy.newProxyInstance( - context.aiServiceClass.getClassLoader(), - new Class[] { context.aiServiceClass }, - new InvocationHandler() { - - private final ExecutorService executor = Executors.newCachedThreadPool(); - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Exception { - - if (method.getDeclaringClass() == Object.class) { - // methods like equals(), hashCode() and toString() should not be handled by this proxy - return method.invoke(this, args); - } - - validateParameters(method); - - Object memoryId = findMemoryId(method, args).orElse(DEFAULT); - - Optional systemMessage = prepareSystemMessage(memoryId, method, args); - UserMessage userMessage = prepareUserMessage(method, args); - AugmentationResult augmentationResult = null; - if (context.retrievalAugmentor != null) { - List chatMemory = context.hasChatMemory() - ? context.chatMemory(memoryId).messages() - : null; - Metadata metadata = Metadata.from(userMessage, memoryId, chatMemory); - AugmentationRequest augmentationRequest = new AugmentationRequest(userMessage, metadata); - augmentationResult = context.retrievalAugmentor.augment(augmentationRequest); - userMessage = (UserMessage) augmentationResult.chatMessage(); - } - - // TODO give user ability to provide custom OutputParser - Type returnType = method.getGenericReturnType(); - - boolean streaming = returnType == TokenStream.class || canAdaptTokenStreamTo(returnType); - - boolean supportsJsonSchema = supportsJsonSchema(); - Optional jsonSchema = Optional.empty(); - if (supportsJsonSchema && !streaming) { - jsonSchema = jsonSchemaFrom(returnType); - } - - if ((!supportsJsonSchema || !jsonSchema.isPresent()) && !streaming) { - // TODO append after storing in the memory? - userMessage = appendOutputFormatInstructions(returnType, userMessage); - } - - if (context.hasChatMemory()) { - ChatMemory chatMemory = context.chatMemory(memoryId); - systemMessage.ifPresent(chatMemory::add); - chatMemory.add(userMessage); - } - - List messages; - if (context.hasChatMemory()) { - messages = context.chatMemory(memoryId).messages(); - } else { - messages = new ArrayList<>(); - systemMessage.ifPresent(messages::add); - messages.add(userMessage); - } - - Future moderationFuture = triggerModerationIfNeeded(method, messages); - - List toolSpecifications = context.toolSpecifications; - Map toolExecutors = context.toolExecutors; - - if (context.toolProvider != null) { - toolSpecifications = new ArrayList<>(); - toolExecutors = new HashMap<>(); - ToolProviderRequest toolProviderRequest = new ToolProviderRequest(memoryId, userMessage); - ToolProviderResult toolProviderResult = context.toolProvider.provideTools(toolProviderRequest); - if (toolProviderResult != null) { - Map tools = toolProviderResult.tools(); - for (ToolSpecification toolSpecification : tools.keySet()) { - toolSpecifications.add(toolSpecification); - toolExecutors.put(toolSpecification.name(), tools.get(toolSpecification)); - } - } - } - - if (streaming) { - TokenStream tokenStream = new SmallRyeAiServiceTokenStream(new AiServiceTokenStream( - messages, - toolSpecifications, - toolExecutors, - augmentationResult != null ? augmentationResult.contents() : null, - context, - memoryId)); - // TODO moderation - if (returnType == TokenStream.class) { - return tokenStream; - } else { - return adapt(tokenStream, returnType); - } - } - - Response response; - if (supportsJsonSchema && jsonSchema.isPresent()) { - ChatRequest chatRequest = ChatRequest.builder() - .messages(messages) - .toolSpecifications(toolSpecifications) - .responseFormat(ResponseFormat.builder() - .type(JSON) - .jsonSchema(jsonSchema.get()) - .build()) - .build(); - - ChatResponse chatResponse = context.chatModel.chat(chatRequest); - - response = new Response<>( - chatResponse.aiMessage(), - chatResponse.tokenUsage(), - chatResponse.finishReason()); - } else { - // TODO migrate to new API - response = toolSpecifications == null || toolSpecifications.isEmpty() - ? context.chatModel.generate(messages) - : context.chatModel.generate(messages, toolSpecifications); - } - - TokenUsage tokenUsageAccumulator = response.tokenUsage(); - - verifyModerationIfNeeded(moderationFuture); - - int executionsLeft = MAX_SEQUENTIAL_TOOL_EXECUTIONS; - List toolExecutions = new ArrayList<>(); - while (true) { - - if (executionsLeft-- == 0) { - throw runtime("Something is wrong, exceeded %s sequential tool executions", - MAX_SEQUENTIAL_TOOL_EXECUTIONS); - } - - AiMessage aiMessage = response.content(); - - if (context.hasChatMemory()) { - context.chatMemory(memoryId).add(aiMessage); - } else { - messages = new ArrayList<>(messages); - messages.add(aiMessage); - } - - if (!aiMessage.hasToolExecutionRequests()) { - break; - } - - for (ToolExecutionRequest toolExecutionRequest : aiMessage.toolExecutionRequests()) { - ToolExecutor toolExecutor = toolExecutors.get(toolExecutionRequest.name()); - String toolExecutionResult = toolExecutor.execute(toolExecutionRequest, memoryId); - toolExecutions.add(ToolExecution.builder() - .request(toolExecutionRequest) - .result(toolExecutionResult) - .build()); - ToolExecutionResultMessage toolExecutionResultMessage = ToolExecutionResultMessage.from( - toolExecutionRequest, - toolExecutionResult); - if (context.hasChatMemory()) { - context.chatMemory(memoryId).add(toolExecutionResultMessage); - } else { - messages.add(toolExecutionResultMessage); - } - } - - if (context.hasChatMemory()) { - messages = context.chatMemory(memoryId).messages(); - } - - response = context.chatModel.generate(messages, toolSpecifications); - tokenUsageAccumulator = TokenUsage.sum(tokenUsageAccumulator, response.tokenUsage()); - } - - response = Response.from(response.content(), tokenUsageAccumulator, response.finishReason()); - - Object parsedResponse = serviceOutputParser.parse(response, returnType); - if (typeHasRawClass(returnType, Result.class)) { - return Result.builder() - .content(parsedResponse) - .tokenUsage(tokenUsageAccumulator) - .sources(augmentationResult == null ? null : augmentationResult.contents()) - .finishReason(response.finishReason()) - .toolExecutions(toolExecutions) - .build(); - } else { - return parsedResponse; - } - } - - private boolean canAdaptTokenStreamTo(Type returnType) { - for (TokenStreamAdapter tokenStreamAdapter : tokenStreamAdapters) { - if (tokenStreamAdapter.canAdaptTokenStreamTo(returnType)) { - return true; - } - } - return false; - } - - private Object adapt(TokenStream tokenStream, Type returnType) { - for (TokenStreamAdapter tokenStreamAdapter : tokenStreamAdapters) { - if (tokenStreamAdapter.canAdaptTokenStreamTo(returnType)) { - return tokenStreamAdapter.adapt(tokenStream); - } - } - throw new IllegalStateException("Can't find suitable TokenStreamAdapter"); - } - - private boolean supportsJsonSchema() { - return context.chatModel != null - && context.chatModel.supportedCapabilities().contains(RESPONSE_FORMAT_JSON_SCHEMA); - } - - private UserMessage appendOutputFormatInstructions(Type returnType, UserMessage userMessage) { - String outputFormatInstructions = serviceOutputParser.outputFormatInstructions(returnType); - String text = userMessage.singleText() + outputFormatInstructions; - if (isNotNullOrBlank(userMessage.name())) { - userMessage = UserMessage.from(userMessage.name(), text); - } else { - userMessage = UserMessage.from(text); - } - return userMessage; - } - - private Future triggerModerationIfNeeded(Method method, List messages) { - if (method.isAnnotationPresent(Moderate.class)) { - return executor.submit(() -> { - List messagesToModerate = removeToolMessages(messages); - return context.moderationModel.moderate(messagesToModerate).content(); - }); - } - return null; - } - }); - - return (T) proxyInstance; - } - - static void validateParameters(Method method) { - Parameter[] parameters = method.getParameters(); - if (parameters == null || parameters.length < 2) { - return; - } - - for (Parameter parameter : parameters) { - V v = parameter.getAnnotation(V.class); - org.eclipse.microprofile.ai.llm.UserMessage userMessage = parameter - .getAnnotation(org.eclipse.microprofile.ai.llm.UserMessage.class); - MemoryId memoryId = parameter.getAnnotation(MemoryId.class); - UserName userName = parameter.getAnnotation(UserName.class); - if (v == null && userMessage == null && memoryId == null && userName == null) { - throw illegalConfiguration( - "Parameter '%s' of method '%s' should be annotated with @V or @UserMessage " + - "or @UserName or @MemoryId", - parameter.getName(), method.getName()); - } - } - } - - private static Optional findMemoryId(Method method, Object[] args) { - Parameter[] parameters = method.getParameters(); - for (int i = 0; i < parameters.length; i++) { - if (parameters[i].isAnnotationPresent(MemoryId.class)) { - Object memoryId = args[i]; - if (memoryId == null) { - throw illegalArgument( - "The value of parameter '%s' annotated with @MemoryId in method '%s' must not be null", - parameters[i].getName(), method.getName()); - } - return Optional.of(memoryId); - } - } - return Optional.empty(); - } - - private Optional prepareSystemMessage(Object memoryId, Method method, Object[] args) { - return findSystemMessageTemplate(memoryId, method) - .map(systemMessageTemplate -> PromptTemplate.from(systemMessageTemplate) - .apply(findTemplateVariables(systemMessageTemplate, method, args)) - .toSystemMessage()); - } - - private Optional findSystemMessageTemplate(Object memoryId, Method method) { - org.eclipse.microprofile.ai.llm.SystemMessage annotation = method - .getAnnotation(org.eclipse.microprofile.ai.llm.SystemMessage.class); - if (annotation != null) { - return Optional - .of(getTemplate(method, "System", annotation.fromResource(), annotation.value(), annotation.delimiter())); - } - - return context.systemMessageProvider.apply(memoryId); - } - - private static Map findTemplateVariables(String template, Method method, Object[] args) { - Parameter[] parameters = method.getParameters(); - - Map variables = new HashMap<>(); - for (int i = 0; i < parameters.length; i++) { - V annotation = parameters[i].getAnnotation(V.class); - if (annotation != null) { - String variableName = annotation.value(); - Object variableValue = args[i]; - variables.put(variableName, variableValue); - } - } - - if (template.contains("{{it}}") && !variables.containsKey("it")) { - String itValue = getValueOfVariableIt(parameters, args); - variables.put("it", itValue); - } - - return variables; - } - - private static String getValueOfVariableIt(Parameter[] parameters, Object[] args) { - if (parameters.length == 1) { - Parameter parameter = parameters[0]; - if (!parameter.isAnnotationPresent(MemoryId.class) - && !parameter.isAnnotationPresent(org.eclipse.microprofile.ai.llm.UserMessage.class) - && !parameter.isAnnotationPresent(UserName.class) - && (!parameter.isAnnotationPresent(V.class) || isAnnotatedWithIt(parameter))) { - return toString(args[0]); - } - } - - for (int i = 0; i < parameters.length; i++) { - if (isAnnotatedWithIt(parameters[i])) { - return toString(args[i]); - } - } - - throw illegalConfiguration("Error: cannot find the value of the prompt template variable \"{{it}}\"."); - } - - private static boolean isAnnotatedWithIt(Parameter parameter) { - V annotation = parameter.getAnnotation(V.class); - return annotation != null && "it".equals(annotation.value()); - } - - private static UserMessage prepareUserMessage(Method method, Object[] args) { - - String template = getUserMessageTemplate(method, args); - Map variables = findTemplateVariables(template, method, args); - - Prompt prompt = PromptTemplate.from(template).apply(variables); - - Optional maybeUserName = findUserName(method.getParameters(), args); - return maybeUserName.map(userName -> UserMessage.from(userName, prompt.text())) - .orElseGet(prompt::toUserMessage); - } - - private static String getUserMessageTemplate(Method method, Object[] args) { - - Optional templateFromMethodAnnotation = findUserMessageTemplateFromMethodAnnotation(method); - Optional templateFromParameterAnnotation = findUserMessageTemplateFromAnnotatedParameter(method.getParameters(), - args); - - if (templateFromMethodAnnotation.isPresent() && templateFromParameterAnnotation.isPresent()) { - throw illegalConfiguration( - "Error: The method '%s' has multiple @UserMessage annotations. Please use only one.", - method.getName()); - } - - if (templateFromMethodAnnotation.isPresent()) { - return templateFromMethodAnnotation.get(); - } - if (templateFromParameterAnnotation.isPresent()) { - return templateFromParameterAnnotation.get(); - } - - Optional templateFromTheOnlyArgument = findUserMessageTemplateFromTheOnlyArgument(method.getParameters(), args); - if (templateFromTheOnlyArgument.isPresent()) { - return templateFromTheOnlyArgument.get(); - } - - throw illegalConfiguration("Error: The method '%s' does not have a user message defined.", method.getName()); - } - - private static Optional findUserMessageTemplateFromMethodAnnotation(Method method) { - return Optional.ofNullable(method.getAnnotation(org.eclipse.microprofile.ai.llm.UserMessage.class)) - .map(a -> getTemplate(method, "User", a.fromResource(), a.value(), a.delimiter())); - } - - private static Optional findUserMessageTemplateFromAnnotatedParameter(Parameter[] parameters, Object[] args) { - for (int i = 0; i < parameters.length; i++) { - if (parameters[i].isAnnotationPresent(org.eclipse.microprofile.ai.llm.UserMessage.class)) { - return Optional.of(toString(args[i])); - } - } - return Optional.empty(); - } - - private static Optional findUserMessageTemplateFromTheOnlyArgument(Parameter[] parameters, Object[] args) { - if (parameters != null && parameters.length == 1 && parameters[0].getAnnotations().length == 0) { - return Optional.of(toString(args[0])); - } - return Optional.empty(); - } - - private static Optional findUserName(Parameter[] parameters, Object[] args) { - for (int i = 0; i < parameters.length; i++) { - if (parameters[i].isAnnotationPresent(UserName.class)) { - return Optional.of(args[i].toString()); - } - } - return Optional.empty(); - } - - private static String getTemplate(Method method, String type, String resource, String[] value, String delimiter) { - String messageTemplate; - if (!resource.trim().isEmpty()) { - messageTemplate = getResourceText(method.getDeclaringClass(), resource); - if (messageTemplate == null) { - throw illegalConfiguration("@%sMessage's resource '%s' not found", type, resource); - } - } else { - messageTemplate = String.join(delimiter, value); - } - if (messageTemplate.trim().isEmpty()) { - throw illegalConfiguration("@%sMessage's template cannot be empty", type); - } - return messageTemplate; - } - - private static String getResourceText(Class clazz, String resource) { - InputStream inputStream = clazz.getResourceAsStream(resource); - if (inputStream == null) { - inputStream = clazz.getResourceAsStream("/" + resource); - } - return getText(inputStream); - } - - private static String getText(InputStream inputStream) { - if (inputStream == null) { - return null; - } - try (Scanner scanner = new Scanner(inputStream); - Scanner s = scanner.useDelimiter("\\A")) { - return s.hasNext() ? s.next() : ""; - } - } - - private static String toString(Object arg) { - if (arg.getClass().isArray()) { - return arrayToString(arg); - } else if (arg.getClass().isAnnotationPresent(StructuredPrompt.class)) { - return StructuredPromptProcessor.toPrompt(arg).text(); - } else { - return arg.toString(); - } - } - - private static String arrayToString(Object arg) { - StringBuilder sb = new StringBuilder("["); - int length = Array.getLength(arg); - for (int i = 0; i < length; i++) { - sb.append(toString(Array.get(arg, i))); - if (i < length - 1) { - sb.append(", "); - } - } - sb.append("]"); - return sb.toString(); - } -} diff --git a/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeLang4JchainAiServicesFactory.java b/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeLang4JchainAiServicesFactory.java deleted file mode 100644 index f74fe16..0000000 --- a/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeLang4JchainAiServicesFactory.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.smallrye.llm.core.langchain4j.services; - -import dev.langchain4j.service.AiServiceContext; -import dev.langchain4j.service.AiServices; -import dev.langchain4j.spi.services.AiServicesFactory; - -/** - * @author Buhake Sindi - * @since 10 October 2024 - */ -public class SmallRyeLang4JchainAiServicesFactory implements AiServicesFactory { - - /* - * (non-Javadoc) - * - * @see dev.langchain4j.spi.services.AiServicesFactory#create(dev.langchain4j.service.AiServiceContext) - */ - @Override - public AiServices create(AiServiceContext context) { - // TODO Auto-generated method stub - return new SmallRyeLang4JAiServices(context); - } -} diff --git a/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeStructuredPromptFactory.java b/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeStructuredPromptFactory.java deleted file mode 100644 index 3b47182..0000000 --- a/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/SmallRyeStructuredPromptFactory.java +++ /dev/null @@ -1,82 +0,0 @@ -package io.smallrye.llm.core.langchain4j.services; - -import java.util.Map; - -import org.eclipse.microprofile.ai.llm.StructuredPrompt; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.ToNumberPolicy; -import com.google.gson.reflect.TypeToken; - -import dev.langchain4j.internal.ValidationUtils; -import dev.langchain4j.model.input.Prompt; -import dev.langchain4j.model.input.PromptTemplate; -import dev.langchain4j.spi.prompt.structured.StructuredPromptFactory; - -/** - * @author Buhake Sindi - * @since 10 October 2024 - */ -public class SmallRyeStructuredPromptFactory implements StructuredPromptFactory { - private static final Gson GSON = new GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create(); - - /* - * (non-Javadoc) - * - * @see dev.langchain4j.spi.prompt.structured.StructuredPromptFactory#toPrompt(java.lang.Object) - */ - - @Override - public Prompt toPrompt(Object structuredPrompt) { - // TODO Auto-generated method stub - StructuredPrompt annotation = validateStructuredPrompt(structuredPrompt); - - String promptTemplateString = join(annotation); - PromptTemplate promptTemplate = PromptTemplate.from(promptTemplateString); - - Map variables = extractVariables(structuredPrompt); - - return promptTemplate.apply(variables); - } - - /** - * Extracts the variables from the structured prompt. - * - * @param structuredPrompt The structured prompt. - * @return The variables map. - */ - private static Map extractVariables(Object structuredPrompt) { - String json = GSON.toJson(structuredPrompt); - TypeToken> mapType = new TypeToken>() { - }; - return GSON.fromJson(json, mapType); - } - - /** - * Validates that the given object is annotated with {@link StructuredPrompt}. - * - * @param structuredPrompt the object to validate. - * @return the annotation. - */ - private static StructuredPrompt validateStructuredPrompt(Object structuredPrompt) { - ValidationUtils.ensureNotNull(structuredPrompt, "structuredPrompt"); - - Class cls = structuredPrompt.getClass(); - - return ValidationUtils.ensureNotNull( - cls.getAnnotation(StructuredPrompt.class), - "%s should be annotated with @StructuredPrompt to be used as a structured prompt", - cls.getName()); - } - - /** - * Joins the lines of the prompt template. - * - * @param structuredPrompt the structured prompt. - * @return the joined prompt template. - */ - private static String join(StructuredPrompt structuredPrompt) { - return String.join(structuredPrompt.delimiter(), structuredPrompt.value()); - } -} diff --git a/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/ToolSpecifications.java b/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/ToolSpecifications.java deleted file mode 100644 index ec3d2a9..0000000 --- a/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/core/langchain4j/services/ToolSpecifications.java +++ /dev/null @@ -1,279 +0,0 @@ -package io.smallrye.llm.core.langchain4j.services; - -import static dev.langchain4j.agent.tool.JsonSchemaProperty.ARRAY; -import static dev.langchain4j.agent.tool.JsonSchemaProperty.BOOLEAN; -import static dev.langchain4j.agent.tool.JsonSchemaProperty.INTEGER; -import static dev.langchain4j.agent.tool.JsonSchemaProperty.NUMBER; -import static dev.langchain4j.agent.tool.JsonSchemaProperty.OBJECT; -import static dev.langchain4j.agent.tool.JsonSchemaProperty.STRING; -import static dev.langchain4j.agent.tool.JsonSchemaProperty.description; -import static dev.langchain4j.agent.tool.JsonSchemaProperty.enums; -import static dev.langchain4j.agent.tool.JsonSchemaProperty.from; -import static dev.langchain4j.agent.tool.JsonSchemaProperty.items; -import static dev.langchain4j.agent.tool.JsonSchemaProperty.objectItems; -import static dev.langchain4j.internal.TypeUtils.isJsonBoolean; -import static dev.langchain4j.internal.TypeUtils.isJsonInteger; -import static dev.langchain4j.internal.TypeUtils.isJsonNumber; -import static dev.langchain4j.internal.Utils.isNullOrBlank; -import static java.lang.String.format; -import static java.util.Arrays.stream; -import static java.util.stream.Collectors.toList; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; - -import org.eclipse.microprofile.ai.llm.P; -import org.eclipse.microprofile.ai.llm.Tool; -import org.eclipse.microprofile.ai.llm.ToolMemoryId; - -import dev.langchain4j.agent.tool.JsonSchemaProperty; -import dev.langchain4j.agent.tool.ToolSpecification; -import dev.langchain4j.model.output.structured.Description; - -/** - * @author Buhake Sindi - * @since 10 October 2024 - */ -public class ToolSpecifications { - - private ToolSpecifications() { - } - - /** - * Returns {@link ToolSpecification}s for all methods annotated with @{@link Tool} within the specified class. - * - * @param classWithTools the class. - * @return the {@link ToolSpecification}s. - */ - public static List toolSpecificationsFrom(Class classWithTools) { - List toolSpecifications = stream(classWithTools.getDeclaredMethods()) - .filter(method -> method.isAnnotationPresent(Tool.class)) - .map(ToolSpecifications::toolSpecificationFrom) - .collect(toList()); - validateSpecifications(toolSpecifications); - return toolSpecifications; - } - - /** - * Returns {@link ToolSpecification}s for all methods annotated with @{@link Tool} - * within the class of the specified object. - * - * @param objectWithTools the object. - * @return the {@link ToolSpecification}s. - */ - public static List toolSpecificationsFrom(Object objectWithTools) { - return toolSpecificationsFrom(objectWithTools.getClass()); - } - - /** - * Validates all the {@link ToolSpecification}s. The validation checks for duplicate method names. - * Throws {@link IllegalArgumentException} if validation fails - * - * @param toolSpecifications list of ToolSpecification to be validated. - */ - public static void validateSpecifications(List toolSpecifications) throws IllegalArgumentException { - - // Checks for duplicates methods - Set names = new HashSet<>(); - for (ToolSpecification toolSpecification : toolSpecifications) { - if (!names.add(toolSpecification.name())) { - throw new IllegalArgumentException( - format("Tool names must be unique. The tool '%s' appears several times", toolSpecification.name())); - } - } - } - - /** - * Returns the {@link ToolSpecification} for the given method annotated with @{@link Tool}. - * - * @param method the method. - * @return the {@link ToolSpecification}. - */ - public static ToolSpecification toolSpecificationFrom(Method method) { - Tool annotation = method.getAnnotation(Tool.class); - - String name = isNullOrBlank(annotation.name()) ? method.getName() : annotation.name(); - String description = String.join("\n", annotation.value()); // TODO provide null instead of "" ? - - ToolSpecification.Builder builder = ToolSpecification.builder() - .name(name) - .description(description); - - for (Parameter parameter : method.getParameters()) { - if (parameter.isAnnotationPresent(ToolMemoryId.class)) { - continue; - } - - boolean required = Optional.ofNullable(parameter.getAnnotation(P.class)) - .map(P::required) - .orElse(true); - - if (required) { - builder.addParameter(parameter.getName(), toJsonSchemaProperties(parameter)); - } else { - builder.addOptionalParameter(parameter.getName(), toJsonSchemaProperties(parameter)); - } - } - - return builder.build(); - } - - /** - * Convert a {@link Parameter} to a {@link JsonSchemaProperty}. - * - * @param parameter the parameter. - * @return the {@link JsonSchemaProperty}. - */ - static Iterable toJsonSchemaProperties(Parameter parameter) { - - Class type = parameter.getType(); - - P annotation = parameter.getAnnotation(P.class); - JsonSchemaProperty description = annotation == null ? null : description(annotation.value()); - - Iterable simpleType = toJsonSchemaProperties(type, description); - - if (simpleType != null) { - return simpleType; - } - - if (Collection.class.isAssignableFrom(type)) { - return removeNulls(ARRAY, arrayTypeFrom(parameter.getParameterizedType()), description); - } - - return removeNulls(OBJECT, schema(type), description); - } - - static JsonSchemaProperty schema(Class structured) { - return schema(structured, new HashMap<>()); - } - - private static JsonSchemaProperty schema(Class structured, HashMap, JsonSchemaProperty> visited) { - if (visited.containsKey(structured)) { - return visited.get(structured); - } - - // Mark the class as visited by inserting it in the visited map with a null value initially. - visited.put(structured, null); - Map properties = new HashMap<>(); - for (Field field : structured.getDeclaredFields()) { - String name = field.getName(); - if (name.equals("this$0") || java.lang.reflect.Modifier.isStatic(field.getModifiers())) { - // Skip inner class reference. - continue; - } - Iterable schemaProperties = toJsonSchemaProperties(field, visited); - Map objectMap = new HashMap<>(); - for (JsonSchemaProperty jsonSchemaProperty : schemaProperties) { - objectMap.put(jsonSchemaProperty.key(), jsonSchemaProperty.value()); - } - properties.put(name, objectMap); - } - JsonSchemaProperty jsonSchemaProperty = from("properties", properties); - // Update the visited map with the final JsonSchemaProperty for the current class - visited.put(structured, jsonSchemaProperty); - return jsonSchemaProperty; - } - - private static Iterable toJsonSchemaProperties(Field field, - HashMap, JsonSchemaProperty> visited) { - - Class type = field.getType(); - - Description annotation = field.getAnnotation(Description.class); - JsonSchemaProperty description = annotation == null ? null : description(String.join(" ", annotation.value())); - - Iterable simpleType = toJsonSchemaProperties(type, description); - - if (simpleType != null) { - return simpleType; - } - - if (Collection.class.isAssignableFrom(type)) { - return removeNulls(ARRAY, - arrayTypeFrom((Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]), - description); - } - - return removeNulls(OBJECT, schema(type, visited), description); - } - - private static Iterable toJsonSchemaProperties(Class type, JsonSchemaProperty description) { - - if (type == String.class) { - return removeNulls(STRING, description); - } - - if (isJsonBoolean(type)) { - return removeNulls(BOOLEAN, description); - } - - if (isJsonInteger(type)) { - return removeNulls(INTEGER, description); - } - - if (isJsonNumber(type)) { - return removeNulls(NUMBER, description); - } - - if (type.isArray()) { - return removeNulls(ARRAY, arrayTypeFrom(type.getComponentType()), description); - } - - if (type.isEnum()) { - return removeNulls(STRING, enums((Class) type), description); - } - - return null; - } - - private static JsonSchemaProperty arrayTypeFrom(Type type) { - if (type instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) type; - Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); - if (actualTypeArguments.length == 1) { - return arrayTypeFrom((Class) actualTypeArguments[0]); - } - } - return items(JsonSchemaProperty.OBJECT); - } - - private static JsonSchemaProperty arrayTypeFrom(Class clazz) { - if (clazz == String.class) { - return items(JsonSchemaProperty.STRING); - } - if (isJsonBoolean(clazz)) { - return items(JsonSchemaProperty.BOOLEAN); - } - if (isJsonInteger(clazz)) { - return items(JsonSchemaProperty.INTEGER); - } - if (isJsonNumber(clazz)) { - return items(JsonSchemaProperty.NUMBER); - } - return objectItems(schema(clazz)); - } - - /** - * Remove nulls from the given array. - * - * @param items the array - * @return an iterable of the non-null items. - */ - static Iterable removeNulls(JsonSchemaProperty... items) { - return stream(items) - .filter(Objects::nonNull) - .collect(toList()); - } -} diff --git a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/RegisterAIService.java b/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/spi/RegisterAIService.java similarity index 95% rename from mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/RegisterAIService.java rename to smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/spi/RegisterAIService.java index 2c3f8c5..b48605f 100644 --- a/mp-ai-api/src/main/java/org/eclipse/microprofile/ai/llm/RegisterAIService.java +++ b/smallrye-llm-langchain4j-core/src/main/java/io/smallrye/llm/spi/RegisterAIService.java @@ -1,4 +1,4 @@ -package org.eclipse.microprofile.ai.llm; +package io.smallrye.llm.spi; import static java.lang.annotation.RetentionPolicy.RUNTIME; diff --git a/smallrye-llm-langchain4j-core/src/main/resources/META-INF/services/dev.langchain4j.spi.prompt.structured.StructuredPromptFactory b/smallrye-llm-langchain4j-core/src/main/resources/META-INF/services/dev.langchain4j.spi.prompt.structured.StructuredPromptFactory deleted file mode 100644 index c5471d4..0000000 --- a/smallrye-llm-langchain4j-core/src/main/resources/META-INF/services/dev.langchain4j.spi.prompt.structured.StructuredPromptFactory +++ /dev/null @@ -1 +0,0 @@ -io.smallrye.llm.core.langchain4j.services.SmallRyeStructuredPromptFactory \ No newline at end of file diff --git a/smallrye-llm-langchain4j-core/src/main/resources/META-INF/services/dev.langchain4j.spi.services.AiServicesFactory b/smallrye-llm-langchain4j-core/src/main/resources/META-INF/services/dev.langchain4j.spi.services.AiServicesFactory deleted file mode 100644 index d5e51a5..0000000 --- a/smallrye-llm-langchain4j-core/src/main/resources/META-INF/services/dev.langchain4j.spi.services.AiServicesFactory +++ /dev/null @@ -1 +0,0 @@ -io.smallrye.llm.core.langchain4j.services.SmallRyeLang4JchainAiServicesFactory \ No newline at end of file diff --git a/smallrye-llm-langchain4j-portable-extension/pom.xml b/smallrye-llm-langchain4j-portable-extension/pom.xml index 17c206b..0bbf84d 100644 --- a/smallrye-llm-langchain4j-portable-extension/pom.xml +++ b/smallrye-llm-langchain4j-portable-extension/pom.xml @@ -42,6 +42,7 @@ io.smallrye.config smallrye-config + 3.8.1 test diff --git a/smallrye-llm-langchain4j-portable-extension/src/main/java/io/smallrye/llm/core/langchain4j/portableextension/LangChain4JAIServicePortableExtension.java b/smallrye-llm-langchain4j-portable-extension/src/main/java/io/smallrye/llm/core/langchain4j/portableextension/LangChain4JAIServicePortableExtension.java index 44c8800..304de6c 100644 --- a/smallrye-llm-langchain4j-portable-extension/src/main/java/io/smallrye/llm/core/langchain4j/portableextension/LangChain4JAIServicePortableExtension.java +++ b/smallrye-llm-langchain4j-portable-extension/src/main/java/io/smallrye/llm/core/langchain4j/portableextension/LangChain4JAIServicePortableExtension.java @@ -17,10 +17,10 @@ import jakarta.enterprise.inject.spi.ProcessInjectionPoint; import jakarta.enterprise.inject.spi.WithAnnotations; -import org.eclipse.microprofile.ai.llm.RegisterAIService; import org.jboss.logging.Logger; import io.smallrye.llm.aiservice.CommonAIServiceCreator; +import io.smallrye.llm.spi.RegisterAIService; public class LangChain4JAIServicePortableExtension implements Extension { private static final Logger LOGGER = Logger.getLogger(LangChain4JAIServicePortableExtension.class); diff --git a/smallrye-llm-langchain4j-portable-extension/src/test/java/io/smallrye/llm/core/MyDummyAIService.java b/smallrye-llm-langchain4j-portable-extension/src/test/java/io/smallrye/llm/core/MyDummyAIService.java index 5d656c1..fb87b1f 100644 --- a/smallrye-llm-langchain4j-portable-extension/src/test/java/io/smallrye/llm/core/MyDummyAIService.java +++ b/smallrye-llm-langchain4j-portable-extension/src/test/java/io/smallrye/llm/core/MyDummyAIService.java @@ -1,9 +1,9 @@ package io.smallrye.llm.core; -import org.eclipse.microprofile.ai.llm.RegisterAIService; -import org.eclipse.microprofile.ai.llm.SystemMessage; -import org.eclipse.microprofile.ai.llm.UserMessage; -import org.eclipse.microprofile.ai.llm.V; +import dev.langchain4j.service.SystemMessage; +import dev.langchain4j.service.UserMessage; +import dev.langchain4j.service.V; +import io.smallrye.llm.spi.RegisterAIService; @SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService diff --git a/smallrye-llm-langchain4j-portable-extension/src/test/java/io/smallrye/llm/core/MyDummyApplicationScopedAIService.java b/smallrye-llm-langchain4j-portable-extension/src/test/java/io/smallrye/llm/core/MyDummyApplicationScopedAIService.java index c86cf42..81deb7e 100644 --- a/smallrye-llm-langchain4j-portable-extension/src/test/java/io/smallrye/llm/core/MyDummyApplicationScopedAIService.java +++ b/smallrye-llm-langchain4j-portable-extension/src/test/java/io/smallrye/llm/core/MyDummyApplicationScopedAIService.java @@ -2,7 +2,7 @@ import jakarta.enterprise.context.ApplicationScoped; -import org.eclipse.microprofile.ai.llm.RegisterAIService; +import io.smallrye.llm.spi.RegisterAIService; @SuppressWarnings("CdiManagedBeanInconsistencyInspection") @RegisterAIService(scope = ApplicationScoped.class) From 679e76a6bdec9c0fc39cb024aefea625b83c85c5 Mon Sep 17 00:00:00 2001 From: Emmanuel Hugonnet Date: Thu, 31 Oct 2024 17:55:59 +0100 Subject: [PATCH 2/2] Removing the role as it doesn't exist in smallrye Signed-off-by: Emmanuel Hugonnet --- examples/liberty-car-booking/pom.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/liberty-car-booking/pom.xml b/examples/liberty-car-booking/pom.xml index 89923cd..cb0c9c4 100644 --- a/examples/liberty-car-booking/pom.xml +++ b/examples/liberty-car-booking/pom.xml @@ -14,9 +14,6 @@ Buhake Sindi +2 - - PROJECT LEAD -