Skip to content

Commit 041de1f

Browse files
committed
fix(embeddings): drop a capability the selected model no longer offers
The per-model Dimensions and Task Type dropdowns each share one subblock id, and nothing clears a stored subblock value when its dependsOn fields change — dependsOn only feeds rendering. A choice made for one model therefore outlives a switch to another. Picking 3072 on text-embedding-3-large and switching to -3-small left 3072 stored while the dropdown offered at most 1536, and the block forwarded it. Same for a task type: 'similarity' chosen on Gemini survived a switch to Cohere, which has no equivalent input type. The guards only checked that the model declared the capability at all, not that the value was one it lists. Check membership so a stale value falls back to the model's native size, or is omitted, instead of being sent and rejected. The user cannot have deliberately chosen an option the dropdown stopped presenting.
1 parent 350c389 commit 041de1f

2 files changed

Lines changed: 73 additions & 5 deletions

File tree

apps/sim/blocks/blocks/embeddings.test.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,63 @@ describe('Embeddings block', () => {
144144
})
145145
})
146146

147+
/**
148+
* Every per-model Dimensions dropdown shares the `dimensions` id and nothing
149+
* clears a stored subblock value when its `dependsOn` fields change, so a
150+
* reduction chosen for one model outlives a switch to another.
151+
*/
152+
it('drops a dimension the newly selected model no longer offers', () => {
153+
const params = EmbeddingsBlock.tools.config?.params
154+
155+
// 3072 is valid for text-embedding-3-large but not for -3-small.
156+
expect(
157+
params?.({
158+
provider: 'openai',
159+
model: 'text-embedding-3-small',
160+
input: 'hello',
161+
apiKey: 'k',
162+
dimensions: '3072',
163+
})
164+
).toEqual({ apiKey: 'k', input: 'hello', model: 'text-embedding-3-small' })
165+
166+
// A model with no reduction support never forwards one.
167+
expect(
168+
params?.({
169+
provider: 'mistral',
170+
model: 'mistral-embed',
171+
input: 'hello',
172+
apiKey: 'k',
173+
dimensions: '512',
174+
})
175+
).toEqual({ apiKey: 'k', input: 'hello', model: 'mistral-embed' })
176+
})
177+
178+
it('drops a task type the newly selected model no longer offers', () => {
179+
const params = EmbeddingsBlock.tools.config?.params
180+
181+
// Gemini supports 'similarity'; Cohere does not.
182+
expect(
183+
params?.({
184+
provider: 'cohere',
185+
model: 'embed-v4.0',
186+
input: 'hello',
187+
apiKey: 'k',
188+
taskType: 'similarity',
189+
})
190+
).toEqual({ apiKey: 'k', input: 'hello', model: 'embed-v4.0' })
191+
192+
// A model with no task conditioning never forwards one.
193+
expect(
194+
params?.({
195+
provider: 'openai',
196+
model: 'text-embedding-3-small',
197+
input: 'hello',
198+
apiKey: 'k',
199+
taskType: 'query',
200+
})
201+
).toEqual({ apiKey: 'k', input: 'hello', model: 'text-embedding-3-small' })
202+
})
203+
147204
it('requires input text', () => {
148205
expect(() =>
149206
EmbeddingsBlock.tools.config?.params?.({ provider: 'openai', apiKey: 'k' })

apps/sim/blocks/blocks/embeddings.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { EmbeddingsIcon } from '@/components/icons'
1212
* `embeddings.test.ts` drift test asserts the literals still match the catalog.
1313
*/
1414
import { EMBEDDING_MODELS } from '@/lib/embeddings/catalog'
15-
import type { EmbeddingCatalogProvider } from '@/lib/embeddings/types'
15+
import type { EmbeddingCatalogProvider, EmbeddingTaskType } from '@/lib/embeddings/types'
1616
import type { BlockConfig, BlockMeta } from '@/blocks/types'
1717
import { AuthMode, IntegrationType } from '@/blocks/types'
1818
import type { EmbeddingsResponse } from '@/tools/embeddings/types'
@@ -290,10 +290,21 @@ export const EmbeddingsBlock: BlockConfig<EmbeddingsResponse> = {
290290
input: params.input,
291291
model,
292292
/** Only send capabilities the selected model actually declares. */
293-
...(info?.supportedTaskTypes && params.taskType && { taskType: params.taskType }),
294-
...(info?.supportedDimensions &&
295-
dimensions !== undefined &&
296-
!Number.isNaN(dimensions) && { dimensions }),
293+
...(info?.supportedTaskTypes &&
294+
params.taskType &&
295+
info.supportedTaskTypes.includes(params.taskType as EmbeddingTaskType) && {
296+
taskType: params.taskType,
297+
}),
298+
/**
299+
* Every per-model Dimensions dropdown shares the `dimensions` id, and
300+
* switching models does not clear the stored value — so a reduction
301+
* picked for one model can outlive it. Drop anything the current model
302+
* no longer offers and fall back to its native size, rather than
303+
* sending a value the dropdown stopped presenting.
304+
*/
305+
...(dimensions !== undefined &&
306+
!Number.isNaN(dimensions) &&
307+
info?.supportedDimensions?.includes(dimensions) && { dimensions }),
297308
}
298309
},
299310
},

0 commit comments

Comments
 (0)