double-context
Version:
Intelligently optimize and compress context for LLM prompts to greatly increase effective context window
63 lines • 2.9 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.optimizePrompt = optimizePrompt;
const tokenizer_1 = require("./tokenizer");
const dedupe_1 = require("./dedupe");
const compressor_1 = require("./compressor");
const prioritizer_1 = require("./prioritizer");
const embeddings_1 = require("./embeddings");
async function optimizePrompt(opts) {
if (!opts.userPrompt) {
throw new Error("User prompt is required");
}
if (!opts.context || opts.context.length === 0) {
return {
finalPrompt: opts.userPrompt,
tokenCount: (0, tokenizer_1.countTokens)(opts.userPrompt),
droppedChunks: []
};
}
if (opts.maxTokens <= 0) {
throw new Error("maxTokens must be positive");
}
let chunks = [...opts.context];
const originalChunks = [...chunks];
// Create embedding provider if API key is provided
const embeddingProvider = await (0, embeddings_1.createEmbeddingProvider)(opts.openaiApiKey, opts.embeddingModel, opts.embedder || "openai");
// Step 1: Deduplication
if (opts.dedupe !== false) { // Default to true
chunks = await (0, dedupe_1.deduplicate)(chunks, embeddingProvider || undefined, opts.semanticThreshold);
}
// Step 2: Prioritization (relevance/recency/hybrid)
chunks = await (0, prioritizer_1.prioritize)(chunks, opts.userPrompt, opts.strategy || "hybrid", embeddingProvider || undefined);
// Step 3: Compress if needed and requested
const promptTokens = (0, tokenizer_1.countTokens)(opts.userPrompt);
const availableTokensForContext = Math.max(0, opts.maxTokens - promptTokens - 10); // Buffer for formatting
let contextText = chunks.join("\n");
let contextTokens = (0, tokenizer_1.countTokens)(contextText);
if (contextTokens > availableTokensForContext && opts.compress) {
chunks = await (0, compressor_1.compress)(chunks, availableTokensForContext, opts.embedder);
contextText = chunks.join("\n");
contextTokens = (0, tokenizer_1.countTokens)(contextText);
}
// Step 4: Final trimming - remove chunks until under budget
while (contextTokens > availableTokensForContext && chunks.length > 0) {
chunks.pop(); // Remove least prioritized chunk
contextText = chunks.join("\n");
contextTokens = (0, tokenizer_1.countTokens)(contextText);
}
// Build final prompt
const finalPrompt = contextText
? `${opts.userPrompt}\n\n${contextText}`
: opts.userPrompt;
const finalTokenCount = (0, tokenizer_1.countTokens)(finalPrompt);
// Calculate dropped chunks
const keptChunks = new Set(chunks);
const droppedChunks = originalChunks.filter(chunk => !keptChunks.has(chunk));
return {
finalPrompt,
tokenCount: finalTokenCount,
droppedChunks
};
}
//# sourceMappingURL=optimizer.js.map
;