Hello, 各位 iT 邦幫忙 的粉絲們大家好~~~
在本系列文會展開使用 Avalonia UI 技術所建立的 TopAOAIConnector App 。由於使用 Avalonia UI 可以很快速的進行各平台的 桌面 應用程式開發,並且透過此 TopAOAIConnector App 來串接 Azure OpenAI Service 時所需的功能研究。
本篇是 就是要來點 A.I. 的 TopAOAIConnector App 系列文的 EP15。
在 EP 13 成功的可以跟 AOAI Service 的 "聊天" 互動後,要完成 EP 14 的方式其實不難。
來回顧一下 EP 13 跟 AOAI Service 互動所做的事情。
首先在 Utilities 當中設計的 AoaiServiceHelper 類別:
internal class AoaiServiceHelper
{
static readonly string endpoint = AOAISettings.Instance.Endpoint!;
static readonly string key = AOAISettings.Instance.SecretKey1!;
static readonly string deployModelName = AOAISettings.Instance.DeployModelName!;
public static async Task<string> Go(string userMessage)
{
var azureOpenAIclient = new AzureOpenAIClient(new Uri(endpoint), new AzureKeyCredential(key));
var chatClient = azureOpenAIclient.GetChatClient(deployModelName);
var completionChat = await chatClient.CompleteChatAsync(
new List<ChatMessage>()
{
new UserChatMessage(userMessage)
});
var result = $"{completionChat.Value.Role}:{Environment.NewLine}{completionChat.Value.Content[0].Text}";
return result;
}
}
可以注意到:
var completionChat = await chatClient.CompleteChatAsync(
new List<ChatMessage>()
{
new UserChatMessage(userMessage)
});
所呼叫的 CompleteChatAsync 方法傳遞的參數是個 List<ChatMessage>,這就代表著呼叫 CompleteChatAsync 方法時可以傳遞多個 ChatMessage 進去,而 ChatMessage 又可以是:
在目前來講,上述五種 ChatMessage 的子類別,就會對應到要如何呼叫 CompleteChatAsync 的方式,也就代表著這次的對話將會帶入所建立的 GPT 模型 prompt 進去。
而別忘記 LLM 模型通常是沒有記憶能力的,所以每次對話必須把過去交談的資料也再帶回去當作 input。
所以就會變成這樣像 EP 13 結果,而我們如果把有輸入的 input 跟模型所回答的 output 不斷的串接到下一次送出的資料 input,就可以做出一些連續提問並產生有效回答的結果。
按照以上所說的概念,開始來實作吧~~~
首先將原本的 AoaiServiceHelper 類別設計中,設計一個型別為 AzureOpenAIClient 為 static 的 Instance 屬性,並將 Go 方法改變成下列撰寫:
static readonly AzureOpenAIClient _instance = new(new Uri(endpoint), new ApiKeyCredential(key));
static AzureOpenAIClient Instance => _instance;
public static async Task<string> Go(List<ChatMessage> chatMessage)
{
var chatClient = Instance.GetChatClient(deployModelName);
var completionChat = await chatClient.CompleteChatAsync(chatMessage);
var result = $"{completionChat.Value.Role}:{Environment.NewLine}{completionChat.Value.Content[0].Text}";
return result;
}
改變處可參考下圖紅框:
再來回到 Views/ChatPageViewModel.cs 在 ChatPageViewModel 類別當中增加一個 List<ChatMessage> 欄位的設計:
private readonly List<ChatMessage> messages = [];
完成結果如下圖紅框:
並對 BuildAoaiResultToChatText 方法進行修正 (點 1):
private async Task BuildAoaiResultToChatText()
{
var assistantMessage = await Utilities.AoaiServiceHelper.Go(messages).ContinueWith(async task =>
{
var result = await task;
ChatText = $"{ChatText}{Environment.NewLine}{result}{Environment.NewLine}";
messages.Add(result);
});
}
在原本的 Send 方法除了改變對 BuildAoaiResultToChatText 方法的呼叫修正外,也增加紀錄到前面所宣告的 message (點 2):
messages.Add(textContent);
await BuildAoaiResultToChatText();
在原本的 Attach 方法也一樣,改變對 BuildAoaiResultToChatText 方法的呼叫修正外,也增加紀錄到前面所宣告的 message (點 1):
messages.Add(textContent);
await BuildAoaiResultToChatText();
但考慮到若上傳新的附加檔時,先前對於前一份文字檔的對話紀錄應該就無效,所以在 Attach 方法最一開始執行檢查一下紀錄,並變更 ChatText 的顯示 (點 2):
if (!string.IsNullOrEmpty(fileContent) && messages.Count > 0)
{
ChatText = $"{Environment.NewLine}{ChatText}{Environment.NewLine}=======Another Attach TextFile======={Environment.NewLine}";
messages.Clear();
}
所以這時候就可以來試試看效果囉~~~
以上完成!
下回見囉!