Java 11+ client for the public VectorAmp API.
Licensed under the Apache License 2.0.
Gradle:
repositories { mavenCentral() }
dependencies {
implementation 'com.vectoramp:vectoramp-java:0.3.0'
}Maven:
<dependency>
<groupId>com.vectoramp</groupId>
<artifactId>vectoramp-java</artifactId>
<version>0.3.0</version>
</dependency>The API key is the only required input. VectorAmpClient.create(...) reads it from your code or
from the VECTORAMP_API_KEY environment variable, and defaults to the production base URL.
import com.vectoramp.VectorAmpClient;
import com.vectoramp.models.*;
try (VectorAmpClient client = VectorAmpClient.create(System.getenv("VECTORAMP_API_KEY"))) {
// One-call create: name only. Defaults to the VectorAmp-Embedding-4B model (dim 2560),
// cosine metric, and the SABLE index.
Dataset dataset = client.datasets().create("product-docs");
// Object -> method style: call instance methods on the dataset directly.
dataset.addTexts(java.util.List.of(
"VectorAmp ships a high-performance SABLE vector index.",
"The API supports RAG over ingested datasets."
));
AskResponse answer = dataset.ask("What index does VectorAmp use?");
System.out.println(answer.getAnswer());
}The default base URL is https://api.vectoramp.com. Override it for development or tests:
VectorAmpClient client = VectorAmpClient.builder(System.getenv("VECTORAMP_API_KEY"))
.baseUrl("https://api.vectoramp.com")
.timeout(java.time.Duration.ofSeconds(60))
.build();Authentication uses the public API-key header X-API-Key: <api_key>.
create, get, and list return Dataset resource objects. Each keeps the raw API payload
(getRawData()), the dataset id, and bound SDK services, so you can call instance methods without
passing the id around. The id-based service methods (client.datasets().search(id, ...)) remain
available for explicit usage.
Page<Dataset> page = client.datasets().list(50, 0);
Dataset dataset = client.datasets().get("dataset-uuid");
SearchResponse results = dataset.search("release notes");
dataset.insert(java.util.List.of(VectorRecord.of("doc-1", java.util.List.of(0.1, 0.2), null)));
dataset.addText("hello world");
AskResponse answer = dataset.ask("Summarize this dataset");
dataset.delete();// Minimal: name only. Embedding config is omitted so VectorAmp uses
// the managed VectorAmp-Embedding-4B model and infers dim 2560.
Dataset docs = client.datasets().create("docs");
// Hybrid dense + sparse dataset.
Dataset hybrid = client.datasets().create("hybrid-docs", true);
// Optional BYOM: use OpenAI only when you intentionally want that provider.
// EmbeddingConfig.openai(...) uses the org secret ref emb:openai:api_key by default.
Dataset openaiDocs = client.datasets().create(
CreateDatasetRequest.builder("openai-docs")
.embedding(EmbeddingConfig.openai("small"))
.metric("cosine")
.hybrid(true)
.build()
);
// One-call BYOM helper: store/update the org OpenAI key, then create the dataset
// with embedding.secret_ref pointing at that stored secret.
Dataset byom = client.datasets().createWithOpenAiApiKey(
"openai-docs",
System.getenv("OPENAI_API_KEY")
);
// Custom/unknown embedding model: provide dim explicitly.
Dataset bespoke = client.datasets().create(
CreateDatasetRequest.builder("bespoke")
.embedding(EmbeddingConfig.of("acme", "acme-embed-v2"))
.dim(768)
.build()
);
// Optional typed metadata schema. Canonical field types are STRING, U32, I32,
// I64, F32, and F64.
List<MetadataSchemaField> schema = List.of(
MetadataSchemaField.of("price", MetadataFieldType.F32),
MetadataSchemaField.of("category", MetadataFieldType.STRING)
);
Dataset products = client.datasets().create(
CreateDatasetRequest.builder("products").metadataSchemaFields(schema).build()
);
// Merge fields while retaining existing ones, or replace the complete schema.
client.datasets().patchMetadataSchema(products.getId(), List.of(
MetadataSchemaField.of("inventory", MetadataFieldType.U32)
));
client.datasets().replaceMetadataSchema(products.getId(), schema);The SDK always sends index_type: "sable" and never exposes other index types.
// Bare text query; top_k defaults to 10.
SearchResponse results = dataset.search("machine learning best practices");
// Add options only when you need them.
SearchResponse filtered = dataset.search(
SearchRequest.text("machine learning best practices")
.filters(java.util.Map.of("category", "research"))
.includeDocuments(true)
.rerank(true) // expands to the full rerank object
);
// Hybrid dense/sparse search.
SearchResponse hybridResults = dataset.search(
SearchRequest.text("zero downtime upgrade").hybrid("zero downtime", 0.5)
);
// Vector search.
SearchResponse vectorResults = dataset.search(
SearchRequest.vector(java.util.List.of(0.1, 0.2, 0.3))
);Vector ids accept a String or a number. Numeric ids are sent as JSON numbers, so the API
preserves them exactly.
dataset.insert(java.util.List.of(
VectorRecord.of("doc-001", java.util.List.of(0.1, 0.2, 0.3), java.util.Map.of("title", "Intro")),
VectorRecord.of(42L, java.util.List.of(0.4, 0.5, 0.6), null) // serialized as "id": 42
));
DeleteVectorsResponse deleted = dataset.deleteVectors(java.util.List.of("doc-001", 42L));client.orgSecrets().putOpenAiApiKey(System.getenv("OPENAI_API_KEY"));
client.orgSecrets().putOpenAiApiKey(
System.getenv("OPENAI_API_KEY"),
"emb:openai:api_key",
true, // validate before storing
"text-embedding-3-small"
);addTexts embeds text through /datasets/{id}/embed, then inserts the generated vectors through
/datasets/{id}/insert with the source text copied into metadata.text. Ids are auto-generated
when omitted.
dataset.addText("hello world");
dataset.addTexts(java.util.List.of("hello", "world"));
// With explicit numeric ids and per-text metadata.
dataset.addTexts(AddTextsRequest.ofNumericIds(
java.util.List.of("first", "second"),
java.util.List.of(1L, 2L),
java.util.List.of(java.util.Map.of("page", 1), java.util.Map.of("page", 2))
));Document listing is cursor-based. Pass getNextCursor() into the next request. Downloads return
the retained original bytes; the default transport follows redirects to storage.
DatasetDocumentPage docs = dataset.listDocuments(50, null, "ready");
for (DatasetDocument doc : docs.getDocuments()) {
if (Boolean.TRUE.equals(doc.getDownloadAvailable())) {
byte[] original = dataset.downloadDocument(doc.getId());
}
}
if (docs.getNextCursor() != null) {
DatasetDocumentPage next = dataset.listDocuments(50, docs.getNextCursor(), "ready");
}Typed source helpers cover web, s3, gcs, gdrive, jira, confluence, and file_upload.
Use GenericSource as an escape hatch for new source types.
Source web = client.ingestion().createWeb("https://docs.vectoramp.com");
Source s3 = client.ingestion().createS3("my-docs-bucket");
Source gdrive = client.ingestion().createGoogleDrive("google-drive-folder-id");
Source jira = client.ingestion().createJira("atlassian-cloud-id");
Source confluence = client.ingestion().createConfluence("atlassian-cloud-id");
Source uploadSource = client.ingestion().createFileUpload("dataset-uuid");
// Names and advanced config are available when you need them.
Source deepWeb = client.ingestion().createWeb(
WebSource.builder("docs-site").url("https://docs.vectoramp.com").crawlDepth(2).build()
);
Source spaces = client.ingestion().createConfluence(
ConfluenceSource.builder("eng-confluence")
.cloudId("atlassian-cloud-id")
.spaces(java.util.List.of("ENG", "DOCS"))
.includeAttachments(true)
.build()
);
IngestionJob job = client.ingestion().startJob(web.getId(), "dataset-uuid");Dataset resource objects can create a typed source and start ingestion in one flow:
Source source = dataset.ingestSource(WebSource.of("https://docs.vectoramp.com"));
IngestionJob job = dataset.ingestSource(source.getId());UploadSession session = dataset.ingestFiles(java.util.List.of(
FileUpload.fromPath(java.nio.file.Path.of("docs/whitepaper.pdf"))
));
// PUT file bytes to each session.getUploads().get(i).getUploadUrl() with your HTTP client.
dataset.completeUpload(session);ask defaults to top_k=5, includes sources, and queries all accessible datasets when unscoped.
// Top-level convenience.
AskResponse response = client.ask(
AskRequest.of("What are the key features?").allDatasets().topK(5).includeSources(true)
);
// Or via the intelligence client (query is an alias for ask).
AskResponse scoped = client.intelligence().query(
AskRequest.of("Summarize the roadmap").datasetId("dataset-uuid")
);
// Streaming SSE.
try (java.util.stream.Stream<SseEvent> events = client.askStream(
AskRequest.of("Summarize the roadmap").datasetId("dataset-uuid")
)) {
events.forEach(event -> System.out.print(event.getContent()));
}IntelligenceSession session = client.intelligence().createSession(
SessionCreateRequest.of("support chat").datasetId("dataset-uuid")
);
client.intelligence().appendMessage(session.getId(), SessionMessageCreateRequest.user("Hello"));
java.util.List<SessionMessage> history = client.intelligence().listMessages(session.getId());
java.util.List<IntelligenceSession> recent = client.intelligence().listSessions(50);
client.intelligence().deleteSession(session.getId());Schedule schedule = client.schedules().create(
CreateScheduleRequest.builder()
.sourceId("source-uuid")
.datasetId("dataset-uuid")
.cron("0 2 * * *")
.timezone("UTC")
.build()
);
client.schedules().trigger(schedule.getId());
client.schedules().update(schedule.getId(), UpdateScheduleRequest.builder().enabled(false).build());Both access styles work everywhere the language allows: client.datasets().search(id, ...) and
datasetObj.search(...). Required arguments are listed first; optional arguments note their default.
| Method | Object-style | Args |
|---|---|---|
list(limit?, offset?) |
— | limit, offset optional (API defaults) |
create(name) |
— | name; embedding vectoramp/VectorAmp-Embedding-4B, dim 2560, metric cosine |
create(name, hybrid) |
— | hybrid -> hybrid:true |
create(name, dim, metric, embedding) |
— | full explicit form |
create(CreateDatasetRequest) |
— | builder: dim?, metric?(cosine), embedding?, hybrid?, metadata? |
get(id) |
— | id |
delete(id) |
ds.delete() |
id |
search(id, query) |
ds.search(query) |
query (text or SearchRequest); top_k default 10 |
insert(id, vectors) |
ds.insert(vectors) |
vectors (VectorRecord with String or numeric id) |
embed(id, texts) |
ds.embed(texts) |
texts |
addText(id, text) / addTexts(id, texts) |
ds.addText(text) / ds.addTexts(texts) |
texts; AddTextsRequest for ids/metadata |
listDocuments(id, limit?, cursor?, status?) |
ds.listDocuments(...) |
cursor pagination |
downloadDocument(id, docId) |
ds.downloadDocument(docId) |
raw bytes |
| Method | Args |
|---|---|
ask(query) / query(query) |
query (String or AskRequest); top_k default 5, sources on, all datasets |
askStream(query) / stream(query) |
returns Stream<SseEvent> |
createSession(title | SessionCreateRequest) |
optional title/workspace/dataset/metadata |
listSessions(limit?) |
returns List<IntelligenceSession> |
getSession(id) / deleteSession(id) |
id |
appendMessage(sessionId, role, content | request) |
role, content, optional metadata |
listMessages(sessionId, limit?) |
returns List<SessionMessage> |
| Method | Args |
|---|---|
listSources(limit?, offset?) / getSource(id) |
pagination / id |
createSource(CreateSourceRequest | IngestionSourceInput) |
generic create |
createWeb/createS3/createGCS/createGoogleDrive/createJira/createConfluence/createFileUpload(...) |
typed convenience creators |
startJob(sourceId, datasetId, pipelineId?) |
start ingestion |
listJobs(datasetId?, limit?, offset?) / getJob(id) / retryJob(id) |
jobs |
initializeUpload(sourceId, files) / completeUpload(sourceId, jobId, fileIds) |
presigned upload flow |
list(limit?, offset?), get(id), create(CreateScheduleRequest),
update(id, UpdateScheduleRequest), delete(id), trigger(id).
WebSource, S3Source, GCSSource, GoogleDriveSource, JiraSource, ConfluenceSource,
FileUploadSource, and GenericSource provide .of(...)/.builder(...) factories. Each maps to
its API source_type (web, s3, gcs, gdrive, jira, confluence, file_upload).
Public services depend on a small Transport interface. The default implementation is REST/JSON
over Java's built-in HttpClient; a future gRPC transport can be added without changing
client.datasets(), client.ingestion(), client.intelligence(), or client.ask() usage.
gradle clean checkCI runs the same command and publishes JUnit/Jacoco artifacts.