Skip to content

Commit 407410e

Browse files
committed
fix: reduce hallucination, add model warmup, and fix first-token timing
1 parent 3d34d93 commit 407410e

1 file changed

Lines changed: 32 additions & 4 deletions

File tree

apps/server/src/index.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,12 @@ Estou em desenvolvimento! Em breve estarei totalmente integrado com todos os doc
7070
const SYSTEM_PROMPT = `Você é o Ifinho, assistente virtual do IFRS Campus Canoas.
7171
Responda sempre em português, de forma clara e objetiva, usando Markdown para formatar suas respostas (títulos, listas, negrito quando fizer sentido).
7272
Use emojis com frequência para deixar as respostas mais visuais e amigáveis — em títulos, itens de lista, destaques e no início de seções. Cada item de lista deve ter um emoji relevante.
73-
Ao citar fontes, mantenha os links Markdown exatamente como aparecem no contexto, no formato [texto](url).`;
73+
Ao citar fontes, mantenha os links Markdown exatamente como aparecem no contexto, no formato [texto](url).
74+
75+
REGRAS IMPORTANTES:
76+
- Responda APENAS com base nas informações fornecidas no contexto abaixo.
77+
- Se a resposta não estiver no contexto, diga claramente que não encontrou essa informação nos documentos disponíveis. NÃO invente, suponha ou complete com informações que não estão no contexto.
78+
- Nunca crie listas de notícias, datas, eventos ou qualquer dado que não esteja explicitamente no contexto fornecido.`;
7479

7580
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
7681

@@ -161,8 +166,8 @@ app.post("/api/chat", async (req, res) => {
161166
const context = await retrieveContext(trimmed);
162167

163168
const systemPrompt = context
164-
? `${SYSTEM_PROMPT}\n\n## Informações relevantes encontradas na base de dados do IFRS Canoas:\n\n${context}\n\nUse as informações acima para responder. Se a resposta não estiver no contexto, diga que não encontrou informação sobre isso nos documentos disponíveis.`
165-
: SYSTEM_PROMPT;
169+
? `${SYSTEM_PROMPT}\n\n## Trechos encontrados na base de dados do IFRS Canoas:\n\n${context}\n\nUse SOMENTE os trechos acima para responder. Não adicione informações que não estejam nesses trechos.`
170+
: `${SYSTEM_PROMPT}\n\nNenhuma informação relevante foi encontrada na base de dados para essa pergunta. Informe ao usuário que não há dados disponíveis sobre isso nos documentos do campus.`;
166171

167172
const tLlm = Date.now();
168173
const stream = await ollama.chat({
@@ -173,11 +178,15 @@ app.post("/api/chat", async (req, res) => {
173178
{ role: "user", content: trimmed },
174179
],
175180
});
176-
console.log(`[chat] llm first token: ${Date.now() - tLlm}ms`);
177181

182+
let firstToken = true;
178183
for await (const chunk of stream) {
179184
const token = chunk.message.content;
180185
if (token) {
186+
if (firstToken) {
187+
console.log(`[chat] llm first token: ${Date.now() - tLlm}ms`);
188+
firstToken = false;
189+
}
181190
res.write(`data: ${JSON.stringify({ token })}\n\n`);
182191
}
183192
}
@@ -225,6 +234,25 @@ if (newlyApplied.length === 0) {
225234
}
226235
console.log(`[migrations] Done. Total applied: ${after.length}`);
227236

237+
// Warmup: preload models into memory to avoid cold start on first chat request
238+
console.log(`[warmup] Loading embed model: ${env.OLLAMA_EMBED_MODEL}`);
239+
console.log(`[warmup] Loading chat model: ${env.OLLAMA_MODEL}`);
240+
const tWarmup = Date.now();
241+
try {
242+
await Promise.all([
243+
ollama.embed({ model: env.OLLAMA_EMBED_MODEL, input: "warmup" }),
244+
ollama.chat({
245+
model: env.OLLAMA_MODEL,
246+
stream: false,
247+
messages: [{ role: "user", content: "oi" }],
248+
options: { num_predict: 1 },
249+
}),
250+
]);
251+
console.log(`[warmup] Models ready in ${Date.now() - tWarmup}ms.`);
252+
} catch (err) {
253+
console.warn("[warmup] Failed to preload models:", err);
254+
}
255+
228256
app.listen(3000, () => {
229257
console.log("Server is running on http://localhost:3000");
230258
});

0 commit comments

Comments
 (0)