docs: replace README with Next.js boilerplate template

Updated README.md from a detailed OllaHub project description to the standard Next.js getting started template, likely to initialize or reset the project as a Next.js application.
This commit is contained in:
Evandro Fonseca Junior committed 2025-10-28 12:51:19 -03:00
1 parent 58e5522700
commit a3f8226fda
42 files changed
+4465 -314

No files matched your search

+50
View File
@@ -0,0 +1,50 @@
export type ChatRole = "user" | "assistant" | "system";
export type Message = {
id: string;
role: ChatRole;
content: string;
timestamp: number;
};
export type ChatState = {
messages: Message[];
selectedModel: string | null;
isStreaming: boolean;
streamingContent: string;
};
export function createMessage(role: ChatRole, content: string): Message {
return {
id: crypto.randomUUID(),
role,
content,
timestamp: Date.now(),
};
}
export function formatTimestamp(timestamp: number): string {
const now = Date.now();
const diff = now - timestamp;
const minutes = Math.floor(diff / 60000);
if (minutes < 1) return "agora";
if (minutes < 60) return `${minutes} min atrás`;
const hours = Math.floor(minutes / 60);
if (hours < 24) return `${hours}h atrás`;
const days = Math.floor(hours / 24);
return `${days}d atrás`;
}
export function convertToOllamaMessages(messages: Message[]) {
return messages.map((msg) => ({
role: msg.role,
content: msg.content,
}));
}
export function createSystemMessage(content: string): Message {
return createMessage("system", content);
}
+100
View File
@@ -0,0 +1,100 @@
export type Device = "CPU" | "GPU";
export type ModelInfo = {
id: string;
name: string;
sizeGB: number;
quantization: string;
device: Device;
estCpuUsagePct?: number;
estVramGB?: number;
};
export const mockModels: ModelInfo[] = [
{
id: "llama3.1-8b-q4",
name: "llama3.1:8b-q4",
sizeGB: 4.8,
quantization: "Q4",
device: "CPU",
estCpuUsagePct: 85,
estVramGB: 0.0,
},
{
id: "llama3.1-8b-q8",
name: "llama3.1:8b-q8",
sizeGB: 8.9,
quantization: "Q8",
device: "GPU",
estCpuUsagePct: 20,
estVramGB: 8,
},
{
id: "mistral-7b-q4",
name: "mistral:7b-q4",
sizeGB: 4.1,
quantization: "Q4",
device: "CPU",
estCpuUsagePct: 75,
estVramGB: 0,
},
{
id: "mistral-7b-q8",
name: "mistral:7b-q8",
sizeGB: 7.9,
quantization: "Q8",
device: "GPU",
estCpuUsagePct: 18,
estVramGB: 8,
},
{
id: "qwen2.5-7b-q4",
name: "qwen2.5:7b-q4",
sizeGB: 4.2,
quantization: "Q4",
device: "CPU",
estCpuUsagePct: 80,
estVramGB: 0,
},
{
id: "qwen2.5-7b-q8",
name: "qwen2.5:7b-q8",
sizeGB: 8.1,
quantization: "Q8",
device: "GPU",
estCpuUsagePct: 22,
estVramGB: 8,
},
];
export function inferQuantization(nameOrDetails: string | unknown): string {
const s =
typeof nameOrDetails === "string" ? nameOrDetails.toLowerCase() : "";
if (s.includes("q8")) return "Q8";
if (s.includes("q5")) return "Q5";
if (s.includes("q4")) return "Q4";
return "Q?";
}
export function inferDevice(details?: unknown): Device {
const s = typeof details === "string" ? details.toLowerCase() : "";
if (s.includes("cuda") || s.includes("metal") || s.includes("gpu"))
return "GPU";
return "CPU";
}
export function estimateCpuVram(
info: Pick<ModelInfo, "sizeGB" | "quantization" | "device">,
) {
const q = info.quantization.toUpperCase();
let cpuPct = 50;
let vramGB = 0;
if (info.device === "GPU") {
vramGB = Math.max(4, Math.round(info.sizeGB));
cpuPct = 20;
} else {
// heurística simples: quantizações mais baixas usam mais CPU
cpuPct = q === "Q8" ? 60 : q === "Q5" ? 70 : 85;
}
return { cpuPct, vramGB };
}
+42
View File
@@ -0,0 +1,42 @@
import { Ollama } from "ollama";
export const OLLAMA_HOST = process.env.OLLAMA_HOST || "http://localhost:11434";
export async function listModelsViaSdk() {
try {
const client = new Ollama({ host: OLLAMA_HOST });
const res = await client.list();
return res?.models ?? [];
} catch (e) {
throw e;
}
}
export async function listModelsViaHttp() {
const url = `${OLLAMA_HOST}/api/tags`;
const res = await fetch(url, { cache: "no-store" });
if (!res.ok) throw new Error(`Ollama HTTP error ${res.status}`);
const data = await res.json();
return data?.models ?? [];
}
export async function chatWithStream(
model: string,
messages: Array<{ role: string; content: string }>,
options?: Record<string, unknown>,
system?: string
) {
const client = new Ollama({ host: OLLAMA_HOST });
return client.chat({
model,
messages,
stream: true,
options,
system,
});
}
export async function pullModel(model: string) {
const client = new Ollama({ host: OLLAMA_HOST });
return client.pull({ model, stream: true });
}
+30
View File
@@ -0,0 +1,30 @@
export const DEFAULT_SYSTEM_PROMPT = `Você é um assistente de IA especializado em desenvolvimento de software e análise técnica.
FORMATAÇÃO OBRIGATÓRIA:
- Sempre use blocos de código markdown com especificação de linguagem
- Para JavaScript/TypeScript: \`\`\`javascript ou \`\`\`typescript
- Para Python: \`\`\`python
- Para Bash/Shell: \`\`\`bash
- Para SQL: \`\`\`sql
- Para JSON: \`\`\`json
- Para YAML: \`\`\`yaml
- Para Docker: \`\`\`dockerfile
- Para configurações: \`\`\`toml, \`\`\`ini, \`\`\`conf
ESTRUTURA DE RESPOSTAS:
1. Explicação conceitual clara
2. Exemplo prático em bloco de código
3. Explicação do código quando necessário
4. Boas práticas
5. Possíveis problemas e soluções
CONTEXTO OLLAHUB:
- Execução local via Ollama
- Stack frequente: Next.js, React, Node.js
- Priorize exemplos executáveis e explique comandos e configurações.`;
export function mergeSystemPrompt(userPrompt?: string) {
if (!userPrompt || userPrompt.trim().length === 0)
return DEFAULT_SYSTEM_PROMPT;
return `${DEFAULT_SYSTEM_PROMPT}\n\nDiretivas do usuário:\n${userPrompt}`;
}