From 595d6f974f22202f5f86bb0117e2e0d10f8e4be6 Mon Sep 17 00:00:00 2001 From: Marco Minerva Date: Wed, 16 Jul 2025 15:45:09 +0200 Subject: [PATCH] Enhance ChatService with new prompt settings Updated ChatService to use AzureOpenAIPromptExecutionSettings for improved chat message generation. The CreateChatAsync method now returns both ChatHistory and settings, allowing for better configuration. Refined question reformulation prompts to ensure context relevance and language consistency. These changes enhance the overall functionality and interaction of the chat service. --- .../Services/ChatService.cs | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/SqlDatabaseVectorSearch/Services/ChatService.cs b/SqlDatabaseVectorSearch/Services/ChatService.cs index 9ee1816..001af84 100644 --- a/SqlDatabaseVectorSearch/Services/ChatService.cs +++ b/SqlDatabaseVectorSearch/Services/ChatService.cs @@ -19,19 +19,26 @@ public class ChatService(IChatCompletionService chatCompletionService, Tokenizer { var chat = await GetChatHistoryAsync(conversationId, cancellationToken); + var settings = new AzureOpenAIPromptExecutionSettings + { + ChatSystemPrompt = """ + You are a helpful assistant that reformulates questions to perform embeddings search. + Your task is to reformulate the question taking into account the context of the chat. + The reformulated question must always explicitly contain the subject of the question. + You must reformulate the question in the same language of the user's question. For example, if the user asks a question in English, the answer must be in English. + Never add "in this chat", "in the context of this chat", "in the context of our conversation", "search for" or something like that in your answer. + """ + }; + var embeddingQuestion = $""" - Reformulate the following question taking into account the context of the chat to perform embeddings search: + Reformulate the following question: --- {question} - --- - The reformulation must always explicitly contain the subject of the question. - You must reformulate the question in the same language of the user's question. For example, it the user asks a question in English, the answer must be in English. - Never add "in this chat", "in the context of this chat", "in the context of our conversation", "search for" or something like that in your answer. """; chat.AddUserMessage(embeddingQuestion); - var reformulatedQuestion = await chatCompletionService.GetChatMessageContentAsync(chat, cancellationToken: cancellationToken); + var reformulatedQuestion = await chatCompletionService.GetChatMessageContentAsync(chat, settings, cancellationToken: cancellationToken); chat.AddAssistantMessage(reformulatedQuestion.Content!); await UpdateCacheAsync(conversationId, chat, cancellationToken); @@ -44,12 +51,9 @@ public class ChatService(IChatCompletionService chatCompletionService, Tokenizer public async Task AskQuestionAsync(Guid conversationId, IEnumerable chunks, string question, CancellationToken cancellationToken = default) { - var chat = CreateChatAsync(chunks, question); + var (chat, settings) = CreateChatAsync(chunks, question); - var answer = await chatCompletionService.GetChatMessageContentAsync(chat, new AzureOpenAIPromptExecutionSettings - { - MaxTokens = appSettings.MaxOutputTokens - }, cancellationToken: cancellationToken); + var answer = await chatCompletionService.GetChatMessageContentAsync(chat, settings, cancellationToken: cancellationToken); // Add question and answer to the chat history. await SetChatHistoryAsync(conversationId, question, answer.Content!, cancellationToken); @@ -62,13 +66,10 @@ public class ChatService(IChatCompletionService chatCompletionService, Tokenizer public async IAsyncEnumerable AskStreamingAsync(Guid conversationId, IEnumerable chunks, string question, [EnumeratorCancellation] CancellationToken cancellationToken = default) { - var chat = CreateChatAsync(chunks, question); + var (chat, settings) = CreateChatAsync(chunks, question); var answer = new StringBuilder(); - await foreach (var token in chatCompletionService.GetStreamingChatMessageContentsAsync(chat, new AzureOpenAIPromptExecutionSettings - { - MaxTokens = appSettings.MaxOutputTokens - }, cancellationToken: cancellationToken)) + await foreach (var token in chatCompletionService.GetStreamingChatMessageContentsAsync(chat, settings, cancellationToken: cancellationToken)) { if (!string.IsNullOrEmpty(token.Content)) { @@ -111,8 +112,13 @@ public class ChatService(IChatCompletionService chatCompletionService, Tokenizer return null; } - private ChatHistory CreateChatAsync(IEnumerable chunks, string question) + private (ChatHistory Chat, AzureOpenAIPromptExecutionSettings Settings) CreateChatAsync(IEnumerable chunks, string question) { + var settings = new AzureOpenAIPromptExecutionSettings + { + MaxTokens = appSettings.MaxOutputTokens + }; + var chat = new ChatHistory(""" You can use only the information provided in this chat to answer questions. If you don't know the answer, reply suggesting to refine the question. @@ -209,7 +215,7 @@ public class ChatService(IChatCompletionService chatCompletionService, Tokenizer } chat.AddUserMessage(prompt.ToString()); - return chat; + return (chat, settings); } private async Task UpdateCacheAsync(Guid conversationId, ChatHistory chat, CancellationToken cancellationToken)