Skip to content

Commit 0ac5d91

Browse files
committed
feat(embeddings): add Voyage AI embedding models, contextualized embeddings and rerank
Adds a voyage provider to the embedding catalog (voyage-4-large, voyage-4, voyage-4-lite, voyage-code-4, voyage-finance-2, voyage-law-2 and the voyage-3.x generation) with an adapter for /v1/embeddings, the embeddings_voyage tool, BYOK key support, VOYAGE_API_KEY for hosted use and per-model pricing. Adds a Voyage AI block with contextualized embeddings (list of chunk lists per document) and rerank tools, with hosted-key billing and a string detail error extractor.
1 parent 69bfb1b commit 0ac5d91

44 files changed

Lines changed: 1332 additions & 23 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎apps/docs/components/ui/icon-mapping.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
822822
video_generator_v3: VideoIcon,
823823
vision: EyeIcon,
824824
vision_v2: EyeIcon,
825+
voyageai: EmbeddingsIcon,
825826
wait: CirclePause,
826827
wealthbox: WealthboxIcon,
827828
webflow: WebflowIcon,

‎apps/docs/content/docs/integrations/embeddings.mdx‎

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Knowledge bases embed separately. Each base fixes an embedding model and vector
3535

3636
## Use the block [#usage-instructions]
3737

38-
Turn text into embedding vectors for semantic search, clustering, and similarity. Supports OpenAI, OpenRouter, Google Gemini, Cohere, and Mistral embedding models, plus embedding models on a self-hosted Ollama.
38+
Turn text into embedding vectors for semantic search, clustering, and similarity. Supports OpenAI, OpenRouter, Google Gemini, Cohere, Mistral, and Voyage AI embedding models, plus embedding models on a self-hosted Ollama.
3939

4040
## Actions
4141

@@ -189,6 +189,36 @@ Generate embeddings from text using Mistral's embedding models
189189

190190
</ReferenceDetails>
191191

192+
### Voyage AI Embeddings
193+
194+
Generate embeddings from text using Voyage AI's embedding models
195+
196+
<ReferenceDetails>
197+
198+
#### Input
199+
200+
| Parameter | Type | Required | Description |
201+
| --------- | ---- | -------- | ----------- |
202+
| `input` | string | Yes | Text to embed, or an array of texts to embed in one call |
203+
| `model` | string | Yes | Embedding model to use |
204+
| `taskType` | string | No | What the embedding is for, when the model supports task conditioning: document, query, similarity, classification, or clustering |
205+
| `dimensions` | number | No | Output dimensions, when the model supports truncation. Defaults to native. |
206+
| `apiKey` | string | Yes | API key for the selected embedding provider |
207+
208+
#### Output
209+
210+
| Parameter | Type | Description |
211+
| --------- | ---- | ----------- |
212+
| `embeddings` | json | Generated embedding vectors, one per input, in input order |
213+
| `model` | string | Model used |
214+
| `provider` | string | Provider used |
215+
| `dimensions` | number | Dimensionality of each returned vector |
216+
| `usage` | json | Token usage |
217+
| ↳ `prompt_tokens` | number | Tokens in the input |
218+
| ↳ `total_tokens` | number | Total tokens billed |
219+
220+
</ReferenceDetails>
221+
192222
### Ollama Embeddings
193223

194224
Generate embeddings on a self-hosted Ollama server

