fix: address issues in model pull and chat API

- Refactored model pull logic to improve error handling and user feedback.
- Enhanced chat API to ensure better performance and reliability during message fetching.
- Updated UI components for a more intuitive user experience when interacting with models and messages.
This commit is contained in:
Evandro Fonseca Junior committed 2025-11-19 00:01:14 -03:00
1 parent ad9d5d32d2
commit b2a06ed994
261 files changed
+19968

No files matched your search

+41
View File
@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
+36
View File
@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
+208
View File
@@ -0,0 +1,208 @@
'use client';
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { MessageSquare, Settings, Server, Moon, Sun, PanelLeftClose, PanelLeftOpen } from "lucide-react";
import { ChatInput } from "@/components/chat/chat-input";
import { ChatMessage } from "@/components/chat/chat-message";
import { SystemPanel } from "@/components/chat/system-panel";
import { PromptGeneratorDialog } from "@/components/chat/prompt-generator";
import { useChat } from "@/hooks/use-chat";
import { useLocalModels } from "@/hooks/use-local-models";
import { useState, useEffect, useRef } from "react";
import { useTheme } from "next-themes";
import { ImperativePanelHandle } from "react-resizable-panels";
export default function ChatPage() {
const { messages, sendMessage, isLoading, stop } = useChat();
const { models } = useLocalModels();
const { theme, setTheme } = useTheme();
const [selectedModel, setSelectedModel] = useState("");
const [systemPrompt, setSystemPrompt] = useState("Você é um assistente útil e prestativo.");
const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);
const sidebarRef = useRef<ImperativePanelHandle>(null);
// Auto-select first model
useEffect(() => {
if (models.length > 0 && !selectedModel) {
setSelectedModel(models[0].name);
}
}, [models, selectedModel]);
const handleSend = (content: string) => {
if (!selectedModel) return;
sendMessage(content, selectedModel, systemPrompt);
};
const toggleSidebar = () => {
const panel = sidebarRef.current;
if (panel) {
if (isSidebarCollapsed) {
panel.expand();
} else {
panel.collapse();
}
}
};
return (
<div className="h-screen w-full bg-background overflow-hidden flex">
{/* Left Sidebar (Nav) */}
<ResizablePanelGroup direction="horizontal" className="flex-1">
<ResizablePanel
ref={sidebarRef}
defaultSize={4}
minSize={4}
maxSize={15}
collapsible={true}
collapsedSize={0}
onCollapse={() => setIsSidebarCollapsed(true)}
onExpand={() => setIsSidebarCollapsed(false)}
className="border-r flex flex-col items-center py-4 gap-4 bg-muted/20 min-w-[60px]"
>
<Button variant="ghost" size="icon" className="rounded-lg bg-primary/10 text-primary">
<MessageSquare className="w-5 h-5" />
</Button>
<Button variant="ghost" size="icon" className="rounded-lg text-muted-foreground hover:text-foreground">
<Server className="w-5 h-5" />
</Button>
<div className="flex-1" />
<Button
variant="ghost"
size="icon"
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
className="rounded-lg text-muted-foreground hover:text-foreground"
>
{theme === "dark" ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
</Button>
<Button variant="ghost" size="icon" className="rounded-lg text-muted-foreground hover:text-foreground">
<Settings className="w-5 h-5" />
</Button>
</ResizablePanel>
<ResizableHandle />
{/* Main Chat Area */}
<ResizablePanel defaultSize={75} minSize={50}>
<div className="h-full flex flex-col">
{/* Header */}
<div className="h-14 border-b flex items-center px-4 justify-between bg-background/50 backdrop-blur gap-4">
<div className="flex items-center gap-2">
{isSidebarCollapsed && (
<Button variant="ghost" size="icon" onClick={toggleSidebar} className="h-8 w-8">
<PanelLeftOpen className="w-4 h-4" />
</Button>
)}
{!isSidebarCollapsed && (
<Button variant="ghost" size="icon" onClick={toggleSidebar} className="h-8 w-8 text-muted-foreground">
<PanelLeftClose className="w-4 h-4" />
</Button>
)}
<div className="font-semibold">Chat</div>
</div>
<div className="flex-1 max-w-[300px]">
<Select value={selectedModel} onValueChange={setSelectedModel}>
<SelectTrigger className="h-9">
<SelectValue placeholder="Selecione um modelo..." />
</SelectTrigger>
<SelectContent>
{models.map(m => (
<SelectItem key={m.name} value={m.name}>{m.name}</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
{/* Messages */}
<div className="flex-1 overflow-y-auto scroll-smooth">
{messages.length === 0 ? (
<div className="h-full flex flex-col items-center justify-center text-muted-foreground space-y-4">
<div className="p-4 rounded-full bg-muted/50">
<MessageSquare className="w-8 h-8" />
</div>
<p>Inicie uma conversa com {selectedModel}</p>
</div>
) : (
<div className="flex flex-col pb-4">
{messages.map((msg, i) => (
<ChatMessage key={i} message={msg} />
))}
{isLoading && (
<div className="px-6 py-4 text-xs text-muted-foreground animate-pulse">
Gerando resposta...
</div>
)}
</div>
)}
</div>
{/* Input */}
<ChatInput
onSend={handleSend}
onStop={stop}
isLoading={isLoading}
/>
</div>
</ResizablePanel>
<ResizableHandle withHandle />
{/* Right Sidebar (Settings & Monitor) */}
<ResizablePanel defaultSize={25} minSize={20} maxSize={40} className="bg-muted/10">
<Tabs defaultValue="params" className="h-full flex flex-col">
<div className="border-b px-4">
<TabsList className="w-full justify-start h-12 bg-transparent p-0 gap-4">
<TabsTrigger
value="params"
className="data-[state=active]:bg-transparent data-[state=active]:shadow-none data-[state=active]:border-b-2 data-[state=active]:border-primary rounded-none px-0"
>
Parâmetros
</TabsTrigger>
<TabsTrigger
value="system"
className="data-[state=active]:bg-transparent data-[state=active]:shadow-none data-[state=active]:border-b-2 data-[state=active]:border-primary rounded-none px-0"
>
Sistema
</TabsTrigger>
</TabsList>
</div>
<TabsContent value="params" className="flex-1 p-4 space-y-6 overflow-y-auto m-0">
<div className="space-y-2">
<div className="flex items-center justify-between">
<label className="text-sm font-medium">System Prompt</label>
<PromptGeneratorDialog
defaultModel={selectedModel}
onPromptGenerated={setSystemPrompt}
/>
</div>
<Textarea
value={systemPrompt}
onChange={(e) => setSystemPrompt(e.target.value)}
className="min-h-[300px] resize-none font-mono text-sm"
placeholder="Defina como a IA deve se comportar..."
/>
<p className="text-xs text-muted-foreground">
Instruções globais para o comportamento do modelo.
</p>
</div>
</TabsContent>
<TabsContent value="system" className="flex-1 m-0 overflow-hidden">
<SystemPanel />
</TabsContent>
</Tabs>
</ResizablePanel>
</ResizablePanelGroup>
</div>
);
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

+122
View File
@@ -0,0 +1,122 @@
@import "tailwindcss";
@import "tw-animate-css";
@custom-variant dark (&:is(.dark *));
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
--color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar: var(--sidebar);
--color-chart-5: var(--chart-5);
--color-chart-4: var(--chart-4);
--color-chart-3: var(--chart-3);
--color-chart-2: var(--chart-2);
--color-chart-1: var(--chart-1);
--color-ring: var(--ring);
--color-input: var(--input);
--color-border: var(--border);
--color-destructive: var(--destructive);
--color-accent-foreground: var(--accent-foreground);
--color-accent: var(--accent);
--color-muted-foreground: var(--muted-foreground);
--color-muted: var(--muted);
--color-secondary-foreground: var(--secondary-foreground);
--color-secondary: var(--secondary);
--color-primary-foreground: var(--primary-foreground);
--color-primary: var(--primary);
--color-popover-foreground: var(--popover-foreground);
--color-popover: var(--popover);
--color-card-foreground: var(--card-foreground);
--color-card: var(--card);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
}
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.141 0.005 285.823);
--card: oklch(1 0 0);
--card-foreground: oklch(0.141 0.005 285.823);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.141 0.005 285.823);
--primary: oklch(0.21 0.006 285.885);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.967 0.001 286.375);
--secondary-foreground: oklch(0.21 0.006 285.885);
--muted: oklch(0.967 0.001 286.375);
--muted-foreground: oklch(0.552 0.016 285.938);
--accent: oklch(0.967 0.001 286.375);
--accent-foreground: oklch(0.21 0.006 285.885);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.92 0.004 286.32);
--input: oklch(0.92 0.004 286.32);
--ring: oklch(0.705 0.015 286.067);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.141 0.005 285.823);
--sidebar-primary: oklch(0.21 0.006 285.885);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.967 0.001 286.375);
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
--sidebar-border: oklch(0.92 0.004 286.32);
--sidebar-ring: oklch(0.705 0.015 286.067);
}
.dark {
--background: oklch(0.141 0.005 285.823);
--foreground: oklch(0.985 0 0);
--card: oklch(0.21 0.006 285.885);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.21 0.006 285.885);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.92 0.004 286.32);
--primary-foreground: oklch(0.21 0.006 285.885);
--secondary: oklch(0.274 0.006 286.033);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.274 0.006 286.033);
--muted-foreground: oklch(0.705 0.015 286.067);
--accent: oklch(0.274 0.006 286.033);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.552 0.016 285.938);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.21 0.006 285.885);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.274 0.006 286.033);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.552 0.016 285.938);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}
+42
View File
@@ -0,0 +1,42 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import { ThemeProvider } from "@/components/theme-provider";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "OllaHub",
description: "Interface moderna para Ollama",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="pt-BR" suppressHydrationWarning>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</ThemeProvider>
</body>
</html>
);
}
+66
View File
@@ -0,0 +1,66 @@
'use client';
import { useOllamaCheck } from "@/hooks/use-ollama-check";
import { Hero } from "@/components/landing/hero";
import { InstallModal } from "@/components/modals/install-modal";
import { StoppedCard } from "@/components/landing/stopped-card";
import { Loader2 } from "lucide-react";
import { useRouter } from "next/navigation";
export default function Home() {
const { status, check } = useOllamaCheck();
const router = useRouter();
const handleStart = () => {
const setupComplete = localStorage.getItem("ollahub_setup_complete");
if (setupComplete) {
router.push("/chat");
} else {
router.push("/setup");
}
};
if (status === 'checking') {
return (
<div className="flex h-screen w-full items-center justify-center bg-background">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
<span className="ml-2 text-muted-foreground">Verificando sistema...</span>
</div>
);
}
return (
<main className="flex min-h-screen flex-col items-center justify-center p-4 bg-background text-foreground transition-colors duration-300">
{/* Layout for Running State */}
{status === 'running' && (
<Hero onStart={handleStart} />
)}
{/* Layout for Stopped State */}
{status === 'installed_stopped' && (
<div className="flex flex-col items-center gap-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
<div className="text-center space-y-2">
<h1 className="text-3xl font-bold tracking-tighter">OllaHub</h1>
<p className="text-muted-foreground">Detectamos o Ollama, mas ele não está rodando.</p>
</div>
<StoppedCard onCheckAgain={check} />
</div>
)}
{/* Layout for Not Installed State (Background + Modal) */}
{status === 'not_installed' && (
<>
<div className="opacity-20 pointer-events-none blur-sm">
<Hero onStart={() => {}} />
</div>
{/* Hero is shown in background, modal is open */}
<InstallModal
open={true}
onCheckAgain={check}
/>
</>
)}
</main>
);
}
+41
View File
@@ -0,0 +1,41 @@
'use client';
import { useHardware } from "@/hooks/use-hardware";
import { HardwareScan } from "@/components/setup/hardware-scan";
import { ModelSelector } from "@/components/setup/model-selector";
import { getRecommendation } from "@/lib/recommendation";
import { useRouter } from "next/navigation";
export default function SetupPage() {
const { specs, loading } = useHardware();
const router = useRouter();
const handleComplete = () => {
// Save setup state if needed
localStorage.setItem("ollahub_setup_complete", "true");
router.push("/chat");
};
return (
<main className="flex min-h-screen flex-col items-center justify-center p-4 bg-background text-foreground">
<div className="w-full max-w-2xl space-y-8 animate-in fade-in duration-700">
<div className="text-center space-y-2">
<h1 className="text-3xl font-bold tracking-tighter">Configuração Inicial</h1>
<p className="text-muted-foreground">Vamos preparar o ambiente ideal para você.</p>
</div>
<HardwareScan specs={specs} loading={loading} />
{!loading && specs && (
<div className="animate-in slide-in-from-bottom-8 duration-700 delay-300 fill-mode-backwards">
<ModelSelector
recommendation={getRecommendation(specs)}
onComplete={handleComplete}
/>
</div>
)}
</div>
</main>
);
}
+22
View File
@@ -0,0 +1,22 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "app/globals.css",
"baseColor": "zinc",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"registries": {}
}
+72
View File
@@ -0,0 +1,72 @@
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Send, Square } from "lucide-react";
import { useState, useRef, useEffect } from "react";
interface ChatInputProps {
onSend: (message: string) => void;
onStop: () => void;
isLoading: boolean;
}
export function ChatInput({ onSend, onStop, isLoading }: ChatInputProps) {
const [input, setInput] = useState("");
const textareaRef = useRef<HTMLTextAreaElement>(null);
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
handleSend();
}
};
const handleSend = () => {
if (input.trim() && !isLoading) {
onSend(input);
setInput("");
}
};
useEffect(() => {
if (textareaRef.current) {
textareaRef.current.style.height = "auto";
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
}
}, [input]);
return (
<div className="p-4 border-t bg-background">
<div className="relative flex items-end gap-2 max-w-3xl mx-auto">
<Textarea
ref={textareaRef}
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Digite sua mensagem..."
className="min-h-[50px] max-h-[200px] resize-none pr-12 py-3"
rows={1}
/>
<div className="absolute right-2 bottom-2">
{isLoading ? (
<Button size="icon" variant="destructive" onClick={onStop} className="h-8 w-8">
<Square className="h-4 w-4 fill-current" />
</Button>
) : (
<Button
size="icon"
onClick={handleSend}
disabled={!input.trim()}
className="h-8 w-8"
>
<Send className="h-4 w-4" />
</Button>
)}
</div>
</div>
<div className="text-xs text-center text-muted-foreground mt-2">
OllaHub pode cometer erros. Verifique informações importantes.
</div>
</div>
);
}
+33
View File
@@ -0,0 +1,33 @@
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { cn } from "@/lib/utils";
import { Message } from "@/hooks/use-chat";
import { Bot, User } from "lucide-react";
export function ChatMessage({ message }: { message: Message }) {
const isUser = message.role === 'user';
return (
<div className={cn(
"flex w-full gap-4 p-6",
isUser ? "bg-background" : "bg-muted/30"
)}>
<div className="flex-shrink-0 mt-1">
<div className={cn(
"w-8 h-8 rounded-sm flex items-center justify-center",
isUser ? "bg-primary text-primary-foreground" : "bg-secondary text-secondary-foreground"
)}>
{isUser ? <User className="w-5 h-5" /> : <Bot className="w-5 h-5" />}
</div>
</div>
<div className="flex-1 overflow-hidden">
<div className="prose dark:prose-invert max-w-none break-words">
<ReactMarkdown remarkPlugins={[remarkGfm]}>
{message.content}
</ReactMarkdown>
</div>
</div>
</div>
);
}
+114
View File
@@ -0,0 +1,114 @@
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Sparkles, Loader2 } from "lucide-react";
import { useState, useEffect } from "react";
import { usePromptGenerator } from "@/hooks/use-prompt-generator";
import { useLocalModels } from "@/hooks/use-local-models";
interface PromptGeneratorDialogProps {
defaultModel: string;
onPromptGenerated: (prompt: string) => void;
}
export function PromptGeneratorDialog({ defaultModel, onPromptGenerated }: PromptGeneratorDialogProps) {
const [open, setOpen] = useState(false);
const [goal, setGoal] = useState("");
const [selectedModel, setSelectedModel] = useState(defaultModel);
const { generatePrompt, isGenerating } = usePromptGenerator();
const { models } = useLocalModels();
// Set default model when dialog opens or defaultModel changes
useEffect(() => {
if (defaultModel) {
setSelectedModel(defaultModel);
}
}, [defaultModel]);
// Try to set specific default if available, otherwise fallback
useEffect(() => {
const preferredModel = "llama3.2-abliterate:3b";
const hasPreferred = models.some(m => m.name === preferredModel);
if (hasPreferred && !selectedModel) {
setSelectedModel(preferredModel);
}
}, [models, selectedModel]);
const handleGenerate = async () => {
if (!goal.trim() || !selectedModel) return;
try {
const prompt = await generatePrompt(goal, selectedModel);
onPromptGenerated(prompt);
setOpen(false);
setGoal("");
} catch (error) {
// Error handling usually done in hook or global toast
}
};
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button variant="ghost" size="icon" className="h-6 w-6 text-yellow-500 hover:text-yellow-600 hover:bg-yellow-100 dark:hover:bg-yellow-900/20" title="Gerar com IA">
<Sparkles className="w-4 h-4" />
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[500px]">
<DialogHeader>
<DialogTitle>Gerador de Prompts</DialogTitle>
<DialogDescription>
Descreva o que você quer que a IA faça, e nós criaremos um System Prompt otimizado para você.
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
<div className="space-y-2">
<label className="text-sm font-medium">Modelo para Geração</label>
<Select value={selectedModel} onValueChange={setSelectedModel}>
<SelectTrigger>
<SelectValue placeholder="Selecione um modelo..." />
</SelectTrigger>
<SelectContent>
{models.map(m => (
<SelectItem key={m.name} value={m.name}>{m.name}</SelectItem>
))}
</SelectContent>
</Select>
<p className="text-xs text-muted-foreground">
Recomendado: Modelos com boa capacidade de instrução (ex: Llama 3, Mistral).
</p>
</div>
<div className="space-y-2">
<label className="text-sm font-medium">Seu Objetivo</label>
<Textarea
value={goal}
onChange={(e) => setGoal(e.target.value)}
placeholder="Ex: Quero um assistente especialista em Python que explique conceitos complexos de forma simples..."
className="min-h-[150px]"
/>
</div>
</div>
<DialogFooter>
<Button variant="ghost" onClick={() => setOpen(false)}>Cancelar</Button>
<Button onClick={handleGenerate} disabled={isGenerating || !goal.trim() || !selectedModel}>
{isGenerating ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Gerando...
</>
) : (
<>
<Sparkles className="mr-2 h-4 w-4" />
Gerar Prompt
</>
)}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
+105
View File
@@ -0,0 +1,105 @@
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Progress } from "@/components/ui/progress";
import { Button } from "@/components/ui/button";
import { Trash2, HardDrive, Cpu, Database } from "lucide-react";
import { useSystemMonitor } from "@/hooks/use-system-monitor";
import { useLocalModels } from "@/hooks/use-local-models";
export function SystemPanel() {
const stats = useSystemMonitor();
const { models, deleteModel, refresh } = useLocalModels();
const ramUsagePercent = stats
? (stats.memory_used / stats.memory_total) * 100
: 0;
const formatBytes = (bytes: number) => {
const gb = bytes / (1024 * 1024 * 1024);
return `${gb.toFixed(1)} GB`;
};
return (
<div className="h-full overflow-y-auto p-4 space-y-6">
{/* Hardware Stats */}
<div className="space-y-4">
<h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
Monitoramento
</h3>
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium flex items-center gap-2">
<Cpu className="w-4 h-4" /> Processador
</CardTitle>
</CardHeader>
<CardContent>
<div className="flex justify-between text-xs mb-1">
<span>Uso</span>
<span>{stats?.cpu_usage.toFixed(1)}%</span>
</div>
<Progress value={stats?.cpu_usage || 0} className="h-2" />
</CardContent>
</Card>
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium flex items-center gap-2">
<HardDrive className="w-4 h-4" /> Memória RAM
</CardTitle>
</CardHeader>
<CardContent>
<div className="flex justify-between text-xs mb-1">
<span>{stats ? formatBytes(stats.memory_used) : '-'}</span>
<span>{stats ? formatBytes(stats.memory_total) : '-'}</span>
</div>
<Progress value={ramUsagePercent} className="h-2" />
</CardContent>
</Card>
</div>
{/* Models List */}
<div className="space-y-4">
<div className="flex items-center justify-between">
<h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
Modelos Instalados
</h3>
<Button variant="ghost" size="sm" onClick={refresh} className="h-6 text-xs">
Atualizar
</Button>
</div>
<div className="space-y-2">
{models.map((model) => (
<Card key={model.id} className="overflow-hidden">
<CardContent className="p-3 flex items-center justify-between">
<div className="min-w-0">
<div className="font-medium text-sm truncate" title={model.name}>
{model.name}
</div>
<div className="text-xs text-muted-foreground flex items-center gap-2">
<Database className="w-3 h-3" />
{model.size}
</div>
</div>
<Button
variant="ghost"
size="icon"
className="h-8 w-8 text-destructive hover:text-destructive hover:bg-destructive/10"
onClick={() => deleteModel(model.name)}
>
<Trash2 className="w-4 h-4" />
</Button>
</CardContent>
</Card>
))}
{models.length === 0 && (
<div className="text-center text-sm text-muted-foreground py-4">
Nenhum modelo encontrado.
</div>
)}
</div>
</div>
</div>
);
}
+26
View File
@@ -0,0 +1,26 @@
import { Button } from "@/components/ui/button";
import { ArrowRight, Cpu } from "lucide-react";
export function Hero({ onStart }: { onStart: () => void }) {
return (
<div className="flex flex-col items-center justify-center min-h-[60vh] text-center px-4 space-y-6 animate-in fade-in zoom-in duration-500">
<div className="p-4 rounded-full bg-primary/10 animate-pulse">
<Cpu className="w-12 h-12 text-primary" />
</div>
<h1 className="text-4xl md:text-6xl font-bold tracking-tighter bg-clip-text text-transparent bg-gradient-to-r from-primary to-primary/60">
OllaHub
</h1>
<p className="text-lg md:text-xl text-muted-foreground max-w-[600px]">
Sua interface moderna e poderosa para interagir com Ollama e Modelos de Linguagem Locais.
</p>
<div className="flex gap-4 pt-4">
<Button size="lg" onClick={onStart} className="group text-lg px-8 h-12">
Iniciar Chat
<ArrowRight className="ml-2 w-5 h-5 transition-transform group-hover:translate-x-1" />
</Button>
</div>
</div>
);
}
+85
View File
@@ -0,0 +1,85 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { RefreshCw, Copy, Check, Play, Loader2 } from "lucide-react"
import { useState } from "react"
import { invoke } from "@tauri-apps/api/core"
export function StoppedCard({ onCheckAgain }: { onCheckAgain: () => void }) {
const [copied, setCopied] = useState(false);
const [starting, setStarting] = useState(false);
const command = "ollama serve";
const handleCopy = () => {
navigator.clipboard.writeText(command);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
const handleStart = async () => {
setStarting(true);
try {
await invoke('start_ollama_server');
// Wait a bit for the server to start before checking again
setTimeout(() => {
onCheckAgain();
setStarting(false);
}, 3000);
} catch (error) {
console.error("Failed to start ollama:", error);
setStarting(false);
}
};
return (
<Card className="w-full max-w-md mx-auto border-yellow-500/50 bg-yellow-50/10 dark:bg-yellow-900/10">
<CardHeader>
<CardTitle className="text-yellow-600 dark:text-yellow-500">Ollama está parado</CardTitle>
<CardDescription>
O Ollama está instalado mas não está rodando. Você pode iniciá-lo automaticamente ou executar o comando manualmente.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<Button
onClick={handleStart}
className="w-full bg-yellow-600 hover:bg-yellow-700 text-white"
disabled={starting}
>
{starting ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Iniciando...
</>
) : (
<>
<Play className="mr-2 h-4 w-4" />
Iniciar Ollama Automaticamente
</>
)}
</Button>
<div className="relative">
<div className="absolute inset-0 flex items-center">
<span className="w-full border-t border-yellow-500/20" />
</div>
<div className="relative flex justify-center text-xs uppercase">
<span className="bg-background px-2 text-muted-foreground">Ou manualmente</span>
</div>
</div>
<div className="flex items-center space-x-2">
<div className="bg-muted p-3 rounded-md font-mono text-sm flex-1 border">
{command}
</div>
<Button size="icon" variant="outline" onClick={handleCopy}>
{copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
</Button>
</div>
<Button onClick={onCheckAgain} className="w-full" variant="secondary">
<RefreshCw className="mr-2 h-4 w-4" />
Verificar Novamente
</Button>
</CardContent>
</Card>
)
}
+86
View File
@@ -0,0 +1,86 @@
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Button } from "@/components/ui/button"
import { Download } from "lucide-react"
interface InstallModalProps {
open: boolean;
onCheckAgain: () => void;
}
export function InstallModal({ open, onCheckAgain }: InstallModalProps) {
return (
<Dialog open={open}>
<DialogContent className="sm:max-w-[600px]">
<DialogHeader>
<DialogTitle>Ollama não encontrado</DialogTitle>
<DialogDescription>
Para usar o OllaHub, você precisa ter o Ollama instalado no seu sistema.
Siga os passos abaixo para o seu sistema operacional.
</DialogDescription>
</DialogHeader>
<Tabs defaultValue="mac" className="w-full">
<TabsList className="grid w-full grid-cols-3">
<TabsTrigger value="mac">macOS</TabsTrigger>
<TabsTrigger value="linux">Linux</TabsTrigger>
<TabsTrigger value="windows">Windows</TabsTrigger>
</TabsList>
<TabsContent value="mac" className="space-y-4 py-4">
<div className="space-y-2">
<h3 className="font-medium">1. Download e Instalação</h3>
<Button variant="outline" className="w-full" asChild>
<a href="https://ollama.com/download/Ollama-darwin.zip" target="_blank" rel="noopener noreferrer">
<Download className="mr-2 h-4 w-4" />
Baixar para macOS
</a>
</Button>
</div>
<div className="text-sm text-muted-foreground">
Após instalar, abra o terminal e digite <code>ollama serve</code> se necessário.
</div>
</TabsContent>
<TabsContent value="linux" className="space-y-4 py-4">
<div className="space-y-2">
<h3 className="font-medium">Instalação via Terminal</h3>
<div className="bg-muted p-4 rounded-md relative group">
<code className="text-sm break-all">curl -fsSL https://ollama.com/install.sh | sh</code>
</div>
</div>
<div className="space-y-2">
<h3 className="font-medium">Comando Manual</h3>
<div className="text-sm text-muted-foreground">
Ou consulte <a href="https://ollama.com/download/linux" className="underline text-primary" target="_blank" rel="noopener noreferrer">ollama.com/download/linux</a> para instruções manuais.
</div>
</div>
</TabsContent>
<TabsContent value="windows" className="space-y-4 py-4">
<div className="space-y-2">
<h3 className="font-medium">1. Download do Instalador</h3>
<Button variant="outline" className="w-full" asChild>
<a href="https://ollama.com/download/OllamaSetup.exe" target="_blank" rel="noopener noreferrer">
<Download className="mr-2 h-4 w-4" />
Baixar para Windows
</a>
</Button>
</div>
<div className="text-sm text-muted-foreground">
Execute o instalador baixado e siga as instruções na tela.
</div>
</TabsContent>
</Tabs>
<div className="flex justify-end gap-2 mt-4">
<Button onClick={onCheckAgain}>
Verificar Novamente
</Button>
</div>
</DialogContent>
</Dialog>
)
}
+72
View File
@@ -0,0 +1,72 @@
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Progress } from "@/components/ui/progress";
import { Cpu, HardDrive, Laptop } from "lucide-react";
import { SystemSpecs } from "@/lib/recommendation";
import { useEffect, useState } from "react";
interface HardwareScanProps {
specs: SystemSpecs | null;
loading: boolean;
}
export function HardwareScan({ specs, loading }: HardwareScanProps) {
const [progress, setProgress] = useState(0);
useEffect(() => {
if (loading) {
const interval = setInterval(() => {
setProgress((prev) => (prev >= 90 ? 90 : prev + 10));
}, 150);
return () => clearInterval(interval);
} else {
setProgress(100);
}
}, [loading]);
if (loading) {
return (
<Card className="w-full max-w-md mx-auto border-primary/20">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Cpu className="animate-pulse text-primary" />
Analisando Hardware...
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<Progress value={progress} className="h-2" />
<p className="text-sm text-muted-foreground text-center">
Verificando memória e processador para recomendação ideal.
</p>
</CardContent>
</Card>
);
}
if (!specs) return null;
const ramGB = (specs.total_memory / (1024 * 1024 * 1024)).toFixed(1);
return (
<Card className="w-full max-w-md mx-auto bg-muted/30 animate-in fade-in slide-in-from-bottom-4">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-lg">
<Laptop className="text-primary" />
Sistema Detectado
</CardTitle>
</CardHeader>
<CardContent className="grid grid-cols-2 gap-4">
<div className="flex flex-col items-center p-3 bg-background rounded-lg border">
<HardDrive className="w-6 h-6 mb-2 text-muted-foreground" />
<span className="text-xl font-bold">{ramGB} GB</span>
<span className="text-xs text-muted-foreground">RAM Total</span>
</div>
<div className="flex flex-col items-center p-3 bg-background rounded-lg border">
<Cpu className="w-6 h-6 mb-2 text-muted-foreground" />
<span className="text-xl font-bold">{specs.cpu_count}</span>
<span className="text-xs text-muted-foreground">Núcleos CPU</span>
</div>
</CardContent>
</Card>
);
}
+163
View File
@@ -0,0 +1,163 @@
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Progress } from "@/components/ui/progress";
import { Badge } from "@/components/ui/badge";
import { Check, Download, Loader2, Play } from "lucide-react";
import { RECOMMENDED_MODELS, ModelRecommendation } from "@/lib/recommendation";
import { useState, useEffect } from "react";
import { invoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";
interface ModelSelectorProps {
recommendation: ModelRecommendation;
onComplete: () => void;
}
export function ModelSelector({ recommendation, onComplete }: ModelSelectorProps) {
const [selectedModelId, setSelectedModelId] = useState(recommendation.modelId);
const [isInstalled, setIsInstalled] = useState(false);
const [isDownloading, setIsDownloading] = useState(false);
const [downloadProgress, setDownloadProgress] = useState(0);
const [downloadStatus, setDownloadStatus] = useState("");
const selectedModel = RECOMMENDED_MODELS.find(m => m.id === selectedModelId) || RECOMMENDED_MODELS[0];
useEffect(() => {
checkInstallation(selectedModelId);
}, [selectedModelId]);
useEffect(() => {
const unlisten = listen<string>('download-progress', (event) => {
const line = event.payload;
setDownloadStatus(line);
// Simple heuristic parsing for progress
// Ollama output example: "pulling manifest", "downloading 10%", "verifying sha256 digest"
if (line.includes('%')) {
const match = line.match(/(\d+)%/);
if (match) {
setDownloadProgress(parseInt(match[1], 10));
}
} else if (line.includes('success')) {
setDownloadProgress(100);
}
});
return () => {
unlisten.then(f => f());
};
}, []);
const checkInstallation = async (modelId: string) => {
try {
const installed = await invoke<boolean>('check_if_model_installed', { name: modelId });
setIsInstalled(installed);
} catch (e) {
console.error("Check failed", e);
}
};
const handleDownload = async () => {
setIsDownloading(true);
setDownloadProgress(0);
try {
await invoke('pull_model', { name: selectedModelId });
setIsInstalled(true);
setIsDownloading(false);
} catch (error) {
console.error("Download failed", error);
setDownloadStatus("Falha no download. Tente novamente.");
setIsDownloading(false);
}
};
return (
<Card className="w-full max-w-md mx-auto mt-6 border-primary shadow-lg">
<CardHeader>
<div className="flex justify-between items-start">
<div>
<CardTitle>Escolha seu Modelo</CardTitle>
<CardDescription>
{selectedModelId === recommendation.modelId
? "Baseado no seu hardware, recomendamos:"
: "Você selecionou um modelo personalizado:"}
</CardDescription>
</div>
{selectedModelId === recommendation.modelId && (
<Badge variant="secondary" className="bg-green-100 text-green-800 hover:bg-green-100 dark:bg-green-900 dark:text-green-100">
Recomendado
</Badge>
)}
</div>
</CardHeader>
<CardContent className="space-y-4">
<Select
value={selectedModelId}
onValueChange={setSelectedModelId}
disabled={isDownloading}
>
<SelectTrigger className="w-full h-14 text-lg">
<SelectValue placeholder="Selecione um modelo" />
</SelectTrigger>
<SelectContent>
{RECOMMENDED_MODELS.map((model) => (
<SelectItem key={model.id} value={model.id}>
<div className="flex flex-col items-start">
<span className="font-medium">{model.name}</span>
<span className="text-xs text-muted-foreground">{model.size} • Min RAM: {model.minRam}GB</span>
</div>
</SelectItem>
))}
</SelectContent>
</Select>
<div className="bg-muted/50 p-4 rounded-md text-sm">
<p className="font-medium mb-1">Sobre este modelo:</p>
<p className="text-muted-foreground">
{selectedModelId === recommendation.modelId
? recommendation.reason
: "Modelo alternativo selecionado. Certifique-se de ter memória suficiente."}
</p>
</div>
{isDownloading && (
<div className="space-y-2">
<div className="flex justify-between text-xs text-muted-foreground">
<span>{downloadStatus || "Iniciando..."}</span>
<span>{downloadProgress}%</span>
</div>
<Progress value={downloadProgress} className="h-2" />
</div>
)}
</CardContent>
<CardFooter>
{isInstalled ? (
<Button className="w-full h-12 text-lg" onClick={onComplete}>
Ir para o Chat
<Play className="ml-2 w-5 h-5" />
</Button>
) : (
<Button
className="w-full h-12 text-lg"
onClick={handleDownload}
disabled={isDownloading}
>
{isDownloading ? (
<>
<Loader2 className="mr-2 h-5 w-5 animate-spin" />
Baixando...
</>
) : (
<>
<Download className="mr-2 h-5 w-5" />
Baixar e Instalar ({selectedModel.size})
</>
)}
</Button>
)}
</CardFooter>
</Card>
);
}
+12
View File
@@ -0,0 +1,12 @@
"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
export function ThemeProvider({
children,
...props
}: React.ComponentProps<typeof NextThemesProvider>) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}
+46
View File
@@ -0,0 +1,46 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const badgeVariants = cva(
"inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
secondary:
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
destructive:
"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
},
},
defaultVariants: {
variant: "default",
},
}
)
function Badge({
className,
variant,
asChild = false,
...props
}: React.ComponentProps<"span"> &
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
const Comp = asChild ? Slot : "span"
return (
<Comp
data-slot="badge"
className={cn(badgeVariants({ variant }), className)}
{...props}
/>
)
}
export { Badge, badgeVariants }
+60
View File
@@ -0,0 +1,60 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost:
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
icon: "size-9",
"icon-sm": "size-8",
"icon-lg": "size-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
function Button({
className,
variant,
size,
asChild = false,
...props
}: React.ComponentProps<"button"> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean
}) {
const Comp = asChild ? Slot : "button"
return (
<Comp
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))}
{...props}
/>
)
}
export { Button, buttonVariants }
+92
View File
@@ -0,0 +1,92 @@
import * as React from "react"
import { cn } from "@/lib/utils"
function Card({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card"
className={cn(
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
className
)}
{...props}
/>
)
}
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-header"
className={cn(
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
className
)}
{...props}
/>
)
}
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-title"
className={cn("leading-none font-semibold", className)}
{...props}
/>
)
}
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-description"
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
}
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-action"
className={cn(
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
className
)}
{...props}
/>
)
}
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-content"
className={cn("px-6", className)}
{...props}
/>
)
}
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-footer"
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
{...props}
/>
)
}
export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardAction,
CardDescription,
CardContent,
}
+143
View File
@@ -0,0 +1,143 @@
"use client"
import * as React from "react"
import * as DialogPrimitive from "@radix-ui/react-dialog"
import { XIcon } from "lucide-react"
import { cn } from "@/lib/utils"
function Dialog({
...props
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
return <DialogPrimitive.Root data-slot="dialog" {...props} />
}
function DialogTrigger({
...props
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
}
function DialogPortal({
...props
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
}
function DialogClose({
...props
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
}
function DialogOverlay({
className,
...props
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
return (
<DialogPrimitive.Overlay
data-slot="dialog-overlay"
className={cn(
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
className
)}
{...props}
/>
)
}
function DialogContent({
className,
children,
showCloseButton = true,
...props
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
showCloseButton?: boolean
}) {
return (
<DialogPortal data-slot="dialog-portal">
<DialogOverlay />
<DialogPrimitive.Content
data-slot="dialog-content"
className={cn(
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
className
)}
{...props}
>
{children}
{showCloseButton && (
<DialogPrimitive.Close
data-slot="dialog-close"
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
>
<XIcon />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
)}
</DialogPrimitive.Content>
</DialogPortal>
)
}
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="dialog-header"
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
{...props}
/>
)
}
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="dialog-footer"
className={cn(
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
className
)}
{...props}
/>
)
}
function DialogTitle({
className,
...props
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
return (
<DialogPrimitive.Title
data-slot="dialog-title"
className={cn("text-lg leading-none font-semibold", className)}
{...props}
/>
)
}
function DialogDescription({
className,
...props
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
return (
<DialogPrimitive.Description
data-slot="dialog-description"
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
}
export {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogOverlay,
DialogPortal,
DialogTitle,
DialogTrigger,
}
+27
View File
@@ -0,0 +1,27 @@
import * as React from "react"
import * as ProgressPrimitive from "@radix-ui/react-progress"
import { cn } from "@/lib/utils"
const Progress = React.forwardRef<
React.ElementRef<typeof ProgressPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
>(({ className, value, ...props }, ref) => (
<ProgressPrimitive.Root
ref={ref}
className={cn(
"relative h-4 w-full overflow-hidden rounded-full bg-secondary",
className
)}
{...props}
>
<ProgressPrimitive.Indicator
className="h-full w-full flex-1 bg-primary transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>
))
Progress.displayName = ProgressPrimitive.Root.displayName
export { Progress }
+44
View File
@@ -0,0 +1,44 @@
import * as React from "react"
import { GripVertical } from "lucide-react"
import * as ResizablePrimitive from "react-resizable-panels"
import { cn } from "@/lib/utils"
const ResizablePanelGroup = ({
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
<ResizablePrimitive.PanelGroup
className={cn(
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
className
)}
{...props}
/>
)
const ResizablePanel = ResizablePrimitive.Panel
const ResizableHandle = ({
withHandle,
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
withHandle?: boolean
}) => (
<ResizablePrimitive.PanelResizeHandle
className={cn(
"relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
className
)}
{...props}
>
{withHandle && (
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
<GripVertical className="h-2.5 w-2.5" />
</div>
)}
</ResizablePrimitive.PanelResizeHandle>
)
export { ResizablePanelGroup, ResizablePanel, ResizableHandle }
+159
View File
@@ -0,0 +1,159 @@
import * as React from "react"
import * as SelectPrimitive from "@radix-ui/react-select"
import { Check, ChevronDown, ChevronUp } from "lucide-react"
import { cn } from "@/lib/utils"
const Select = SelectPrimitive.Root
const SelectGroup = SelectPrimitive.Group
const SelectValue = SelectPrimitive.Value
const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Trigger
ref={ref}
className={cn(
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className
)}
{...props}
>
{children}
<SelectPrimitive.Icon asChild>
<ChevronDown className="h-4 w-4 opacity-50" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
))
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
const SelectScrollUpButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
>(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollUpButton
ref={ref}
className={cn(
"flex cursor-default items-center justify-center py-1",
className
)}
{...props}
>
<ChevronUp className="h-4 w-4" />
</SelectPrimitive.ScrollUpButton>
))
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
const SelectScrollDownButton = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
>(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollDownButton
ref={ref}
className={cn(
"flex cursor-default items-center justify-center py-1",
className
)}
{...props}
>
<ChevronDown className="h-4 w-4" />
</SelectPrimitive.ScrollDownButton>
))
SelectScrollDownButton.displayName =
SelectPrimitive.ScrollDownButton.displayName
const SelectContent = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
>(({ className, children, position = "popper", ...props }, ref) => (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
ref={ref}
className={cn(
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className
)}
position={position}
{...props}
>
<SelectScrollUpButton />
<SelectPrimitive.Viewport
className={cn(
"p-1",
position === "popper" &&
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
)}
>
{children}
</SelectPrimitive.Viewport>
<SelectScrollDownButton />
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
))
SelectContent.displayName = SelectPrimitive.Content.displayName
const SelectLabel = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Label
ref={ref}
className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
{...props}
/>
))
SelectLabel.displayName = SelectPrimitive.Label.displayName
const SelectItem = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
>(({ className, children, ...props }, ref) => (
<SelectPrimitive.Item
ref={ref}
className={cn(
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
))
SelectItem.displayName = SelectPrimitive.Item.displayName
const SelectSeparator = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
>(({ className, ...props }, ref) => (
<SelectPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
))
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
export {
Select,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectItem,
SelectSeparator,
SelectScrollUpButton,
SelectScrollDownButton,
}
+28
View File
@@ -0,0 +1,28 @@
"use client"
import * as React from "react"
import * as SeparatorPrimitive from "@radix-ui/react-separator"
import { cn } from "@/lib/utils"
function Separator({
className,
orientation = "horizontal",
decorative = true,
...props
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
return (
<SeparatorPrimitive.Root
data-slot="separator"
decorative={decorative}
orientation={orientation}
className={cn(
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
className
)}
{...props}
/>
)
}
export { Separator }
+66
View File
@@ -0,0 +1,66 @@
"use client"
import * as React from "react"
import * as TabsPrimitive from "@radix-ui/react-tabs"
import { cn } from "@/lib/utils"
function Tabs({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
return (
<TabsPrimitive.Root
data-slot="tabs"
className={cn("flex flex-col gap-2", className)}
{...props}
/>
)
}
function TabsList({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.List>) {
return (
<TabsPrimitive.List
data-slot="tabs-list"
className={cn(
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
className
)}
{...props}
/>
)
}
function TabsTrigger({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
return (
<TabsPrimitive.Trigger
data-slot="tabs-trigger"
className={cn(
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
/>
)
}
function TabsContent({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
return (
<TabsPrimitive.Content
data-slot="tabs-content"
className={cn("flex-1 outline-none", className)}
{...props}
/>
)
}
export { Tabs, TabsList, TabsTrigger, TabsContent }
+23
View File
@@ -0,0 +1,23 @@
import * as React from "react"
import { cn } from "@/lib/utils"
const Textarea = React.forwardRef<
HTMLTextAreaElement,
React.ComponentProps<"textarea">
>(({ className, ...props }, ref) => {
return (
<textarea
className={cn(
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)}
ref={ref}
{...props}
/>
)
})
Textarea.displayName = "Textarea"
export { Textarea }
+20
View File
@@ -0,0 +1,20 @@
{
"model": "alfred",
"url": "https://ollama.com/library/alfred",
"description": "A robust conversational model designed to be used for both chat and instruct use cases.",
"variantsCount": 2,
"variants": [
{
"name": "alfred:latest",
"size": "24GB",
"context": "2K",
"inputType": "Text"
},
{
"name": "alfred:40b",
"size": "24GB",
"context": "2K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "all-minilm",
"url": "https://ollama.com/library/all-minilm",
"description": "Embedding models on very large sentence level datasets.",
"variantsCount": 3,
"variants": [
{
"name": "all-minilm:latest",
"size": "46MB",
"context": "512",
"inputType": "Text"
},
{
"name": "all-minilm:22m",
"size": "46MB",
"context": "512",
"inputType": "Text"
},
{
"name": "all-minilm:33m",
"size": "67MB",
"context": "512",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "athene-v2",
"url": "https://ollama.com/library/athene-v2",
"description": "Athene-V2 is a 72B parameter model which excels at code completion, mathematics, and log extraction tasks.",
"variantsCount": 2,
"variants": [
{
"name": "athene-v2:latest",
"size": "47GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "athene-v2:72b",
"size": "47GB",
"context": "32K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "aya-expanse",
"url": "https://ollama.com/library/aya-expanse",
"description": "Cohere For AI's language models trained to perform well across 23 different languages.",
"variantsCount": 3,
"variants": [
{
"name": "aya-expanse:latest",
"size": "5.1GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "aya-expanse:8b",
"size": "5.1GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "aya-expanse:32b",
"size": "20GB",
"context": "8K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "aya",
"url": "https://ollama.com/library/aya",
"description": "Aya 23, released by Cohere, is a new family of state-of-the-art, multilingual models that support 23 languages. ",
"variantsCount": 3,
"variants": [
{
"name": "aya:latest",
"size": "4.8GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "aya:8b",
"size": "4.8GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "aya:35b",
"size": "20GB",
"context": "8K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "bakllava",
"url": "https://ollama.com/library/bakllava",
"description": "BakLLaVA is a multimodal model consisting of the Mistral 7B base model augmented with the LLaVA architecture.",
"variantsCount": 2,
"variants": [
{
"name": "bakllava:latest",
"size": "4.7GB",
"context": "32K",
"inputType": "Text, Image"
},
{
"name": "bakllava:7b",
"size": "4.7GB",
"context": "32K",
"inputType": "Text, Image"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "bespoke-minicheck",
"url": "https://ollama.com/library/bespoke-minicheck",
"description": "A state-of-the-art fact-checking model developed by Bespoke Labs.",
"variantsCount": 2,
"variants": [
{
"name": "bespoke-minicheck:latest",
"size": "4.7GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "bespoke-minicheck:7b",
"size": "4.7GB",
"context": "32K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "bge-large",
"url": "https://ollama.com/library/bge-large",
"description": "Embedding model from BAAI mapping texts to vectors.",
"variantsCount": 2,
"variants": [
{
"name": "bge-large:latest",
"size": "671MB",
"context": "512",
"inputType": "Text"
},
{
"name": "bge-large:335m",
"size": "671MB",
"context": "512",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "bge-m3",
"url": "https://ollama.com/library/bge-m3",
"description": "BGE-M3 is a new model from BAAI distinguished for its versatility in Multi-Functionality, Multi-Linguality, and Multi-Granularity.",
"variantsCount": 2,
"variants": [
{
"name": "bge-m3:latest",
"size": "1.2GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "bge-m3:567m",
"size": "1.2GB",
"context": "8K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "codebooga",
"url": "https://ollama.com/library/codebooga",
"description": "A high-performing code instruct model created by merging two existing code models.",
"variantsCount": 2,
"variants": [
{
"name": "codebooga:latest",
"size": "19GB",
"context": "16K",
"inputType": "Text"
},
{
"name": "codebooga:34b",
"size": "19GB",
"context": "16K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "codegeex4",
"url": "https://ollama.com/library/codegeex4",
"description": "A versatile model for AI software development scenarios, including code completion.",
"variantsCount": 2,
"variants": [
{
"name": "codegeex4:latest",
"size": "5.5GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "codegeex4:9b",
"size": "5.5GB",
"context": "128K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "codegemma",
"url": "https://ollama.com/library/codegemma",
"description": "CodeGemma is a collection of powerful, lightweight models that can perform a variety of coding tasks like fill-in-the-middle code completion, code generation, natural language understanding, mathematical reasoning, and instruction following.",
"variantsCount": 3,
"variants": [
{
"name": "codegemma:latest",
"size": "5.0GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "codegemma:2b",
"size": "1.6GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "codegemma:7b",
"size": "5.0GB",
"context": "8K",
"inputType": "Text"
}
]
}
+38
View File
@@ -0,0 +1,38 @@
{
"model": "codellama",
"url": "https://ollama.com/library/codellama",
"description": "A large language model that can use text prompts to generate and discuss code.",
"variantsCount": 5,
"variants": [
{
"name": "codellama:latest",
"size": "3.8GB",
"context": "16K",
"inputType": "Text"
},
{
"name": "codellama:7b",
"size": "3.8GB",
"context": "16K",
"inputType": "Text"
},
{
"name": "codellama:13b",
"size": "7.4GB",
"context": "16K",
"inputType": "Text"
},
{
"name": "codellama:34b",
"size": "19GB",
"context": "16K",
"inputType": "Text"
},
{
"name": "codellama:70b",
"size": "39GB",
"context": "2K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "codeqwen",
"url": "https://ollama.com/library/codeqwen",
"description": "CodeQwen1.5 is a large language model pretrained on a large amount of code data.",
"variantsCount": 2,
"variants": [
{
"name": "codeqwen:latest",
"size": "4.2GB",
"context": "64K",
"inputType": "Text"
},
{
"name": "codeqwen:7b",
"size": "4.2GB",
"context": "64K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "codestral",
"url": "https://ollama.com/library/codestral",
"description": "Codestral is Mistral AI’s first-ever code model designed for code generation tasks.",
"variantsCount": 2,
"variants": [
{
"name": "codestral:latest",
"size": "13GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "codestral:22b",
"size": "13GB",
"context": "32K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "codeup",
"url": "https://ollama.com/library/codeup",
"description": "Great code generation model based on Llama2.",
"variantsCount": 2,
"variants": [
{
"name": "codeup:latest",
"size": "7.4GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "codeup:13b",
"size": "7.4GB",
"context": "4K",
"inputType": "Text"
}
]
}
+44
View File
@@ -0,0 +1,44 @@
{
"model": "cogito",
"url": "https://ollama.com/library/cogito",
"description": "Cogito v1 Preview is a family of hybrid reasoning models by Deep Cogito that outperform the best available open models of the same size, including counterparts from LLaMA, DeepSeek, and Qwen across most standard benchmarks.",
"variantsCount": 6,
"variants": [
{
"name": "cogito:latest",
"size": "4.9GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "cogito:3b",
"size": "2.2GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "cogito:8b",
"size": "4.9GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "cogito:14b",
"size": "9.0GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "cogito:32b",
"size": "20GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "cogito:70b",
"size": "43GB",
"context": "128K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "command-a",
"url": "https://ollama.com/library/command-a",
"description": "111 billion parameter model optimized for demanding enterprises that require fast, secure, and high-quality AI",
"variantsCount": 2,
"variants": [
{
"name": "command-a:latest",
"size": "67GB",
"context": "16K",
"inputType": "Text"
},
{
"name": "command-a:111b",
"size": "67GB",
"context": "16K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "command-r-plus",
"url": "https://ollama.com/library/command-r-plus",
"description": "Command R+ is a powerful, scalable large language model purpose-built to excel at real-world enterprise use cases.",
"variantsCount": 2,
"variants": [
{
"name": "command-r-plus:latest",
"size": "59GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "command-r-plus:104b",
"size": "59GB",
"context": "128K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "command-r",
"url": "https://ollama.com/library/command-r",
"description": "Command R is a Large Language Model optimized for conversational interaction and long context tasks.",
"variantsCount": 2,
"variants": [
{
"name": "command-r:latest",
"size": "19GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "command-r:35b",
"size": "19GB",
"context": "128K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "command-r7b-arabic",
"url": "https://ollama.com/library/command-r7b-arabic",
"description": "A new state-of-the-art version of the lightweight Command R7B model that excels in advanced Arabic language capabilities for enterprises in the Middle East and Northern Africa.",
"variantsCount": 2,
"variants": [
{
"name": "command-r7b-arabic:latest",
"size": "5.1GB",
"context": "16K",
"inputType": "Text"
},
{
"name": "command-r7b-arabic:7b",
"size": "5.1GB",
"context": "16K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "command-r7b",
"url": "https://ollama.com/library/command-r7b",
"description": "The smallest model in Cohere's R series delivers top-tier speed, efficiency, and quality to build powerful AI applications on commodity GPUs and edge devices.",
"variantsCount": 2,
"variants": [
{
"name": "command-r7b:latest",
"size": "5.1GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "command-r7b:7b",
"size": "5.1GB",
"context": "8K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "dbrx",
"url": "https://ollama.com/library/dbrx",
"description": "DBRX is an open, general-purpose LLM created by Databricks.",
"variantsCount": 2,
"variants": [
{
"name": "dbrx:latest",
"size": "74GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "dbrx:132b",
"size": "74GB",
"context": "32K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "deepcoder",
"url": "https://ollama.com/library/deepcoder",
"description": "DeepCoder is a fully open-Source 14B coder model at O3-mini level, with a 1.5B version also available.",
"variantsCount": 3,
"variants": [
{
"name": "deepcoder:latest",
"size": "9.0GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "deepcoder:1.5b",
"size": "1.1GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "deepcoder:14b",
"size": "9.0GB",
"context": "128K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "deepscaler",
"url": "https://ollama.com/library/deepscaler",
"description": "A fine-tuned version of Deepseek-R1-Distilled-Qwen-1.5B that surpasses the performance of OpenAI’s o1-preview with just 1.5B parameters on popular math evaluations.",
"variantsCount": 2,
"variants": [
{
"name": "deepscaler:latest",
"size": "3.6GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "deepscaler:1.5b",
"size": "3.6GB",
"context": "128K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "deepseek-coder-v2",
"url": "https://ollama.com/library/deepseek-coder-v2",
"description": "An open-source Mixture-of-Experts code language model that achieves performance comparable to GPT4-Turbo in code-specific tasks.",
"variantsCount": 3,
"variants": [
{
"name": "deepseek-coder-v2:latest",
"size": "8.9GB",
"context": "160K",
"inputType": "Text"
},
{
"name": "deepseek-coder-v2:16b",
"size": "8.9GB",
"context": "160K",
"inputType": "Text"
},
{
"name": "deepseek-coder-v2:236b",
"size": "133GB",
"context": "4K",
"inputType": "Text"
}
]
}
+32
View File
@@ -0,0 +1,32 @@
{
"model": "deepseek-coder",
"url": "https://ollama.com/library/deepseek-coder",
"description": "DeepSeek Coder is a capable coding model trained on two trillion code and natural language tokens.",
"variantsCount": 4,
"variants": [
{
"name": "deepseek-coder:latest",
"size": "776MB",
"context": "16K",
"inputType": "Text"
},
{
"name": "deepseek-coder:1.3b",
"size": "776MB",
"context": "16K",
"inputType": "Text"
},
{
"name": "deepseek-coder:6.7b",
"size": "3.8GB",
"context": "16K",
"inputType": "Text"
},
{
"name": "deepseek-coder:33b",
"size": "19GB",
"context": "16K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "deepseek-llm",
"url": "https://ollama.com/library/deepseek-llm",
"description": "An advanced language model crafted with 2 trillion bilingual tokens.",
"variantsCount": 3,
"variants": [
{
"name": "deepseek-llm:latest",
"size": "4.0GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "deepseek-llm:7b",
"size": "4.0GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "deepseek-llm:67b",
"size": "38GB",
"context": "4K",
"inputType": "Text"
}
]
}
+56
View File
@@ -0,0 +1,56 @@
{
"model": "deepseek-r1",
"url": "https://ollama.com/library/deepseek-r1",
"description": "DeepSeek-R1 is a family of open reasoning models with performance approaching that of leading models, such as O3 and Gemini 2.5 Pro.",
"variantsCount": 8,
"variants": [
{
"name": "deepseek-r1:latest",
"size": "5.2GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "deepseek-r1:1.5b",
"size": "1.1GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "deepseek-r1:7b",
"size": "4.7GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "deepseek-r1:8b",
"size": "5.2GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "deepseek-r1:14b",
"size": "9.0GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "deepseek-r1:32b",
"size": "20GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "deepseek-r1:70b",
"size": "43GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "deepseek-r1:671b",
"size": "404GB",
"context": "160K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "deepseek-v2.5",
"url": "https://ollama.com/library/deepseek-v2.5",
"description": "An upgraded version of DeekSeek-V2 that integrates the general and coding abilities of both DeepSeek-V2-Chat and DeepSeek-Coder-V2-Instruct.",
"variantsCount": 2,
"variants": [
{
"name": "deepseek-v2.5:latest",
"size": "133GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "deepseek-v2.5:236b",
"size": "133GB",
"context": "4K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "deepseek-v2",
"url": "https://ollama.com/library/deepseek-v2",
"description": "A strong, economical, and efficient Mixture-of-Experts language model.",
"variantsCount": 3,
"variants": [
{
"name": "deepseek-v2:latest",
"size": "8.9GB",
"context": "160K",
"inputType": "Text"
},
{
"name": "deepseek-v2:16b",
"size": "8.9GB",
"context": "160K",
"inputType": "Text"
},
{
"name": "deepseek-v2:236b",
"size": "133GB",
"context": "4K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "deepseek-v3.1",
"url": "https://ollama.com/library/deepseek-v3.1",
"description": "DeepSeek-V3.1-Terminus is a hybrid model that supports both thinking mode and non-thinking mode.",
"variantsCount": 3,
"variants": [
{
"name": "deepseek-v3.1:latest",
"size": "404GB",
"context": "160K",
"inputType": "Text"
},
{
"name": "deepseek-v3.1:671b",
"size": "404GB",
"context": "160K",
"inputType": "Text"
},
{
"name": "deepseek-v3.1:671b-cloud",
"size": "-",
"context": "160K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "deepseek-v3",
"url": "https://ollama.com/library/deepseek-v3",
"description": "A strong Mixture-of-Experts (MoE) language model with 671B total parameters with 37B activated for each token.",
"variantsCount": 2,
"variants": [
{
"name": "deepseek-v3:latest",
"size": "404GB",
"context": "160K",
"inputType": "Text"
},
{
"name": "deepseek-v3:671b",
"size": "404GB",
"context": "160K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "devstral",
"url": "https://ollama.com/library/devstral",
"description": "Devstral: the best open source model for coding agents",
"variantsCount": 2,
"variants": [
{
"name": "devstral:latest",
"size": "14GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "devstral:24b",
"size": "14GB",
"context": "128K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "dolphin-llama3",
"url": "https://ollama.com/library/dolphin-llama3",
"description": "Dolphin 2.9 is a new model with 8B and 70B sizes by Eric Hartford based on Llama 3 that has a variety of instruction, conversational, and coding skills.",
"variantsCount": 3,
"variants": [
{
"name": "dolphin-llama3:latest",
"size": "4.7GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "dolphin-llama3:8b",
"size": "4.7GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "dolphin-llama3:70b",
"size": "40GB",
"context": "8K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "dolphin-mistral",
"url": "https://ollama.com/library/dolphin-mistral",
"description": "The uncensored Dolphin model based on Mistral that excels at coding tasks. Updated to version 2.8.",
"variantsCount": 2,
"variants": [
{
"name": "dolphin-mistral:latest",
"size": "4.1GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "dolphin-mistral:7b",
"size": "4.1GB",
"context": "32K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "dolphin-mixtral",
"url": "https://ollama.com/library/dolphin-mixtral",
"description": "Uncensored, 8x7b and 8x22b fine-tuned models based on the Mixtral mixture of experts models that excels at coding tasks. Created by Eric Hartford.",
"variantsCount": 3,
"variants": [
{
"name": "dolphin-mixtral:latest",
"size": "26GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "dolphin-mixtral:8x7b",
"size": "26GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "dolphin-mixtral:8x22b",
"size": "80GB",
"context": "64K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "dolphin-phi",
"url": "https://ollama.com/library/dolphin-phi",
"description": "2.7B uncensored Dolphin model by Eric Hartford, based on the Phi language model by Microsoft Research.",
"variantsCount": 2,
"variants": [
{
"name": "dolphin-phi:latest",
"size": "1.6GB",
"context": "2K",
"inputType": "Text"
},
{
"name": "dolphin-phi:2.7b",
"size": "1.6GB",
"context": "2K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "dolphin3",
"url": "https://ollama.com/library/dolphin3",
"description": "Dolphin 3.0 Llama 3.1 8B 🐬 is the next generation of the Dolphin series of instruct-tuned models designed to be the ultimate general purpose local model, enabling coding, math, agentic, function calling, and general use cases.",
"variantsCount": 2,
"variants": [
{
"name": "dolphin3:latest",
"size": "4.9GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "dolphin3:8b",
"size": "4.9GB",
"context": "128K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "dolphincoder",
"url": "https://ollama.com/library/dolphincoder",
"description": "A 7B and 15B uncensored variant of the Dolphin model family that excels at coding, based on StarCoder2.",
"variantsCount": 3,
"variants": [
{
"name": "dolphincoder:latest",
"size": "4.2GB",
"context": "16K",
"inputType": "Text"
},
{
"name": "dolphincoder:7b",
"size": "4.2GB",
"context": "16K",
"inputType": "Text"
},
{
"name": "dolphincoder:15b",
"size": "9.1GB",
"context": "16K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "duckdb-nsql",
"url": "https://ollama.com/library/duckdb-nsql",
"description": "7B parameter text-to-SQL model made by MotherDuck and Numbers Station.",
"variantsCount": 2,
"variants": [
{
"name": "duckdb-nsql:latest",
"size": "3.8GB",
"context": "16K",
"inputType": "Text"
},
{
"name": "duckdb-nsql:7b",
"size": "3.8GB",
"context": "16K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "embeddinggemma",
"url": "https://ollama.com/library/embeddinggemma",
"description": "EmbeddingGemma is a 300M parameter embedding model from Google.",
"variantsCount": 2,
"variants": [
{
"name": "embeddinggemma:latest",
"size": "622MB",
"context": "2K",
"inputType": "Text"
},
{
"name": "embeddinggemma:300m",
"size": "622MB",
"context": "2K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "everythinglm",
"url": "https://ollama.com/library/everythinglm",
"description": "Uncensored Llama2 based model with support for a 16K context window.",
"variantsCount": 2,
"variants": [
{
"name": "everythinglm:latest",
"size": "7.4GB",
"context": "16K",
"inputType": "Text"
},
{
"name": "everythinglm:13b",
"size": "7.4GB",
"context": "16K",
"inputType": "Text"
}
]
}
+32
View File
@@ -0,0 +1,32 @@
{
"model": "exaone-deep",
"url": "https://ollama.com/library/exaone-deep",
"description": "EXAONE Deep exhibits superior capabilities in various reasoning tasks including math and coding benchmarks, ranging from 2.4B to 32B parameters developed and released by LG AI Research.",
"variantsCount": 4,
"variants": [
{
"name": "exaone-deep:latest",
"size": "4.8GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "exaone-deep:2.4b",
"size": "1.6GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "exaone-deep:7.8b",
"size": "4.8GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "exaone-deep:32b",
"size": "19GB",
"context": "32K",
"inputType": "Text"
}
]
}
+32
View File
@@ -0,0 +1,32 @@
{
"model": "exaone3.5",
"url": "https://ollama.com/library/exaone3.5",
"description": "EXAONE 3.5 is a collection of instruction-tuned bilingual (English and Korean) generative models ranging from 2.4B to 32B parameters, developed and released by LG AI Research. ",
"variantsCount": 4,
"variants": [
{
"name": "exaone3.5:latest",
"size": "4.8GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "exaone3.5:2.4b",
"size": "1.6GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "exaone3.5:7.8b",
"size": "4.8GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "exaone3.5:32b",
"size": "19GB",
"context": "32K",
"inputType": "Text"
}
]
}
+32
View File
@@ -0,0 +1,32 @@
{
"model": "falcon",
"url": "https://ollama.com/library/falcon",
"description": "A large language model built by the Technology Innovation Institute (TII) for use in summarization, text generation, and chat bots.",
"variantsCount": 4,
"variants": [
{
"name": "falcon:latest",
"size": "4.2GB",
"context": "2K",
"inputType": "Text"
},
{
"name": "falcon:7b",
"size": "4.2GB",
"context": "2K",
"inputType": "Text"
},
{
"name": "falcon:40b",
"size": "24GB",
"context": "2K",
"inputType": "Text"
},
{
"name": "falcon:180b",
"size": "101GB",
"context": "2K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "falcon2",
"url": "https://ollama.com/library/falcon2",
"description": "Falcon2 is an 11B parameters causal decoder-only model built by TII and trained over 5T tokens.",
"variantsCount": 2,
"variants": [
{
"name": "falcon2:latest",
"size": "6.4GB",
"context": "2K",
"inputType": "Text"
},
{
"name": "falcon2:11b",
"size": "6.4GB",
"context": "2K",
"inputType": "Text"
}
]
}
+38
View File
@@ -0,0 +1,38 @@
{
"model": "falcon3",
"url": "https://ollama.com/library/falcon3",
"description": "A family of efficient AI models under 10B parameters performant in science, math, and coding through innovative training techniques.",
"variantsCount": 5,
"variants": [
{
"name": "falcon3:latest",
"size": "4.6GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "falcon3:1b",
"size": "1.8GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "falcon3:3b",
"size": "2.0GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "falcon3:7b",
"size": "4.6GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "falcon3:10b",
"size": "6.3GB",
"context": "32K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "firefunction-v2",
"url": "https://ollama.com/library/firefunction-v2",
"description": "An open weights function calling model based on Llama 3, competitive with GPT-4o function calling capabilities.",
"variantsCount": 2,
"variants": [
{
"name": "firefunction-v2:latest",
"size": "40GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "firefunction-v2:70b",
"size": "40GB",
"context": "8K",
"inputType": "Text"
}
]
}
+14
View File
@@ -0,0 +1,14 @@
{
"model": "gemini-3-pro-preview",
"url": "https://ollama.com/library/gemini-3-pro-preview",
"description": "Google's most intelligent model with SOTA reasoning and multimodal understanding, and powerful agentic and vibe coding capabilities.",
"variantsCount": 1,
"variants": [
{
"name": "gemini-3-pro-preview:latest",
"size": "-",
"context": "1M",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "gemma",
"url": "https://ollama.com/library/gemma",
"description": "Gemma is a family of lightweight, state-of-the-art open models built by Google DeepMind. Updated to version 1.1",
"variantsCount": 3,
"variants": [
{
"name": "gemma:latest",
"size": "5.0GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "gemma:2b",
"size": "1.7GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "gemma:7b",
"size": "5.0GB",
"context": "8K",
"inputType": "Text"
}
]
}
+32
View File
@@ -0,0 +1,32 @@
{
"model": "gemma2",
"url": "https://ollama.com/library/gemma2",
"description": "Google Gemma 2 is a high-performing and efficient model available in three sizes: 2B, 9B, and 27B.",
"variantsCount": 4,
"variants": [
{
"name": "gemma2:latest",
"size": "5.4GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "gemma2:2b",
"size": "1.6GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "gemma2:9b",
"size": "5.4GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "gemma2:27b",
"size": "16GB",
"context": "8K",
"inputType": "Text"
}
]
}
+44
View File
@@ -0,0 +1,44 @@
{
"model": "gemma3",
"url": "https://ollama.com/library/gemma3",
"description": "The current, most capable model that runs on a single GPU.",
"variantsCount": 6,
"variants": [
{
"name": "gemma3:latest",
"size": "3.3GB",
"context": "128K",
"inputType": "Text, Image"
},
{
"name": "gemma3:270m",
"size": "292MB",
"context": "32K",
"inputType": "Text"
},
{
"name": "gemma3:1b",
"size": "815MB",
"context": "32K",
"inputType": "Text"
},
{
"name": "gemma3:4b",
"size": "3.3GB",
"context": "128K",
"inputType": "Text, Image"
},
{
"name": "gemma3:12b",
"size": "8.1GB",
"context": "128K",
"inputType": "Text, Image"
},
{
"name": "gemma3:27b",
"size": "17GB",
"context": "128K",
"inputType": "Text, Image"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "gemma3n",
"url": "https://ollama.com/library/gemma3n",
"description": "Gemma 3n models are designed for efficient execution on everyday devices such as laptops, tablets or phones. ",
"variantsCount": 3,
"variants": [
{
"name": "gemma3n:latest",
"size": "7.5GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "gemma3n:e2b",
"size": "5.6GB",
"context": "32K",
"inputType": "Text"
},
{
"name": "gemma3n:e4b",
"size": "7.5GB",
"context": "32K",
"inputType": "Text"
}
]
}
+14
View File
@@ -0,0 +1,14 @@
{
"model": "glm-4.6",
"url": "https://ollama.com/library/glm-4.6",
"description": "Advanced agentic, reasoning and coding capabilities.",
"variantsCount": 1,
"variants": [
{
"name": "glm-4.6:cloud",
"size": "-",
"context": "198K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "glm4",
"url": "https://ollama.com/library/glm4",
"description": "A strong multi-lingual general language model with competitive performance to Llama 3.",
"variantsCount": 2,
"variants": [
{
"name": "glm4:latest",
"size": "5.5GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "glm4:9b",
"size": "5.5GB",
"context": "128K",
"inputType": "Text"
}
]
}
+104
View File
@@ -0,0 +1,104 @@
{
"model": "goliath",
"url": "https://ollama.com/library/goliath",
"description": "A language model created by combining two fine-tuned Llama 2 70B models into one.",
"variantsCount": 16,
"variants": [
{
"name": "goliath:latest",
"size": "66GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q2_K",
"size": "50GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q3_K_S",
"size": "51GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q3_K_M",
"size": "56GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q3_K_L",
"size": "62GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q4_0",
"size": "66GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q4_1",
"size": "74GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q4_K_S",
"size": "66GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q4_K_M",
"size": "71GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q5_0",
"size": "81GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q5_1",
"size": "88GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q5_K_S",
"size": "81GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q5_K_M",
"size": "83GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q6_K",
"size": "97GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-q8_0",
"size": "125GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "goliath:120b-fp16",
"size": "236GB",
"context": "4K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "gpt-oss-safeguard",
"url": "https://ollama.com/library/gpt-oss-safeguard",
"description": "gpt-oss-safeguard-20b and gpt-oss-safeguard-120b are safety reasoning models built-upon gpt-oss",
"variantsCount": 3,
"variants": [
{
"name": "gpt-oss-safeguard:latest",
"size": "14GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "gpt-oss-safeguard:20b",
"size": "14GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "gpt-oss-safeguard:120b",
"size": "65GB",
"context": "128K",
"inputType": "Text"
}
]
}
+38
View File
@@ -0,0 +1,38 @@
{
"model": "gpt-oss",
"url": "https://ollama.com/library/gpt-oss",
"description": "OpenAI’s open-weight models designed for powerful reasoning, agentic tasks, and versatile developer use cases.",
"variantsCount": 5,
"variants": [
{
"name": "gpt-oss:latest",
"size": "14GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "gpt-oss:20b",
"size": "14GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "gpt-oss:120b",
"size": "65GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "gpt-oss:20b-cloud",
"size": "-",
"context": "128K",
"inputType": "Text"
},
{
"name": "gpt-oss:120b-cloud",
"size": "-",
"context": "128K",
"inputType": "Text"
}
]
}
+38
View File
@@ -0,0 +1,38 @@
{
"model": "granite-code",
"url": "https://ollama.com/library/granite-code",
"description": "A family of open foundation models by IBM for Code Intelligence",
"variantsCount": 5,
"variants": [
{
"name": "granite-code:latest",
"size": "2.0GB",
"context": "125K",
"inputType": "Text"
},
{
"name": "granite-code:3b",
"size": "2.0GB",
"context": "125K",
"inputType": "Text"
},
{
"name": "granite-code:8b",
"size": "4.6GB",
"context": "125K",
"inputType": "Text"
},
{
"name": "granite-code:20b",
"size": "12GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "granite-code:34b",
"size": "19GB",
"context": "8K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "granite-embedding",
"url": "https://ollama.com/library/granite-embedding",
"description": "The IBM Granite Embedding 30M and 278M models models are text-only dense biencoder embedding models, with 30M available in English only and 278M serving multilingual use cases.",
"variantsCount": 3,
"variants": [
{
"name": "granite-embedding:latest",
"size": "63MB",
"context": "512",
"inputType": "Text"
},
{
"name": "granite-embedding:30m",
"size": "63MB",
"context": "512",
"inputType": "Text"
},
{
"name": "granite-embedding:278m",
"size": "563MB",
"context": "512",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "granite3-dense",
"url": "https://ollama.com/library/granite3-dense",
"description": "The IBM Granite 2B and 8B models are designed to support tool-based use cases and support for retrieval augmented generation (RAG), streamlining code generation, translation and bug fixing.",
"variantsCount": 3,
"variants": [
{
"name": "granite3-dense:latest",
"size": "1.6GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "granite3-dense:2b",
"size": "1.6GB",
"context": "4K",
"inputType": "Text"
},
{
"name": "granite3-dense:8b",
"size": "4.9GB",
"context": "4K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "granite3-guardian",
"url": "https://ollama.com/library/granite3-guardian",
"description": "The IBM Granite Guardian 3.0 2B and 8B models are designed to detect risks in prompts and/or responses.",
"variantsCount": 3,
"variants": [
{
"name": "granite3-guardian:latest",
"size": "2.7GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "granite3-guardian:2b",
"size": "2.7GB",
"context": "8K",
"inputType": "Text"
},
{
"name": "granite3-guardian:8b",
"size": "5.8GB",
"context": "8K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "granite3-moe",
"url": "https://ollama.com/library/granite3-moe",
"description": "The IBM Granite 1B and 3B models are the first mixture of experts (MoE) Granite models from IBM designed for low latency usage.",
"variantsCount": 3,
"variants": [
{
"name": "granite3-moe:latest",
"size": "822MB",
"context": "4K",
"inputType": "Text"
},
{
"name": "granite3-moe:1b",
"size": "822MB",
"context": "4K",
"inputType": "Text"
},
{
"name": "granite3-moe:3b",
"size": "2.1GB",
"context": "4K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "granite3.1-dense",
"url": "https://ollama.com/library/granite3.1-dense",
"description": "The IBM Granite 2B and 8B models are text-only dense LLMs trained on over 12 trillion tokens of data, demonstrated significant improvements over their predecessors in performance and speed in IBM’s initial testing.",
"variantsCount": 3,
"variants": [
{
"name": "granite3.1-dense:latest",
"size": "5.0GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "granite3.1-dense:2b",
"size": "1.6GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "granite3.1-dense:8b",
"size": "5.0GB",
"context": "128K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "granite3.1-moe",
"url": "https://ollama.com/library/granite3.1-moe",
"description": "The IBM Granite 1B and 3B models are long-context mixture of experts (MoE) Granite models from IBM designed for low latency usage.",
"variantsCount": 3,
"variants": [
{
"name": "granite3.1-moe:latest",
"size": "2.0GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "granite3.1-moe:1b",
"size": "1.4GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "granite3.1-moe:3b",
"size": "2.0GB",
"context": "128K",
"inputType": "Text"
}
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"model": "granite3.2-vision",
"url": "https://ollama.com/library/granite3.2-vision",
"description": "A compact and efficient vision-language model, specifically designed for visual document understanding, enabling automated content extraction from tables, charts, infographics, plots, diagrams, and more.",
"variantsCount": 2,
"variants": [
{
"name": "granite3.2-vision:latest",
"size": "2.4GB",
"context": "16K",
"inputType": "Text, Image"
},
{
"name": "granite3.2-vision:2b",
"size": "2.4GB",
"context": "16K",
"inputType": "Text, Image"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "granite3.2",
"url": "https://ollama.com/library/granite3.2",
"description": "Granite-3.2 is a family of long-context AI models from IBM Granite fine-tuned for thinking capabilities.",
"variantsCount": 3,
"variants": [
{
"name": "granite3.2:latest",
"size": "4.9GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "granite3.2:2b",
"size": "1.5GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "granite3.2:8b",
"size": "4.9GB",
"context": "128K",
"inputType": "Text"
}
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"model": "granite3.3",
"url": "https://ollama.com/library/granite3.3",
"description": "IBM Granite 2B and 8B models are 128K context length language models that have been fine-tuned for improved reasoning and instruction-following capabilities.",
"variantsCount": 3,
"variants": [
{
"name": "granite3.3:latest",
"size": "4.9GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "granite3.3:2b",
"size": "1.5GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "granite3.3:8b",
"size": "4.9GB",
"context": "128K",
"inputType": "Text"
}
]
}
+32
View File
@@ -0,0 +1,32 @@
{
"model": "granite4",
"url": "https://ollama.com/library/granite4",
"description": "Granite 4 features improved instruction following (IF) and tool-calling capabilities, making them more effective in enterprise applications.",
"variantsCount": 4,
"variants": [
{
"name": "granite4:latest",
"size": "2.1GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "granite4:350m",
"size": "708MB",
"context": "32K",
"inputType": "Text"
},
{
"name": "granite4:1b",
"size": "3.3GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "granite4:3b",
"size": "2.1GB",
"context": "128K",
"inputType": "Text"
}
]
}
+38
View File
@@ -0,0 +1,38 @@
{
"model": "hermes3",
"url": "https://ollama.com/library/hermes3",
"description": "Hermes 3 is the latest version of the flagship Hermes series of LLMs by Nous Research",
"variantsCount": 5,
"variants": [
{
"name": "hermes3:latest",
"size": "4.7GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "hermes3:3b",
"size": "2.0GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "hermes3:8b",
"size": "4.7GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "hermes3:70b",
"size": "40GB",
"context": "128K",
"inputType": "Text"
},
{
"name": "hermes3:405b",
"size": "229GB",
"context": "128K",
"inputType": "Text"
}
]
}
Loaded 100 of 261 files, more files were not shown because too many files have changed in this diff. Show more