diff --git a/src/Purrse.Api/Services/ChatService.cs b/src/Purrse.Api/Services/ChatService.cs index 5dba62b..9675c6e 100644 --- a/src/Purrse.Api/Services/ChatService.cs +++ b/src/Purrse.Api/Services/ChatService.cs @@ -1,5 +1,6 @@ using System.Text; using System.Text.Json; +using System.Text.RegularExpressions; using Microsoft.EntityFrameworkCore; using Purrse.Core.DTOs; using Purrse.Core.Interfaces.Services; @@ -37,11 +38,16 @@ public class ChatService : IChatService private const string SystemPromptTemplate = """ You are a helpful personal finance assistant for Purrse. - You have access to tools that can search transactions, view spending reports, check account balances, update transaction categories, manage categories, view budgets, check loan details, list payees, and view scheduled transactions. - IMPORTANT: Always use the provided function tools to look up data. NEVER generate code (Python, JavaScript, or otherwise). Call the tools directly — the system will execute them and return the results to you. - When presenting results, format financial amounts as currency. - When showing transactions, include the date, payee, amount, and category. - Be concise and conversational in your responses. Summarize the data from tool results naturally. + You have tools to search transactions, view spending reports, check account balances, update transaction categories, manage categories, view budgets, check loan details, list payees, and view scheduled transactions. + + RULES: + - To look up data, call the provided function tools. The system executes them and returns results. + - NEVER write or output code. No Python, no JavaScript, no code blocks, no pseudocode. + - Respond in plain conversational English only. + - Format financial amounts as currency (e.g. $1,234.56). + - When showing transactions, include date, payee, amount, and category. + - Be concise. Summarize tool results naturally. + Today's date is {0}. """; @@ -222,7 +228,7 @@ public class ChatService : IChatService else { // No tool calls - save final assistant message - var content = response?.Message?.Content ?? "I'm sorry, I couldn't process that request."; + var content = StripCodeBlocks(response?.Message?.Content ?? "I'm sorry, I couldn't process that request."); assistantDbMessage = new ChatMessage { Id = Guid.NewGuid(), @@ -1102,6 +1108,14 @@ public class ChatService : IChatService }; } + // Strip fenced code blocks that smaller models sometimes generate instead of using tools + private static readonly Regex CodeBlockRegex = new(@"```[\s\S]*?```", RegexOptions.Compiled); + private static string StripCodeBlocks(string content) + { + var cleaned = CodeBlockRegex.Replace(content, "").Trim(); + return string.IsNullOrWhiteSpace(cleaned) ? content.Trim() : cleaned; + } + // Argument parsing helpers private static string? ParseStringArg(Dictionary args, string key) {