🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@ai-sdk/mistral

Package Overview
Dependencies
Maintainers
3
Versions
381
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ai-sdk/mistral - npm Package Compare versions

Comparing version
4.0.16
to
4.0.17
+63
src/mistral-transcription-model-options.ts
import {
lazySchema,
zodSchema,
type InferSchema,
} from '@ai-sdk/provider-utils';
import { z } from 'zod/v4';
export type MistralTranscriptionModelId = 'voxtral-mini-latest' | (string & {});
// https://docs.mistral.ai/api/endpoint/audio/transcriptions
export const mistralTranscriptionModelOptions = lazySchema(() =>
zodSchema(
z.object({
/**
* The language of the audio, e.g. "en". Providing the language can boost
* accuracy.
*/
language: z.string().min(1).optional(),
/**
* The sampling temperature.
*/
temperature: z.number().optional(),
/**
* The timestamp granularities to include in the transcription response.
*/
timestampGranularities: z
.array(z.enum(['segment', 'word']))
.min(1)
.optional(),
/**
* Whether to identify speakers in the transcription.
*/
diarize: z.boolean().optional(),
/**
* Words or phrases to guide the model toward correct spellings of names,
* technical terms, or domain-specific vocabulary.
*
* Mistral requires each item to omit commas and whitespace. Use
* underscores to represent multi-word phrases.
*/
contextBias: z
.array(
z
.string()
.min(1)
.regex(
/^[^\s,]+$/,
'Context bias items must not contain commas or whitespace.',
),
)
.max(100)
.optional(),
}),
),
);
export type MistralTranscriptionModelOptions = InferSchema<
typeof mistralTranscriptionModelOptions
>;
import {
InvalidArgumentError,
type JSONObject,
type SharedV4Warning,
type TranscriptionModelV4,
} from '@ai-sdk/provider';
import {
combineHeaders,
convertBase64ToUint8Array,
createJsonResponseHandler,
mediaTypeToExtension,
parseProviderOptions,
postFormDataToApi,
serializeModelOptions,
WORKFLOW_DESERIALIZE,
WORKFLOW_SERIALIZE,
type FetchFunction,
} from '@ai-sdk/provider-utils';
import { z } from 'zod/v4';
import { mistralFailedResponseHandler } from './mistral-error';
import {
mistralTranscriptionModelOptions,
type MistralTranscriptionModelId,
} from './mistral-transcription-model-options';
type MistralTranscriptionModelConfig = {
provider: string;
baseURL: string;
headers?: () => Record<string, string | undefined>;
fetch?: FetchFunction;
_internal?: {
currentDate?: () => Date;
};
};
export class MistralTranscriptionModel implements TranscriptionModelV4 {
readonly specificationVersion = 'v4';
static [WORKFLOW_SERIALIZE](model: MistralTranscriptionModel) {
return serializeModelOptions({
modelId: model.modelId,
config: model.config,
});
}
static [WORKFLOW_DESERIALIZE](options: {
modelId: MistralTranscriptionModelId;
config: MistralTranscriptionModelConfig;
}) {
return new MistralTranscriptionModel(options.modelId, options.config);
}
get provider(): string {
return this.config.provider;
}
constructor(
readonly modelId: MistralTranscriptionModelId,
private readonly config: MistralTranscriptionModelConfig,
) {}
private async getArgs({
audio,
mediaType,
providerOptions,
}: Parameters<TranscriptionModelV4['doGenerate']>[0]) {
const warnings: SharedV4Warning[] = [];
const mistralOptions = await parseProviderOptions({
provider: 'mistral',
providerOptions,
schema: mistralTranscriptionModelOptions,
});
// Mistral documents these options as mutually incompatible. Rejecting the
// combination locally provides a stable SDK error instead of an API 4xx.
if (
mistralOptions?.language != null &&
mistralOptions.timestampGranularities != null
) {
throw new InvalidArgumentError({
argument: 'providerOptions',
message:
'providerOptions.mistral.language cannot be combined with providerOptions.mistral.timestampGranularities',
});
}
const formData = new FormData();
const blob =
audio instanceof Uint8Array
? new Blob([audio])
: new Blob([convertBase64ToUint8Array(audio)]);
formData.append('model', this.modelId);
formData.append(
'file',
new File([blob], 'audio', { type: mediaType }),
`audio.${mediaTypeToExtension(mediaType)}`,
);
if (mistralOptions != null) {
appendFormValue(formData, 'language', mistralOptions.language);
appendFormValue(formData, 'temperature', mistralOptions.temperature);
appendFormValue(
formData,
'timestamp_granularities',
mistralOptions.timestampGranularities,
);
appendFormValue(formData, 'diarize', mistralOptions.diarize);
appendFormValue(formData, 'context_bias', mistralOptions.contextBias);
}
return { formData, warnings };
}
async doGenerate(
options: Parameters<TranscriptionModelV4['doGenerate']>[0],
): Promise<Awaited<ReturnType<TranscriptionModelV4['doGenerate']>>> {
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
const { formData, warnings } = await this.getArgs(options);
const {
value: response,
responseHeaders,
rawValue: rawResponse,
} = await postFormDataToApi({
url: `${this.config.baseURL}/audio/transcriptions`,
headers: combineHeaders(this.config.headers?.(), options.headers),
formData,
failedResponseHandler: mistralFailedResponseHandler,
successfulResponseHandler: createJsonResponseHandler(
mistralTranscriptionResponseSchema,
),
abortSignal: options.abortSignal,
fetch: this.config.fetch,
});
const segments =
response.segments?.map(segment => ({
text: segment.text,
startSecond: segment.start,
endSecond: segment.end,
})) ?? [];
const mistralMetadata: JSONObject = {};
if (response.usage != null) {
mistralMetadata.usage = {
...(response.usage.prompt_tokens != null && {
promptTokens: response.usage.prompt_tokens,
}),
...(response.usage.completion_tokens != null && {
completionTokens: response.usage.completion_tokens,
}),
...(response.usage.total_tokens != null && {
totalTokens: response.usage.total_tokens,
}),
...(response.usage.prompt_audio_seconds != null && {
promptAudioSeconds: response.usage.prompt_audio_seconds,
}),
...(response.usage.request_count != null && {
requestCount: response.usage.request_count,
}),
};
}
const providerSegments = response.segments
?.filter(
segment =>
segment.type != null ||
segment.score != null ||
segment.speaker_id != null,
)
.map(segment => ({
text: segment.text,
startSecond: segment.start,
endSecond: segment.end,
...(segment.type != null && { type: segment.type }),
...(segment.score != null && { score: segment.score }),
...(segment.speaker_id != null && {
speakerId: segment.speaker_id,
}),
}));
if (providerSegments != null && providerSegments.length > 0) {
mistralMetadata.segments = providerSegments;
}
return {
text: response.text,
segments,
language: response.language ?? undefined,
durationInSeconds:
response.usage?.prompt_audio_seconds ??
segments.at(-1)?.endSecond ??
undefined,
warnings,
response: {
timestamp: currentDate,
modelId: response.model,
headers: responseHeaders,
body: rawResponse,
},
...(Object.keys(mistralMetadata).length > 0 && {
providerMetadata: {
mistral: mistralMetadata,
},
}),
};
}
}
function appendFormValue(
formData: FormData,
key: string,
value: string | number | boolean | string[] | undefined,
): void {
if (value == null) {
return;
}
if (Array.isArray(value)) {
for (const item of value) {
formData.append(key, item);
}
return;
}
formData.append(key, String(value));
}
const mistralTranscriptionResponseSchema = z.object({
model: z.string(),
text: z.string(),
language: z.string().nullish(),
segments: z
.array(
z.object({
type: z.literal('transcription_segment').nullish(),
text: z.string(),
start: z.number(),
end: z.number(),
score: z.number().nullish(),
speaker_id: z.string().nullish(),
}),
)
.nullish(),
usage: z
.object({
prompt_tokens: z.number().nullish(),
completion_tokens: z.number().nullish(),
total_tokens: z.number().nullish(),
prompt_audio_seconds: z.number().nullish(),
request_count: z.number().nullish(),
})
.nullish(),
});
+9
-0
# @ai-sdk/mistral
## 4.0.17
### Patch Changes
- 4e116c9: Add Voxtral batch transcription support through `mistral.transcription()` and `mistral.transcriptionModel()`.
- Updated dependencies [1659cd5]
- Updated dependencies [6a5bdff]
- @ai-sdk/provider-utils@5.0.15
## 4.0.16

