- Update .gitignore to exclude database files, extensions, and .cursor directory - Enhance chat streaming API with safe enqueue and close functions to prevent errors - Integrate ConversationSidebar component into ClientHome for better UI - Add dependencies like better-sqlite3 and esbuild packages for database functionality This commit introduces database persistence for conversations, improves error handling in streaming responses, and adds a sidebar for managing chats, enhancing overall app robustness and user experience.
103 lines
3.1 KiB
TypeScript
103 lines
3.1 KiB
TypeScript
import { Ollama } from "ollama";
|
|
|
|
const ollama = new Ollama({
|
|
host: process.env.OLLAMA_HOST || "http://localhost:11434",
|
|
});
|
|
|
|
export async function generateEmbedding(
|
|
text: string,
|
|
model: string = "nomic-embed-text"
|
|
): Promise<Float32Array> {
|
|
try {
|
|
const response = await ollama.embeddings({
|
|
model,
|
|
prompt: text,
|
|
});
|
|
|
|
return new Float32Array(response.embedding);
|
|
} catch (error) {
|
|
console.error("Erro ao gerar embedding:", error);
|
|
|
|
// Fallback: retornar vetor zero se modelo não estiver disponível
|
|
console.warn(
|
|
`Modelo ${model} não disponível, usando vetor zero como fallback`
|
|
);
|
|
return new Float32Array(384); // 384 dimensões padrão
|
|
}
|
|
}
|
|
|
|
const EMOJI_CATEGORIES = {
|
|
code: ["💻", "🖥️", "⌨️", "🔧", "🛠️"],
|
|
idea: ["💡", "🧠", "💭", "🤔", "✨"],
|
|
question: ["❓", "🤷", "🔍", "🧐", "📚"],
|
|
creative: ["🎨", "🎭", "🎪", "🌈", "🎬"],
|
|
business: ["💼", "📊", "💰", "📈", "🏢"],
|
|
science: ["🔬", "🧪", "🔭", "⚗️", "🧬"],
|
|
education: ["📖", "📝", "🎓", "✏️", "📚"],
|
|
communication: ["💬", "📱", "📧", "🗣️", "💌"],
|
|
general: ["🌟", "🎯", "🚀", "⚡", "🔥"],
|
|
};
|
|
|
|
export async function generateChatTitle(firstMessage: string): Promise<string> {
|
|
try {
|
|
const response = await ollama.generate({
|
|
model: "qwen2.5:0.5b",
|
|
prompt: `Analise esta mensagem e crie um título curto e descritivo (MAX 30 caracteres, sem emoji):
|
|
|
|
Mensagem: "${firstMessage}"
|
|
|
|
Título (direto, sem explicação):`,
|
|
options: {
|
|
temperature: 0.7,
|
|
num_predict: 15,
|
|
},
|
|
});
|
|
|
|
let title = response.response
|
|
.trim()
|
|
.replace(/['"]/g, "")
|
|
.replace(/^Título:\s*/i, "")
|
|
.substring(0, 30);
|
|
|
|
// Selecionar emoji baseado no conteúdo
|
|
const emoji = selectEmoji(firstMessage);
|
|
|
|
return `${emoji} ${title}`;
|
|
} catch (error) {
|
|
console.error("Erro ao gerar título:", error);
|
|
// Fallback: usar título simples baseado no conteúdo
|
|
const emoji = selectEmoji(firstMessage);
|
|
const fallbackTitle = firstMessage.substring(0, 20).trim();
|
|
return `${emoji} ${fallbackTitle}`;
|
|
}
|
|
}
|
|
|
|
function selectEmoji(content: string): string {
|
|
const lower = content.toLowerCase();
|
|
|
|
if (/code|program|debug|function|class/.test(lower))
|
|
return EMOJI_CATEGORIES.code[
|
|
Math.floor(Math.random() * EMOJI_CATEGORIES.code.length)
|
|
];
|
|
if (/why|how|what|when|where/.test(lower))
|
|
return EMOJI_CATEGORIES.question[
|
|
Math.floor(Math.random() * EMOJI_CATEGORIES.question.length)
|
|
];
|
|
if (/idea|think|create|design/.test(lower))
|
|
return EMOJI_CATEGORIES.idea[
|
|
Math.floor(Math.random() * EMOJI_CATEGORIES.idea.length)
|
|
];
|
|
if (/business|money|sale|market/.test(lower))
|
|
return EMOJI_CATEGORIES.business[
|
|
Math.floor(Math.random() * EMOJI_CATEGORIES.business.length)
|
|
];
|
|
if (/science|research|experiment/.test(lower))
|
|
return EMOJI_CATEGORIES.science[
|
|
Math.floor(Math.random() * EMOJI_CATEGORIES.science.length)
|
|
];
|
|
|
|
return EMOJI_CATEGORIES.general[
|
|
Math.floor(Math.random() * EMOJI_CATEGORIES.general.length)
|
|
];
|
|
}
|