@sconedev/ai_toolkit
Version:
Simplify AI integration in web apps with local and offline model support
68 lines (67 loc) • 3.21 kB
JavaScript
// Updated for @mistralai/mistralai v1.6.0
import { Mistral } from '@mistralai/mistralai';
export class MistralProvider {
constructor(apiKey, model) {
if (!apiKey) {
throw new Error('API key is required for Mistral provider');
}
// FIXED: Pass apiKey as an object parameter, not as a direct value
this.client = new Mistral({ apiKey: apiKey });
this.defaultModel = model || 'mistral-small'; // Current default model
}
async chat(messages, options) {
try {
// Log for debugging
console.log(`Using Mistral model: ${options?.model || this.defaultModel}`);
// FIXED: Changed API call to match the official example
const completion = await this.client.chat.complete({
model: options?.model || this.defaultModel,
messages: messages.map(msg => ({
role: msg.role,
content: msg.content
})),
temperature: options?.temperature || 0.7,
maxTokens: options?.maxTokens || undefined,
topP: options?.topP || undefined
});
// Log sample of response for debugging
console.log('Mistral response:', JSON.stringify(completion, null, 2).substring(0, 200) + '...');
// Extract content from response structure
if (!completion || !completion.choices || completion.choices.length === 0) {
throw new Error('No choices in response from Mistral');
}
const content = completion.choices[0]?.message?.content;
if (content === undefined || content === null) {
throw new Error('No valid content in response from Mistral');
}
if (Array.isArray(content)) {
return content
.filter(chunk => 'text' in chunk) // Ensure the chunk has a 'text' property
.map(chunk => chunk.text) // Safely cast to the correct type
.join(''); // Combine chunks into a single string
}
return content;
}
catch (error) {
// Detailed error logging
console.error('Mistral API error details:', error);
if (error instanceof Error) {
// Check for common API errors
if (error.message.includes('401')) {
throw new Error('Mistral API error: Invalid API key or unauthorized');
}
else if (error.message.includes('404')) {
throw new Error(`Mistral API error: Model not found - check if "${options?.model || this.defaultModel}" is valid`);
}
else if (error.message.includes('429')) {
throw new Error('Mistral API error: Rate limit exceeded');
}
throw new Error(`Mistral API error: ${error.message}`);
}
throw new Error('Unknown error occurred in Mistral provider');
}
}
async generateImage(description, options) {
throw new Error('Image generation is not supported by Mistral');
}
}