UNPKG

sambanova

Version:

TypeScript/Javascript client for Sambanova AI API with comprehensive model support

146 lines (145 loc) 6.86 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SambanovaError = exports.SambanovaClient = void 0; const utils_1 = require("./utils"); const types_1 = require("./types"); const utils_2 = require("./utils"); class SambanovaClient { constructor(apiKey, options = {}) { this.apiKey = apiKey; this.baseUrl = options.baseUrl || 'https://api.sambanova.ai/v1'; this.defaultModel = options.defaultModel || 'Meta-Llama-3.2-3B-Instruct'; this.defaultRetryCount = options.defaultRetryCount || 3; this.defaultRetryDelay = options.defaultRetryDelay || 1000; } async makeRequest(endpoint, data, retryCount = this.defaultRetryCount, stream = false) { let lastError = null; for (let attempt = 0; attempt <= retryCount; attempt++) { try { const response = await fetch(`${this.baseUrl}${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` }, body: JSON.stringify(data) }); if (!response.ok) { const errorData = await response.json(); throw new types_1.SambanovaError(errorData.message || 'API request failed', response.status, errorData.code, errorData); } if (stream) { return response; } return await response.json(); } catch (error) { lastError = error; if (attempt < retryCount) { await (0, utils_1.sleep)(this.defaultRetryDelay * Math.pow(2, attempt)); continue; } } } throw lastError || new Error('Request failed after retries'); } async chat(messages, options = {}) { var _a, _b, _c, _d; const model = options.model || this.defaultModel; if ((0, utils_1.isVisionModel)(model)) { for (const msg of messages) { if (Array.isArray(msg.content)) { for (const content of msg.content) { if (content.type === 'image_url' && ((_a = content.image_url) === null || _a === void 0 ? void 0 : _a.url)) { try { content.image_url.url = await (0, utils_2.getBase64Image)(content.image_url.url); } catch (error) { throw new types_1.SambanovaError(`Failed to process image: ${error}`, 400, 'INVALID_IMAGE_FORMAT'); } } } } } } messages.forEach(msg => (0, utils_1.validateMessage)(msg, (0, utils_1.isVisionModel)(model))); const payload = { model, messages, temperature: (_b = options.temperature) !== null && _b !== void 0 ? _b : 0.1, top_p: (_c = options.top_p) !== null && _c !== void 0 ? _c : 0.1, max_tokens: options.max_tokens, stream: (_d = options.stream) !== null && _d !== void 0 ? _d : false }; const response = await this.makeRequest('/chat/completions', payload, options.retry_count, payload.stream); if (payload.stream && response instanceof Response) { throw new Error('Stream response received in chat method. Use streamChat instead.'); } return response; } async *streamChat(messages, options = {}) { var _a, _b, _c, _d, _e, _f; const model = options.model || this.defaultModel; if ((0, utils_1.isVisionModel)(model)) { for (const msg of messages) { if (Array.isArray(msg.content)) { for (const content of msg.content) { if (content.type === 'image_url' && ((_a = content.image_url) === null || _a === void 0 ? void 0 : _a.url)) { try { content.image_url.url = await (0, utils_2.getBase64Image)(content.image_url.url); } catch (error) { throw new types_1.SambanovaError(`Failed to process image: ${error}`, 400, 'INVALID_IMAGE_FORMAT'); } } } } } } const payload = { model, messages, temperature: (_b = options.temperature) !== null && _b !== void 0 ? _b : 0.1, top_p: (_c = options.top_p) !== null && _c !== void 0 ? _c : 0.1, max_tokens: options.max_tokens, stream: true, stream_options: { include_usage: true } // Optional }; const response = await this.makeRequest('/chat/completions', payload, options.retry_count, true); if (!response || !('body' in response) || typeof response.body.getReader !== 'function') { throw new Error('Expected a streaming response'); } const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop() || ''; for (const line of lines) { if (line.trim().startsWith('data: ')) { const dataStr = line.trim().slice(6); if (dataStr === '[DONE]') return; try { const chunk = JSON.parse(dataStr); const content = (_f = (_e = (_d = chunk.choices) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.delta) === null || _f === void 0 ? void 0 : _f.content; if (content) yield content; } catch (error) { console.error('Failed to parse stream data:', error); } } } } } } exports.SambanovaClient = SambanovaClient; var types_2 = require("./types"); Object.defineProperty(exports, "SambanovaError", { enumerable: true, get: function () { return types_2.SambanovaError; } });