UNPKG

@rocketnew/llm-sdk

Version:

Universal LLM SDK for JavaScript/TypeScript - OpenAI, Anthropic, Gemini, Perplexity and more

329 lines (325 loc) 10.6 kB
import { DEFAULT_MAX_TOKENS, RESPONSE_FORMAT_TOOL_NAME, __esm, __export, init_constants } from "./chunk-DDRQKMV4.mjs"; // src/llms/base_llm/base_utils.ts function updateRefs(schema, refTemplate) { const stack = [[schema, []]]; const visited = /* @__PURE__ */ new Set(); while (stack.length > 0) { const [obj, path] = stack.pop(); if (visited.has(obj)) { continue; } visited.add(obj); if (obj && typeof obj === "object") { if ("$ref" in obj) { const refPath = obj["$ref"]; const modelName = refPath.split("/").pop(); obj["$ref"] = refTemplate.replace("{model}", modelName || ""); } if (Array.isArray(obj)) { for (let i = 0; i < obj.length; i++) { if (obj[i] && typeof obj[i] === "object") { stack.push([obj[i], [...path, i]]); } } } else { for (const [k, v] of Object.entries(obj)) { if (v && typeof v === "object") { stack.push([v, [...path, k]]); } } } } } } function dictToResponseFormatHelper(responseFormat, refTemplate) { if (refTemplate && responseFormat.type === "json_schema") { const modifiedFormat = JSON.parse(JSON.stringify(responseFormat)); const schema = modifiedFormat.json_schema?.schema; if (schema) { updateRefs(schema, refTemplate); } return modifiedFormat; } return responseFormat; } function typeToResponseFormatParam(responseFormat, refTemplate) { if (responseFormat === null || responseFormat === void 0) { return null; } if (typeof responseFormat === "object") { return dictToResponseFormatHelper(responseFormat, refTemplate); } throw new TypeError(`Unsupported response_format type - ${typeof responseFormat}`); } function mapDeveloperRoleToSystemRole(messages) { const newMessages = []; for (const m of messages) { if (m.role === "developer") { newMessages.push({ role: "system", content: m.content }); } else { newMessages.push(m); } } return newMessages; } var init_base_utils = __esm({ "src/llms/base_llm/base_utils.ts"() { "use strict"; } }); // src/llms/base_llm/chat/transformation.ts var transformation_exports = {}; __export(transformation_exports, { BaseConfig: () => BaseConfig, BaseLLMException: () => BaseLLMException }); var BaseLLMException, BaseConfig; var init_transformation = __esm({ "src/llms/base_llm/chat/transformation.ts"() { "use strict"; init_constants(); init_base_utils(); BaseLLMException = class extends Error { constructor(options) { super(options.message); this.name = "BaseLLMException"; this.statusCode = options.statusCode; this.message = options.message; this.headers = options.headers; this.request = options.request; this.response = options.response; this.body = options.body; } }; BaseConfig = class { constructor() { } /** * Get configuration as a dictionary * * Returns all non-private, non-function class attributes. */ static getConfig() { const config = {}; for (const [key, value] of Object.entries(this)) { if (!key.startsWith("_") && typeof value !== "function" && value !== null && value !== void 0) { config[key] = value; } } return config; } /** * Get JSON schema from response format * * Converts a response format object to the appropriate JSON schema format. */ getJsonSchemaFromResponseFormat(responseFormat) { return typeToResponseFormatParam(responseFormat); } /** * Check if thinking/reasoning is enabled in the parameters */ isThinkingEnabled(nonDefaultParams) { return nonDefaultParams.thinking?.type === "enabled" || nonDefaultParams.reasoning_effort !== void 0 && nonDefaultParams.reasoning_effort !== null; } /** * Check if max_tokens is specified in the request * * OpenAI spec allows max_tokens or max_completion_tokens to be specified. */ isMaxTokensInRequest(nonDefaultParams) { return "max_tokens" in nonDefaultParams || "max_completion_tokens" in nonDefaultParams; } /** * Update optional params with thinking tokens * * Handles scenario where max tokens is not specified. For anthropic models, * this requires having the max tokens being set and being greater than * the thinking token budget. * * If 'thinking' is enabled and 'max_tokens' is not specified, * set 'max_tokens' to the thinking token budget + DEFAULT_MAX_TOKENS */ updateOptionalParamsWithThinkingTokens(nonDefaultParams, optionalParams) { const isThinkingEnabled = this.isThinkingEnabled(optionalParams); if (isThinkingEnabled && !("max_tokens" in nonDefaultParams)) { const thinkingTokenBudget = optionalParams.thinking?.budget_tokens; if (thinkingTokenBudget !== null && thinkingTokenBudget !== void 0) { optionalParams.max_tokens = thinkingTokenBudget + DEFAULT_MAX_TOKENS; } } } /** * Returns True if the model/provider should fake stream * * Some providers don't support native streaming, so we need to * simulate it by making a non-streaming request and yielding chunks. */ shouldFakeStream(model, stream, customLLMProvider) { return false; } /** * Helper util to add tools to optional_params */ addToolsToOptionalParams(optionalParams, tools) { if (!("tools" in optionalParams)) { optionalParams.tools = tools; } else { optionalParams.tools = [...optionalParams.tools, ...tools]; } return optionalParams; } /** * Translate `developer` role to `system` role for non-OpenAI providers. * * Overridden by OpenAI/Azure to preserve the developer role. */ translateDeveloperRoleToSystemRole(messages) { return mapDeveloperRoleToSystemRole(messages); } /** * Returns True if the model/provider should retry the LLM API on HTTP error * * Overridden by providers where different models support different parameters. */ shouldRetryLLMApiInsideLLMTranslationOnHttpError(error, rocketllmParams) { return false; } /** * Transform the request data on UnprocessableEntityError */ transformRequestOnUnprocessableEntityError(error, requestData) { return requestData; } /** * Returns the max retry count for UnprocessableEntityError * * Used if `shouldRetryLLMApiInsideLLMTranslationOnHttpError` returns true. */ get maxRetryOnUnprocessableEntityError() { return 0; } /** * Add response format to tools * * Follow similar approach to anthropic - translate to a single tool call. * This is used to translate response_format to a tool call, for models/APIs * that don't support response_format directly. */ addResponseFormatToTools(optionalParams, value, isResponseFormatSupported, enforceToolChoice = true) { let jsonSchema = null; if ("response_schema" in value) { jsonSchema = value.response_schema; } else if ("json_schema" in value) { jsonSchema = value.json_schema?.schema; } if (jsonSchema && !isResponseFormatSupported) { const toolChoice = { type: "function", function: { name: RESPONSE_FORMAT_TOOL_NAME } }; const tool = { type: "function", function: { name: RESPONSE_FORMAT_TOOL_NAME, parameters: jsonSchema } }; if (!optionalParams.tools) { optionalParams.tools = []; } optionalParams.tools.push(tool); if (enforceToolChoice) { optionalParams.tool_choice = toolChoice; } optionalParams.json_mode = true; } else if (isResponseFormatSupported) { optionalParams.response_format = value; } return optionalParams; } /** * Sign the request * * Some providers like Bedrock require signing the request. * The sign request function needs access to `requestData` and `completeUrl`. * * @returns Tuple of [signed headers, signed body (if any)] */ signRequest(headers, optionalParams, requestData, apiBase, apiKey, model, stream, fakeStream) { return [headers, void 0]; } /** * Get the complete URL for the request * * Some providers need `model` in `api_base`. */ getCompleteUrl(apiBase, apiKey, model, optionalParams, rocketllmParams, stream) { if (apiBase === null) { throw new Error("api_base is required"); } return apiBase; } /** * Async version of transform request * * Override to allow for http requests on async calls - e.g. converting url to base64. */ async asyncTransformRequest(model, messages, optionalParams, rocketllmParams, headers) { return this.transformRequest( model, messages, optionalParams, rocketllmParams, headers ); } /** * Get model response iterator for streaming * * Returns an iterator that yields streaming chunks from the response. */ getModelResponseIterator(streamingResponse, syncStream, jsonMode) { return null; } /** * Custom LLM provider identifier */ get customLLMProvider() { return null; } /** * Whether this provider has a custom stream wrapper */ get hasCustomStreamWrapper() { return false; } /** * Whether this provider supports the stream parameter in the request body * * Some providers like Bedrock invoke do not support the stream parameter * in the request body. By default, this is true for almost all providers. */ get supportsStreamParamInRequestBody() { return true; } }; } }); export { BaseLLMException, BaseConfig, transformation_exports, init_transformation };