Project

vector_amp

0.0
The project is in a healthy, maintained state
Official Ruby client for VectorAmp datasets, ingestion, and intelligence APIs.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

 Project Readme

VectorAmp Ruby SDK

Official Ruby client for the VectorAmp API.

  • Default API: https://api.vectoramp.com
  • Auth: X-Api-Key
  • Transport abstraction: REST today, designed so gRPC can be added later
  • Licensed under Apache-2.0.

Installation

Add to your Gemfile:

gem "vector_amp"

Or install from a local checkout while developing:

bundle install

Quick start

require "vector_amp"

# api_key defaults to ENV["VECTORAMP_API_KEY"]; base_url defaults to production.
client = VectorAmp::Client.new

# One-call create: only a name is required. The SDK defaults to the managed
# vectoramp/VectorAmp-Embedding-4B model, infers dim (2560), metric "cosine",
# and always uses the SABLE index (index type is never exposed).
dataset = client.datasets.create(name: "product-docs")

# Create/get/list return VectorAmp::Dataset resources. Prefer the object->method
# style: call helpers directly on the returned dataset.
dataset.add_texts(
  ["VectorAmp is powered by SABLE."],
  metadata: { source: "readme" }
)

# Add raw vectors. Ids may be strings or integers; integer ids stay numbers.
dataset.insert(vectors: [
  { id: 1, values: [0.1, 0.2, 0.3], metadata: { title: "Intro" } },
  { id: "doc-002", values: [0.4, 0.5, 0.6], metadata: { title: "Details" } }
])

results = dataset.search("What powers VectorAmp?", top_k: 5, include_documents: true)
answer = dataset.ask("What powers VectorAmp?")

Creating datasets

# Minimal: name only. Embedding config is omitted so VectorAmp uses
# the managed VectorAmp-Embedding-4B model and infers dim 2560.
client.datasets.create(name: "docs")

# Enable hybrid (dense + sparse) search.
client.datasets.create(name: "docs", hybrid: true)

# Optional BYOM: use OpenAI only when you intentionally want that provider
# (dim inferred from the model).
client.datasets.create(name: "openai-docs", embedding: VectorAmp::Embedding.openai("large"))

# Custom/unknown model: pass dim explicitly.
client.datasets.create(name: "docs", embedding: { provider: "acme", model: "acme-embed" }, dim: 1024)

Configuration

client = VectorAmp::Client.new(
  api_key: "va_...",
  base_url: "https://api.vectoramp.com",
  timeout: 30
)

api_key defaults to ENV["VECTORAMP_API_KEY"].

Datasets

# Paginated envelope: { "datasets" => [VectorAmp::Dataset, ...], "total" => n, "limit" => 50, "offset" => 0 }
page = client.datasets.list(limit: 50, offset: 0)
dataset = page["datasets"].first

# Object->method style (preferred).
dataset = client.datasets.get("dataset-uuid")
dataset.stats
dataset.search(
  "wireless headphones",
  top_k: 10,
  filters: { category: "electronics" },
  advanced_filters: [
    { field: "price", op: "lt", value: 100.0 }
  ],
  include_metadata: true,
  include_documents: false,
  rerank: true # expands to vectoramp / VectorAmp-Rerank-v1
)
dataset.insert(vectors: [{ id: "sku-1", values: [0.1, 0.2], metadata: { category: "electronics" } }])
dataset.add_texts(["Wireless headphones"], metadata: { category: "electronics" })
dataset.ask("Which headphones should I buy?")
dataset.ingest_source("source-uuid")
dataset.delete

# Hybrid search: pass a sparse query and/or alpha weighting on a hybrid dataset.
dataset.search("wireless headphones", hybrid: true, sparse_query: "headphones", alpha: 0.5)

# Client-namespaced methods are equivalent and also supported.
client.datasets.stats("dataset-uuid")
client.datasets.search("dataset-uuid", "wireless headphones", top_k: 10)
client.datasets.insert("dataset-uuid", vectors: [])

client.datasets.create intentionally does not accept index_type; all datasets are created with SABLE.

