Fix problem with expanding of prompts and articles (it is returned back), remove not used code
This commit is contained in:
parent
f66dd0920b
commit
3d3af78563
2
main.ts
2
main.ts
|
|
@ -72,7 +72,7 @@ export default class LLMAgentPlugin extends Plugin {
|
|||
// Клонируем настройки, чтобы не испортить исходные пути в конфиге плагина
|
||||
const settingsToSync = JSON.parse(JSON.stringify(this.settings));
|
||||
|
||||
// Собираем промпты (раскрываем все цепочки ссылок)
|
||||
// Собираем промпты (раскрываем все цепочки ссылок) для работы с аудиологами на бекенде
|
||||
settingsToSync.systemPrompt = await engine.processRawSettingValue(this.settings.systemPrompt);
|
||||
settingsToSync.promptRegular = await engine.processRawSettingValue(this.settings.promptRegular);
|
||||
settingsToSync.promptCommands = await engine.processRawSettingValue(this.settings.promptCommands);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { TFile, normalizePath, FileSystemAdapter } from 'obsidian';
|
|||
import LLMAgentPlugin from 'main';
|
||||
import { v4 as uuidv4 } from 'uuid'; // Нужно установить: npm install uuid @types/uuid
|
||||
import { getMimeType } from 'src/utils/fileUtils';
|
||||
import { TemplateEngine } from './TemplateEngine';
|
||||
|
||||
export class CacheManager {
|
||||
private plugin: LLMAgentPlugin;
|
||||
|
|
@ -67,11 +68,9 @@ export class CacheManager {
|
|||
await this.ensureCacheFolderExists();
|
||||
|
||||
const uuid = uuidv4();
|
||||
const extension = file.extension;
|
||||
const extension = file.extension.toLowerCase();
|
||||
const cachedFileName = `${file.basename}-${uuid}.${extension}`;
|
||||
|
||||
const content = await this.plugin.app.vault.readBinary(file);
|
||||
|
||||
const cacheFolderPath = this.getCacheFolderPath();
|
||||
const cachedFilePath = `${cacheFolderPath}/${cachedFileName}`;
|
||||
|
||||
|
|
@ -80,7 +79,25 @@ export class CacheManager {
|
|||
}
|
||||
|
||||
const fs = window.require('fs').promises;
|
||||
await fs.writeFile(cachedFilePath, Buffer.from(content));
|
||||
|
||||
// Список расширений, внутри которых мы ищем и разворачиваем макросы
|
||||
const textExtensions = ['md', 'txt']; // , 'canvas'
|
||||
|
||||
if (textExtensions.includes(extension)) {
|
||||
// Читаем как текст
|
||||
let content = await this.plugin.app.vault.read(file);
|
||||
|
||||
// Инициализируем движок и полностью разворачиваем все вложенные @{} и #{}
|
||||
const templateEngine = new TemplateEngine(this.plugin);
|
||||
const expandedContent = await templateEngine.expandPromptTemplate(content);
|
||||
|
||||
// Сохраняем в кеш РАЗВЕРНУТЫЙ текст (снапшот)
|
||||
await fs.writeFile(cachedFilePath, expandedContent, 'utf8');
|
||||
} else {
|
||||
// Если это картинка, PDF или другой бинарник, просто копируем байты
|
||||
const content = await this.plugin.app.vault.readBinary(file);
|
||||
await fs.writeFile(cachedFilePath, Buffer.from(content));
|
||||
}
|
||||
|
||||
return {
|
||||
uuid: uuid,
|
||||
|
|
@ -122,6 +139,7 @@ export class CacheManager {
|
|||
};
|
||||
}
|
||||
|
||||
// TODO: Кажется, не используется
|
||||
/**
|
||||
* Восстанавливает кеш из исходного файла
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -26,58 +26,6 @@ export class ReferenceExpander {
|
|||
|
||||
// ----------------------------------------------- Public Methods ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Заменяет все ссылки на содержимое файлов (перед отправкой на сервер)
|
||||
* @param text - текст с ссылками
|
||||
* @param references - массив ссылок для обработки
|
||||
* @returns текст с развернутыми ссылками
|
||||
*/
|
||||
/*async expandReferences(text: string, references: FileReference[]): Promise<string> {
|
||||
if (references.length === 0) {
|
||||
return text;
|
||||
}
|
||||
|
||||
let expandedText = text;
|
||||
|
||||
// Обрабатываем ссылки от конца к началу, чтобы не сбивать индексы
|
||||
const sortedReferences = [...references].sort((a, b) => {
|
||||
const aMatches = ReferenceParser.parseReferences(text).filter((m) => m.name === a.name);
|
||||
const bMatches = ReferenceParser.parseReferences(text).filter((m) => m.name === b.name);
|
||||
const aIndex = aMatches.length > 0 ? aMatches[aMatches.length - 1].startIndex : 0;
|
||||
const bIndex = bMatches.length > 0 ? bMatches[bMatches.length - 1].startIndex : 0;
|
||||
return bIndex - aIndex;
|
||||
});
|
||||
|
||||
for (const reference of sortedReferences) {
|
||||
expandedText = await this.expandSingleReference(expandedText, reference);
|
||||
}
|
||||
|
||||
return expandedText;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Обрабатывает историю сообщений, раскрывая постоянные ссылки (@@/##)
|
||||
* @param messages - массив сообщений
|
||||
* @returns обработанные сообщения
|
||||
*/
|
||||
/*async expandMessageHistory(messages: any[]): Promise<any[]> {
|
||||
const expandedMessages = [];
|
||||
|
||||
for (const message of messages) {
|
||||
if (message.role === 'user') {
|
||||
const expandedContent = await this.expandPermanentReferences(message.content);
|
||||
expandedMessages.push({
|
||||
...message,
|
||||
content: expandedContent
|
||||
});
|
||||
} else {
|
||||
expandedMessages.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
return expandedMessages;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Извлекает вложения из текста и кеширует файлы.
|
||||
* Обрабатывает как физические файлы, так и виртуальные (current-log).
|
||||
|
|
@ -195,221 +143,4 @@ export class ReferenceExpander {
|
|||
attachments: attachments
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготавливает сообщения для LLM с учетом вложений.
|
||||
* Раскрывает только постоянные (@@/##) ссылки и ссылки в последнем сообщении.
|
||||
*/
|
||||
/*async prepareMessagesForLLM(messages: ChatHistoryItem[], isLastMessage: boolean = false): Promise<any[]> {
|
||||
const preparedMessages = [];
|
||||
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
const msg = messages[i];
|
||||
const isLast = i === messages.length - 1;
|
||||
|
||||
if (msg.role === 'user' && msg.attachments && msg.attachments.length > 0) {
|
||||
// Определяем, какие вложения нужно раскрыть
|
||||
const attachmentsToExpand = msg.attachments.filter((att) => att.permanent || (isLast && isLastMessage));
|
||||
|
||||
if (attachmentsToExpand.length > 0) {
|
||||
// Формируем сообщение с раскрытыми вложениями
|
||||
let expandedContent = msg.content;
|
||||
|
||||
for (const attachment of attachmentsToExpand) {
|
||||
const formattedContent = this.formatContentForInsertion(attachment.content || '', attachment);
|
||||
expandedContent += '\n' + formattedContent;
|
||||
}
|
||||
|
||||
preparedMessages.push({
|
||||
role: msg.role,
|
||||
content: expandedContent
|
||||
});
|
||||
} else {
|
||||
// Вложения есть, но раскрывать не нужно
|
||||
preparedMessages.push({
|
||||
role: msg.role,
|
||||
content: msg.content
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Сообщение без вложений
|
||||
preparedMessages.push({
|
||||
role: msg.role,
|
||||
content: msg.content
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return preparedMessages;
|
||||
}*/
|
||||
|
||||
// TODO: При реализации снапшотов - сохранять содержимое файлов
|
||||
// async expandReferencesWithSnapshots(text: string, references: FileReference[], messageId: string): Promise<{expandedText: string, snapshots: Record<string, string>}> {
|
||||
// const snapshots: Record<string, string> = {};
|
||||
// let expandedText = text;
|
||||
//
|
||||
// for (const reference of references) {
|
||||
// const content = await this.loadFileContent(reference);
|
||||
// if (content !== null) {
|
||||
// snapshots[reference.path] = content;
|
||||
// expandedText = await this.expandSingleReference(expandedText, reference, content);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return { expandedText, snapshots };
|
||||
// }
|
||||
|
||||
// ----------------------------------------------- Private Methods ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Раскрывает одну ссылку в тексте
|
||||
* @param text - текст для обработки
|
||||
* @param reference - ссылка для раскрытия
|
||||
* @param preloadedContent - предзагруженное содержимое (для снапшотов)
|
||||
* @returns текст с раскрытой ссылкой
|
||||
*/
|
||||
/*private async expandSingleReference(text: string, reference: FileReference, preloadedContent?: string): Promise<string> {
|
||||
const content = preloadedContent || (await this.loadFileContent(reference));
|
||||
|
||||
if (content === null) {
|
||||
console.warn(`Не удалось загрузить содержимое для ссылки: ${reference.name}`);
|
||||
return text;
|
||||
}
|
||||
|
||||
// Определяем паттерн для замены
|
||||
const prefix = reference.permanent ? (reference.type === 'file' ? '@@' : '##') : reference.type === 'file' ? '@' : '#';
|
||||
|
||||
// Создаем регулярное выражение для поиска ссылки
|
||||
const escapedName = this.escapeRegExp(reference.name);
|
||||
const pattern = new RegExp(`${this.escapeRegExp(prefix)}(?:"${escapedName}"|${escapedName})(?=\\s|$|[^\\w-])`, 'g');
|
||||
|
||||
// Форматируем содержимое для вставки
|
||||
const formattedContent = this.formatContentForInsertion(content, reference);
|
||||
|
||||
return text.replace(pattern, formattedContent);
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Раскрывает только постоянные ссылки (@@/##) в тексте
|
||||
* @param text - текст для обработки
|
||||
* @returns текст с раскрытыми постоянными ссылками
|
||||
*/
|
||||
/*private async expandPermanentReferences(text: string): Promise<string> {
|
||||
const matches = ReferenceParser.parseReferences(text);
|
||||
const permanentMatches = matches.filter((match) => match.prefix.length === 2); // @@ или ##
|
||||
|
||||
if (permanentMatches.length === 0) {
|
||||
return text;
|
||||
}
|
||||
|
||||
let expandedText = text;
|
||||
|
||||
// Обрабатываем ссылки от конца к началу
|
||||
const sortedMatches = [...permanentMatches].sort((a, b) => b.startIndex - a.startIndex);
|
||||
|
||||
for (const match of sortedMatches) {
|
||||
const reference: FileReference = {
|
||||
type: match.type,
|
||||
name: match.name,
|
||||
path: await this.resolveFilePath(match.name, match.type),
|
||||
permanent: true
|
||||
};
|
||||
|
||||
const content = await this.loadFileContent(reference);
|
||||
if (content !== null) {
|
||||
const formattedContent = this.formatContentForInsertion(content, reference);
|
||||
expandedText = expandedText.substring(0, match.startIndex) + formattedContent + expandedText.substring(match.endIndex);
|
||||
}
|
||||
}
|
||||
|
||||
return expandedText;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Загружает содержимое файла
|
||||
* @param reference - ссылка на файл
|
||||
* @returns содержимое файла или null если не найден
|
||||
*/
|
||||
/*private async loadFileContent(reference: FileReference): Promise<string | null> {
|
||||
try {
|
||||
const file = this.findFile(reference.path, reference.type);
|
||||
if (!file) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const content = await this.plugin.app.vault.read(file);
|
||||
|
||||
// Для промптов обрабатываем шаблоны
|
||||
if (reference.type === 'prompt') {
|
||||
return await this.templateEngine.expandPromptTemplate(content);
|
||||
}
|
||||
|
||||
return content;
|
||||
} catch (error) {
|
||||
console.error(`Ошибка загрузки файла ${reference.path}:`, error);
|
||||
return null;
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Находит файл по пути
|
||||
* @param path - путь к файлу
|
||||
* @param type - тип файла
|
||||
* @returns файл или null
|
||||
*/
|
||||
/*private findFile(path: string, type: 'file' | 'prompt'): TFile | null {
|
||||
let file = this.plugin.app.vault.getAbstractFileByPath(path);
|
||||
|
||||
if (!file && type === 'prompt') {
|
||||
// Попробуем найти в папке промптов
|
||||
const promptsFolder = this.plugin.settings.promptsFolder;
|
||||
if (promptsFolder) {
|
||||
const fullPath = `${promptsFolder}/${path}`;
|
||||
file = this.plugin.app.vault.getAbstractFileByPath(fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
return file instanceof TFile ? file : null;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Разрешает полный путь к файлу по имени
|
||||
* @param name - имя файла
|
||||
* @param type - тип файла
|
||||
* @returns полный путь к файлу
|
||||
*/
|
||||
/*private async resolveFilePath(name: string, type: 'file' | 'prompt'): Promise<string> {
|
||||
if (type === 'prompt') {
|
||||
const promptsFolder = this.plugin.settings.promptsFolder;
|
||||
return promptsFolder ? `${promptsFolder}/${name}.md` : `${name}.md`;
|
||||
} else {
|
||||
// Ищем файл в хранилище
|
||||
const files = this.plugin.app.vault.getMarkdownFiles();
|
||||
const matchingFile = files.find((f) => f.basename === name);
|
||||
return matchingFile ? matchingFile.path : `${name}.md`;
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Форматирует содержимое для вставки в сообщение
|
||||
* @param content - содержимое файла
|
||||
* @param reference - информация о ссылке
|
||||
* @returns отформатированное содержимое
|
||||
*/
|
||||
/*private formatContentForInsertion(content: string, reference: FileReference): string {
|
||||
// Добавляем заголовок с информацией о файле
|
||||
const header = `\n\n--- Содержимое ${reference.type === 'prompt' ? 'промпта' : 'файла'}: ${reference.name} ---\n`;
|
||||
const footer = `\n--- Конец ${reference.type === 'prompt' ? 'промпта' : 'файла'}: ${reference.name} ---\n\n`;
|
||||
|
||||
return header + content.trim() + footer;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Экранирует специальные символы для регулярного выражения
|
||||
* @param string - строка для экранирования
|
||||
* @returns экранированная строка
|
||||
*/
|
||||
/*private escapeRegExp(string: string): string {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { ItemView, Notice, WorkspaceLeaf } from 'obsidian';
|
|||
import { ChatPanel } from '../components/ChatPanel';
|
||||
import LLMAgentPlugin from 'main';
|
||||
import { Attachment } from 'src/components/models/ChatHistoryItem';
|
||||
import { TemplateEngine } from '../references/TemplateEngine';
|
||||
|
||||
export const CHAT_VIEW_TYPE = 'llm-agent-chat-view';
|
||||
|
||||
|
|
@ -275,10 +276,17 @@ export class ChatView extends ItemView {
|
|||
systemPrompt: string | null = null,
|
||||
cacheFolder?: string
|
||||
): Promise<void> {
|
||||
// Разворачиваем системный промпт (например, если там передано "#my_system_instructions")
|
||||
let finalSystemPrompt = systemPrompt;
|
||||
if (systemPrompt) {
|
||||
const templateEngine = new TemplateEngine(this.plugin);
|
||||
finalSystemPrompt = await templateEngine.processRawSettingValue(systemPrompt);
|
||||
}
|
||||
|
||||
const body = {
|
||||
graph_id: graphId,
|
||||
user_node_id: userNodeId,
|
||||
system_prompt: systemPrompt,
|
||||
system_prompt: finalSystemPrompt,
|
||||
model: selectedModel || this.plugin.settings.defaultModel,
|
||||
cache_folder: cacheFolder
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user