UNPKG

@push.rocks/smartai

Version:

SmartAi is a versatile TypeScript library designed to facilitate integration and interaction with various AI models, offering functionalities for chat, audio generation, document processing, and vision tasks.

192 lines (166 loc) 5.86 kB
import * as plugins from './plugins.js'; import * as paths from './paths.js'; import { MultiModalModel } from './abstract.classes.multimodal.js'; import type { ChatOptions, ChatResponse, ChatMessage } from './abstract.classes.multimodal.js'; export interface IGroqProviderOptions { groqToken: string; model?: string; } export class GroqProvider extends MultiModalModel { private options: IGroqProviderOptions; private baseUrl = 'https://api.groq.com/v1'; constructor(optionsArg: IGroqProviderOptions) { super(); this.options = { ...optionsArg, model: optionsArg.model || 'llama-3.3-70b-versatile', // Default model }; } async start() {} async stop() {} public async chatStream(input: ReadableStream<Uint8Array>): Promise<ReadableStream<string>> { // Create a TextDecoder to handle incoming chunks const decoder = new TextDecoder(); let buffer = ''; let currentMessage: { role: string; content: string; } | null = null; // Create a TransformStream to process the input const transform = new TransformStream<Uint8Array, string>({ transform: async (chunk, controller) => { buffer += decoder.decode(chunk, { stream: true }); // Try to parse complete JSON messages from the buffer while (true) { const newlineIndex = buffer.indexOf('\n'); if (newlineIndex === -1) break; const line = buffer.slice(0, newlineIndex); buffer = buffer.slice(newlineIndex + 1); if (line.trim()) { try { const message = JSON.parse(line); currentMessage = { role: message.role || 'user', content: message.content || '', }; } catch (e) { console.error('Failed to parse message:', e); } } } // If we have a complete message, send it to Groq if (currentMessage) { const response = await fetch(`${this.baseUrl}/chat/completions`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.options.groqToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ model: this.options.model, messages: [{ role: currentMessage.role, content: currentMessage.content }], stream: true, }), }); // Process each chunk from Groq const reader = response.body?.getReader(); if (reader) { try { while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = new TextDecoder().decode(value); const lines = chunk.split('\n'); for (const line of lines) { if (line.startsWith('data: ')) { const data = line.slice(6); if (data === '[DONE]') break; try { const parsed = JSON.parse(data); const content = parsed.choices[0]?.delta?.content; if (content) { controller.enqueue(content); } } catch (e) { console.error('Failed to parse SSE data:', e); } } } } } finally { reader.releaseLock(); } } currentMessage = null; } }, flush(controller) { if (buffer) { try { const message = JSON.parse(buffer); controller.enqueue(message.content || ''); } catch (e) { console.error('Failed to parse remaining buffer:', e); } } } }); // Connect the input to our transform stream return input.pipeThrough(transform); } // Implementing the synchronous chat interaction public async chat(optionsArg: ChatOptions): Promise<ChatResponse> { const messages = [ // System message { role: 'system', content: optionsArg.systemMessage, }, // Message history ...optionsArg.messageHistory.map(msg => ({ role: msg.role, content: msg.content, })), // User message { role: 'user', content: optionsArg.userMessage, }, ]; const response = await fetch(`${this.baseUrl}/chat/completions`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.options.groqToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ model: this.options.model, messages, temperature: 0.7, max_completion_tokens: 1024, stream: false, }), }); if (!response.ok) { const error = await response.json(); throw new Error(`Groq API error: ${error.message || response.statusText}`); } const result = await response.json(); return { role: 'assistant', message: result.choices[0].message.content, }; } public async audio(optionsArg: { message: string }): Promise<NodeJS.ReadableStream> { // Groq does not provide an audio API, so this method is not implemented. throw new Error('Audio generation is not yet supported by Groq.'); } public async vision(optionsArg: { image: Buffer; prompt: string }): Promise<string> { throw new Error('Vision tasks are not yet supported by Groq.'); } public async document(optionsArg: { systemMessage: string; userMessage: string; pdfDocuments: Uint8Array[]; messageHistory: ChatMessage[]; }): Promise<{ message: any }> { throw new Error('Document processing is not yet supported by Groq.'); } }