feat: enhance context handling by adding code context selection and implementing summary generation (#1091) #release
* feat: add context annotation types and enhance file handling in LLM processing * feat: enhance context handling by adding chatId to annotations and implementing summary generation * removed useless changes * feat: updated token counts to include optimization requests * prompt fix * logging added * useless logs removed
This commit is contained in:
128
app/lib/.server/llm/utils.ts
Normal file
128
app/lib/.server/llm/utils.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
import { type Message } from 'ai';
|
||||
import { DEFAULT_MODEL, DEFAULT_PROVIDER, MODEL_REGEX, PROVIDER_REGEX } from '~/utils/constants';
|
||||
import { IGNORE_PATTERNS, type FileMap } from './constants';
|
||||
import ignore from 'ignore';
|
||||
import type { ContextAnnotation } from '~/types/context';
|
||||
|
||||
export function extractPropertiesFromMessage(message: Omit<Message, 'id'>): {
|
||||
model: string;
|
||||
provider: string;
|
||||
content: string;
|
||||
} {
|
||||
const textContent = Array.isArray(message.content)
|
||||
? message.content.find((item) => item.type === 'text')?.text || ''
|
||||
: message.content;
|
||||
|
||||
const modelMatch = textContent.match(MODEL_REGEX);
|
||||
const providerMatch = textContent.match(PROVIDER_REGEX);
|
||||
|
||||
/*
|
||||
* Extract model
|
||||
* const modelMatch = message.content.match(MODEL_REGEX);
|
||||
*/
|
||||
const model = modelMatch ? modelMatch[1] : DEFAULT_MODEL;
|
||||
|
||||
/*
|
||||
* Extract provider
|
||||
* const providerMatch = message.content.match(PROVIDER_REGEX);
|
||||
*/
|
||||
const provider = providerMatch ? providerMatch[1] : DEFAULT_PROVIDER.name;
|
||||
|
||||
const cleanedContent = Array.isArray(message.content)
|
||||
? message.content.map((item) => {
|
||||
if (item.type === 'text') {
|
||||
return {
|
||||
type: 'text',
|
||||
text: item.text?.replace(MODEL_REGEX, '').replace(PROVIDER_REGEX, ''),
|
||||
};
|
||||
}
|
||||
|
||||
return item; // Preserve image_url and other types as is
|
||||
})
|
||||
: textContent.replace(MODEL_REGEX, '').replace(PROVIDER_REGEX, '');
|
||||
|
||||
return { model, provider, content: cleanedContent };
|
||||
}
|
||||
|
||||
export function simplifyBoltActions(input: string): string {
|
||||
// Using regex to match boltAction tags that have type="file"
|
||||
const regex = /(<boltAction[^>]*type="file"[^>]*>)([\s\S]*?)(<\/boltAction>)/g;
|
||||
|
||||
// Replace each matching occurrence
|
||||
return input.replace(regex, (_0, openingTag, _2, closingTag) => {
|
||||
return `${openingTag}\n ...\n ${closingTag}`;
|
||||
});
|
||||
}
|
||||
|
||||
export function createFilesContext(files: FileMap, useRelativePath?: boolean) {
|
||||
const ig = ignore().add(IGNORE_PATTERNS);
|
||||
let filePaths = Object.keys(files);
|
||||
filePaths = filePaths.filter((x) => {
|
||||
const relPath = x.replace('/home/project/', '');
|
||||
return !ig.ignores(relPath);
|
||||
});
|
||||
|
||||
const fileContexts = filePaths
|
||||
.filter((x) => files[x] && files[x].type == 'file')
|
||||
.map((path) => {
|
||||
const dirent = files[path];
|
||||
|
||||
if (!dirent || dirent.type == 'folder') {
|
||||
return '';
|
||||
}
|
||||
|
||||
const codeWithLinesNumbers = dirent.content
|
||||
.split('\n')
|
||||
// .map((v, i) => `${i + 1}|${v}`)
|
||||
.join('\n');
|
||||
|
||||
let filePath = path;
|
||||
|
||||
if (useRelativePath) {
|
||||
filePath = path.replace('/home/project/', '');
|
||||
}
|
||||
|
||||
return `<file path="${filePath}">\n${codeWithLinesNumbers}\n</file>`;
|
||||
});
|
||||
|
||||
return `<codebase>${fileContexts.join('\n\n')}\n\n</codebase>`;
|
||||
}
|
||||
|
||||
export function extractCurrentContext(messages: Message[]) {
|
||||
const lastAssistantMessage = messages.filter((x) => x.role == 'assistant').slice(-1)[0];
|
||||
|
||||
if (!lastAssistantMessage) {
|
||||
return { summary: undefined, codeContext: undefined };
|
||||
}
|
||||
|
||||
let summary: ContextAnnotation | undefined;
|
||||
let codeContext: ContextAnnotation | undefined;
|
||||
|
||||
if (!lastAssistantMessage.annotations?.length) {
|
||||
return { summary: undefined, codeContext: undefined };
|
||||
}
|
||||
|
||||
for (let i = 0; i < lastAssistantMessage.annotations.length; i++) {
|
||||
const annotation = lastAssistantMessage.annotations[i];
|
||||
|
||||
if (!annotation || typeof annotation !== 'object') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(annotation as any).type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const annotationObject = annotation as any;
|
||||
|
||||
if (annotationObject.type === 'codeContext') {
|
||||
codeContext = annotationObject;
|
||||
break;
|
||||
} else if (annotationObject.type === 'chatSummary') {
|
||||
summary = annotationObject;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return { summary, codeContext };
|
||||
}
|
||||
Reference in New Issue
Block a user