mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-20 05:28:13 +02:00
Fetch and display all available AI models from OpenRouter's API
Integrate OpenRouter API to dynamically fetch and display available AI models in the client, and update the AI generation endpoint to accept a model override. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/h6F2mtY
This commit is contained in:
1 parent
0c257d991d
commit
97b1a76270
4 files changed
+79
-28
No files matched your search
@@ -1,10 +1,10 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { apiRequest, queryClient } from "@/lib/queryClient";
|
||||
import { Bot, User, Lightbulb, History, Zap, Sparkles } from "lucide-react";
|
||||
import { Bot, User, Lightbulb, History, Zap, Sparkles, Loader2 } from "lucide-react";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
|
||||
@@ -14,21 +14,15 @@ interface Message {
|
||||
variants?: Array<{ variant: string; text: string; characterCount: number }>;
|
||||
}
|
||||
|
||||
const OPENROUTER_MODELS = [
|
||||
{ id: "anthropic/claude-3.5-sonnet", name: "Claude 3.5 Sonnet (Recommandé)", category: "Anthropic" },
|
||||
{ id: "anthropic/claude-sonnet-3.7", name: "Claude Sonnet 3.7", category: "Anthropic" },
|
||||
{ id: "anthropic/claude-opus", name: "Claude Opus", category: "Anthropic" },
|
||||
{ id: "openai/gpt-5", name: "GPT-5", category: "OpenAI" },
|
||||
{ id: "openai/gpt-4o", name: "GPT-4o", category: "OpenAI" },
|
||||
{ id: "openai/gpt-3.5-turbo", name: "GPT-3.5 Turbo", category: "OpenAI" },
|
||||
{ id: "google/gemini-2.5-flash", name: "Gemini 2.5 Flash", category: "Google" },
|
||||
{ id: "google/gemini-pro", name: "Gemini Pro", category: "Google" },
|
||||
{ id: "meta-llama/llama-4-maverick:free", name: "Llama 4 Maverick (Gratuit)", category: "Meta" },
|
||||
{ id: "meta-llama/llama-3.1-70b-instruct", name: "Llama 3.1 70B", category: "Meta" },
|
||||
{ id: "x-ai/grok-3", name: "Grok 3", category: "xAI" },
|
||||
{ id: "mistralai/mistral-small-3.1:free", name: "Mistral Small 3.1 (Gratuit)", category: "Mistral AI" },
|
||||
{ id: "qwen/qwen-qwq-32b:free", name: "Qwen QwQ 32B (Gratuit)", category: "Alibaba" },
|
||||
];
|
||||
interface OpenRouterModel {
|
||||
id: string;
|
||||
name: string;
|
||||
context_length?: number;
|
||||
pricing?: {
|
||||
prompt: string;
|
||||
completion: string;
|
||||
};
|
||||
}
|
||||
|
||||
export default function AiChat() {
|
||||
const [messages, setMessages] = useState<Message[]>([
|
||||
@@ -41,6 +35,13 @@ export default function AiChat() {
|
||||
const [selectedModel, setSelectedModel] = useState("anthropic/claude-3.5-sonnet");
|
||||
const { toast } = useToast();
|
||||
|
||||
// Fetch available models from OpenRouter
|
||||
const { data: modelsData, isLoading: modelsLoading } = useQuery<{ models: OpenRouterModel[] }>({
|
||||
queryKey: ['/api/ai/models'],
|
||||
});
|
||||
|
||||
const availableModels = modelsData?.models || [];
|
||||
|
||||
const generateMutation = useMutation({
|
||||
mutationFn: async (productInfo: any) => {
|
||||
const response = await apiRequest("POST", "/api/ai/generate", {
|
||||
@@ -113,16 +114,27 @@ export default function AiChat() {
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<label className="text-sm font-medium text-foreground">Modèle IA:</label>
|
||||
<Select value={selectedModel} onValueChange={setSelectedModel}>
|
||||
<Select value={selectedModel} onValueChange={setSelectedModel} disabled={modelsLoading}>
|
||||
<SelectTrigger className="w-[300px] rounded-xl" data-testid="select-ai-model">
|
||||
<SelectValue />
|
||||
{modelsLoading ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
<span>Chargement des modèles...</span>
|
||||
</div>
|
||||
) : (
|
||||
<SelectValue placeholder="Sélectionner un modèle" />
|
||||
)}
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{OPENROUTER_MODELS.map((model) => (
|
||||
<SelectContent className="max-h-[300px] overflow-y-auto">
|
||||
{availableModels.map((model: OpenRouterModel) => (
|
||||
<SelectItem key={model.id} value={model.id} data-testid={`model-option-${model.id}`}>
|
||||
<div className="flex flex-col">
|
||||
<span>{model.name}</span>
|
||||
<span className="text-xs text-muted-foreground">{model.category}</span>
|
||||
<span className="font-medium">{model.name}</span>
|
||||
{model.pricing && (
|
||||
<span className="text-xs text-muted-foreground">
|
||||
${model.pricing.prompt} / ${model.pricing.completion}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
|
||||
Reference in new issue
Block a user