@@ -4,0 +13,0 @@

+22
-3

@@ -1,3 +0,4 @@

import { ProviderV4, LanguageModelV4, EmbeddingModelV4, SpeechModelV4 } from '@ai-sdk/provider';
import { FetchFunction } from '@ai-sdk/provider-utils';
import { ProviderV4, LanguageModelV4, EmbeddingModelV4, SpeechModelV4, TranscriptionModelV4 } from '@ai-sdk/provider';
import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
import { InferSchema, FetchFunction } from '@ai-sdk/provider-utils';
import { z } from 'zod/v4';

@@ -40,2 +41,12 @@

type MistralTranscriptionModelId = 'voxtral-mini-latest' | (string & {});
declare const mistralTranscriptionModelOptions: _ai_sdk_provider_utils.LazySchema<{
language?: string | undefined;
temperature?: number | undefined;
timestampGranularities?: ("segment" | "word")[] | undefined;
diarize?: boolean | undefined;
contextBias?: string[] | undefined;
}>;
type MistralTranscriptionModelOptions = InferSchema<typeof mistralTranscriptionModelOptions>;
interface MistralProvider extends ProviderV4 {

@@ -68,2 +79,10 @@ (modelId: MistralChatModelId): LanguageModelV4;

/**
* Creates a model for audio transcription.
*/
transcription(modelId: MistralTranscriptionModelId): TranscriptionModelV4;
/**
* Creates a model for audio transcription.
*/
transcriptionModel(modelId: MistralTranscriptionModelId): TranscriptionModelV4;
/**
* @deprecated Use `embedding` instead.

@@ -110,2 +129,2 @@ */

export { type MistralEmbeddingModelOptions, type MistralLanguageModelChatOptions, type MistralLanguageModelChatOptions as MistralLanguageModelOptions, type MistralProvider, type MistralProviderSettings, type MistralSpeechModelId, type MistralSpeechModelOptions, VERSION, createMistral, mistral };
export { type MistralEmbeddingModelOptions, type MistralLanguageModelChatOptions, type MistralLanguageModelChatOptions as MistralLanguageModelOptions, type MistralProvider, type MistralProviderSettings, type MistralSpeechModelId, type MistralSpeechModelOptions, type MistralTranscriptionModelId, type MistralTranscriptionModelOptions, VERSION, createMistral, mistral };

@@ -1097,4 +1097,235 @@ // src/mistral-provider.ts

// src/mistral-transcription-model.ts
import {
InvalidArgumentError
} from "@ai-sdk/provider";
import {
combineHeaders as combineHeaders4,
convertBase64ToUint8Array,
createJsonResponseHandler as createJsonResponseHandler4,
mediaTypeToExtension,
parseProviderOptions as parseProviderOptions4,
postFormDataToApi,
serializeModelOptions as serializeModelOptions4,
WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE4,
WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE4
} from "@ai-sdk/provider-utils";
import { z as z9 } from "zod/v4";
// src/mistral-transcription-model-options.ts
import {
lazySchema,
zodSchema
} from "@ai-sdk/provider-utils";
import { z as z8 } from "zod/v4";
var mistralTranscriptionModelOptions = lazySchema(
() => zodSchema(
z8.object({
/**
* The language of the audio, e.g. "en". Providing the language can boost
* accuracy.
*/
language: z8.string().min(1).optional(),
/**
* The sampling temperature.
*/
temperature: z8.number().optional(),
/**
* The timestamp granularities to include in the transcription response.
*/
timestampGranularities: z8.array(z8.enum(["segment", "word"])).min(1).optional(),
/**
* Whether to identify speakers in the transcription.
*/
diarize: z8.boolean().optional(),
/**
* Words or phrases to guide the model toward correct spellings of names,
* technical terms, or domain-specific vocabulary.
*
* Mistral requires each item to omit commas and whitespace. Use
* underscores to represent multi-word phrases.
*/
contextBias: z8.array(
z8.string().min(1).regex(
/^[^\s,]+$/,
"Context bias items must not contain commas or whitespace."
)
).max(100).optional()
})
)
);
// src/mistral-transcription-model.ts
var MistralTranscriptionModel = class _MistralTranscriptionModel {
constructor(modelId, config) {
this.modelId = modelId;
this.config = config;
this.specificationVersion = "v4";
}
static [WORKFLOW_SERIALIZE4](model) {
return serializeModelOptions4({
modelId: model.modelId,
config: model.config
});
}
static [WORKFLOW_DESERIALIZE4](options) {
return new _MistralTranscriptionModel(options.modelId, options.config);
}
get provider() {
return this.config.provider;
}
async getArgs({
audio,
mediaType,
providerOptions
}) {
const warnings = [];
const mistralOptions = await parseProviderOptions4({
provider: "mistral",
providerOptions,
schema: mistralTranscriptionModelOptions
});
if ((mistralOptions == null ? void 0 : mistralOptions.language) != null && mistralOptions.timestampGranularities != null) {
throw new InvalidArgumentError({
argument: "providerOptions",
message: "providerOptions.mistral.language cannot be combined with providerOptions.mistral.timestampGranularities"
});
}
const formData = new FormData();
const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([convertBase64ToUint8Array(audio)]);
formData.append("model", this.modelId);
formData.append(
"file",
new File([blob], "audio", { type: mediaType }),
`audio.${mediaTypeToExtension(mediaType)}`
);
if (mistralOptions != null) {
appendFormValue(formData, "language", mistralOptions.language);
appendFormValue(formData, "temperature", mistralOptions.temperature);
appendFormValue(
formData,
"timestamp_granularities",
mistralOptions.timestampGranularities
);
appendFormValue(formData, "diarize", mistralOptions.diarize);
appendFormValue(formData, "context_bias", mistralOptions.contextBias);
}
return { formData, warnings };
}
async doGenerate(options) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
const { formData, warnings } = await this.getArgs(options);
const {
value: response,
responseHeaders,
rawValue: rawResponse
} = await postFormDataToApi({
url: `${this.config.baseURL}/audio/transcriptions`,
headers: combineHeaders4((_e = (_d = this.config).headers) == null ? void 0 : _e.call(_d), options.headers),
formData,
failedResponseHandler: mistralFailedResponseHandler,
successfulResponseHandler: createJsonResponseHandler4(
mistralTranscriptionResponseSchema
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
const segments = (_g = (_f = response.segments) == null ? void 0 : _f.map((segment) => ({
text: segment.text,
startSecond: segment.start,
endSecond: segment.end
}))) != null ? _g : [];
const mistralMetadata = {};
if (response.usage != null) {
mistralMetadata.usage = {
...response.usage.prompt_tokens != null && {
promptTokens: response.usage.prompt_tokens
},
...response.usage.completion_tokens != null && {
completionTokens: response.usage.completion_tokens
},
...response.usage.total_tokens != null && {
totalTokens: response.usage.total_tokens
},
...response.usage.prompt_audio_seconds != null && {
promptAudioSeconds: response.usage.prompt_audio_seconds
},
...response.usage.request_count != null && {
requestCount: response.usage.request_count
}
};
}
const providerSegments = (_h = response.segments) == null ? void 0 : _h.filter(
(segment) => segment.type != null || segment.score != null || segment.speaker_id != null
).map((segment) => ({
text: segment.text,
startSecond: segment.start,
endSecond: segment.end,
...segment.type != null && { type: segment.type },
...segment.score != null && { score: segment.score },
...segment.speaker_id != null && {
speakerId: segment.speaker_id
}
}));
if (providerSegments != null && providerSegments.length > 0) {
mistralMetadata.segments = providerSegments;
}
return {
text: response.text,
segments,
language: (_i = response.language) != null ? _i : void 0,
durationInSeconds: (_m = (_l = (_j = response.usage) == null ? void 0 : _j.prompt_audio_seconds) != null ? _l : (_k = segments.at(-1)) == null ? void 0 : _k.endSecond) != null ? _m : void 0,
warnings,
response: {
timestamp: currentDate,
modelId: response.model,
headers: responseHeaders,
body: rawResponse
},
...Object.keys(mistralMetadata).length > 0 && {
providerMetadata: {
mistral: mistralMetadata
}
}
};
}
};
function appendFormValue(formData, key, value) {
if (value == null) {
return;
}
if (Array.isArray(value)) {
for (const item of value) {
formData.append(key, item);
}
return;
}
formData.append(key, String(value));
}
var mistralTranscriptionResponseSchema = z9.object({
model: z9.string(),
text: z9.string(),
language: z9.string().nullish(),
segments: z9.array(
z9.object({
type: z9.literal("transcription_segment").nullish(),
text: z9.string(),
start: z9.number(),
end: z9.number(),
score: z9.number().nullish(),
speaker_id: z9.string().nullish()
})
).nullish(),
usage: z9.object({
prompt_tokens: z9.number().nullish(),
completion_tokens: z9.number().nullish(),
total_tokens: z9.number().nullish(),
prompt_audio_seconds: z9.number().nullish(),
request_count: z9.number().nullish()
}).nullish()
});
// src/version.ts
var VERSION = true ? "4.0.16" : "0.0.0-test";
var VERSION = true ? "4.0.17" : "0.0.0-test";

@@ -1135,2 +1366,8 @@ // src/mistral-provider.ts

});
const createTranscriptionModel = (modelId) => new MistralTranscriptionModel(modelId, {
provider: "mistral.transcription",
baseURL,
headers: getHeaders,
fetch: options.fetch
});
const provider = function(modelId) {

@@ -1153,2 +1390,4 @@ if (new.target) {

provider.speechModel = createSpeechModel;
provider.transcription = createTranscriptionModel;
provider.transcriptionModel = createTranscriptionModel;
provider.imageModel = (modelId) => {

@@ -1155,0 +1394,0 @@ throw new NoSuchModelError({ modelId, modelType: "imageModel" });

+3
-3
{
"name": "@ai-sdk/mistral",
"version": "4.0.16",
"version": "4.0.17",
"type": "module",

@@ -32,4 +32,4 @@ "license": "Apache-2.0",

"dependencies": {
"@ai-sdk/provider": "4.0.4",
"@ai-sdk/provider-utils": "5.0.14"
"@ai-sdk/provider-utils": "5.0.15",
"@ai-sdk/provider": "4.0.4"
},

@@ -36,0 +36,0 @@ "devDependencies": {

@@ -16,2 +16,6 @@ export { createMistral, mistral } from './mistral-provider';

} from './mistral-speech-model-options';
export type {
MistralTranscriptionModelId,
MistralTranscriptionModelOptions,
} from './mistral-transcription-model-options';
export { VERSION } from './version';

@@ -7,2 +7,3 @@ import {

type SpeechModelV4,
type TranscriptionModelV4,
} from '@ai-sdk/provider';

@@ -21,2 +22,4 @@ import {

import type { MistralSpeechModelId } from './mistral-speech-model-options';
import { MistralTranscriptionModel } from './mistral-transcription-model';
import type { MistralTranscriptionModelId } from './mistral-transcription-model-options';
import { VERSION } from './version';

@@ -58,2 +61,14 @@

/**
* Creates a model for audio transcription.
*/
transcription(modelId: MistralTranscriptionModelId): TranscriptionModelV4;
/**
* Creates a model for audio transcription.
*/
transcriptionModel(
modelId: MistralTranscriptionModelId,
): TranscriptionModelV4;
/**
* @deprecated Use `embedding` instead.

@@ -143,2 +158,10 @@ */

const createTranscriptionModel = (modelId: MistralTranscriptionModelId) =>
new MistralTranscriptionModel(modelId, {
provider: 'mistral.transcription',
baseURL,
headers: getHeaders,
fetch: options.fetch,
});
const provider = function (modelId: MistralChatModelId) {

@@ -163,2 +186,4 @@ if (new.target) {

provider.speechModel = createSpeechModel;
provider.transcription = createTranscriptionModel;
provider.transcriptionModel = createTranscriptionModel;

@@ -165,0 +190,0 @@ provider.imageModel = (modelId: string) => {

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet