feat: implement AI-powered Human-in-the-Loop Norm Builder interface and standard CRUD endpoints
This commit is contained in:
@@ -597,4 +597,88 @@ export const analyzeWithMinimax = async (file: File, apiKey: string, model: stri
|
||||
}
|
||||
|
||||
return cleanAndParseJson(content) as ReportData[];
|
||||
};
|
||||
|
||||
export const buildStandardWithAI = async (
|
||||
options: { provider: AIProvider; apiKey: string; model: string; endpoint?: string },
|
||||
standardName: string,
|
||||
categoryDescription: string
|
||||
) => {
|
||||
const prompt = `Você é um engenheiro de materiais sênior. O usuário solicitou a criação de uma tabela de limites para a norma técnica: "${standardName}".
|
||||
A categoria deste material é descrita como: "${categoryDescription}".
|
||||
|
||||
Sua tarefa é acessar seu conhecimento sobre esta norma e gerar os limites estritos (mínimos e máximos) exigidos.
|
||||
|
||||
RESPONDA APENAS UM JSON VÁLIDO no seguinte formato EXATO:
|
||||
{
|
||||
"codigo": "Nome oficial da norma (ex: ASTM A36/A36M-19)",
|
||||
"produto_especifico": "Descreva o tipo de produto que essa norma cobre",
|
||||
"parametros_controle": {
|
||||
"mecanicos": {
|
||||
"nome_do_parametro_1": valor_numerico,
|
||||
"nome_do_parametro_2": valor_numerico
|
||||
},
|
||||
"quimicos": {
|
||||
"nome_do_parametro": valor_numerico
|
||||
},
|
||||
"fisicos": {
|
||||
"nome_do_parametro": valor_numerico
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Regras Cruciais:
|
||||
1. USE APENAS NÚMEROS (floats/ints) nos valores. NUNCA use strings como "0.25" ou "250". Use 0.25 e 250.
|
||||
2. Se a norma não especifica um limite máximo ou mínimo para um elemento, coloque null (sem aspas).
|
||||
3. O nome da chave dentro de mecânicos/químicos/físicos deve ser em minúsculo, sem acentos, com underscores, e deve conter a unidade ou a palavra min/max (ex: "limite_escoamento_min_mpa", "carbono_max_percentual", "espessura_min_microns").
|
||||
4. Crie APENAS os grupos (mecanicos, quimicos, fisicos) que fazem sentido para a norma solicitada.
|
||||
5. DEVOLVA APENAS O JSON, sem nenhuma formatação ou texto explicativo ao redor.`;
|
||||
|
||||
try {
|
||||
let resultJson = '';
|
||||
|
||||
if (options.provider === 'gemini') {
|
||||
const ai = new GoogleGenAI({ apiKey: options.apiKey });
|
||||
const response = await ai.models.generateContent({
|
||||
model: options.model || 'gemini-2.5-flash',
|
||||
contents: prompt
|
||||
});
|
||||
resultJson = response.text || '';
|
||||
} else if (options.provider === 'openai') {
|
||||
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${options.apiKey}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: options.model || 'gpt-4o',
|
||||
messages: [{ role: "user", content: prompt }]
|
||||
})
|
||||
});
|
||||
const data = await response.json();
|
||||
resultJson = data.choices[0].message.content;
|
||||
} else if (options.provider === 'openrouter') {
|
||||
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${options.apiKey}`,
|
||||
'HTTP-Referer': 'https://steelcheck.reifonas.cloud'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: options.model || 'google/gemini-2.5-flash',
|
||||
messages: [{ role: "user", content: prompt }]
|
||||
})
|
||||
});
|
||||
const data = await response.json();
|
||||
resultJson = data.choices[0].message.content;
|
||||
}
|
||||
|
||||
const parsed = cleanAndParseJson(resultJson);
|
||||
return parsed;
|
||||
} catch (error) {
|
||||
console.error("Erro no buildStandardWithAI:", error);
|
||||
throw new Error("Falha ao gerar norma com a IA. Tente novamente.");
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user