From 421c711165899fb8b66252a3f0c52526d6481630 Mon Sep 17 00:00:00 2001 From: Tomer Aberbach Date: Sat, 25 Jan 2025 15:15:55 -0500 Subject: [PATCH 1/2] docs: many more examples --- README.md | 2 + anthropic-java-example/build.gradle.kts | 4 +- .../anthropic/example/BatchAsyncExample.java | 105 ++++++++++++++++++ .../com/anthropic/example/BatchExample.java | 75 +++++++++++++ .../example/MessagesAsyncExample.java | 33 ++++++ .../MessagesConversationAsyncExample.java | 49 ++++++++ ....java => MessagesConversationExample.java} | 34 +++--- .../anthropic/example/MessagesExample.java | 30 +++++ .../MessagesStreamingAsyncExample.java | 49 ++++++++ .../example/MessagesStreamingExample.java | 36 ++++++ .../example/ModelListAsyncExample.java | 30 +++++ .../anthropic/example/ModelListExample.java | 20 ++++ 12 files changed, 445 insertions(+), 22 deletions(-) create mode 100644 anthropic-java-example/src/main/java/com/anthropic/example/BatchAsyncExample.java create mode 100644 anthropic-java-example/src/main/java/com/anthropic/example/BatchExample.java create mode 100644 anthropic-java-example/src/main/java/com/anthropic/example/MessagesAsyncExample.java create mode 100644 anthropic-java-example/src/main/java/com/anthropic/example/MessagesConversationAsyncExample.java rename anthropic-java-example/src/main/java/com/anthropic/example/{Main.java => MessagesConversationExample.java} (53%) create mode 100644 anthropic-java-example/src/main/java/com/anthropic/example/MessagesExample.java create mode 100644 anthropic-java-example/src/main/java/com/anthropic/example/MessagesStreamingAsyncExample.java create mode 100644 anthropic-java-example/src/main/java/com/anthropic/example/MessagesStreamingExample.java create mode 100644 anthropic-java-example/src/main/java/com/anthropic/example/ModelListAsyncExample.java create mode 100644 anthropic-java-example/src/main/java/com/anthropic/example/ModelListExample.java diff --git a/README.md b/README.md index 2fca26a..498cb80 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,8 @@ This library requires Java 8 or later. ## Usage +See the [`anthropic-java-example`](anthropic-java-example/src/main/java/com/anthropic/example) directory for complete and runnable examples. + ### Configure the client Use `AnthropicOkHttpClient.builder()` to configure the client. diff --git a/anthropic-java-example/build.gradle.kts b/anthropic-java-example/build.gradle.kts index 970f95d..56ac2d5 100644 --- a/anthropic-java-example/build.gradle.kts +++ b/anthropic-java-example/build.gradle.kts @@ -10,9 +10,9 @@ dependencies { tasks.withType().configureEach { // Allow using more modern APIs, like `List.of` and `Map.of`, in examples. - options.release.set(9) + options.release.set(11) } application { - mainClass = "com.anthropic.example.Main" + mainClass = "com.anthropic.example.MessagesExample" } diff --git a/anthropic-java-example/src/main/java/com/anthropic/example/BatchAsyncExample.java b/anthropic-java-example/src/main/java/com/anthropic/example/BatchAsyncExample.java new file mode 100644 index 0000000..2a84b32 --- /dev/null +++ b/anthropic-java-example/src/main/java/com/anthropic/example/BatchAsyncExample.java @@ -0,0 +1,105 @@ +package com.anthropic.example; + +import com.anthropic.client.AnthropicClientAsync; +import com.anthropic.client.okhttp.AnthropicOkHttpClientAsync; +import com.anthropic.core.http.AsyncStreamResponse; +import com.anthropic.models.*; +import com.anthropic.models.MessageBatch.ProcessingStatus; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +public final class BatchAsyncExample { + private BatchAsyncExample() {} + + public static void main(String[] args) throws Exception { + // Configures using the `ANTHROPIC_API_KEY` environment variable + AnthropicClientAsync client = AnthropicOkHttpClientAsync.fromEnv(); + + MessageBatchCreateParams createParams = MessageBatchCreateParams.builder() + .addRequest(MessageBatchCreateParams.Request.builder() + .customId("best-sdk") + .params(MessageBatchCreateParams.Request.Params.builder() + .model(Model.CLAUDE_3_5_SONNET_LATEST) + .maxTokens(2048) + .addMessage(MessageParam.builder() + .role(MessageParam.Role.USER) + .content("Tell me a story about building the best SDK!") + .build()) + .build()) + .build()) + .addRequest(MessageBatchCreateParams.Request.builder() + .customId("sdk-company") + .params(MessageBatchCreateParams.Request.Params.builder() + .model(Model.CLAUDE_3_5_SONNET_LATEST) + .maxTokens(2048) + .addMessage(MessageParam.builder() + .role(MessageParam.Role.USER) + .content("Which company made of metal generates SDKs?") + .build()) + .build()) + .build()) + .build(); + + client.messages() + .batches() + .create(createParams) + .thenComposeAsync(batch -> pollBatch(client, batch)) + .thenComposeAsync(batch -> { + System.out.println(); + + CompletableFuture batchFuture = new CompletableFuture<>(); + + // TODO: Update this example once we support expose an `onCompleteFuture()` method. + client.messages() + .batches() + .resultsStreaming(MessageBatchResultsParams.builder() + .messageBatchId(batch.id()) + .build()) + .subscribe(new AsyncStreamResponse.Handler<>() { + @Override + public void onNext(MessageBatchIndividualResponse response) { + System.out.println(response.customId()); + Message message = + response.result().asSucceeded().message(); + message.content().stream() + .flatMap(contentBlock -> contentBlock.text().stream()) + .forEach(textBlock -> System.out.println(textBlock.text())); + } + + @Override + public void onComplete(Optional error) { + error.ifPresentOrElse( + batchFuture::completeExceptionally, () -> batchFuture.complete(batch)); + } + }); + return batchFuture; + }) + .thenComposeAsync(batch -> client.messages() + .batches() + .delete(MessageBatchDeleteParams.builder() + .messageBatchId(batch.id()) + .build())) + .thenAccept(deletedMessageBatch -> System.out.println("Batch deleted: " + deletedMessageBatch.id())) + .join(); + } + + private static CompletableFuture pollBatch(AnthropicClientAsync client, MessageBatch batch) { + if (!batch.processingStatus().equals(ProcessingStatus.IN_PROGRESS)) { + return CompletableFuture.completedFuture(batch); + } + + System.out.println("Polling batch..."); + try { + java.lang.Thread.sleep(2000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + return client.messages() + .batches() + .retrieve(MessageBatchRetrieveParams.builder() + .messageBatchId(batch.id()) + .build()) + .thenComposeAsync(newBatch -> pollBatch(client, newBatch)); + } +} diff --git a/anthropic-java-example/src/main/java/com/anthropic/example/BatchExample.java b/anthropic-java-example/src/main/java/com/anthropic/example/BatchExample.java new file mode 100644 index 0000000..e7a7a09 --- /dev/null +++ b/anthropic-java-example/src/main/java/com/anthropic/example/BatchExample.java @@ -0,0 +1,75 @@ +package com.anthropic.example; + +import com.anthropic.client.AnthropicClient; +import com.anthropic.client.okhttp.AnthropicOkHttpClient; +import com.anthropic.core.http.StreamResponse; +import com.anthropic.models.*; +import com.anthropic.models.MessageBatch.ProcessingStatus; + +public final class BatchExample { + private BatchExample() {} + + public static void main(String[] args) throws Exception { + // Configures using the `ANTHROPIC_API_KEY` environment variable + AnthropicClient client = AnthropicOkHttpClient.fromEnv(); + + MessageBatchCreateParams createParams = MessageBatchCreateParams.builder() + .addRequest(MessageBatchCreateParams.Request.builder() + .customId("best-sdk") + .params(MessageBatchCreateParams.Request.Params.builder() + .model(Model.CLAUDE_3_5_SONNET_LATEST) + .maxTokens(2048) + .addMessage(MessageParam.builder() + .role(MessageParam.Role.USER) + .content("Tell me a story about building the best SDK!") + .build()) + .build()) + .build()) + .addRequest(MessageBatchCreateParams.Request.builder() + .customId("sdk-company") + .params(MessageBatchCreateParams.Request.Params.builder() + .model(Model.CLAUDE_3_5_SONNET_LATEST) + .maxTokens(2048) + .addMessage(MessageParam.builder() + .role(MessageParam.Role.USER) + .content("Which company made of metal generates SDKs?") + .build()) + .build()) + .build()) + .build(); + + MessageBatch batch = client.messages().batches().create(createParams); + while (batch.processingStatus().equals(ProcessingStatus.IN_PROGRESS)) { + System.out.println("Polling batch..."); + Thread.sleep(2000); + batch = client.messages() + .batches() + .retrieve(MessageBatchRetrieveParams.builder() + .messageBatchId(batch.id()) + .build()); + } + System.out.println(); + + try (StreamResponse streamResponse = client.messages() + .batches() + .resultsStreaming(MessageBatchResultsParams.builder() + .messageBatchId(batch.id()) + .build())) { + streamResponse.stream().forEach(response -> { + System.out.println(response.customId()); + Message message = response.result().asSucceeded().message(); + message.content().stream() + .flatMap(contentBlock -> contentBlock.text().stream()) + .forEach(textBlock -> System.out.println(textBlock.text())); + }); + } + System.out.println(); + + DeletedMessageBatch deletedMessageBatch = client.messages() + .batches() + .delete(MessageBatchDeleteParams.builder() + .messageBatchId(batch.id()) + .build()); + System.out.println("Batch deleted: " + deletedMessageBatch.id()); + } +} diff --git a/anthropic-java-example/src/main/java/com/anthropic/example/MessagesAsyncExample.java b/anthropic-java-example/src/main/java/com/anthropic/example/MessagesAsyncExample.java new file mode 100644 index 0000000..0b4e39f --- /dev/null +++ b/anthropic-java-example/src/main/java/com/anthropic/example/MessagesAsyncExample.java @@ -0,0 +1,33 @@ +package com.anthropic.example; + +import com.anthropic.client.AnthropicClientAsync; +import com.anthropic.client.okhttp.AnthropicOkHttpClientAsync; +import com.anthropic.models.MessageCreateParams; +import com.anthropic.models.MessageParam; +import com.anthropic.models.MessageParam.Role; +import com.anthropic.models.Model; + +public final class MessagesAsyncExample { + private MessagesAsyncExample() {} + + public static void main(String[] args) { + // Configures using the `ANTHROPIC_API_KEY` environment variable + AnthropicClientAsync client = AnthropicOkHttpClientAsync.fromEnv(); + + MessageCreateParams createParams = MessageCreateParams.builder() + .model(Model.CLAUDE_3_5_SONNET_LATEST) + .maxTokens(2048) + .addMessage(MessageParam.builder() + .role(Role.USER) + .content("Tell me a story about building the best SDK!") + .build()) + .build(); + + client.messages() + .create(createParams) + .thenAccept(message -> message.content().stream() + .flatMap(contentBlock -> contentBlock.text().stream()) + .forEach(textBlock -> System.out.println(textBlock.text()))) + .join(); + } +} diff --git a/anthropic-java-example/src/main/java/com/anthropic/example/MessagesConversationAsyncExample.java b/anthropic-java-example/src/main/java/com/anthropic/example/MessagesConversationAsyncExample.java new file mode 100644 index 0000000..661dacd --- /dev/null +++ b/anthropic-java-example/src/main/java/com/anthropic/example/MessagesConversationAsyncExample.java @@ -0,0 +1,49 @@ +package com.anthropic.example; + +import com.anthropic.client.AnthropicClientAsync; +import com.anthropic.client.okhttp.AnthropicOkHttpClientAsync; +import com.anthropic.models.MessageCreateParams; +import com.anthropic.models.MessageParam; +import com.anthropic.models.Model; +import java.util.concurrent.CompletableFuture; + +public final class MessagesConversationAsyncExample { + private MessagesConversationAsyncExample() {} + + public static void main(String[] args) { + // Configures using the `ANTHROPIC_API_KEY` environment variable + AnthropicClientAsync client = AnthropicOkHttpClientAsync.fromEnv(); + + // Use a builder so that we can append more messages to it below. + // Each time we call .build()` we get an immutable object that's unaffected by future mutations of the builder. + MessageCreateParams.Builder createParamsBuilder = MessageCreateParams.builder() + .model(Model.CLAUDE_3_5_SONNET_LATEST) + .maxTokens(2048) + .addMessage(MessageParam.builder() + .role(MessageParam.Role.USER) + .content("Tell me a story about building the best SDK!") + .build()); + + CompletableFuture future = CompletableFuture.completedFuture(null); + for (int i = 0; i < 4; i++) { + final int index = i; + future = future.thenComposeAsync(unused -> client.messages().create(createParamsBuilder.build())) + .thenAccept(message -> { + message.content().stream() + .flatMap(contentBlock -> contentBlock.text().stream()) + .forEach(textBlock -> System.out.println(textBlock.text())); + + System.out.println("\n-----------------------------------\n"); + + createParamsBuilder + .addMessage(message) + .addMessage(MessageParam.builder() + .role(MessageParam.Role.USER) + .content("But why?" + "?".repeat(index)) + .build()); + }); + } + + future.join(); + } +} diff --git a/anthropic-java-example/src/main/java/com/anthropic/example/Main.java b/anthropic-java-example/src/main/java/com/anthropic/example/MessagesConversationExample.java similarity index 53% rename from anthropic-java-example/src/main/java/com/anthropic/example/Main.java rename to anthropic-java-example/src/main/java/com/anthropic/example/MessagesConversationExample.java index 33bea33..dd5e46d 100644 --- a/anthropic-java-example/src/main/java/com/anthropic/example/Main.java +++ b/anthropic-java-example/src/main/java/com/anthropic/example/MessagesConversationExample.java @@ -2,23 +2,28 @@ import com.anthropic.client.AnthropicClient; import com.anthropic.client.okhttp.AnthropicOkHttpClient; -import com.anthropic.core.http.StreamResponse; -import com.anthropic.models.*; +import com.anthropic.models.Message; +import com.anthropic.models.MessageCreateParams; +import com.anthropic.models.MessageParam; +import com.anthropic.models.Model; -public final class Main { - private Main() {} +public final class MessagesConversationExample { + private MessagesConversationExample() {} public static void main(String[] args) { + // Configures using the `ANTHROPIC_API_KEY` environment variable AnthropicClient client = AnthropicOkHttpClient.fromEnv(); + + // Use a builder so that we can append more messages to it below. + // Each time we call .build()` we get an immutable object that's unaffected by future mutations of the builder. MessageCreateParams.Builder createParamsBuilder = MessageCreateParams.builder() .model(Model.CLAUDE_3_5_SONNET_LATEST) - .maxTokens(1000) + .maxTokens(2048) .addMessage(MessageParam.builder() .role(MessageParam.Role.USER) - .content(MessageParam.Content.ofString("Tell me a story about building the best SDK!")) + .content("Tell me a story about building the best SDK!") .build()); - // Having a conversation in a loop for (int i = 0; i < 4; i++) { Message message = client.messages().create(createParamsBuilder.build()); @@ -29,22 +34,11 @@ public static void main(String[] args) { System.out.println("\n-----------------------------------\n"); createParamsBuilder - .addMessage(message.toParam()) + .addMessage(message) .addMessage(MessageParam.builder() .role(MessageParam.Role.USER) - .content(MessageParam.Content.ofString("But why???")) + .content("But why?" + "?".repeat(i)) .build()); } - - // Streaming example - try (StreamResponse streamResponse = - client.messages().createStreaming(createParamsBuilder.build())) { - streamResponse.stream() - .flatMap(event -> event.contentBlockDelta().stream()) - .flatMap(deltaEvent -> deltaEvent.delta().text().stream()) - .forEach(textDelta -> System.out.print(textDelta.text())); - } catch (Exception e) { - System.out.println(e.getMessage()); - } } } diff --git a/anthropic-java-example/src/main/java/com/anthropic/example/MessagesExample.java b/anthropic-java-example/src/main/java/com/anthropic/example/MessagesExample.java new file mode 100644 index 0000000..6da7404 --- /dev/null +++ b/anthropic-java-example/src/main/java/com/anthropic/example/MessagesExample.java @@ -0,0 +1,30 @@ +package com.anthropic.example; + +import com.anthropic.client.AnthropicClient; +import com.anthropic.client.okhttp.AnthropicOkHttpClient; +import com.anthropic.models.MessageCreateParams; +import com.anthropic.models.MessageParam; +import com.anthropic.models.MessageParam.Role; +import com.anthropic.models.Model; + +public final class MessagesExample { + private MessagesExample() {} + + public static void main(String[] args) { + // Configures using the `ANTHROPIC_API_KEY` environment variable + AnthropicClient client = AnthropicOkHttpClient.fromEnv(); + + MessageCreateParams createParams = MessageCreateParams.builder() + .model(Model.CLAUDE_3_5_SONNET_LATEST) + .maxTokens(2048) + .addMessage(MessageParam.builder() + .role(Role.USER) + .content("Tell me a story about building the best SDK!") + .build()) + .build(); + + client.messages().create(createParams).content().stream() + .flatMap(contentBlock -> contentBlock.text().stream()) + .forEach(textBlock -> System.out.println(textBlock.text())); + } +} diff --git a/anthropic-java-example/src/main/java/com/anthropic/example/MessagesStreamingAsyncExample.java b/anthropic-java-example/src/main/java/com/anthropic/example/MessagesStreamingAsyncExample.java new file mode 100644 index 0000000..5048f4b --- /dev/null +++ b/anthropic-java-example/src/main/java/com/anthropic/example/MessagesStreamingAsyncExample.java @@ -0,0 +1,49 @@ +package com.anthropic.example; + +import com.anthropic.client.AnthropicClientAsync; +import com.anthropic.client.okhttp.AnthropicOkHttpClientAsync; +import com.anthropic.core.http.AsyncStreamResponse; +import com.anthropic.models.MessageCreateParams; +import com.anthropic.models.MessageParam; +import com.anthropic.models.MessageParam.Role; +import com.anthropic.models.Model; +import com.anthropic.models.RawMessageStreamEvent; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +public final class MessagesStreamingAsyncExample { + private MessagesStreamingAsyncExample() {} + + public static void main(String[] args) { + // Configures using the `ANTHROPIC_API_KEY` environment variable + AnthropicClientAsync client = AnthropicOkHttpClientAsync.fromEnv(); + + MessageCreateParams createParams = MessageCreateParams.builder() + .model(Model.CLAUDE_3_5_SONNET_LATEST) + .maxTokens(2048) + .addMessage(MessageParam.builder() + .role(Role.USER) + .content("Tell me a story about building the best SDK!") + .build()) + .build(); + + CompletableFuture onCompleteFuture = new CompletableFuture<>(); + + // TODO: Update this example once we support expose an `onCompleteFuture()` method. + client.messages().createStreaming(createParams).subscribe(new AsyncStreamResponse.Handler<>() { + @Override + public void onNext(RawMessageStreamEvent event) { + event.contentBlockDelta().stream() + .flatMap(deltaEvent -> deltaEvent.delta().text().stream()) + .forEach(textDelta -> System.out.print(textDelta.text())); + } + + @Override + public void onComplete(Optional error) { + onCompleteFuture.complete(null); + } + }); + + onCompleteFuture.join(); + } +} diff --git a/anthropic-java-example/src/main/java/com/anthropic/example/MessagesStreamingExample.java b/anthropic-java-example/src/main/java/com/anthropic/example/MessagesStreamingExample.java new file mode 100644 index 0000000..3e7f2a6 --- /dev/null +++ b/anthropic-java-example/src/main/java/com/anthropic/example/MessagesStreamingExample.java @@ -0,0 +1,36 @@ +package com.anthropic.example; + +import com.anthropic.client.AnthropicClient; +import com.anthropic.client.okhttp.AnthropicOkHttpClient; +import com.anthropic.core.http.StreamResponse; +import com.anthropic.models.MessageCreateParams; +import com.anthropic.models.MessageParam; +import com.anthropic.models.MessageParam.Role; +import com.anthropic.models.Model; +import com.anthropic.models.RawMessageStreamEvent; + +public final class MessagesStreamingExample { + private MessagesStreamingExample() {} + + public static void main(String[] args) throws Exception { + // Configures using the `ANTHROPIC_API_KEY` environment variable + AnthropicClient client = AnthropicOkHttpClient.fromEnv(); + + MessageCreateParams createParams = MessageCreateParams.builder() + .model(Model.CLAUDE_3_5_SONNET_LATEST) + .maxTokens(2048) + .addMessage(MessageParam.builder() + .role(Role.USER) + .content("Tell me a story about building the best SDK!") + .build()) + .build(); + + try (StreamResponse streamResponse = + client.messages().createStreaming(createParams)) { + streamResponse.stream() + .flatMap(event -> event.contentBlockDelta().stream()) + .flatMap(deltaEvent -> deltaEvent.delta().text().stream()) + .forEach(textDelta -> System.out.print(textDelta.text())); + } + } +} diff --git a/anthropic-java-example/src/main/java/com/anthropic/example/ModelListAsyncExample.java b/anthropic-java-example/src/main/java/com/anthropic/example/ModelListAsyncExample.java new file mode 100644 index 0000000..0c69140 --- /dev/null +++ b/anthropic-java-example/src/main/java/com/anthropic/example/ModelListAsyncExample.java @@ -0,0 +1,30 @@ +package com.anthropic.example; + +import com.anthropic.client.AnthropicClientAsync; +import com.anthropic.client.okhttp.AnthropicOkHttpClientAsync; +import com.anthropic.models.ModelListPageAsync; +import com.anthropic.models.ModelListParams; +import java.util.concurrent.CompletableFuture; + +public final class ModelListAsyncExample { + private ModelListAsyncExample() {} + + public static void main(String[] args) { + // Configures using the `ANTHROPIC_API_KEY` environment variable + AnthropicClientAsync client = AnthropicOkHttpClientAsync.fromEnv(); + + CompletableFuture pageFuture = + // TODO: Update this example once we support `.list()` without arguments. + client.models().list(ModelListParams.builder().build()); + pageFuture + .thenComposeAsync(page -> page.autoPager() + .forEach( + model -> { + System.out.println(model.id()); + // Keep iterating + return true; + }, + pageFuture.defaultExecutor())) + .join(); + } +} diff --git a/anthropic-java-example/src/main/java/com/anthropic/example/ModelListExample.java b/anthropic-java-example/src/main/java/com/anthropic/example/ModelListExample.java new file mode 100644 index 0000000..017467a --- /dev/null +++ b/anthropic-java-example/src/main/java/com/anthropic/example/ModelListExample.java @@ -0,0 +1,20 @@ +package com.anthropic.example; + +import com.anthropic.client.AnthropicClient; +import com.anthropic.client.okhttp.AnthropicOkHttpClient; +import com.anthropic.models.ModelListParams; + +public final class ModelListExample { + private ModelListExample() {} + + public static void main(String[] args) { + // Configures using the `ANTHROPIC_API_KEY` environment variable + AnthropicClient client = AnthropicOkHttpClient.fromEnv(); + + client.models() + // TODO: Update this example once we support `.list()` without arguments. + .list(ModelListParams.builder().build()) + .autoPager() + .forEach(model -> System.out.println(model.id())); + } +} From d6b6fcb0ae2450f1a0e16440c4a86a7d28a8317a Mon Sep 17 00:00:00 2001 From: Tomer Aberbach Date: Mon, 27 Jan 2025 12:53:46 -0500 Subject: [PATCH 2/2] chore: delete not needed dir --- examples/.keep | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 examples/.keep diff --git a/examples/.keep b/examples/.keep deleted file mode 100644 index d8c73e9..0000000 --- a/examples/.keep +++ /dev/null @@ -1,4 +0,0 @@ -File generated from our OpenAPI spec by Stainless. - -This directory can be used to store example files demonstrating usage of this SDK. -It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file