diff --git a/AIClasses/Gemini/Gemini.ts b/AIClasses/Gemini/Gemini.ts index c2efc7d..c775ece 100644 --- a/AIClasses/Gemini/Gemini.ts +++ b/AIClasses/Gemini/Gemini.ts @@ -71,11 +71,19 @@ export class Gemini implements IAIClass { text: this.aiPrompt.systemInstruction() }, { - text: `IMPORTANT: When you need current information from the web (recent events, news, current prices, weather, etc.), you should: - 1. First call the 'request_web_search' function to indicate you need web access - 2. After that, you'll be given access to Google Search - 3. Once you have the information from the search, you can answer the user's question - 4. Subsequent communication will return to providing custom function calls` + text: `## IMPORTANT: Web Search Directive + **You *must* proactively use the web search tool whenever a user's query requires current, real-time, or frequently changing information.** This includes, but is not limited to: + - Current date or time. + - Current weather conditions or forecasts. + - Recent news, events, or happenings. + - Up-to-date prices, statistics, or factual data that is dynamic. + - Any information where "current," "latest," or "today's" is implied or explicitly requested. + + When you need current information from the web, you *must* follow these steps: + 1. First call the \`request_web_search\` function with a clear and concise \`reasoning\` explaining why web search is needed. + 2. After calling this, you will be given access to Google Search. + 3. Once you have obtained the necessary information from the search results, use it to formulate your complete and accurate answer. + 4. Subsequent interactions will revert to standard function calls or general assistance as appropriate.` }, { text: await this.aiPrompt.userInstruction() diff --git a/Components/ChatArea.svelte b/Components/ChatArea.svelte index bc52f46..94884cc 100644 --- a/Components/ChatArea.svelte +++ b/Components/ChatArea.svelte @@ -171,22 +171,32 @@ {:else} + {#if isStreaming && messageIndex === messages.length - 1} + + {#if message.content && message.content !== ''}
-
- - {#if isStreaming && messageIndex === messages.length - 1} +
- - - {:else} - - {@html getStaticHTML(message, messageIndex)} - {/if}
{/if} + + + {:else} + + {#if message.content && message.content !== ''} +
+
+
+ {@html getStaticHTML(message, messageIndex)} +
+
+
+ {/if} + {/if} + {/if} {/if} {/each} diff --git a/Components/ChatWindow.svelte b/Components/ChatWindow.svelte index 7d74693..a5312d0 100644 --- a/Components/ChatWindow.svelte +++ b/Components/ChatWindow.svelte @@ -97,6 +97,7 @@ : msg ); isStreaming = false; + await conversationService.saveConversation(conversation); break; } @@ -115,12 +116,17 @@ if (chunk.isComplete) { isStreaming = false; - conversation.contents = conversation.contents.map((msg, messageIndex) => - messageIndex === aiMessageIndex - ? { ...msg, content: accumulatedContent } - : msg - ); - + // Only save the message if it has content or a function call + if (accumulatedContent.trim() !== "" || capturedFunctionCall) { + conversation.contents = conversation.contents.map((msg, messageIndex) => + messageIndex === aiMessageIndex + ? { ...msg, content: accumulatedContent } + : msg + ); + } else { + // Remove the empty placeholder message + conversation.contents = conversation.contents.filter((_, messageIndex) => messageIndex !== aiMessageIndex); + } await conversationService.saveConversation(conversation); } } diff --git a/Enums/AIFunction.ts b/Enums/AIFunction.ts index 130eb6d..b32dd69 100644 --- a/Enums/AIFunction.ts +++ b/Enums/AIFunction.ts @@ -1,3 +1,5 @@ export enum AIFunction { - ListVaultFiles = "list_vault_files" + ListVaultFiles = "list_vault_files", + + RequestWebSearch = "request_web_search" } \ No newline at end of file diff --git a/Services/AIFunctionService.ts b/Services/AIFunctionService.ts index 613bf3a..3276aa0 100644 --- a/Services/AIFunctionService.ts +++ b/Services/AIFunctionService.ts @@ -13,10 +13,12 @@ export class AIFunctionService { public async performAIFunction(functionCall: AIFunctionCall): Promise { switch (functionCall.name) { case AIFunction.ListVaultFiles: - return new AIFunctionResponse( - functionCall.name, - await this.listVaultFiles() - ); + return new AIFunctionResponse(functionCall.name, await this.listVaultFiles()); + + // this is only used by gemini + case AIFunction.RequestWebSearch: + return new AIFunctionResponse(functionCall.name, {}) + default: const error = `Unknown function request ${functionCall.name}` console.error(error); diff --git a/Services/ConversationFileSystemService.ts b/Services/ConversationFileSystemService.ts index 90d11dd..0eaa520 100644 --- a/Services/ConversationFileSystemService.ts +++ b/Services/ConversationFileSystemService.ts @@ -77,7 +77,7 @@ export class ConversationFileSystemService { conversation.created = new Date(data.created); conversation.contents = data.contents.map(content => { return new ConversationContent( - content.role, content.content, new Date(content.timestamp), content.isFunctionCall); + content.role, content.content, new Date(content.timestamp), content.isFunctionCall, content.isFunctionCallResponse); }); conversations.push(conversation); }