sarvam-ai-sdk
Version:
Sarvam AI Provider support for AI-SDK
1,589 lines (1,564 loc) • 48.6 kB
JavaScript
// src/sarvam-provider.ts
import {
loadApiKey,
withoutTrailingSlash
} from "@ai-sdk/provider-utils";
// src/sarvam-chat-language-model.ts
import {
InvalidResponseDataError
} from "@ai-sdk/provider";
import {
combineHeaders,
createEventSourceResponseHandler,
createJsonResponseHandler,
generateId as generateId2,
isParsableJson,
parseProviderOptions,
postJsonToApi
} from "@ai-sdk/provider-utils";
import { z as z2 } from "zod";
// src/convert-to-sarvam-chat-messages.ts
import {
UnsupportedFunctionalityError
} from "@ai-sdk/provider";
import { convertUint8ArrayToBase64 } from "@ai-sdk/provider-utils";
function convertToSarvamChatMessages(prompt, fakeToolSystemPrompt) {
const messages = [];
for (const { role, content } of prompt) {
switch (role) {
case "system": {
const contentData = fakeToolSystemPrompt ? `${content}
${fakeToolSystemPrompt}` : content;
messages.push({ role: "system", content: contentData });
break;
}
case "user": {
if (content.length === 1 && content[0].type === "text") {
messages.push({ role: "user", content: content[0].text });
break;
}
messages.push({
role: "user",
content: content.map((part) => {
var _a;
switch (part.type) {
case "text": {
return { type: "text", text: part.text };
}
case "image": {
return {
type: "image_url",
image_url: {
url: part.image instanceof URL ? part.image.toString() : `data:${(_a = part.mimeType) != null ? _a : "image/jpeg"};base64,${convertUint8ArrayToBase64(part.image)}`
}
};
}
case "file": {
throw new UnsupportedFunctionalityError({
functionality: "File content parts in user messages"
});
}
}
})
});
break;
}
case "assistant": {
let text = "";
const toolCalls = [];
for (const part of content) {
switch (part.type) {
case "text": {
text += part.text;
break;
}
case "tool-call": {
toolCalls.push({
id: part.toolCallId,
type: "function",
function: {
name: part.toolName,
arguments: JSON.stringify(part.args)
}
});
break;
}
}
}
messages.push({
role: "assistant",
content: text,
tool_calls: toolCalls.length > 0 ? toolCalls : void 0
});
break;
}
case "tool": {
for (const toolResponse of content) {
messages.push({
role: "tool",
tool_call_id: toolResponse.toolCallId,
content: JSON.stringify(toolResponse.result)
});
}
break;
}
default: {
const _exhaustiveCheck = role;
throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
}
}
}
return messages;
}
// src/get-response-metadata.ts
function getResponseMetadata({
id,
model,
created
}) {
return {
id: id != null ? id : void 0,
modelId: model != null ? model : void 0,
timestamp: created != null ? new Date(created * 1e3) : void 0
};
}
// src/map-sarvam-finish-reason.ts
function mapSarvamFinishReason(finishReason) {
switch (finishReason) {
case "stop":
return "stop";
case "length":
return "length";
case "content_filter":
return "content-filter";
case "function_call":
case "tool_calls":
return "tool-calls";
default:
return "unknown";
}
}
// src/sarvam-error.ts
import { z } from "zod";
import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils";
var sarvamErrorDataSchema = z.object({
error: z.object({
message: z.string(),
type: z.string()
})
});
var sarvamFailedResponseHandler = createJsonErrorResponseHandler({
errorSchema: sarvamErrorDataSchema,
errorToMessage: (data) => data.error.message
});
// src/sarvam-prepare-tools.ts
import {
UnsupportedFunctionalityError as UnsupportedFunctionalityError2
} from "@ai-sdk/provider";
import { generateId } from "@ai-sdk/provider-utils";
import { compile } from "json-schema-to-typescript";
function prepareTools({
mode
}) {
var _a;
const tools = ((_a = mode.tools) == null ? void 0 : _a.length) ? mode.tools : void 0;
const toolWarnings = [];
if (tools == null) {
return { tools: void 0, tool_choice: void 0, toolWarnings };
}
const toolChoice = mode.toolChoice;
const sarvamTools = [];
for (const tool of tools) {
if (tool.type === "provider-defined") {
toolWarnings.push({ type: "unsupported-tool", tool });
} else {
sarvamTools.push({
type: "function",
function: {
name: tool.name,
description: tool.description,
parameters: tool.parameters
}
});
}
}
if (toolChoice == null) {
return { tools: sarvamTools, tool_choice: void 0, toolWarnings };
}
const type = toolChoice.type;
switch (type) {
case "auto":
case "none":
case "required":
return { tools: sarvamTools, tool_choice: type, toolWarnings };
case "tool":
return {
tools: sarvamTools,
tool_choice: {
type: "function",
function: {
name: toolChoice.toolName
}
},
toolWarnings
};
default: {
const _exhaustiveCheck = type;
throw new UnsupportedFunctionalityError2({
functionality: `Unsupported tool choice type: ${_exhaustiveCheck}`
});
}
}
}
var simulateToolCalling = async (tools) => {
const context = [];
const names = [];
for (const tool of tools) {
names.push(tool.function.name);
const tsType = await compile(
tool.function.parameters,
tool.function.name,
{
bannerComment: "",
format: false,
declareExternallyReferenced: true,
enableConstEnums: true,
unreachableDefinitions: false,
strictIndexSignatures: false
}
);
const toolContext = tsType.replace(
/export interface (\w+) \{/,
(_, name) => `type ${tool.function.name} = {`
).replace(/\/\*\*\s*\n\s*\*\s*(.*?)\s*\n\s*\*\//, "// $1");
context.push(`// ${tool.function.description}
${toolContext}`);
}
const text = `These are the available tool you can execute.
${context.join("\n")}
type YourToolChoices = {
'toolName': '${names.join("' | '")}',
'toolData': ${names.join(" | ")}
}
Respond normally.
If user request to execute any tool, respond with pure JSON format
Make sure to translate toolData to English.
eg:
const myChoice: YourToolChoices = {
"toolName": <name>,
"toolData": <data>
}`;
return text;
};
var extractToolCallData = (jsonObject) => {
const toolFunction = jsonObject;
if (!("toolName" in toolFunction)) return;
if (!("toolData" in toolFunction)) return;
return {
args: JSON.stringify(toolFunction.toolData),
toolCallId: generateId(),
toolCallType: "function",
toolName: toolFunction.toolName
};
};
var parseJSON = (text) => {
const jsonRegex = /\{(?:[^{}]*|\{[^{}]*\})*\}/g;
const jsonMatches = text.match(jsonRegex);
if (jsonMatches && jsonMatches[0]) {
try {
const jsonObject = JSON.parse(jsonMatches[0]);
return jsonObject;
} catch (error) {
}
}
};
var simulateJsonSchema = () => "If user doen't specify, make sure to translate json data content into pure English.";
// src/sarvam-chat-language-model.ts
var SarvamChatLanguageModel = class {
constructor(modelId, settings, config) {
this.specificationVersion = "v1";
this.supportsStructuredOutputs = false;
this.defaultObjectGenerationMode = "json";
this.modelId = modelId;
this.settings = settings;
this.config = config;
}
get provider() {
return this.config.provider;
}
get supportsImageUrls() {
return !this.settings.downloadImages;
}
async getArgs({
mode,
prompt,
maxTokens,
temperature,
topP,
topK,
frequencyPenalty,
presencePenalty,
stopSequences,
responseFormat,
seed,
stream,
providerMetadata
}) {
const type = mode.type;
const simulate = this.settings.simulate;
if (type === "object-json" && simulate === "tool-calling")
throw new Error('Use { simulate: "json-object" } with generateObject()');
if (type === "regular" && simulate === "json-object")
throw new Error('Use { simulate: "tool-calling" } with generateText()');
const warnings = [];
if (stream) {
warnings.push({
type: "other",
message: "Streaming is still experimental for Sarvam"
});
}
if (topK != null) {
warnings.push({
type: "unsupported-setting",
setting: "topK"
});
}
if (responseFormat != null && responseFormat.type === "json" && responseFormat.schema != null) {
warnings.push({
type: "unsupported-setting",
setting: "responseFormat",
details: "JSON response format schema is not supported"
});
}
const sarvamOptions = parseProviderOptions({
provider: "sarvam",
providerOptions: providerMetadata,
schema: z2.object({
reasoningFormat: z2.enum(["parsed", "raw", "hidden"]).nullish()
})
});
const baseArgs = (prompt2, extraSystemPrompt) => ({
// model id:
model: this.modelId,
// model specific settings:
user: this.settings.user,
parallel_tool_calls: this.settings.parallelToolCalls,
// standardized settings:
max_tokens: maxTokens,
temperature,
top_p: topP,
frequency_penalty: frequencyPenalty,
presence_penalty: presencePenalty,
stop: stopSequences,
seed,
// response format:
response_format: (
// json object response format is not supported for streaming:
stream === false && (responseFormat == null ? void 0 : responseFormat.type) === "json" ? { type: "json_object" } : void 0
),
// provider options:
reasoning_format: sarvamOptions == null ? void 0 : sarvamOptions.reasoningFormat,
// messages:
messages: convertToSarvamChatMessages(prompt2, extraSystemPrompt)
});
switch (type) {
case "regular": {
const { tools, tool_choice, toolWarnings } = prepareTools({
mode
});
const extraSystemPrompt = tools && simulate === "tool-calling" ? await simulateToolCalling(tools) : void 0;
return {
args: {
...baseArgs(prompt, extraSystemPrompt),
tools,
tool_choice
},
warnings: [...warnings, ...toolWarnings]
};
}
case "object-json": {
const extraSystemPrompt = simulate === "json-object" ? simulateJsonSchema() : void 0;
return {
args: {
...baseArgs(prompt, extraSystemPrompt),
response_format: (
// json object response format is not supported for streaming:
stream === false ? { type: "json_object" } : void 0
)
},
warnings
};
}
case "object-tool": {
return {
args: {
...baseArgs(prompt),
tool_choice: {
type: "function",
function: { name: mode.tool.name }
},
tools: [
{
type: "function",
function: {
name: mode.tool.name,
description: mode.tool.description,
parameters: mode.tool.parameters
}
}
]
},
warnings
};
}
default: {
const _exhaustiveCheck = type;
throw new Error(`Unsupported type: ${_exhaustiveCheck}`);
}
}
}
async doGenerate(options) {
var _a, _b, _c, _d, _e, _f, _g;
const { args, warnings } = await this.getArgs({
...options,
stream: false
});
const body = JSON.stringify(args);
const {
responseHeaders,
value: response,
rawValue: rawResponse
} = await postJsonToApi({
url: this.config.url({
path: "/chat/completions",
modelId: this.modelId
}),
headers: combineHeaders(this.config.headers(), options.headers),
body: args,
failedResponseHandler: sarvamFailedResponseHandler,
successfulResponseHandler: createJsonResponseHandler(
sarvamChatResponseSchema
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
const { messages: rawPrompt, ...rawSettings } = args;
const choice = response.choices[0];
let text = (_a = choice.message.content) != null ? _a : void 0;
let toolCalls = (_b = choice.message.tool_calls) == null ? void 0 : _b.map((toolCall) => {
var _a2;
return {
toolCallType: "function",
toolCallId: (_a2 = toolCall.id) != null ? _a2 : generateId2(),
toolName: toolCall.function.name,
args: toolCall.function.arguments
};
});
if (this.settings.simulate === "tool-calling") {
if (text && text.length !== 0) {
const jsonObject = parseJSON(text);
if (jsonObject) {
const newTools = extractToolCallData(jsonObject);
if (newTools) {
toolCalls = [newTools];
text = void 0;
}
}
}
}
if (this.settings.simulate === "json-object") {
if (text && text.length !== 0) {
const jsonObject = parseJSON(text);
if (jsonObject) {
const newTools = extractToolCallData(jsonObject);
text = JSON.stringify(jsonObject);
}
}
}
return {
text,
toolCalls,
reasoning: (_c = choice.message.reasoning) != null ? _c : void 0,
finishReason: mapSarvamFinishReason(choice.finish_reason),
usage: {
promptTokens: (_e = (_d = response.usage) == null ? void 0 : _d.prompt_tokens) != null ? _e : NaN,
completionTokens: (_g = (_f = response.usage) == null ? void 0 : _f.completion_tokens) != null ? _g : NaN
},
rawCall: { rawPrompt, rawSettings },
rawResponse: { headers: responseHeaders, body: rawResponse },
response: getResponseMetadata(response),
warnings,
request: { body }
};
}
async doStream(options) {
const { args, warnings } = await this.getArgs({ ...options, stream: true });
const body = JSON.stringify({ ...args, stream: true });
const { responseHeaders, value: response } = await postJsonToApi({
url: this.config.url({
path: "/chat/completions",
modelId: this.modelId
}),
headers: combineHeaders(this.config.headers(), options.headers),
body: {
...args,
stream: true
},
failedResponseHandler: sarvamFailedResponseHandler,
successfulResponseHandler: createEventSourceResponseHandler(
sarvamChatChunkSchema
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
const { messages: rawPrompt, ...rawSettings } = args;
const toolCalls = [];
let finishReason = "unknown";
let usage = {
promptTokens: void 0,
completionTokens: void 0
};
let isFirstChunk = true;
let providerMetadata;
return {
stream: response.pipeThrough(
new TransformStream({
transform(chunk, controller) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
if (!chunk.success) {
finishReason = "error";
controller.enqueue({
type: "error",
error: chunk.error
});
return;
}
const value = chunk.value;
if ("error" in value) {
finishReason = "error";
controller.enqueue({
type: "error",
error: value.error
});
return;
}
if (isFirstChunk) {
isFirstChunk = false;
controller.enqueue({
type: "response-metadata",
...getResponseMetadata(value)
});
}
if (((_a = value.x_sarvam) == null ? void 0 : _a.usage) != null) {
usage = {
promptTokens: (_b = value.x_sarvam.usage.prompt_tokens) != null ? _b : void 0,
completionTokens: (_c = value.x_sarvam.usage.completion_tokens) != null ? _c : void 0
};
}
const choice = value.choices[0];
if ((choice == null ? void 0 : choice.finish_reason) != null) {
finishReason = mapSarvamFinishReason(choice.finish_reason);
}
if ((choice == null ? void 0 : choice.delta) == null) {
return;
}
const delta = choice.delta;
if (delta.reasoning != null && delta.reasoning.length > 0) {
controller.enqueue({
type: "reasoning",
textDelta: delta.reasoning
});
}
if (delta.content != null && delta.content.length > 0) {
controller.enqueue({
type: "text-delta",
textDelta: delta.content
});
}
if (delta.tool_calls != null) {
for (const toolCallDelta of delta.tool_calls) {
const index = toolCallDelta.index;
if (toolCalls[index] == null) {
if (toolCallDelta.type !== "function") {
throw new InvalidResponseDataError({
data: toolCallDelta,
message: `Expected 'function' type.`
});
}
if (toolCallDelta.id == null) {
throw new InvalidResponseDataError({
data: toolCallDelta,
message: `Expected 'id' to be a string.`
});
}
if (((_d = toolCallDelta.function) == null ? void 0 : _d.name) == null) {
throw new InvalidResponseDataError({
data: toolCallDelta,
message: `Expected 'function.name' to be a string.`
});
}
toolCalls[index] = {
id: toolCallDelta.id,
type: "function",
function: {
name: toolCallDelta.function.name,
arguments: (_e = toolCallDelta.function.arguments) != null ? _e : ""
},
hasFinished: false
};
const toolCall2 = toolCalls[index];
if (((_f = toolCall2.function) == null ? void 0 : _f.name) != null && ((_g = toolCall2.function) == null ? void 0 : _g.arguments) != null) {
if (toolCall2.function.arguments.length > 0) {
controller.enqueue({
type: "tool-call-delta",
toolCallType: "function",
toolCallId: toolCall2.id,
toolName: toolCall2.function.name,
argsTextDelta: toolCall2.function.arguments
});
}
if (isParsableJson(toolCall2.function.arguments)) {
controller.enqueue({
type: "tool-call",
toolCallType: "function",
toolCallId: (_h = toolCall2.id) != null ? _h : generateId2(),
toolName: toolCall2.function.name,
args: toolCall2.function.arguments
});
toolCall2.hasFinished = true;
}
}
continue;
}
const toolCall = toolCalls[index];
if (toolCall.hasFinished) {
continue;
}
if (((_i = toolCallDelta.function) == null ? void 0 : _i.arguments) != null) {
toolCall.function.arguments += (_k = (_j = toolCallDelta.function) == null ? void 0 : _j.arguments) != null ? _k : "";
}
controller.enqueue({
type: "tool-call-delta",
toolCallType: "function",
toolCallId: toolCall.id,
toolName: toolCall.function.name,
argsTextDelta: (_l = toolCallDelta.function.arguments) != null ? _l : ""
});
if (((_m = toolCall.function) == null ? void 0 : _m.name) != null && ((_n = toolCall.function) == null ? void 0 : _n.arguments) != null && isParsableJson(toolCall.function.arguments)) {
controller.enqueue({
type: "tool-call",
toolCallType: "function",
toolCallId: (_o = toolCall.id) != null ? _o : generateId2(),
toolName: toolCall.function.name,
args: toolCall.function.arguments
});
toolCall.hasFinished = true;
}
}
}
},
flush(controller) {
var _a, _b;
controller.enqueue({
type: "finish",
finishReason,
usage: {
promptTokens: (_a = usage.promptTokens) != null ? _a : NaN,
completionTokens: (_b = usage.completionTokens) != null ? _b : NaN
},
...providerMetadata != null ? { providerMetadata } : {}
});
}
})
),
rawCall: { rawPrompt, rawSettings },
rawResponse: { headers: responseHeaders },
warnings,
request: { body }
};
}
};
var sarvamChatResponseSchema = z2.object({
id: z2.string().nullish(),
created: z2.number().nullish(),
model: z2.string().nullish(),
choices: z2.array(
z2.object({
message: z2.object({
content: z2.string().nullish(),
reasoning: z2.string().nullish(),
tool_calls: z2.array(
z2.object({
id: z2.string().nullish(),
type: z2.literal("function"),
function: z2.object({
name: z2.string(),
arguments: z2.string()
})
})
).nullish()
}),
index: z2.number(),
finish_reason: z2.string().nullish()
})
),
usage: z2.object({
prompt_tokens: z2.number().nullish(),
completion_tokens: z2.number().nullish()
}).nullish()
});
var sarvamChatChunkSchema = z2.union([
z2.object({
id: z2.string().nullish(),
created: z2.number().nullish(),
model: z2.string().nullish(),
choices: z2.array(
z2.object({
delta: z2.object({
content: z2.string().nullish(),
reasoning: z2.string().nullish(),
tool_calls: z2.array(
z2.object({
index: z2.number(),
id: z2.string().nullish(),
type: z2.literal("function").optional(),
function: z2.object({
name: z2.string().nullish(),
arguments: z2.string().nullish()
})
})
).nullish()
}).nullish(),
finish_reason: z2.string().nullable().optional(),
index: z2.number()
})
),
x_sarvam: z2.object({
usage: z2.object({
prompt_tokens: z2.number().nullish(),
completion_tokens: z2.number().nullish()
}).nullish()
}).nullish()
}),
sarvamErrorDataSchema
]);
// src/sarvam-speech-model.ts
import {
combineHeaders as combineHeaders2,
createJsonResponseHandler as createJsonResponseHandler2,
parseProviderOptions as parseProviderOptions2,
postJsonToApi as postJsonToApi2
} from "@ai-sdk/provider-utils";
// src/sarvam-speech-settings.ts
import { z as z3 } from "zod";
var SpeakerSchema = z3.enum([
"meera",
"pavithra",
"maitreyi",
"arvind",
"amol",
"amartya",
"diya",
"neel",
"misha",
"vian",
"arjun",
"maya",
"anushka",
"abhilash",
"manisha",
"vidya",
"arya",
"karun",
"hitesh"
]).default("meera");
var SarvamProviderOptionsSchema = z3.object({
speaker: SpeakerSchema,
pitch: z3.number().min(-0.75).max(0.75).default(0),
pace: z3.number().min(0.5).max(2).default(1),
loudness: z3.number().min(0.3).max(3).default(1),
speech_sample_rate: z3.union([
z3.literal(8e3),
z3.literal(16e3),
z3.literal(22050),
z3.literal(24e3)
]).default(22050),
enable_preprocessing: z3.boolean().default(false)
}).partial();
// src/sarvam-speech-model.ts
import { z as z4 } from "zod";
var SarvamSpeechModel = class {
constructor(modelId, languageCode, config) {
this.modelId = modelId;
this.languageCode = languageCode;
this.config = config;
this.specificationVersion = "v1";
}
get provider() {
return this.config.provider;
}
getArgs({
text,
voice,
outputFormat = "wav",
// speed,
// instructions,
providerOptions
}) {
const warnings = [];
const sarvamOptions = parseProviderOptions2({
provider: "sarvam",
providerOptions: {
sarvam: {
...providerOptions == null ? void 0 : providerOptions.sarvam,
...this.config.speech
}
},
schema: SarvamProviderOptionsSchema
});
const getSpeaker = () => {
if (sarvamOptions == null ? void 0 : sarvamOptions.speaker) return sarvamOptions.speaker;
if (voice) {
return SpeakerSchema.parse(voice);
}
switch (this.modelId) {
case "bulbul:v1":
return "meera";
case "bulbul:v2":
return "manisha";
}
return "meera";
};
const requestBody = {
model: this.modelId,
text,
target_language_code: this.languageCode,
speaker: getSpeaker()
// response_format: "wav",
// speed,
// instructions,
};
if (outputFormat) {
if (["mp3", "opus", "aac", "flac", "wav", "pcm"].includes(
outputFormat
)) {
requestBody.response_format = outputFormat;
} else {
warnings.push({
type: "unsupported-setting",
setting: "outputFormat",
details: `Unsupported output format: ${outputFormat}. Using mp3 instead.`
});
}
}
if (sarvamOptions) {
const speechModelOptions = {};
for (const key in speechModelOptions) {
const value = speechModelOptions[key];
if (value !== void 0) {
requestBody[key] = value;
}
}
}
return {
requestBody,
warnings
};
}
async doGenerate(options) {
var _a, _b, _c;
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 { requestBody, warnings } = this.getArgs(options);
const {
value,
responseHeaders,
rawValue: rawResponse
} = await postJsonToApi2({
url: this.config.url({
path: "/text-to-speech",
modelId: this.modelId
}),
headers: combineHeaders2(this.config.headers(), options.headers),
body: requestBody,
failedResponseHandler: sarvamFailedResponseHandler,
successfulResponseHandler: createJsonResponseHandler2(
z4.object({
request_id: z4.string(),
audios: z4.array(z4.string())
})
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
const audio = value.audios[0];
return {
audio,
warnings,
request: {
body: JSON.stringify(requestBody)
},
response: {
timestamp: currentDate,
modelId: this.modelId,
headers: responseHeaders,
body: rawResponse
}
};
}
};
// src/sarvam-transcription-model.ts
import {
combineHeaders as combineHeaders3,
createJsonResponseHandler as createJsonResponseHandler3,
parseProviderOptions as parseProviderOptions3,
postFormDataToApi
} from "@ai-sdk/provider-utils";
import { z as z6 } from "zod";
// src/sarvam-transcription-settings.ts
import { z as z5 } from "zod";
var SarvamProviderOptionsSchema2 = z5.object({
with_timestamps: z5.boolean().nullish().default(false),
with_diarization: z5.boolean().nullish().default(false),
num_speakers: z5.number().int().nullish()
});
// src/sarvam-transcription-model.ts
var SarvamTranscriptionModel = class {
constructor(modelId, languageCode, config) {
this.modelId = modelId;
this.languageCode = languageCode;
this.config = config;
this.specificationVersion = "v1";
}
get provider() {
return this.config.provider;
}
getArgs({
audio,
mediaType,
providerOptions
}) {
const warnings = [];
if (this.modelId === "saarika:v1" && this.languageCode === "unknown")
throw new Error(
"Language code unknown is not supported for model saarika:v1"
);
const sarvamOptions = parseProviderOptions3({
provider: "sarvam",
providerOptions: {
sarvam: {
...providerOptions == null ? void 0 : providerOptions.sarvam,
...this.config.transcription
}
},
schema: SarvamProviderOptionsSchema2
});
const formData = new FormData();
const blob = audio instanceof Blob ? audio : new Blob([audio], { type: mediaType });
formData.append("file", blob);
formData.append("model", this.modelId);
if (sarvamOptions) {
formData.append("language_code", this.languageCode);
formData.append(
"with_timestamps",
sarvamOptions.with_timestamps ? "true" : "false"
);
formData.append(
"with_diarization",
sarvamOptions.with_diarization ? "true" : "false"
);
if (sarvamOptions.num_speakers !== null && sarvamOptions.num_speakers !== void 0) {
formData.append(
"num_speakers",
sarvamOptions.num_speakers.toString()
);
}
}
return {
formData,
warnings
};
}
async doGenerate(options) {
var _a, _b, _c, _d, _e;
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 } = this.getArgs(options);
const {
value: response,
responseHeaders,
rawValue: rawResponse
} = await postFormDataToApi({
url: this.config.url({
path: "/speech-to-text",
modelId: this.modelId
}),
headers: combineHeaders3(this.config.headers(), options.headers),
formData,
failedResponseHandler: sarvamFailedResponseHandler,
successfulResponseHandler: createJsonResponseHandler3(
sarvamTranscriptionResponseSchema
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
return {
text: response.transcript,
segments: response.timestamps ? response.timestamps.words.map((word, index) => ({
text: word,
startSecond: response.timestamps.start_time_seconds[index],
endSecond: response.timestamps.end_time_seconds[index]
})) : [],
language: response.language_code ? response.language_code : void 0,
durationInSeconds: (_e = (_d = response.timestamps) == null ? void 0 : _d.end_time_seconds[response.timestamps.end_time_seconds.length - 1]) != null ? _e : void 0,
warnings,
response: {
timestamp: currentDate,
modelId: this.modelId,
headers: responseHeaders,
body: rawResponse
}
};
}
};
var sarvamTranscriptionResponseSchema = z6.object({
request_id: z6.string().nullable(),
transcript: z6.string(),
language_code: z6.string().nullable(),
timestamps: z6.object({
end_time_seconds: z6.array(z6.number()),
start_time_seconds: z6.array(z6.number()),
words: z6.array(z6.string())
}).optional(),
diarized_transcript: z6.object({
entries: z6.array(
z6.object({
end_time_seconds: z6.array(z6.number()),
start_time_seconds: z6.array(z6.number()),
transcript: z6.string(),
speaker_id: z6.string()
})
)
}).optional()
});
// src/sarvam-translation-model.ts
import {
combineHeaders as combineHeaders4,
createJsonResponseHandler as createJsonResponseHandler4,
postJsonToApi as postJsonToApi3
} from "@ai-sdk/provider-utils";
import { z as z8 } from "zod";
// src/sarvam-config.ts
import { z as z7 } from "zod";
var SarvamLanguageCodeSchema = z7.enum([
"hi-IN",
"bn-IN",
"kn-IN",
"ml-IN",
"mr-IN",
"od-IN",
"pa-IN",
"ta-IN",
"te-IN",
"en-IN",
"gu-IN"
]);
var SarvamScriptCodeSchema = z7.enum([
"Latn",
"Deva",
"Beng",
"Gujr",
"Knda",
"Mlym",
"Orya",
"Guru",
"Taml",
"Telu"
]);
// src/sarvam-translation-model.ts
var SarvamTranslationModel = class {
constructor(settings, config) {
this.specificationVersion = "v1";
this.supportsStructuredOutputs = false;
this.defaultObjectGenerationMode = "json";
var _a;
this.modelId = (_a = settings.model) != null ? _a : "mayura:v1";
this.settings = settings;
this.config = config;
}
get provider() {
return this.config.provider;
}
get supportsImageUrls() {
return false;
}
getArgs({
mode,
prompt
}) {
var _a, _b, _c, _d, _e, _f, _g, _h;
const type = mode.type;
const warnings = [];
if (this.settings.from === this.settings.to) {
throw new Error(
"Source and target languages code must be different."
);
}
if (this.modelId === "sarvam-translate:v1") {
if (((_a = this.settings.mode) != null ? _a : "formal") !== "formal")
throw new Error(
"Sarvam 'sarvam-translate:v1' only support mode formal."
);
if (((_b = this.settings.from) != null ? _b : "auto") === "auto")
throw new Error(
"Sarvam 'sarvam-translate:v1' requires source language code."
);
}
if (type !== "regular") {
const _exhaustiveCheck = type;
throw new Error(`Unsupported type: ${_exhaustiveCheck}`);
}
const messages = convertToSarvamChatMessages(prompt);
return {
messages,
args: {
input: messages.filter((m) => m.role === "user").map((m) => m.content).join("\n"),
source_language_code: (_c = this.settings.from) != null ? _c : "auto",
target_language_code: this.settings.to,
numerals_format: (_d = this.settings.numerals_format) != null ? _d : "international",
enable_preprocessing: (_e = this.settings.enable_preprocessing) != null ? _e : false,
output_script: (_f = this.settings.output_script) != null ? _f : null,
speaker_gender: (_g = this.settings.speaker_gender) != null ? _g : "Male",
mode: (_h = this.settings.mode) != null ? _h : "formal",
model: this.modelId
},
warnings
};
}
async doGenerate(options) {
var _a;
const { args, warnings, messages } = this.getArgs({
...options,
stream: false
});
const body = JSON.stringify(args);
const {
responseHeaders,
value: response,
rawValue: rawResponse
} = await postJsonToApi3({
url: this.config.url({
path: "/translate"
}),
headers: combineHeaders4(this.config.headers(), options.headers),
body: args,
failedResponseHandler: sarvamFailedResponseHandler,
successfulResponseHandler: createJsonResponseHandler4(
sarvamTranslationResponseSchema
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
const { input: rawPrompt, ...rawSettings } = args;
const text = (_a = response.translated_text) != null ? _a : void 0;
return {
text,
toolCalls: void 0,
reasoning: void 0,
finishReason: "unknown",
usage: {
promptTokens: NaN,
completionTokens: NaN
},
rawCall: { rawPrompt, rawSettings },
rawResponse: { headers: responseHeaders, body: rawResponse },
response: void 0,
warnings,
request: { body }
};
}
async doStream(options) {
throw new Error("Translation feature doesn't support streaming yet");
}
};
var sarvamTranslationResponseSchema = z8.object({
translated_text: z8.string().nullish(),
source_language_code: SarvamLanguageCodeSchema.nullable(),
request_id: z8.string().nullish()
});
// src/sarvam-transliterate-model.ts
import {
combineHeaders as combineHeaders5,
createJsonResponseHandler as createJsonResponseHandler5,
postJsonToApi as postJsonToApi4
} from "@ai-sdk/provider-utils";
import { z as z9 } from "zod";
var SarvamTransliterateModel = class {
constructor(settings, config) {
this.specificationVersion = "v1";
this.supportsStructuredOutputs = false;
this.defaultObjectGenerationMode = "json";
this.modelId = "unknown";
this.settings = settings;
this.config = config;
}
get provider() {
return this.config.provider;
}
get supportsImageUrls() {
return false;
}
getArgs({
mode,
prompt
}) {
var _a, _b, _c;
const type = mode.type;
const warnings = [];
if (this.settings.from !== "auto") {
if (this.settings.to !== "en-IN" && this.settings.from !== "en-IN")
throw new Error(
"Sarvam doesn't support Indic-Indic Transliteration yet"
);
}
if (type !== "regular") {
const _exhaustiveCheck = type;
throw new Error(`Unsupported type: ${_exhaustiveCheck}`);
}
const messages = convertToSarvamChatMessages(prompt);
return {
messages,
args: {
input: messages.filter((m) => m.role === "user").map((m) => m.content).join("\n"),
source_language_code: (_a = this.settings.from) != null ? _a : "auto",
target_language_code: this.settings.to,
numerals_format: (_b = this.settings.numerals_format) != null ? _b : "international",
...this.settings.spoken_form ? {
spoken_form: this.settings.spoken_form,
spoken_form_numerals_language: (_c = this.settings.spoken_form_numerals_language) != null ? _c : "english"
} : {}
},
warnings
};
}
async doGenerate(options) {
var _a;
const { args, warnings, messages } = this.getArgs({
...options,
stream: false
});
const body = JSON.stringify(args);
const {
responseHeaders,
value: response,
rawValue: rawResponse
} = await postJsonToApi4({
url: this.config.url({
path: "/transliterate"
}),
headers: combineHeaders5(this.config.headers(), options.headers),
body: args,
failedResponseHandler: sarvamFailedResponseHandler,
successfulResponseHandler: createJsonResponseHandler5(
sarvamTransliterateResponseSchema
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
const { input: rawPrompt, ...rawSettings } = args;
let text = (_a = response.transliterated_text) != null ? _a : void 0;
return {
text,
toolCalls: void 0,
reasoning: void 0,
finishReason: "unknown",
usage: {
promptTokens: NaN,
completionTokens: NaN
},
rawCall: { rawPrompt, rawSettings },
rawResponse: { headers: responseHeaders, body: rawResponse },
response: void 0,
warnings,
request: { body }
};
}
async doStream(options) {
throw new Error("Transliterate feature doesn't streaming yet");
}
};
var sarvamTransliterateResponseSchema = z9.object({
transliterated_text: z9.string().nullish(),
source_language_code: SarvamLanguageCodeSchema.nullable(),
request_id: z9.string().nullish()
});
// src/sarvam-lid-model.ts
import {
combineHeaders as combineHeaders6,
createJsonResponseHandler as createJsonResponseHandler6,
postJsonToApi as postJsonToApi5
} from "@ai-sdk/provider-utils";
import { z as z10 } from "zod";
var SarvamLidModel = class {
constructor(config) {
this.specificationVersion = "v1";
this.supportsStructuredOutputs = false;
this.defaultObjectGenerationMode = "json";
this.modelId = "unknown";
this.config = config;
}
get provider() {
return this.config.provider;
}
get supportsImageUrls() {
return false;
}
getArgs({
mode,
prompt
}) {
const type = mode.type;
const warnings = [];
if (type !== "regular") {
const _exhaustiveCheck = type;
throw new Error(`Unsupported type: ${_exhaustiveCheck}`);
}
const messages = convertToSarvamChatMessages(prompt);
return {
messages,
args: {
input: messages.filter((m) => m.role === "user").map((m) => m.content).join("\n")
},
warnings
};
}
async doGenerate(options) {
var _a;
const { args, warnings, messages } = this.getArgs({
...options,
stream: false
});
const body = JSON.stringify(args);
const {
responseHeaders,
value: response,
rawValue: rawResponse
} = await postJsonToApi5({
url: this.config.url({
path: "/text-lid"
}),
headers: combineHeaders6(this.config.headers(), options.headers),
body: args,
failedResponseHandler: sarvamFailedResponseHandler,
successfulResponseHandler: createJsonResponseHandler6(
sarvamLidResponseSchema
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
const { input: rawPrompt, ...rawSettings } = args;
const text = (_a = response.language_code) != null ? _a : void 0;
return {
text,
toolCalls: void 0,
reasoning: void 0,
finishReason: "unknown",
usage: {
promptTokens: NaN,
completionTokens: NaN
},
rawCall: { rawPrompt, rawSettings },
rawResponse: { headers: responseHeaders, body: rawResponse },
response: void 0,
warnings,
request: { body }
};
}
async doStream(options) {
throw new Error("Language Identification feature doesn't streaming yet");
}
};
var sarvamLidResponseSchema = z10.object({
script_code: SarvamScriptCodeSchema.nullish(),
language_code: SarvamLanguageCodeSchema.nullable(),
request_id: z10.string().nullish()
});
// src/sarvam-speech-translation-model.ts
import {
combineHeaders as combineHeaders7,
createJsonResponseHandler as createJsonResponseHandler7,
postFormDataToApi as postFormDataToApi2
} from "@ai-sdk/provider-utils";
import { z as z11 } from "zod";
var SarvamSpeechTranslationModel = class {
constructor(modelId, config) {
this.modelId = modelId;
this.config = config;
this.specificationVersion = "v1";
}
get provider() {
return this.config.provider;
}
getArgs({
audio,
mediaType,
providerOptions
}) {
const warnings = [];
const formData = new FormData();
const blob = audio instanceof Blob ? audio : new Blob([audio], { type: mediaType });
formData.append("file", blob);
formData.append("model", this.modelId);
return {
formData,
warnings
};
}
async doGenerate(options) {
var _a, _b, _c;
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 } = this.getArgs(options);
const {
value: response,
responseHeaders,
rawValue: rawResponse
} = await postFormDataToApi2({
url: this.config.url({
path: "/speech-to-text-translate",
modelId: this.modelId
}),
headers: combineHeaders7(this.config.headers(), options.headers),
formData,
failedResponseHandler: sarvamFailedResponseHandler,
successfulResponseHandler: createJsonResponseHandler7(
sarvamTranscriptionResponseSchema2
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
return {
text: response.transcript,
segments: [],
language: response.language_code ? response.language_code : void 0,
durationInSeconds: void 0,
warnings,
response: {
timestamp: currentDate,
modelId: this.modelId,
headers: responseHeaders,
body: rawResponse
}
};
}
};
var sarvamTranscriptionResponseSchema2 = z11.object({
request_id: z11.string().nullable(),
transcript: z11.string(),
language_code: z11.string().nullable(),
// timestamps: z
// .object({
// end_time_seconds: z.array(z.number()),
// start_time_seconds: z.array(z.number()),
// words: z.array(z.string()),
// })
// .optional(),
diarized_transcript: z11.object({
entries: z11.array(
z11.object({
end_time_seconds: z11.array(z11.number()),
start_time_seconds: z11.array(z11.number()),
transcript: z11.string(),
speaker_id: z11.string()
})
)
}).nullable().optional()
});
// src/sarvam-provider.ts
function createSarvam(options = {}) {
var _a;
const baseURL = (_a = withoutTrailingSlash(options.baseURL)) != null ? _a : "https://api.sarvam.ai";
const getApiKey = () => loadApiKey({
apiKey: options.apiKey,
environmentVariableName: "SARVAM_API_KEY",
description: "Sarvam"
});
const getHeaders = () => ({
Authorization: `Bearer ${getApiKey()}`,
"api-subscription-key": getApiKey(),
...options.headers
});
const createChatModel = (modelId, settings = {}) => new SarvamChatLanguageModel(modelId, settings, {
provider: "sarvam.chat",
url: ({ path }) => `${baseURL}/v1${path}`,
headers: getHeaders,
fetch: options.fetch
});
const createLanguageModel = (modelId, settings) => {
if (new.target) {
throw new Error(
"The Sarvam model function cannot be called with the new keyword."
);
}
return createChatModel(modelId, settings);
};
const createTranscriptionModel = (modelId, languageCode = "unknown", settings) => new SarvamTranscriptionModel(modelId, languageCode, {
provider: "sarvam.transcription",
url: ({ path }) => `${baseURL}${path}`,
headers: getHeaders,
fetch: options.fetch,
transcription: settings
});
const createSpeechTranslation = (modelId) => new SarvamSpeechTranslationModel(modelId, {
provider: "sarvam.transcription",
url: ({ path }) => `${baseURL}${path}`,
headers: getHeaders,
fetch: options.fetch
});
const createSpeechModel = (modelId, languageCode, settings) => new SarvamSpeechModel(modelId, languageCode, {
provider: "sarvam.speech",
url: ({ path }) => `${baseURL}${path}`,
headers: getHeaders,
fetch: options.fetch,
speech: settings
});
const createTransliterateModel = (settings) => new SarvamTransliterateModel(
settings,
{
provider: "sarvam.transliterate",
url: ({ path }) => `${baseURL}${path}`,
headers: getHeaders,
fetch: options.fetch
}
);
const createTranslationModel = (settings) => new SarvamTranslationModel(
settings,
{
provider: "sarvam.translation",
url: ({ path }) => `${baseURL}${path}`,
headers: getHeaders,
fetch: options.fetch
}
);
const createLidModel = () => new SarvamLidModel(
{
provider: "sarvam.lid",
url: ({ path }) => `${baseURL}${path}`,
headers: getHeaders,
fetch: options.fetch
}
);
const provider = (modelId, settings) => createLanguageModel(modelId, settings);
provider.languageModel = createLanguageModel;
provider.chat = createChatModel;
provider.transcription = createTranscriptionModel;
provider.speechTranslation = createSpeechTranslation;
provider.speech = createSpeechModel;
provider.transliterate = createTransliterateModel;
provider.translation = createTranslationModel;
provider.languageIdentification = createLidModel;
return provider;
}
var sarvam = createSarvam();
export {
createSarvam,
sarvam
};
//# sourceMappingURL=index.mjs.map