feat: adicionar suporte a modelos MiniMax (2.7 e 3.0)

This commit is contained in:
2026-06-22 20:34:35 +00:00
parent 9f054a777f
commit 176f064c16
4 changed files with 88 additions and 1 deletions
+2
View File
@@ -67,6 +67,7 @@ export const ApiKeySetup: React.FC<ApiKeySetupProps> = ({ onKeySave }) => {
case 'azure': return 'https://portal.azure.com/#view/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps'; case 'azure': return 'https://portal.azure.com/#view/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps';
case 'ollama': return 'https://ollama.com/download'; case 'ollama': return 'https://ollama.com/download';
case 'openrouter': return 'https://openrouter.ai/keys'; case 'openrouter': return 'https://openrouter.ai/keys';
case 'minimax': return 'https://platform.minimaxi.com/user-center/basic-information/interface-key';
default: return '#'; default: return '#';
} }
}; };
@@ -79,6 +80,7 @@ export const ApiKeySetup: React.FC<ApiKeySetupProps> = ({ onKeySave }) => {
case 'azure': return 'Azure OpenAI'; case 'azure': return 'Azure OpenAI';
case 'ollama': return 'Ollama (Local)'; case 'ollama': return 'Ollama (Local)';
case 'openrouter': return 'OpenRouter'; case 'openrouter': return 'OpenRouter';
case 'minimax': return 'MiniMax';
default: return 'API'; default: return 'API';
} }
}; };
+53
View File
@@ -351,6 +351,8 @@ export const analyzeCertificate = async (options: AnalyzeOptions): Promise<Repor
return analyzeWithOllama(file, endpoint!, model); return analyzeWithOllama(file, endpoint!, model);
case 'openrouter': case 'openrouter':
return analyzeWithOpenRouter(file, apiKey, model); return analyzeWithOpenRouter(file, apiKey, model);
case 'minimax':
return analyzeWithMinimax(file, apiKey, model);
default: default:
throw new Error(`Provedor não suportado: ${provider}`); throw new Error(`Provedor não suportado: ${provider}`);
} }
@@ -476,5 +478,56 @@ export const analyzeWithOpenRouter = async (file: File, apiKey: string, model: s
throw new Error("Resposta vazia do OpenRouter"); throw new Error("Resposta vazia do OpenRouter");
} }
return cleanAndParseJson(content) as ReportData;
};
export const analyzeWithMinimax = async (file: File, apiKey: string, model: string = 'minimax-2.7'): Promise<ReportData> => {
if (!apiKey) {
throw new Error("A chave de API do MiniMax não foi fornecida.");
}
const base64Data = await new Promise<string>((resolve) => {
const reader = new FileReader();
reader.onloadend = () => resolve((reader.result as string).split(',')[1]);
reader.readAsDataURL(file);
});
const response = await fetch('https://api.minimax.chat/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model,
messages: [
{
role: 'user',
content: [
{ type: 'text', text: PROMPT_BASE + "\n\nRetorne apenas JSON válido sem formatação markdown." },
{
type: 'image_url',
image_url: { url: `data:${file.type};base64,${base64Data}` }
}
]
}
],
temperature: 0.1,
response_format: { type: 'json_object' }
})
});
if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new Error(`Erro do MiniMax: ${error.error?.message || 'Erro desconhecido'}`);
}
const data = await response.json();
const content = data.choices[0]?.message?.content;
if (!content) {
throw new Error("Resposta vazia do MiniMax");
}
return cleanAndParseJson(content) as ReportData; return cleanAndParseJson(content) as ReportData;
}; };
+25
View File
@@ -28,6 +28,8 @@ export const testApiKey = async (provider: AIProvider, apiKey: string, endpoint?
return await testOllama(endpoint); return await testOllama(endpoint);
case 'openrouter': case 'openrouter':
return await testOpenRouter(apiKey); return await testOpenRouter(apiKey);
case 'minimax':
return await testMinimax(apiKey);
default: default:
return { success: false, error: 'Provedor não suportado' }; return { success: false, error: 'Provedor não suportado' };
} }
@@ -250,4 +252,27 @@ const testOpenRouter = async (apiKey: string): Promise<TestResult> => {
} catch (error: any) { } catch (error: any) {
return { success: false, error: error.message || 'Erro ao conectar com OpenRouter' }; return { success: false, error: error.message || 'Erro ao conectar com OpenRouter' };
} }
};
const testMinimax = async (apiKey: string): Promise<TestResult> => {
try {
const response = await fetch('https://api.minimax.chat/v1/models', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
if (!response.ok) {
const error = await response.json().catch(() => ({}));
return { success: false, error: error.message || 'Chave de API inválida' };
}
return {
success: true,
models: [
{ id: 'minimax-2.7', name: 'MiniMax 2.7' },
{ id: 'minimax-3.0', name: 'MiniMax 3.0' }
]
};
} catch (error: any) {
return { success: false, error: error.message || 'Erro ao conectar com MiniMax' };
}
}; };
+8 -1
View File
@@ -1,6 +1,6 @@
import { AIProvider } from './providers'; import { AIProvider } from './providers';
export type AIProvider = 'gemini' | 'openai' | 'anthropic' | 'azure' | 'ollama' | 'openrouter'; export type AIProvider = 'gemini' | 'openai' | 'anthropic' | 'azure' | 'ollama' | 'openrouter' | 'minimax';
export const OLLAMA_AUTO_DETECT_URLS = [ export const OLLAMA_AUTO_DETECT_URLS = [
'http://localhost:11434', 'http://localhost:11434',
@@ -65,5 +65,12 @@ export const PROVIDERS: ProviderConfig[] = [
description: 'Acesso a múltiplos modelos através do OpenRouter', description: 'Acesso a múltiplos modelos através do OpenRouter',
models: ['google/gemini-2.5-flash', 'google/gemini-2.5-pro', 'anthropic/claude-3.5-sonnet', 'openai/gpt-4o', 'meta-llama/llama-3.1-70b-instruct'], models: ['google/gemini-2.5-flash', 'google/gemini-2.5-pro', 'anthropic/claude-3.5-sonnet', 'openai/gpt-4o', 'meta-llama/llama-3.1-70b-instruct'],
defaultModel: 'google/gemini-2.5-flash' defaultModel: 'google/gemini-2.5-flash'
},
{
id: 'minimax',
name: 'MiniMax',
description: 'Modelos MiniMax (2.7 e 3.0)',
models: ['minimax-2.7', 'minimax-3.0'],
defaultModel: 'minimax-2.7'
} }
]; ];