Source documents

Dataset document listing is cursor-based: pass next_cursor into the next request and do not assume offsets or totals. Downloads return retained original bytes and follow API/storage redirects.

page = client.datasets.list_documents("dataset-uuid", limit: 50, cursor: nil, status: "ready")
page.fetch("documents").each do |doc|
  next unless doc["download_available"]

  bytes = client.datasets.download_document("dataset-uuid", doc.fetch("id"))
end

if page["next_cursor"]
  next_page = client.datasets.list_documents("dataset-uuid", cursor: page["next_cursor"])
end

# Resource-style helpers are available too.
dataset = client.datasets.get("dataset-uuid")
docs = dataset.list_documents(limit: 25)
raw = dataset.download_document(docs.fetch("documents").first.fetch("id"))

Ingestion

# Sources: paginated envelope { "sources" => [...], "total" => n, ... }
client.ingestion.list_sources(limit: 50, offset: 0)
client.ingestion.get_source("source-uuid")

# Typed builders cover the supported source_type values:
# "web", "s3", "gcs", "gdrive", "file_upload", "jira", and "confluence".
source = client.sources.create_web(
  start_urls: ["https://docs.example.com"],
  max_depth: 1,
  include_assets: true,
  max_assets_per_page: 5
)

s3_source = client.sources.create_s3(
  bucket: "vectoramp-docs",
  prefix: "public/"
)

gcs_source = client.sources.create_gcs(bucket: "vectoramp-docs-gcs", prefix: "public/")

jira_source = client.sources.create_jira(
  cloud_id: "atlassian-cloud-id",
  project_keys: ["ENG"],
  include_comments: true # default
)

confluence_source = client.sources.create_confluence(
  cloud_id: "atlassian-cloud-id",
  spaces: ["ENG"],
  username: "service-account@example.com",
  api_token: ENV["CONFLUENCE_API_TOKEN"]
)

gdrive_source = client.sources.create_google_drive(
  folder_ids: ["google-drive-folder-id"]
)

file_source = client.sources.create_file_upload

# You can still pass name: when you want control. If omitted, the SDK chooses
# a readable default from the URL, bucket, Google Drive id, or upload timestamp.

# GenericSource is an escape hatch for API-compatible source configs that are
# not modeled by a typed SDK helper yet.
generic_source = VectorAmp::GenericSource.new(
  source_type: "custom",
  name: "custom-source",
  config: { endpoint: "https://example.com/feed" }
)
client.sources.create(generic_source)

# The lower-level existing API is still supported.
source = client.ingestion.create_source(
  source_type: "web",
  name: "docs-site",
  config: { start_urls: ["https://docs.example.com"], max_depth: 1 }
)

job = client.ingestion.start_job(
  source_id: source["id"],
  dataset_id: "dataset-uuid"
)

# Dataset resources can ingest by source id or by a typed source object that has an id.
dataset.ingest_source(source["id"])
typed_source = VectorAmp::WebSource.new(id: source["id"], name: "docs-site", start_urls: ["https://docs.example.com"])
dataset.ingest_source(typed_source)

# Jobs: paginated envelope { "jobs" => [...], "total" => n, ... }
client.ingestion.list_jobs(dataset_id: "dataset-uuid", limit: 50, offset: 0)
client.ingestion.get_job(job["job_id"])
client.ingestion.job_files(job["job_id"])
client.ingestion.job_statistics(job["job_id"])
client.ingestion.cancel_job(job["job_id"])

Upload files from the filesystem

ingest_files uses the REST upload flow: create a file_upload source, initialize upload, PUT bytes to presigned URLs, then complete the upload.

client.ingestion.ingest_files(
  dataset_id: "dataset-uuid",
  paths: ["docs/whitepaper.pdf", "docs/notes.md"],
  metadata: { team: "product" }
)

# Or from a Dataset resource. No source name is required; the SDK creates a
# file_upload source with a generated name before uploading.
dataset.ingest_files(paths: ["docs/whitepaper.pdf"])

Intelligence / RAG

Non-streaming:

