NLP-IBM-Debater / src /app /services /groq.service.ts
Yassine Mhirsi
argument generation
ee3eb53
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;
};
};
/**
* Sends messages to Groq API and returns the assistant's response
*/
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');
}
// Convert our ChatMessage format to Groq's expected format
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) {
// Skip invalid JSON
}
}
}
}
return fullContent;
} catch (error) {
if (error instanceof Error) {
throw error;
}
throw new Error('Failed to send message to Groq API');
}
}
/**
* Sends messages to Groq API with streaming support
*/
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');
}
// Convert our ChatMessage format to Groq's expected format
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) {
// Skip invalid JSON
}
}
}
}
return fullContent;
} catch (error) {
if (error instanceof Error) {
throw error;
}
throw new Error('Failed to send message to Groq API');
}
}