From f193c92b314bbd8b15043b2027929d49e3308c57 Mon Sep 17 00:00:00 2001 From: LangChain4j Date: Sun, 14 Jan 2024 11:10:31 +0100 Subject: [PATCH] Enable CI, fix LogLevel NPE (#12) --- .github/workflows/main.yaml | 29 +++++++++++ .github/workflows/release.yml | 2 +- README.md | 7 +-- .../java/dev/ai4j/openai4j/OpenAiClient.java | 6 ++- .../openai4j/completion/CompletionModel.java | 2 +- .../completion/CompletionRequest.java | 4 +- .../chat/ChatCompletionAsyncTest.java | 1 + .../chat/ChatCompletionStreamingTest.java | 48 +++++++++++++++---- .../openai4j/chat/ChatCompletionTest.java | 1 + .../completion/CompletionAsyncTest.java | 1 + .../completion/CompletionStreamingTest.java | 48 +++++++++++++++---- .../openai4j/completion/CompletionTest.java | 1 + .../embedding/EmbeddingsAsyncTest.java | 1 + .../openai4j/embedding/EmbeddingsTest.java | 1 + .../moderation/ModerationAsyncTest.java | 1 + .../openai4j/moderation/ModerationTest.java | 1 + 16 files changed, 125 insertions(+), 29 deletions(-) create mode 100644 .github/workflows/main.yaml diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml new file mode 100644 index 0000000..11c3c78 --- /dev/null +++ b/.github/workflows/main.yaml @@ -0,0 +1,29 @@ +name: Java CI + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + java_build: + strategy: + matrix: + java_version: [ 8, 11, 17, 21 ] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up JDK ${{ matrix.java_version }} + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.java_version }} + distribution: 'temurin' + cache: 'maven' + - name: Build with JDK ${{ matrix.java_version }} + run: mvn -B clean test ${{ matrix.included_modules }} + env: + OPENAI_BASE_URL: 'http://langchain4j.dev:8082/v1' + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dfe57b6..56abce4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: gpg-passphrase: GPG_PASSPHRASE - name: release - run: mvn -B clean deploy -Psign -DskipTests + run: mvn -B clean deploy -Psign env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} diff --git a/README.md b/README.md index 96a21b7..f5c3b99 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ Customizable way: String apiKey = System.getenv("OPENAI_API_KEY"); OpenAiClient client = OpenAiClient.builder() + .baseUrl(baseUrl) .openAiApiKey(apiKey) .organizationId(orgId) .callTimeout(ofSeconds(60)) @@ -91,7 +92,7 @@ Customizable way: ``` CompletionRequest request = CompletionRequest.builder() - .model(TEXT_DAVINCI_003) + .model(GPT_3_5_TURBO_INSTRUCT) .prompt("Write a poem about ChatGPT") .temperature(0.9) ... @@ -115,7 +116,7 @@ Customizable way: ``` CompletionRequest request = CompletionRequest.builder() - .model(TEXT_DAVINCI_003) + .model(GPT_3_5_TURBO_INSTRUCT) .prompt("Write a poem about ChatGPT") .temperature(0.9) ... @@ -143,7 +144,7 @@ Customizable way: ``` CompletionRequest request = CompletionRequest.builder() - .model(TEXT_DAVINCI_003) + .model(GPT_3_5_TURBO_INSTRUCT) .prompt("Write a poem about ChatGPT") .temperature(0.9) ... diff --git a/src/main/java/dev/ai4j/openai4j/OpenAiClient.java b/src/main/java/dev/ai4j/openai4j/OpenAiClient.java index ad87d34..3efcf28 100644 --- a/src/main/java/dev/ai4j/openai4j/OpenAiClient.java +++ b/src/main/java/dev/ai4j/openai4j/OpenAiClient.java @@ -21,6 +21,8 @@ import dev.ai4j.openai4j.spi.OpenAiClientBuilderFactory; import dev.ai4j.openai4j.spi.ServiceHelper; +import static dev.ai4j.openai4j.LogLevel.DEBUG; + public abstract class OpenAiClient { public abstract SyncOrAsyncOrStreaming completion(CompletionRequest request); @@ -67,7 +69,7 @@ public abstract static class Builder { streamingStarted.set(true); + System.out.println("[[streaming started]]"); if (streamingCancelled.get()) { cancellationSucceeded.set(false); + System.out.println("[[cancellation failed]]"); } }) - .onComplete(() -> cancellationSucceeded.set(false)) - .onError(e -> cancellationSucceeded.set(false)) + .onComplete(() -> { + cancellationSucceeded.set(false); + System.out.println("[[cancellation failed]]"); + }) + .onError(e -> { + cancellationSucceeded.set(false); + System.out.println("[[cancellation failed]]"); + }) .execute(); while (!streamingStarted.get()) { - Thread.sleep(200); + Thread.sleep(10); } newSingleThreadExecutor().execute(() -> { responseHandle.cancel(); streamingCancelled.set(true); + System.out.println("[[streaming cancelled]]"); }); while (!streamingCancelled.get()) { - Thread.sleep(200); + Thread.sleep(10); } - Thread.sleep(5000); + Thread.sleep(2000); assertThat(cancellationSucceeded).isTrue(); } @@ -792,9 +810,18 @@ void testCancelStreamingBeforeStreamingStarted() throws Exception { AtomicBoolean cancellationSucceeded = new AtomicBoolean(true); ResponseHandle responseHandle = client.chatCompletion("Write a poem about AI in 10 words") - .onPartialResponse(partialResponse -> cancellationSucceeded.set(false)) - .onComplete(() -> cancellationSucceeded.set(false)) - .onError(e -> cancellationSucceeded.set(false)) + .onPartialResponse(partialResponse -> { + cancellationSucceeded.set(false); + System.out.println("[[cancellation failed]]"); + }) + .onComplete(() -> { + cancellationSucceeded.set(false); + System.out.println("[[cancellation failed]]"); + }) + .onError(e -> { + cancellationSucceeded.set(false); + System.out.println("[[cancellation failed]]"); + }) .execute(); AtomicBoolean streamingCancelled = new AtomicBoolean(false); @@ -802,12 +829,13 @@ void testCancelStreamingBeforeStreamingStarted() throws Exception { newSingleThreadExecutor().execute(() -> { responseHandle.cancel(); streamingCancelled.set(true); + System.out.println("[[streaming cancelled]]"); }); while (!streamingCancelled.get()) { - Thread.sleep(200); + Thread.sleep(10); } - Thread.sleep(5000); + Thread.sleep(2000); assertThat(cancellationSucceeded).isTrue(); } diff --git a/src/test/java/dev/ai4j/openai4j/chat/ChatCompletionTest.java b/src/test/java/dev/ai4j/openai4j/chat/ChatCompletionTest.java index ededee1..6ab23db 100644 --- a/src/test/java/dev/ai4j/openai4j/chat/ChatCompletionTest.java +++ b/src/test/java/dev/ai4j/openai4j/chat/ChatCompletionTest.java @@ -35,6 +35,7 @@ class ChatCompletionTest extends RateLimitAwareTest { static final Tool WEATHER_TOOL = Tool.from(WEATHER_FUNCTION); private final OpenAiClient client = OpenAiClient.builder() + .baseUrl(System.getenv("OPENAI_BASE_URL")) .openAiApiKey(System.getenv("OPENAI_API_KEY")) .logRequests() .logResponses() diff --git a/src/test/java/dev/ai4j/openai4j/completion/CompletionAsyncTest.java b/src/test/java/dev/ai4j/openai4j/completion/CompletionAsyncTest.java index ff67af5..583a4f5 100644 --- a/src/test/java/dev/ai4j/openai4j/completion/CompletionAsyncTest.java +++ b/src/test/java/dev/ai4j/openai4j/completion/CompletionAsyncTest.java @@ -14,6 +14,7 @@ class CompletionAsyncTest extends RateLimitAwareTest { private static final String PROMPT = "write exactly the following 2 words: 'hello world'"; private final OpenAiClient client = OpenAiClient.builder() + .baseUrl(System.getenv("OPENAI_BASE_URL")) .openAiApiKey(System.getenv("OPENAI_API_KEY")) .logRequests() .logResponses() diff --git a/src/test/java/dev/ai4j/openai4j/completion/CompletionStreamingTest.java b/src/test/java/dev/ai4j/openai4j/completion/CompletionStreamingTest.java index 5219988..1a962ee 100644 --- a/src/test/java/dev/ai4j/openai4j/completion/CompletionStreamingTest.java +++ b/src/test/java/dev/ai4j/openai4j/completion/CompletionStreamingTest.java @@ -17,6 +17,7 @@ class CompletionStreamingTest extends RateLimitAwareTest { private static final String PROMPT = "write exactly the following 2 words: 'hello world'"; private final OpenAiClient client = OpenAiClient.builder() + .baseUrl(System.getenv("OPENAI_BASE_URL")) .openAiApiKey(System.getenv("OPENAI_API_KEY")) .logRequests() .logResponses() @@ -66,6 +67,14 @@ void testCustomizableApi() throws Exception { @Test void testCancelStreamingAfterStreamingStarted() throws InterruptedException { + OpenAiClient client = OpenAiClient.builder() + // without caching + .openAiApiKey(System.getenv("OPENAI_API_KEY")) + .logRequests() + .logResponses() + .logStreamingResponses() + .build(); + AtomicBoolean streamingStarted = new AtomicBoolean(false); AtomicBoolean streamingCancelled = new AtomicBoolean(false); AtomicBoolean cancellationSucceeded = new AtomicBoolean(true); @@ -73,27 +82,36 @@ void testCancelStreamingAfterStreamingStarted() throws InterruptedException { ResponseHandle responseHandle = client.completion("Write a poem about AI in 10 words") .onPartialResponse(partialResponse -> { streamingStarted.set(true); + System.out.println("[[streaming started]]"); if (streamingCancelled.get()) { cancellationSucceeded.set(false); + System.out.println("[[cancellation failed]]"); } }) - .onComplete(() -> cancellationSucceeded.set(false)) - .onError(e -> cancellationSucceeded.set(false)) + .onComplete(() -> { + cancellationSucceeded.set(false); + System.out.println("[[cancellation failed]]"); + }) + .onError(e -> { + cancellationSucceeded.set(false); + System.out.println("[[cancellation failed]]"); + }) .execute(); while (!streamingStarted.get()) { - Thread.sleep(200); + Thread.sleep(10); } newSingleThreadExecutor().execute(() -> { responseHandle.cancel(); streamingCancelled.set(true); + System.out.println("[[streaming cancelled]]"); }); while (!streamingCancelled.get()) { - Thread.sleep(200); + Thread.sleep(10); } - Thread.sleep(5000); + Thread.sleep(2000); assertThat(cancellationSucceeded).isTrue(); } @@ -104,9 +122,18 @@ void testCancelStreamingBeforeStreamingStarted() throws InterruptedException { AtomicBoolean cancellationSucceeded = new AtomicBoolean(true); ResponseHandle responseHandle = client.completion("Write a poem about AI in 10 words") - .onPartialResponse(partialResponse -> cancellationSucceeded.set(false)) - .onComplete(() -> cancellationSucceeded.set(false)) - .onError(e -> cancellationSucceeded.set(false)) + .onPartialResponse(partialResponse -> { + cancellationSucceeded.set(false); + System.out.println("[[cancellation failed]]"); + }) + .onComplete(() -> { + cancellationSucceeded.set(false); + System.out.println("[[cancellation failed]]"); + }) + .onError(e -> { + cancellationSucceeded.set(false); + System.out.println("[[cancellation failed]]"); + }) .execute(); AtomicBoolean streamingCancelled = new AtomicBoolean(false); @@ -114,12 +141,13 @@ void testCancelStreamingBeforeStreamingStarted() throws InterruptedException { newSingleThreadExecutor().execute(() -> { responseHandle.cancel(); streamingCancelled.set(true); + System.out.println("[[streaming cancelled]]"); }); while (!streamingCancelled.get()) { - Thread.sleep(200); + Thread.sleep(10); } - Thread.sleep(5000); + Thread.sleep(2000); assertThat(cancellationSucceeded).isTrue(); } diff --git a/src/test/java/dev/ai4j/openai4j/completion/CompletionTest.java b/src/test/java/dev/ai4j/openai4j/completion/CompletionTest.java index 59a6fa3..437fd25 100644 --- a/src/test/java/dev/ai4j/openai4j/completion/CompletionTest.java +++ b/src/test/java/dev/ai4j/openai4j/completion/CompletionTest.java @@ -11,6 +11,7 @@ class CompletionTest extends RateLimitAwareTest { private static final String PROMPT = "write exactly the following 2 words: 'hello world'"; private final OpenAiClient client = OpenAiClient.builder() + .baseUrl(System.getenv("OPENAI_BASE_URL")) .openAiApiKey(System.getenv("OPENAI_API_KEY")) .logRequests() .logResponses() diff --git a/src/test/java/dev/ai4j/openai4j/embedding/EmbeddingsAsyncTest.java b/src/test/java/dev/ai4j/openai4j/embedding/EmbeddingsAsyncTest.java index 618e74c..ab159f7 100644 --- a/src/test/java/dev/ai4j/openai4j/embedding/EmbeddingsAsyncTest.java +++ b/src/test/java/dev/ai4j/openai4j/embedding/EmbeddingsAsyncTest.java @@ -15,6 +15,7 @@ public class EmbeddingsAsyncTest extends RateLimitAwareTest { private static final String INPUT = "hello"; private final OpenAiClient client = OpenAiClient.builder() + .baseUrl(System.getenv("OPENAI_BASE_URL")) .openAiApiKey(System.getenv("OPENAI_API_KEY")) .logRequests() .logResponses() diff --git a/src/test/java/dev/ai4j/openai4j/embedding/EmbeddingsTest.java b/src/test/java/dev/ai4j/openai4j/embedding/EmbeddingsTest.java index 1d8299f..7573e45 100644 --- a/src/test/java/dev/ai4j/openai4j/embedding/EmbeddingsTest.java +++ b/src/test/java/dev/ai4j/openai4j/embedding/EmbeddingsTest.java @@ -18,6 +18,7 @@ public class EmbeddingsTest extends RateLimitAwareTest { private static final String INPUT = "hello"; private final OpenAiClient client = OpenAiClient.builder() + .baseUrl(System.getenv("OPENAI_BASE_URL")) .openAiApiKey(System.getenv("OPENAI_API_KEY")) .logRequests() .logResponses() diff --git a/src/test/java/dev/ai4j/openai4j/moderation/ModerationAsyncTest.java b/src/test/java/dev/ai4j/openai4j/moderation/ModerationAsyncTest.java index c774178..9af36cc 100644 --- a/src/test/java/dev/ai4j/openai4j/moderation/ModerationAsyncTest.java +++ b/src/test/java/dev/ai4j/openai4j/moderation/ModerationAsyncTest.java @@ -15,6 +15,7 @@ public class ModerationAsyncTest extends RateLimitAwareTest { private static final String INPUT = "hello"; private final OpenAiClient client = OpenAiClient.builder() + .baseUrl(System.getenv("OPENAI_BASE_URL")) .openAiApiKey(System.getenv("OPENAI_API_KEY")) .logRequests() .logResponses() diff --git a/src/test/java/dev/ai4j/openai4j/moderation/ModerationTest.java b/src/test/java/dev/ai4j/openai4j/moderation/ModerationTest.java index 1acfecb..0019d8f 100644 --- a/src/test/java/dev/ai4j/openai4j/moderation/ModerationTest.java +++ b/src/test/java/dev/ai4j/openai4j/moderation/ModerationTest.java @@ -11,6 +11,7 @@ public class ModerationTest extends RateLimitAwareTest { private static final String INPUT = "hello"; private final OpenAiClient client = OpenAiClient.builder() + .baseUrl(System.getenv("OPENAI_BASE_URL")) .openAiApiKey(System.getenv("OPENAI_API_KEY")) .logRequests() .logResponses()