From 673f438feb09882fa4a48eeb7565e8af10a13c4b Mon Sep 17 00:00:00 2001 From: Benjamin Shafii Date: Wed, 1 Jan 2025 15:16:52 +0100 Subject: [PATCH] fix(plugin): improve handling of prompts --- .../ai-chat/components/example-prompts.tsx | 2 +- packages/web/app/api/(newai)/chat/route.ts | 127 +++++------------- packages/web/lib/prompts/chat-prompt.ts | 48 ++++--- 3 files changed, 69 insertions(+), 108 deletions(-) diff --git a/packages/plugin/views/assistant/ai-chat/components/example-prompts.tsx b/packages/plugin/views/assistant/ai-chat/components/example-prompts.tsx index ce900192..251eb9e0 100644 --- a/packages/plugin/views/assistant/ai-chat/components/example-prompts.tsx +++ b/packages/plugin/views/assistant/ai-chat/components/example-prompts.tsx @@ -53,7 +53,7 @@ const examples: Example[] = [ icon: "🕒" }, { - prompt: "Add notes from this YouTube video", + prompt: "Add notes from this YouTube video https://www.youtube.com/watch?v=AyLXmbTnJIY&t=1s", description: "Content import", icon: "▶️" } diff --git a/packages/web/app/api/(newai)/chat/route.ts b/packages/web/app/api/(newai)/chat/route.ts index e641dfdd..ddb85d89 100644 --- a/packages/web/app/api/(newai)/chat/route.ts +++ b/packages/web/app/api/(newai)/chat/route.ts @@ -60,160 +60,107 @@ export async function POST(req: NextRequest) { messages: convertToCoreMessages(messages), tools: { getSearchQuery: { - description: "Extract queries to search for notes", + description: "Extract semantic search queries to find relevant notes based on content and meaning", parameters: z.object({ - query: z - .string() - .describe("The search query to find relevant notes"), + query: z.string().describe("The semantic search query to find relevant notes"), }), }, searchByName: { - description: "Search for files by name pattern", + description: "Search for files by name pattern or exact match, useful for finding specific notes or groups of notes", parameters: z.object({ - query: z - .string() - .describe( - "The name pattern to search for (e.g., 'Untitled*' or exact name)" - ), + query: z.string().describe("The name pattern to search for (e.g., 'Untitled*', 'daily-*', or exact name)"), }), }, getYoutubeVideoId: { - description: "Get the YouTube video ID from a URL", + description: "Extract YouTube video ID to import and organize video content into notes", parameters: z.object({ videoId: z.string().describe("The YouTube video ID"), }), }, getLastModifiedFiles: { - description: "Get the last modified files in the vault", + description: "Retrieve recently modified files to track changes and activity in the vault", parameters: z.object({ - count: z - .number() - .describe("The number of last modified files to retrieve"), + count: z.number().describe("The number of last modified files to retrieve"), }), }, onboardUser: { - description: "Onboard the user to the vault", + description: "Guide new users through vault setup and organization best practices", parameters: z.object({}), }, appendContentToFile: { - description: "Append content to a file with user confirmation", + description: "Add new content to existing notes while preserving structure and formatting", parameters: z.object({ - content: z.string().describe("The content to append to the file"), - message: z - .string() - .describe("Message to show to the user for confirmation"), - fileName: z - .string() - .optional() - .describe("Optional specific file to append to"), + content: z.string().describe("The formatted content to append to the file"), + message: z.string().describe("Clear explanation of what content will be added"), + fileName: z.string().optional().describe("Optional specific file to append to"), }), }, addTextToDocument: { - description: "Adds the text to the current document when the user requests to do so", + description: "Add new sections or content to notes with proper formatting and structure", parameters: z.object({ - content: z.string().describe("The text content to add to the document"), + content: z.string().describe("The formatted text content to add"), path: z.string().optional().describe("Optional path to the document. If not provided, uses current document"), }), }, modifyDocumentText: { - description: "Modifies the text in the current document or selected text according to user's request", + description: "Edit existing note content while maintaining consistency and structure", parameters: z.object({ - content: z.string().describe("The new text content to replace the current content or selection"), + content: z.string().describe("The new formatted content to replace existing content"), path: z.string().optional().describe("Optional path to the document. If not provided, uses current document"), }), }, generateSettings: { - description: - "Generate vault organization settings based on user preferences", + description: "Create personalized vault organization settings based on user preferences and best practices", parameters: settingsSchema, }, analyzeVaultStructure: { - description: - "Analyze vault structure to suggest organization improvements", + description: "Analyze vault organization and provide actionable improvement suggestions", parameters: z.object({ - path: z - .string() - .describe( - "Path to analyze. Use '/' for all files or specific folder path" - ), - maxDepth: z - .number() - .optional() - .describe("Maximum depth to analyze"), - addToContext: z - .boolean() - .optional() - .describe("Whether to add analyzed files to context"), + path: z.string().describe("Path to analyze. Use '/' for all files or specific folder path"), + maxDepth: z.number().optional().describe("Maximum folder depth to analyze"), + addToContext: z.boolean().optional().describe("Whether to add analyzed files to context"), }), }, getScreenpipeDailySummary: { - description: "Get a summary of the user's day using Screenpipe data", + description: "Generate comprehensive daily summaries from Screenpipe data with key insights and activities", parameters: z.object({ - startTime: z - .string() - .optional() - .describe("Start time in ISO format"), + startTime: z.string().optional().describe("Start time in ISO format"), endTime: z.string().optional().describe("End time in ISO format"), }), }, moveFiles: { - description: "Move files to their designated folders", + description: "Organize files into appropriate folders based on content and structure", parameters: z.object({ moves: z.array( z.object({ - sourcePath: z - .string() - .describe( - "Source path (e.g., '/' for root, or specific folder path)" - ), + sourcePath: z.string().describe("Source path (e.g., '/' for root, or specific folder path)"), destinationPath: z.string().describe("Destination folder path"), - pattern: z - .object({ - namePattern: z - .string() - .optional() - .describe( - "File name pattern to match (e.g., 'untitled-*')" - ), - extension: z - .string() - .optional() - .describe("File extension to match"), - }) - .optional(), + pattern: z.object({ + namePattern: z.string().optional().describe("File name pattern to match (e.g., 'untitled-*', 'daily-*')"), + extension: z.string().optional().describe("File extension to match"), + }).optional(), }) ), - message: z.string().describe("Confirmation message to show user"), + message: z.string().describe("Clear explanation of the proposed file organization"), }), }, renameFiles: { - description: "Rename files based on pattern or criteria", + description: "Rename files intelligently based on content and organizational patterns", parameters: z.object({ files: z.array( z.object({ - oldPath: z - .string() - .describe("The current full path of the file"), - newName: z - .string() - .describe("Proposed new file name (no directories)"), + oldPath: z.string().describe("Current full path of the file"), + newName: z.string().describe("Descriptive new file name based on content"), }) ), - message: z.string().describe("Confirmation message to show user"), + message: z.string().describe("Clear explanation of the naming strategy"), }), }, executeActionsOnFileBasedOnPrompt: { - description: - "Analyze file content and apply one of (recommendTags & appendTag), (recommendFolders & moveFile), or (recommendName & moveFile)", + description: "Analyze and organize files through tagging, moving, or renaming based on content analysis", parameters: z.object({ - filePaths: z - .array(z.string()) - .describe("List of file paths to analyze"), - userPrompt: z - .string() - .describe( - "User instructions to decide how to rename or re-tag or re-folder the files" - ), + filePaths: z.array(z.string()).describe("List of file paths to analyze and organize"), + userPrompt: z.string().describe("Specific instructions for file organization strategy"), }), }, }, diff --git a/packages/web/lib/prompts/chat-prompt.ts b/packages/web/lib/prompts/chat-prompt.ts index 16ac51eb..cf65daa0 100644 --- a/packages/web/lib/prompts/chat-prompt.ts +++ b/packages/web/lib/prompts/chat-prompt.ts @@ -1,29 +1,43 @@ -export const getChatSystemPrompt = (contextString: string, enableScreenpipe: boolean, currentDatetime: string) => `You are a helpful assistant with access to various files, notes, YouTube video transcripts, and Screenpipe data. Your context includes: +export const getChatSystemPrompt = (contextString: string, enableScreenpipe: boolean, currentDatetime: string) => `You are a helpful AI assistant specialized in managing and organizing notes in Obsidian. Your core capabilities include content editing, smart search, daily summaries, and vault organization. Your context includes: ${contextString} -Use this context to inform your responses. Key points: +Core Capabilities: +1. Content Editing + - Add or modify content in notes (summaries, sections, formatting) + - Smart content suggestions based on context + - Handle YouTube video content integration -1. For YouTube videos, refer to them by title and use transcript information. -2. For other queries, use the context without explicitly mentioning files unless necessary. -3. Understand that '#' in queries refers to tags in the system, which will be provided in the context. -4. When asked to "format" or "summarize" without specific content, assume it refers to the entire current context. -${enableScreenpipe ? "5. For Screenpipe-related queries, use the provided tools to fetch and analyze meeting summaries or daily information." : ""} +2. Smart Search & Analysis + - Search through notes with semantic understanding + - Analyze vault structure and suggest improvements + - Track and report on recent modifications + +3. Daily Summaries & Integration + ${enableScreenpipe ? "- Provide daily summaries and meeting insights via Screenpipe\n - Track and summarize daily activities" : ""} + - Organize and structure daily notes + - Integrate external content seamlessly + +4. Vault Organization + - Help with vault setup and settings + - Suggest organizational improvements + - Manage note structure and hierarchy The current date and time is: ${currentDatetime} -Use these reference formats: -- Obsidian-style: [[File/Path]], [[Filename#Header]], [[Filename#^unique-identifier]] -- When you mention a file always reference it by path and output like this [[File/Path]] -- YouTube videos: [YouTube: Video Title] -- General references: [^1^] +Reference Formats: +- Obsidian links: [[File/Path]], [[Filename#Header]], [[Filename#^unique-identifier]] +- YouTube references: [YouTube: Video Title] - Quotes: "quoted text"[^2^] Always use these formats when referencing context items. Use numbered references and provide sources at the end of your response. -Recognize and handle requests like: -- "Summarize the meeting I had just now": Use the summarizeMeeting tool -- "Summarize my day": Use the getDailyInformation tool -Adapt to various summarization or content-specific requests based on the user's input and available context. +Key Instructions: +1. When adding content to notes, maintain existing structure and formatting +2. For YouTube content, extract key points and organize them logically +3. When suggesting organizational changes, explain the reasoning +4. Keep responses focused and actionable +5. Use context to inform responses but don't explicitly mention files unless necessary +6. Understand that '#' in queries refers to tags in the system -only use tools if the user asks for them.`; +Only use tools when explicitly needed for the task at hand. Focus on providing clear, actionable responses that help users organize and manage their knowledge effectively.`;