answer = client.ask(
  "What are the key features?",
  dataset_id: "all",
  top_k: 5
)
puts answer["answer"]

Multi-turn conversations: the Intelligence API is stateless, so send prior turns in conversation_history. You decide how many previous messages to include.

history = [
  { role: "user", content: "What are the key features?" },
  { role: "assistant", content: "Hybrid search, reranking, and managed ingestion." }
]

follow_up = client.intelligence.query(
  "Which of those help with relevance?",
  dataset_id: "all",
  conversation_history: history.last(10) # include as many prior turns as you want
)
puts follow_up["answer"]

Streaming SSE:

client.ask_stream("Summarize the docs", dataset_id: "dataset-uuid") do |event|
  print event["content"] if event["chunk_type"] == "text"
end

# Or as an Enumerator:
client.ask_stream("Summarize").each do |event|
  puts event.inspect
end

Sessions

Persist multi-turn conversations server-side instead of resending history.

session = client.intelligence.create_session(title: "Onboarding", dataset_id: "dataset-uuid")

client.intelligence.append_message(session.fetch("id"), role: "user", content: "What is SABLE?")
client.intelligence.append_message(session.fetch("id"), role: "assistant", content: "A managed index type.")

messages = client.intelligence.list_messages(session.fetch("id"))
sessions = client.intelligence.list_sessions(limit: 20)
client.intelligence.get_session(session.fetch("id"))
client.intelligence.delete_session(session.fetch("id"))

Error handling

Non-2xx responses raise VectorAmp::APIError with status, body, and headers.

begin
  client.datasets.get("missing")
rescue VectorAmp::APIError => e
  warn "VectorAmp API error #{e.status}: #{e.message}"
end

Development

bundle install
bundle exec rake test

Tests mock HTTP with WebMock and enforce SimpleCov coverage.

Method reference

Both access styles work everywhere: client.datasets.<m>(id, ...) and the equivalent datasetObj.<m>(...) on a returned VectorAmp::Dataset.

Datasets — client.datasets

Method Required Optional (defaults)
create(name:) name dim (inferred), embedding (vectoramp/VectorAmp-Embedding-4B), metric ("cosine"), hybrid, filters, metadata_schema, tuning, metadata
list limit (50), offset (0)
get(id) id
delete(id) id
stats(id) id
search(id, query = nil) id query/query_text/search_text, top_k (10), filters, advanced_filters, hybrid, sparse_query, alpha, rerank, include_documents, include_metadata, include_embeddings, embedding_model, embedding_provider, nprobe_override, rerank_depth_override
insert(id, vectors:) id, vectors — (integer ids preserved as numbers)
embed(id) id text, texts (one required)
add_texts(id, texts = nil) id, texts ids (auto-generated), metadata
list_documents(id) id limit (50), cursor, status
download_document(id, document_id) id, document_id

Dataset-object helpers: search, insert, add_texts, embed, delete, stats, list_documents, download_document, ask, ingest_source, ingest_files.

Intelligence — client.intelligence (and client.ask / client.ask_stream)

Method Required Optional (defaults)
query(query) / ask / ask_stream query dataset_id ("all" when unscoped), top_k (5 server-side), conversation_history, include_sources, stream
create_session title, dataset_id, workspace_id, metadata
list_sessions limit (50)
get_session(session_id) session_id
delete_session(session_id) session_id
append_message(session_id, role:, content:) session_id, role, content metadata
list_messages(session_id) session_id limit (100)

Sources — client.sources (alias of client.ingestion)

create(source), create_web(start_urls:), create_s3(bucket:), create_gcs(bucket:), create_google_drive(folder_ids:|file_ids:), create_jira(cloud_id:), create_confluence(cloud_id:|base_url:), create_file_upload, list_sources, get_source(id). Jobs: start_job(source_id:, dataset_id:), list_jobs, get_job(id), retry_job(id), ingest_files(dataset_id:, paths:).

Schedules — client.schedules

list, get(id), create(source_id:, dataset_id:, cron:), update(id), delete(id), trigger(id).

License

Apache-2.0. See LICENSE and NOTICE.