| import type { ChatMessage } from '../types/chat.types.ts'; |
|
|
| const GROQ_API_URL = 'https://api.groq.com/openai/v1'; |
| const MODEL = 'meta-llama/llama-4-scout-17b-16e-instruct'; |
|
|
| export type GroqMessage = { |
| role: 'user' | 'assistant' | 'system'; |
| content: string; |
| }; |
|
|
| export type GroqChatResponse = { |
| id: string; |
| object: string; |
| created: number; |
| model: string; |
| choices: Array<{ |
| index: number; |
| message: { |
| role: 'assistant'; |
| content: string; |
| }; |
| finish_reason: string; |
| }>; |
| usage: { |
| prompt_tokens: number; |
| completion_tokens: number; |
| total_tokens: number; |
| }; |
| }; |
|
|
| export type GroqStreamChunk = { |
| id: string; |
| object: string; |
| created: number; |
| model: string; |
| choices: Array<{ |
| index: number; |
| delta: { |
| role?: 'assistant'; |
| content?: string; |
| }; |
| finish_reason: string | null; |
| }>; |
| }; |
|
|
| export type GroqError = { |
| error: { |
| message: string; |
| type: string; |
| code?: string; |
| }; |
| }; |
|
|
| |
| |
| |
| export async function sendChatMessage(messages: ChatMessage[]): Promise<string> { |
| const apiKey = process.env.REACT_APP_GROQ_API_KEY; |
| |
| if (!apiKey) { |
| throw new Error('REACT_APP_GROQ_API_KEY environment variable is not set'); |
| } |
|
|
| |
| const groqMessages: GroqMessage[] = messages.map(msg => ({ |
| role: msg.role, |
| content: msg.content |
| })); |
|
|
| try { |
| const response = await fetch(`${GROQ_API_URL}/chat/completions`, { |
| method: 'POST', |
| headers: { |
| 'Authorization': `Bearer ${apiKey}`, |
| 'Content-Type': 'application/json', |
| }, |
| body: JSON.stringify({ |
| model: MODEL, |
| messages: groqMessages, |
| temperature: 0.7, |
| max_tokens: 4096, |
| top_p: 1, |
| stream: true, |
| }), |
| }); |
|
|
| if (!response.ok) { |
| const errorData: GroqError = await response.json(); |
| throw new Error(errorData.error?.message || `HTTP error! status: ${response.status}`); |
| } |
|
|
| const reader = response.body?.getReader(); |
| if (!reader) { |
| throw new Error('Failed to get response reader'); |
| } |
|
|
| const decoder = new TextDecoder(); |
| let fullContent = ''; |
|
|
| while (true) { |
| const { done, value } = await reader.read(); |
| if (done) break; |
|
|
| const chunk = decoder.decode(value, { stream: true }); |
| const lines = chunk.split('\n'); |
|
|
| for (const line of lines) { |
| if (line.startsWith('data: ')) { |
| const data = line.slice(6); |
| if (data === '[DONE]') continue; |
|
|
| try { |
| const parsed: GroqStreamChunk = JSON.parse(data); |
| const content = parsed.choices[0]?.delta?.content; |
| if (content) { |
| fullContent += content; |
| } |
| } catch (e) { |
| |
| } |
| } |
| } |
| } |
|
|
| return fullContent; |
| } catch (error) { |
| if (error instanceof Error) { |
| throw error; |
| } |
| throw new Error('Failed to send message to Groq API'); |
| } |
| } |
|
|
| |
| |
| |
| export async function sendChatMessageStream( |
| messages: ChatMessage[], |
| onChunk: (chunk: string) => void |
| ): Promise<string> { |
| const apiKey = process.env.REACT_APP_GROQ_API_KEY; |
| |
| if (!apiKey) { |
| throw new Error('REACT_APP_GROQ_API_KEY environment variable is not set'); |
| } |
|
|
| |
| const groqMessages: GroqMessage[] = messages.map(msg => ({ |
| role: msg.role, |
| content: msg.content |
| })); |
|
|
| try { |
| const response = await fetch(`${GROQ_API_URL}/chat/completions`, { |
| method: 'POST', |
| headers: { |
| 'Authorization': `Bearer ${apiKey}`, |
| 'Content-Type': 'application/json', |
| }, |
| body: JSON.stringify({ |
| model: MODEL, |
| messages: groqMessages, |
| temperature: 0.7, |
| max_tokens: 4096, |
| top_p: 1, |
| stream: true, |
| }), |
| }); |
|
|
| if (!response.ok) { |
| const errorData: GroqError = await response.json(); |
| throw new Error(errorData.error?.message || `HTTP error! status: ${response.status}`); |
| } |
|
|
| const reader = response.body?.getReader(); |
| if (!reader) { |
| throw new Error('Failed to get response reader'); |
| } |
|
|
| const decoder = new TextDecoder(); |
| let fullContent = ''; |
|
|
| while (true) { |
| const { done, value } = await reader.read(); |
| if (done) break; |
|
|
| const chunk = decoder.decode(value, { stream: true }); |
| const lines = chunk.split('\n'); |
|
|
| for (const line of lines) { |
| if (line.startsWith('data: ')) { |
| const data = line.slice(6); |
| if (data === '[DONE]') continue; |
|
|
| try { |
| const parsed: GroqStreamChunk = JSON.parse(data); |
| const content = parsed.choices[0]?.delta?.content; |
| if (content) { |
| fullContent += content; |
| onChunk(content); |
| } |
| } catch (e) { |
| |
| } |
| } |
| } |
| } |
|
|
| return fullContent; |
| } catch (error) { |
| if (error instanceof Error) { |
| throw error; |
| } |
| throw new Error('Failed to send message to Groq API'); |
| } |
| } |
|
|