LLM的知識有限,尤其即時資訊,例如股票價格,更是LLM無法做到的,所以這時就得讓模型接上外部資訊,讓AI取得正確資訊後,消化、整理並回應給使用者。本篇文將示範如何利用C#來實作。

假設我們要讓AI回答目前的天氣狀況,那我們就先寫一個外部函式:

[Description("取得指定城市的天氣資訊")]
public async Task<string> GetWeatherFromCityName(
    [Description("城市名稱,例如:台北")]
    string cityName)
{
    string weatherInfo = string.Empty;
    Console.WriteLine($"GetWeatherFromCityName function called with cityName: {cityName}");
    switch (cityName)
    {
        case "台北":
            weatherInfo = "台北目前天氣晴朗,溫度約25度。";
            break;
        case "台中":
            weatherInfo = "台中目前天氣多雲,溫度約28度。";
            break;
        case "高雄":
            weatherInfo = "高雄目前天氣雨天,溫度約30度。";
            break;
        default:
            weatherInfo = $"抱歉,我沒有{cityName}的天氣資訊。";
            break;
    }

    return weatherInfo;
}

為了方便示範,資訊皆為假資料,要注意的是,這個函式必須要設定AI可辨識的資訊,還有參數的意義,這樣AI才能了解如何使用它。

接下來是將外部函式掛載到AI上並下提示詞:

string model = "llama3.1:latest";
IChatClient ollamaClient = new OllamaApiClient(new Uri("http://localhost:11434"), model);
var aiFunctions = new List<AITool>();
aiFunctions.Add(AIFunctionFactory.Create(GetWeatherFromCityName));
IChatClient clientWithTools = new FunctionInvokingChatClient(ollamaClient)
{
    AllowConcurrentInvocation = true,
};
var chatOptions = new ChatOptions
{
    Tools = [AIFunctionFactory.Create(GetWeatherFromCityName)]
};
string userPrompt = "台北的天氣如何?";
string systemPrompt = "你是一個天氣資訊查詢助手,當使用者詢問天氣資訊時,請使用提供的外部函數來查詢天氣資訊,並將結果回覆給使用者。";
string fullPrompt = $"System: {systemPrompt}\n\nUser: {userPrompt}";
Console.WriteLine($"User: {userPrompt}\n");
await foreach (var update in clientWithTools.GetStreamingResponseAsync(fullPrompt, chatOptions))
{
    Console.Write(update);
}

因為有事先設定systemPrompt,所以它會依情況來決定要不要呼叫外部函式,另外選用的模型也很重要,目前微軟的phi4就不支援。

參考資料