‎apps/docs/content/docs/integrations/meta.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@
297297
"uptimerobot",
298298
"vanta",
299299
"vercel",
300+
"voyageai",
300301
"wealthbox",
301302
"wealthbox-service-account",
302303
"webflow",
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
title: Voyage AI
3+
description: Contextualized embeddings and reranking
4+
integration:
5+
type: "voyageai"
6+
color: "#7B4DFF"
7+
---
8+
9+
import { ReferenceDetails } from "@/components/ui/reference-details"
10+
11+
12+
{/* MANUAL-CONTENT-START:intro */}
13+
[Voyage AI](https://www.voyageai.com/) provides embedding and reranking models for search and retrieval.
14+
15+
With the Voyage AI block, you can:
16+
17+
- **Embed documents with context**: Send the full text of each document. Voyage splits it into chunks, and every chunk vector reflects the whole document around it, so retrieval finds the right passage even when the chunk alone is ambiguous. Search queries are embedded with the same model and Input Type set to Query.
18+
- **Rerank results**: Reorder retrieved texts by relevance to a query, so your agent reads the best matches first.
19+
20+
Create an API key in the [Voyage AI dashboard](https://dash.voyageai.com/) and paste it into the block, or store it once as a workspace key under Settings > BYOK.
21+
22+
In Sim, the Voyage AI block lets your agents index documents for search and tighten the results they retrieve before answering.
23+
{/* MANUAL-CONTENT-END */}
24+
25+
## Use the block [#usage-instructions]
26+
27+
Embed documents with Voyage AI contextualized models, so each chunk vector reflects the whole document around it, and rerank texts against a query with Voyage AI rerankers.
28+
29+
## Actions
30+
31+
### Voyage AI Contextualized Embeddings
32+
33+
Embed documents with a contextualized model: Voyage splits each document into chunks, and every chunk vector also reflects the whole document it came from
34+
35+
<ReferenceDetails>
36+
37+
#### Input
38+
39+
| Parameter | Type | Required | Description |
40+
| --------- | ---- | -------- | ----------- |
41+
| `input` | array | Yes | Texts to embed, as a list of strings. For document: the full text of each document, which Voyage chunks itself. For query: one search query per entry. |
42+
| `model` | string | Yes | Embedding model: voyage-context-4 or voyage-context-3 |
43+
| `inputType` | string | Yes | What the embeddings are for: document \(documents to index, chunked by Voyage\) or query \(search queries\) |
44+
| `dimensions` | number | No | Output dimensions: 256, 512, 1024 \(default\), or 2048 |
45+
| `apiKey` | string | Yes | Your Voyage AI API key |
46+
47+
#### Output
48+
49+
| Parameter | Type | Description |
50+
| --------- | ---- | ----------- |
51+
| `embeddings` | json | Embedding vectors grouped by document: one list per input document, one vector per chunk, in input order |
52+
| `chunks` | json | The text of each chunk, grouped like embeddings. Returned for documents, which Voyage chunks itself |
53+
| `model` | string | Model used |
54+
| `dimensions` | number | Dimensionality of each vector |
55+
| `totalTokens` | number | Tokens billed for the request |
56+
57+
</ReferenceDetails>
58+
59+
### Voyage AI Rerank
60+
61+
Rank a list of texts by relevance to a query with a Voyage AI reranker, most relevant first
62+
63+
<ReferenceDetails>
64+
65+
#### Input
66+
67+
| Parameter | Type | Required | Description |
68+
| --------- | ---- | -------- | ----------- |
69+
| `query` | string | Yes | The query to rank the documents against |
70+
| `documents` | array | Yes | The texts to rank, as a list of strings \(up to 1,000\) |
71+
| `model` | string | Yes | Reranker model: rerank-3, rerank-3-lite, rerank-2.5 or rerank-2.5-lite |
72+
| `topK` | number | No | Number of most relevant documents to return. Defaults to all of them. |
73+
| `apiKey` | string | Yes | Your Voyage AI API key |
74+
75+
#### Output
76+
77+
| Parameter | Type | Description |
78+
| --------- | ---- | ----------- |
79+
| `results` | array | Documents ranked by relevance, most relevant first |
80+
| ↳ `index` | number | Position of the document in the input list |
81+
| ↳ `relevanceScore` | number | Relevance of the document to the query |
82+
| ↳ `document` | string | The document text |
83+
| `model` | string | Reranker model used |
84+
| `totalTokens` | number | Tokens billed for the request |
85+
86+
</ReferenceDetails>
87+
88+

‎apps/sim/.env.example‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ CRON_SECRET=your_cron_secret # Use `openssl rand -hex 32` to generate. Authentic
115115
# NEXT_PUBLIC_AZURE_CONFIGURED=true # Set when Azure credentials are pre-configured above. Hides endpoint/key/version fields in Agent block UI.
116116
# COHERE_API_KEY= # Cohere API key for the Knowledge block reranker (rerank-v4.0-pro/-fast, rerank-v3.5). Alternatively set COHERE_API_KEY_1/2/3 for rotation.
117117
# NEXT_PUBLIC_COHERE_CONFIGURED=true # Set when COHERE_API_KEY (or rotation keys) are pre-configured above. Hides the Cohere API Key field on the Knowledge block UI.
118+
# VOYAGE_API_KEY= # Voyage AI API key for the Embeddings block (voyage-4-large, voyage-4, voyage-4-lite, voyage-code-4, ...) and the Voyage AI block (contextualized embeddings, rerank).
118119

119120
# Hosted tool API keys (Optional - lets Sim supply the key so users don't have to bring their own).
120121
# Each provider reads `{PREFIX}_COUNT` then `{PREFIX}_1..N`, distributing requests round-robin across the keys.

‎apps/sim/app/workspace/[workspaceId]/settings/components/byok/byok.tsx‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
ContextDevIcon,
1414
DatagmaIcon,
1515
DropcontactIcon,
16+
EmbeddingsIcon,
1617
EnrowIcon,
1718
ExaAIIcon,
1819
FalIcon,
@@ -106,6 +107,13 @@ const PROVIDERS: (BYOKManagerProvider & { id: BYOKProviderId })[] = [
106107
description: 'LLM calls and Knowledge Base OCR',
107108
placeholder: 'Enter your API key',
108109
},
110+
{
111+
id: 'voyage',
112+
name: 'Voyage AI',
113+
icon: EmbeddingsIcon,
114+
description: 'Embeddings, contextualized embeddings and reranking',
115+
placeholder: 'pa-...',
116+
},
109117
{
110118
id: 'zai',
111119
name: 'Z.ai',
@@ -382,6 +390,7 @@ const PROVIDER_SECTIONS: BYOKProviderSection[] = [
382390
'mistral',
383391
'zai',
384392
'cohere',
393+
'voyage',
385394
'xai',
386395
'kimi',
387396
'typesafe',

‎apps/sim/blocks/blocks/embeddings.ts‎

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const TOOL_ID_BY_PROVIDER: Record<EmbeddingBlockProvider, string> = {
3333
gemini: 'embeddings_gemini',
3434
cohere: 'embeddings_cohere',
3535
mistral: 'embeddings_mistral',
36+
voyage: 'embeddings_voyage',
3637
ollama: 'embeddings_ollama',
3738
}
3839

@@ -42,6 +43,7 @@ const PROVIDER_LABELS: Record<EmbeddingBlockProvider, string> = {
4243
gemini: 'Google Gemini',
4344
cohere: 'Cohere',
4445
mistral: 'Mistral',
46+
voyage: 'Voyage AI',
4547
ollama: 'Ollama',
4648
}
4749

@@ -62,16 +64,37 @@ const TASK_TYPE_LABELS: Record<EmbeddingTaskType, string> = {
6264
* sub-block id, so each is scoped by a `condition` naming the provider.
6365
*/
6466
const MODEL_SUB_BLOCKS: SubBlockConfig[] = EMBEDDING_CATALOG_PROVIDERS.map((provider) => {
67+
const defaultModel = DEFAULT_MODEL_BY_PROVIDER[provider]
68+
const options = getModelsForProvider(provider).map((id) => ({
69+
label: EMBEDDING_MODELS[id].label,
70+
id,
71+
}))
72+
const condition = { field: 'provider', value: provider }
73+
/**
74+
* A provider with no default model must not have one picked for the user: a
75+
* dropdown selects its first option on its own, so this is a combobox whose
76+
* `emptyIsValid` suppresses that, left empty until a model is chosen.
77+
*/
78+
if (!defaultModel) {
79+
return {
80+
id: 'model',
81+
title: 'Model',
82+
type: 'combobox',
83+
options,
84+
placeholder: 'Select a model',
85+
required: true,
86+
emptyIsValid: true,
87+
condition,
88+
dependsOn: ['provider'],
89+
}
90+
}
6591
return {
6692
id: 'model',
6793
title: 'Model',
6894
type: 'dropdown',
69-
options: getModelsForProvider(provider).map((id) => ({
70-
label: EMBEDDING_MODELS[id].label,
71-
id,
72-
})),
73-
value: () => DEFAULT_MODEL_BY_PROVIDER[provider],
74-
condition: { field: 'provider', value: provider },
95+
options,
96+
value: () => defaultModel,
97+
condition,
7598
dependsOn: ['provider'],
7699
}
77100
})
@@ -164,7 +187,7 @@ export const EmbeddingsBlock: BlockConfig = {
164187
description: 'Generate embeddings',
165188
authMode: AuthMode.ApiKey,
166189
longDescription:
167-
'Turn text into embedding vectors for semantic search, clustering, and similarity. Supports OpenAI, OpenRouter, Google Gemini, Cohere, and Mistral embedding models, plus embedding models on a self-hosted Ollama.',
190+
'Turn text into embedding vectors for semantic search, clustering, and similarity. Supports OpenAI, OpenRouter, Google Gemini, Cohere, Mistral, and Voyage AI embedding models, plus embedding models on a self-hosted Ollama.',
168191
category: 'tools',
169192
integrationType: IntegrationType.AI,
170193
docsLink: 'https://docs.sim.ai/integrations/embeddings',
@@ -237,6 +260,7 @@ export const EmbeddingsBlock: BlockConfig = {
237260
'embeddings_gemini',
238261
'embeddings_cohere',
239262
'embeddings_mistral',
263+
'embeddings_voyage',
240264
'embeddings_ollama',
241265
],
242266
config: {
@@ -327,6 +351,7 @@ export const EmbeddingsBlock: BlockConfig = {
327351
savedModel && EMBEDDING_MODELS[savedModel]?.provider === catalogProvider
328352
? savedModel
329353
: DEFAULT_MODEL_BY_PROVIDER[catalogProvider]
354+
if (!model) throw new Error(`A ${PROVIDER_LABELS[catalogProvider]} model is required`)
330355

331356
const info = EMBEDDING_MODELS[model]
332357
const requested =

0 commit comments

Comments
 (0)