Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 49 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# Ark Runtime Java SDK

The Ark Runtime Java SDK provides convenient access to the Volcengine Ark
REST API from Java 8+ applications. It includes typed request/response
models for every API endpoint, synchronous and streaming helpers, and
automatic retry logic.
The official Java library for accessing ModelArk on Volcengine and BytePlus. It provides typed request and response models, synchronous and streaming helpers, authentication, and automatic retries for Java 8+ applications.

## Installation

Expand All @@ -23,34 +20,45 @@ automatic retry logic.
implementation 'com.volcengine:ark-runtime:0.4.0'
```

## Usage
## Choose Volcengine or BytePlus

Set `ARK_API_KEY`, then choose the builder for the service you use. The builder configures the correct base URL and region; request construction and all subsequent SDK calls are the same.

### Volcengine (China)

### Authentication
```java
ArkService service = ArkService.volc()
.apiKey(System.getenv("ARK_API_KEY"))
.build();
```

The SDK reads the `ARK_API_KEY` environment variable by default. You can
also pass the key explicitly via the builder:
### BytePlus (BP)

```java
ArkService service = ArkService.builder()
ArkService service = ArkService.byteplus()
.apiKey(System.getenv("ARK_API_KEY"))
.build();
```

Use a model ID available in the corresponding Volcengine or BytePlus account. Model IDs can differ between the two services; the examples use `doubao-seed-2-1-pro-260628` for Volcengine and `seed-2-0-lite-260428` for BytePlus. Override either default with `ARK_MODEL`.

## Quick start

### Responses API

The Responses API is the primary interface for generating text with Ark
models.

```java
import com.volcengine.ark.runtime.ArkService;
import com.volcengine.ark.runtime.service.ArkService;
import com.volcengine.ark.runtime.models.responses.*;

ArkService service = ArkService.builder()
ArkService service = ArkService.volc()
.apiKey(System.getenv("ARK_API_KEY"))
.build();

ResponsesRequest request = ResponsesRequest.builder()
.model("doubao-seed-2-1-pro-260628")
.model(System.getenv("ARK_MODEL"))
.input(ResponsesInput.ofString("Explain Java generics in two sentences."))
.build();

Expand All @@ -60,13 +68,17 @@ System.out.println(response.getOutput());
service.shutdownExecutor();
```

Set `ARK_MODEL` to a model ID from your account before running the example.

## Usage

### Chat Completions

```java
import com.volcengine.ark.runtime.models.chat.*;

