mirror of
https://github.com/zadam/trilium.git
synced 2025-11-16 18:25:51 +01:00
do a wayyy better job at building the messages with context
This commit is contained in:
120
src/services/llm/formatters/ollama_formatter.ts
Normal file
120
src/services/llm/formatters/ollama_formatter.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
import type { Message } from '../ai_interface.js';
|
||||
import { BaseMessageFormatter } from './base_formatter.js';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
|
||||
/**
|
||||
* Ollama-specific message formatter
|
||||
* Handles the unique requirements of the Ollama API
|
||||
*/
|
||||
export class OllamaMessageFormatter extends BaseMessageFormatter {
|
||||
/**
|
||||
* Maximum recommended context length for Ollama
|
||||
* Smaller than other providers due to Ollama's handling of context
|
||||
*/
|
||||
private static MAX_CONTEXT_LENGTH = 4000;
|
||||
|
||||
/**
|
||||
* Format messages for the Ollama API
|
||||
*/
|
||||
formatMessages(messages: Message[], systemPrompt?: string, context?: string): Message[] {
|
||||
const formattedMessages: Message[] = [];
|
||||
|
||||
// First identify user and system messages
|
||||
const systemMessages = messages.filter(msg => msg.role === 'system');
|
||||
const userMessages = messages.filter(msg => msg.role === 'user' || msg.role === 'assistant');
|
||||
|
||||
// Create base system message with instructions
|
||||
const basePrompt = this.getDefaultSystemPrompt(systemPrompt);
|
||||
|
||||
// Always add a system message with the base prompt
|
||||
formattedMessages.push({
|
||||
role: 'system',
|
||||
content: basePrompt
|
||||
});
|
||||
|
||||
// If we have context, inject it into the first user message
|
||||
if (context && userMessages.length > 0) {
|
||||
let injectedContext = false;
|
||||
|
||||
for (let i = 0; i < userMessages.length; i++) {
|
||||
const msg = userMessages[i];
|
||||
|
||||
if (msg.role === 'user' && !injectedContext) {
|
||||
// Simple context injection directly in the user's message
|
||||
const cleanedContext = this.cleanContextContent(context);
|
||||
const formattedContext =
|
||||
"Here's information from my notes to help answer the question:\n\n" +
|
||||
cleanedContext +
|
||||
"\n\nBased on this information, please answer: " + msg.content;
|
||||
|
||||
formattedMessages.push({
|
||||
role: 'user',
|
||||
content: formattedContext
|
||||
});
|
||||
|
||||
injectedContext = true;
|
||||
} else {
|
||||
formattedMessages.push(msg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No context, just add all messages as-is
|
||||
for (const msg of userMessages) {
|
||||
formattedMessages.push(msg);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Ollama formatter processed ${messages.length} messages into ${formattedMessages.length} messages`);
|
||||
|
||||
return formattedMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up HTML and other problematic content before sending to Ollama
|
||||
* Ollama needs a more aggressive cleaning than other models
|
||||
*/
|
||||
override cleanContextContent(content: string): string {
|
||||
if (!content) return '';
|
||||
|
||||
try {
|
||||
// First use the parent class to do standard cleaning
|
||||
let sanitized = super.cleanContextContent(content);
|
||||
|
||||
// Then apply Ollama-specific aggressive cleaning
|
||||
// Remove any remaining HTML using sanitizeHtml
|
||||
let plaintext = sanitizeHtml(sanitized, {
|
||||
allowedTags: [],
|
||||
allowedAttributes: {},
|
||||
textFilter: (text) => text
|
||||
});
|
||||
|
||||
// Then aggressively sanitize to plain ASCII and simple formatting
|
||||
plaintext = plaintext
|
||||
// Replace common problematic quotes with simple ASCII quotes
|
||||
.replace(/[""]/g, '"')
|
||||
.replace(/['']/g, "'")
|
||||
// Replace other common Unicode characters
|
||||
.replace(/[–—]/g, '-')
|
||||
.replace(/[•]/g, '*')
|
||||
.replace(/[…]/g, '...')
|
||||
// Strip all non-ASCII characters
|
||||
.replace(/[^\x00-\x7F]/g, '')
|
||||
// Normalize whitespace
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(/\n\s+/g, '\n')
|
||||
.trim();
|
||||
|
||||
return plaintext;
|
||||
} catch (error) {
|
||||
console.error("Error cleaning context content for Ollama:", error);
|
||||
return content; // Return original if cleaning fails
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum recommended context length for Ollama
|
||||
*/
|
||||
getMaxContextLength(): number {
|
||||
return OllamaMessageFormatter.MAX_CONTEXT_LENGTH;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user