feat: route invoice analysis through referentiel ia
This commit is contained in:
@@ -677,7 +677,7 @@ export default function Settings() {
|
||||
const [sftpAutoExport, setSftpAutoExport] = useState(false);
|
||||
const [sftpRecipientFilter, setSftpRecipientFilter] = useState("");
|
||||
const [llmLogsRetentionMonths, setLlmLogsRetentionMonths] = useState(3);
|
||||
const [aiProvider, setAiProvider] = useState<"mistral" | "manus" | "gemini">("mistral");
|
||||
const [aiProvider, setAiProvider] = useState<"mistral" | "manus" | "gemini" | "referentiel">("mistral");
|
||||
const [mistralApiKey, setMistralApiKey] = useState("");
|
||||
const [manusForgeApiKey, setManusForgeApiKey] = useState("");
|
||||
const [manusForgeApiUrl, setManusForgeApiUrl] = useState("");
|
||||
@@ -722,6 +722,17 @@ export default function Settings() {
|
||||
},
|
||||
});
|
||||
|
||||
const testReferentielIaMutation = trpc.settings.testReferentielIa.useMutation({
|
||||
onSuccess: (data) => {
|
||||
const engine = data.engineName ? ` Moteur sélectionné : ${data.engineName}.` : "";
|
||||
const model = data.model ? ` Modèle : ${data.model}.` : "";
|
||||
toast.success(`Connexion au Référentiel IA réussie.${engine}${model}`);
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(error.message || "Connexion au Référentiel IA impossible");
|
||||
},
|
||||
});
|
||||
|
||||
const testSftpMutation = trpc.sftp.testConnection.useMutation({
|
||||
onSuccess: (data) => {
|
||||
if (data.success) {
|
||||
@@ -857,7 +868,7 @@ export default function Settings() {
|
||||
<CardContent className="space-y-6 pt-6">
|
||||
|
||||
{/* Provider selector */}
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAiProvider("mistral")}
|
||||
@@ -939,6 +950,32 @@ export default function Settings() {
|
||||
<Badge className="bg-blue-500 text-white text-xs">Actif</Badge>
|
||||
)}
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAiProvider("referentiel")}
|
||||
className={`relative flex flex-col items-center gap-3 p-5 rounded-xl border-2 transition-all cursor-pointer ${
|
||||
aiProvider === "referentiel"
|
||||
? "border-violet-500 bg-violet-50 dark:bg-violet-950/20 shadow-md"
|
||||
: "border-muted hover:border-violet-300 bg-background"
|
||||
}`}
|
||||
>
|
||||
{aiProvider === "referentiel" && (
|
||||
<div className="absolute top-2 right-2">
|
||||
<CheckCircle className="w-5 h-5 text-violet-500" />
|
||||
</div>
|
||||
)}
|
||||
<div className="p-3 bg-violet-100 dark:bg-violet-900/30 rounded-xl">
|
||||
<Brain className="w-8 h-8 text-violet-600" />
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<p className="font-bold text-base">Référentiel IA</p>
|
||||
<p className="text-xs text-muted-foreground mt-1">Choix centralisé<br/>Moteur et modèle décidés par le référentiel</p>
|
||||
</div>
|
||||
{aiProvider === "referentiel" && (
|
||||
<Badge className="bg-violet-500 text-white text-xs">Actif</Badge>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Mistral config */}
|
||||
@@ -1055,6 +1092,32 @@ export default function Settings() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{aiProvider === "referentiel" && (
|
||||
<div className="space-y-4 p-4 bg-violet-50 dark:bg-violet-950/10 rounded-xl border border-violet-200 dark:border-violet-800">
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div>
|
||||
<p className="text-sm font-semibold text-violet-700 dark:text-violet-400 uppercase tracking-wide">Configuration centralisée</p>
|
||||
<p className="text-sm text-violet-900 dark:text-violet-100 mt-2">
|
||||
L’analyse est envoyée à la passerelle du Référentiel IA. Le moteur, le modèle, les droits et les limites d’usage sont ceux sélectionnés pour <strong>Démat. Facturation DSI</strong> dans le Référentiel.
|
||||
</p>
|
||||
<p className="text-xs text-violet-700 dark:text-violet-300 mt-2">
|
||||
Aucune clé du Référentiel n’est affichée ni enregistrée dans ces paramètres.
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="border-violet-300 text-violet-700 hover:bg-violet-100 shrink-0"
|
||||
onClick={() => testReferentielIaMutation.mutate()}
|
||||
disabled={testReferentielIaMutation.isPending}
|
||||
>
|
||||
{testReferentielIaMutation.isPending ? <Loader2 className="w-4 h-4 animate-spin mr-2" /> : <CheckCircle className="w-4 h-4 mr-2" />}
|
||||
Vérifier la connexion
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -1073,20 +1136,27 @@ export default function Settings() {
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6 pt-6">
|
||||
<div className="space-y-3">
|
||||
<Label htmlFor="llmModel" className="text-base font-semibold">Modèle IA (override)</Label>
|
||||
<Input
|
||||
id="llmModel"
|
||||
value={llmModel}
|
||||
onChange={(e) => setLlmModel(e.target.value)}
|
||||
placeholder="mistral-large-latest"
|
||||
className="h-11"
|
||||
/>
|
||||
<p className="text-sm text-muted-foreground flex items-center gap-2">
|
||||
<AlertCircle className="w-4 h-4" />
|
||||
Nom du modèle Mistral à utiliser pour l'extraction
|
||||
</p>
|
||||
</div>
|
||||
{aiProvider === "referentiel" ? (
|
||||
<div className="space-y-2 p-4 rounded-lg bg-violet-50 dark:bg-violet-950/10 border border-violet-200 dark:border-violet-800">
|
||||
<p className="font-medium text-violet-900 dark:text-violet-100">Modèle décidé par le Référentiel IA</p>
|
||||
<p className="text-sm text-violet-700 dark:text-violet-300">La surcharge locale est volontairement désactivée pour garantir un moteur unique, piloté et tracé au niveau Santinova.</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
<Label htmlFor="llmModel" className="text-base font-semibold">Modèle IA (override)</Label>
|
||||
<Input
|
||||
id="llmModel"
|
||||
value={llmModel}
|
||||
onChange={(e) => setLlmModel(e.target.value)}
|
||||
placeholder="mistral-large-latest"
|
||||
className="h-11"
|
||||
/>
|
||||
<p className="text-sm text-muted-foreground flex items-center gap-2">
|
||||
<AlertCircle className="w-4 h-4" />
|
||||
Nom du modèle à utiliser pour l'extraction directe
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-3">
|
||||
<Label htmlFor="llmLogsRetentionMonths" className="text-base font-semibold">
|
||||
|
||||
Reference in New Issue
Block a user