ChatCompletionRequest request = ChatCompletionRequest.builder()
.model("doubao-seed-2-1-pro-260628")
.model(System.getenv("ARK_MODEL"))
.messages(Arrays.asList(
ChatCompletionRequestUserMessage.builder()
.role(ChatCompletionRequestMessageType.USER)
Expand Down Expand Up @@ -104,10 +116,9 @@ method -- you do not need to set it on the request builder.
```java
import io.reactivex.Flowable;
import com.volcengine.ark.runtime.models.responses.*;
import com.volcengine.ark.runtime.models.responses.events.*;

ResponsesRequest request = ResponsesRequest.builder()
.model("doubao-seed-2-1-pro-260628")
.model(System.getenv("ARK_MODEL"))
.input(ResponsesInput.ofString("Write a haiku about Java."))
.build();

Expand Down Expand Up @@ -142,19 +153,28 @@ Build tools with `FunctionTool.builder()` and pass them in the request:

```java
import com.volcengine.ark.runtime.models.responses.*;
import java.util.*;

Map<String, Object> city = new HashMap<>();
city.put("type", "string");
city.put("description", "City name");

Map<String, Object> properties = new HashMap<>();
properties.put("city", city);

Map<String, Object> parameters = new HashMap<>();
parameters.put("type", "object");
parameters.put("properties", properties);
parameters.put("required", Collections.singletonList("city"));

FunctionTool weatherTool = FunctionTool.builder()
.name("get_weather")
.description("Get the current weather for a city")
.parameters(Map.of(
"type", "object",
"properties", Map.of(
"city", Map.of("type", "string", "description", "City name")),
"required", List.of("city")))
.parameters(parameters)
.build();

ResponsesRequest request = ResponsesRequest.builder()
.model("doubao-seed-2-1-pro-260628")
.model(System.getenv("ARK_MODEL"))
.input(ResponsesInput.ofString("What is the weather in Beijing?"))
.tools(Collections.singletonList(Tool.ofFunction(weatherTool)))
.build();
Expand All @@ -178,32 +198,19 @@ try {
}
```

## API Reference

| API | Method |
|------------------------|----------------------------------------------------------------------------|
| Responses | `service.createResponse()` / `service.streamResponse()` |
| Chat Completions | `service.createChatCompletion()` / `service.streamChatCompletion()` |
| Embeddings | `service.createEmbedding()` |
| Multimodal Embeddings | `service.createMultiModalEmbedding()` |
| Content Generation | `service.createContentGenerationTask()` |
| Images | `service.createImageGeneration()` |
| Files | `service.createFile()` / `service.listFiles()` / `service.deleteFile()` |
| Tokenization | `service.createTokenization()` |

## Examples

For detailed usage guidance and legacy migration, see
[`docs/README.md`](docs/README.md) and
[`docs/migration.md`](docs/migration.md).

Runnable single-file programs are available in the
[examples/](./examples) directory:

- **Responses** -- `CreateResponseExample`, `ResponseOperationsExample`
- **Chat Completions** -- `ChatCompletionsExample`, `ChatCompletionsFunctionCallExample`, `ChatCompletionsVisionExample`
- **Embeddings** -- `EmbeddingsExample`, `MultiModalEmbeddingsExample`, `SparseEmbeddingsExample`
- **Content Generation** -- `ContentGenerationTaskExample`
- **Images** -- `ImageGenerationExample`
- **Files** -- `FileUploadExample`, `FileVideoResponsesExample`
- **Tokenization** -- `TokenizationExample`
- **Batch** -- `BatchChatCompletionsExample`
- **[Volcengine China examples](./examples/volc)** -- Chat, Responses, images, video generation, embeddings, files, tokenization, batch APIs, and resource APIs using `ArkService.volc()`
- **[BytePlus examples](./examples/byteplus)** -- supported counterparts using `ArkService.byteplus()` and BytePlus model IDs

MCP is demonstrated in both clouds with `ark-beta-mcp: true`. Other built-in-tool examples are CN-only and explicitly send their required beta headers.

## Requirements

Expand Down
40 changes: 40 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Ark Runtime Java SDK documentation

This directory contains detailed usage and migration guidance for the Ark
Runtime Java SDK.

## Choose the right document

- [Usage guide](usage.md): dependency setup, regional
clients, generated request models, streaming, and built-in tools.
- [Migration guide](migration.md): migrate from either legacy Volcengine or
BytePlus Java SDK.
- [`../examples/volc`](../examples/volc): runnable Volcengine examples.
- [`../examples/byteplus`](../examples/byteplus): runnable BytePlus examples.

## Important usage rules

1. Use `ArkService.volc()` for CN or `ArkService.byteplus()` for BytePlus. Only
client creation and regional model identifiers differ; request setup stays
the same.
2. Read `ARK_API_KEY` from the environment. Never insert credentials into
source, build files, fixtures, logs, or generated patches.
3. Build requests with classes under `com.volcengine.ark.runtime.models`.
Respect generated union factories such as `ResponsesInput.ofString`.
4. Responses streams contain typed event subclasses. Handle the subclasses the
application needs and tolerate additional event types.
5. MCP is supported in CN and BytePlus. Other hosted built-in tools shown in
this repository are CN-only. Pass the matching `ark-beta-*` header to both
streaming and non-streaming requests.
6. Call `shutdownExecutor()` when an application owns the service lifecycle.

## Minimal verification

```bash
mvn test
mvn checkstyle:check
```

Also run one streaming and one non-streaming request in the selected cloud.
Smoke-test each built-in tool separately to validate its entitlement and beta
header.
150 changes: 150 additions & 0 deletions docs/migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# Migrate from the legacy Java SDK

This guide covers:

- `com.volcengine:volcengine-java-sdk-ark-runtime`
- `com.byteplus:byteplus-java-sdk-v2-ark-runtime`

Both migrate to `com.volcengine:ark-runtime`. The new common Java package is
also `com.volcengine.ark.runtime` for BytePlus applications.

## 1. Migration order

Migrate one API flow at a time:

1. Choose the target cloud: Volcengine (CN) or BytePlus.
2. Replace the Ark Runtime dependency and select the regional service builder.
3. Update imports to the new common package and API-specific generated models.
4. Rebuild request unions with the new factories and generated enums.
5. Update response types, Chat deltas, and Responses event subclasses.
6. Add the required beta header to every built-in-tool request and remove any
CN-only tool from a BytePlus target.
7. Compile and smoke-test that flow before migrating the next one.

Do not bulk-replace the old model package or event class names. The correct new
class depends on the request variant and the events the application consumes.

## 2. Dependency and client mapping

```xml
<dependency>
<groupId>com.volcengine</groupId>
<artifactId>ark-runtime</artifactId>
<version>0.1.0</version>
</dependency>
```

| Legacy | New |
|---|---|
| `ArkService.builder()` | CN: `ArkService.volc()`; BP: `ArkService.byteplus()` |
| `new ArkService(apiKey)` | use regional builder, `.apiKey(apiKey).build()` |
| `com.byteplus.ark.runtime...` | `com.volcengine.ark.runtime...` |
| old `.model...` packages | new `.models...` API-specific classes |

Preserve dispatcher, connection pool, timeout, and API key calls after changing
the builder entry point.

## 3. Request-model mapping

The generated model layer changed substantially; do not bulk-replace `model`
with `models` and assume the result is correct.

Chat mappings:

| Legacy | New |
|---|---|
| `model.completion.chat.ChatMessage` | typed `models.chat.ChatCompletionRequest*Message` subtype |
| `ChatMessageRole.USER` | `ChatCompletionRequestMessageType.USER` |
| string message content | `ChatCompletionMessageContent.ofString(value)` |
| `ChatCompletionRequest` | `models.chat.ChatCompletionRequest` |

Responses mappings:

| Legacy | New |
|---|---|
| `CreateResponsesRequest` | `ResponsesRequest` |
| `ResponseObject` | `Response` |
| `ResponsesInput.builder().stringValue(v).build()` | `ResponsesInput.ofString(v)` |
| list input builder | `ResponsesInput.ofList(List<InputItem>)` |
| `ResponsesThinking` | `Thinking` |
| `ResponsesConstants` values | generated enums such as `ThinkingMode` and `MessageRole` |

For a list input, construct a concrete `InputItem` implementation, place it in
a `List<InputItem>`, then call `ResponsesInput.ofList`. For function results,
use `ItemFunctionToolCallOutput` and keep both the tool call ID and previous
response ID.

If the old application persists serialized request JSON, add a fixture test
that deserializes or rebuilds it with new models and compares the outgoing JSON
field by field.

## 4. Streaming mapping

The RxJava flow remains, but payload access changed.

Chat:

| Legacy | New |
|---|---|
| `choice.getChoices().get(0).getMessage().getContent()` | `chunk.getChoices().get(0).getDelta().getContent()` |

Responses:

| Legacy | New |
|---|---|
| `model.responses.event.StreamEvent` | `models.responses.ResponseStreamEvent` |
| old event subpackages | generated event classes directly in `models.responses` |
| `OutputTextDeltaEvent` | `ResponseTextDeltaEvent` |
| `ResponseCompletedEvent` | new `ResponseCompletedEvent` class and `Response` payload |

Use `instanceof` before casting. Capture function/MCP IDs from their typed
output-item event and response IDs from the completed event. Preserve
`doOnError` or an equivalent error path; `blockingForEach` returning normally is
the end of stream, not proof that every expected event was present.

## 5. Extra headers and regional behavior

Both ordinary and stream methods have header-map overloads:

```java
Map<String, String> headers = Collections.singletonMap("ark-beta-mcp", "true");
service.createResponse(request, headers);
service.streamResponse(request, headers);
```

MCP (`ark-beta-mcp`) is supported in both clouds. Web search
(`ark-beta-web-search`), knowledge search (`ark-beta-knowledge-search`), Doubao
App (`ark-beta-doubao-app`), and image process (`ark-beta-image-process`) are
CN-only. A BytePlus migration must stop for review if it finds one of those
tools.

## 6. Regional model IDs

Model names and endpoint IDs are cloud-specific. Prefer application
configuration, and update any legacy hard-coded default when changing clouds:

| API | Volcengine (CN) example | BytePlus example |
|---|---|---|
| Responses / Chat | `doubao-seed-2-1-pro-260628` | `seed-2-0-lite-260428` |
| Multimodal / sparse embeddings | `doubao-embedding-vision-251215` | `skylark-embedding-vision-251215` |
| Image generation | `doubao-seedream-5-0-pro-260628` | `dola-seedream-5-0-pro-260628` |
| Video generation | `doubao-seedance-2-0-fast-260128` | `dreamina-seedance-2-0-fast-260128` |

Use a model or endpoint ID provisioned for the target account if it differs
from these example defaults.

## 7. Validate the migration

1. Search for the legacy dependency, package names, model imports, and generic
service builder; none should remain in migrated Ark Runtime code.
2. Run `mvn test` and `mvn checkstyle:check`.
3. Verify one non-streaming and one streaming Chat or Responses request.
4. Confirm stream text comes from deltas and typed Responses events.
5. Smoke-test every built-in tool with its required beta header.
6. Test CN and BytePlus independently if both are supported. Never reuse a
regional key, model ID, endpoint ID, or service instance across clouds.
7. Confirm `shutdownExecutor()` runs when the owning application shuts down.

A migration is not complete merely because the project compiles. The live
stream and tool checks catch missing deltas, incorrect event casts, unsupported
regional tools, and omitted headers.
Loading
Loading