和他的團隊交流後,我一直在想:傳統軟體公司該如何轉型 AI?怎麼找到合適的產品方向,又該從哪裡起步?我認為,首先要打破過去的產品思維。以往做軟體,常是先關起門研發產品,再找客戶銷售、交付;但 AI 應用仍在快速探索,沒有必要等產品成熟才行動。比起先做出一套完整產品,更重要的是找到真實場景與可行的解決方案。
第一步,讓客戶知道你正在做 AI。 可以透過短影片持續分享 AI 技術、產業觀點、探索過程和初步成果。這不只是為了獲取流量,更是為了讓老客戶、老朋友更新對你的印象。否則,即使他們有 AI 需求,想到的可能仍是你過去提供的 ERP、SRM 等傳統軟體,而不會第一時間找你。起步時,不必急著把產品打磨到完美,先讓客戶看見你、想起你。
第二步,連結夥伴,不必事事自行研發。 如果目前沒有自己的 AI 產品,就多認識做 AI 的朋友,連結產品與技術資源。只要別人的產品能解決客戶問題,就可以協助引進與推廣。這既幫助客戶,也支持合作夥伴;更重要的是,你能參與 AI 專案從需求辨識、方案設計到落地實施的過程。這些經驗會反過來幫助你改進產品,甚至發現新的方向。因此,不必因為想守住客戶資源,就錯過合作機會。
第三步,走進客戶現場,先理解問題。 拜訪合作多年的客戶,不一定要帶著產品,也不一定每次都要談成生意。可以多問問:哪些工作每天都在重複?哪些經驗會隨著員工離職而流失?有價值的 AI 場景,往往藏在業務人員日常的困擾裡,而不是坐在辦公室就能想出來。一次現場交流未必立刻帶來訂單,卻可能讓你找到真正值得解決的問題。
usingMicrosoft.Agents.AI;usingMicrosoft.Extensions.AI;usingOpenAI;usingOpenAI.Chat;usingSystem.ClientModel;usingSystem.ComponentModel;usingSystem.Text;usingSystem.Text.Json.Nodes;namespacecsFunctionCallingAgent;internalclassProgram{privatestaticreadonlyHttpClientHttp=new();privatestaticint_toolCallCount;staticasyncTaskMain(string[]args){Console.OutputEncoding=Encoding.UTF8;varapiKey=Environment.GetEnvironmentVariable("AzureOpenAI_Key");varendpoint=Environment.GetEnvironmentVariable("AzureOpenAI_Endpoint");varmodel="gpt-5.6-luna";if(string.IsNullOrWhiteSpace(apiKey)||string.IsNullOrWhiteSpace(endpoint)){Console.WriteLine("請先設定環境變數 AzureOpenAI_Key 與 AzureOpenAI_Endpoint 後再執行。");return;}IChatClientchatClient=newChatClient(model,newApiKeyCredential(apiKey),newOpenAIClientOptions{Endpoint=newUri(endpoint)}).AsIChatClient();AIAgentagent=newChatClientAgent(chatClient,"你是穿搭顧問,用繁體中文精簡回答。需要天氣資訊時請使用工具查詢,不要自己猜測天氣。",// 系統提示詞"穿搭顧問",// 代理名稱null,// 代理描述[AIFunctionFactory.Create(GetWeatherForecast)]);// 交給代理的工具,要不要呼叫由模型決定string[]questions=["我明天要去台北上班,該穿什麼?","白色襯衫搭什麼顏色的褲子好看?","我明天早上在台北、晚上到高雄,要帶哪些衣服?",];Console.WriteLine($"使用的模型:{model}");foreach(varquestioninquestions){_toolCallCount=0;Console.WriteLine();Console.WriteLine($"❓ {question}");varresponse=awaitagent.RunAsync(question);Console.WriteLine(response.Text);Console.WriteLine($"(本題呼叫工具 {_toolCallCount} 次)");}}[Description("查詢指定城市在今天起第幾天的天氣預報")]privatestaticasyncTask<string>GetWeatherForecast([Description("城市的英文名稱,例如 Taipei、Kaohsiung")]stringcity,[Description("從今天起算第幾天:0=今天,1=明天,最多 6")]intdaysFromToday){_toolCallCount++;Console.WriteLine($"🔧 呼叫 GetWeatherForecast(city: {city}, daysFromToday: {daysFromToday})");daysFromToday=Math.Clamp(daysFromToday,0,6);// 1. 城市名稱 → 經緯度vargeo=JsonNode.Parse(awaitHttp.GetStringAsync($"https://geocoding-api.open-meteo.com/v1/search?name={Uri.EscapeDataString(city)}&count=1&language=zh"));varplace=geo?["results"]?[0];if(placeisnull){return$"找不到城市 {city}";}// 2. 經緯度 → 每日天氣預報varforecast=JsonNode.Parse(awaitHttp.GetStringAsync($"https://api.open-meteo.com/v1/forecast?latitude={place["latitude"]}&longitude={place["longitude"]}"+$"&daily=weather_code,temperature_2m_max,temperature_2m_min,precipitation_probability_max"+$"&timezone=auto&forecast_days={daysFromToday+1}"));vardaily=forecast!["daily"]!;vari=daysFromToday;return$"{place["name"]}{daily["time"]![i]}:{WeatherText((int)daily["weather_code"]![i]!)},"+$"氣溫 {daily["temperature_2m_min"]![i]}~{daily["temperature_2m_max"]![i]}°C,"+$"降雨機率 {daily["precipitation_probability_max"]![i]}%";}// WMO 天氣代碼 → 中文privatestaticstringWeatherText(intcode)=>codeswitch{0=>"晴",1 or 2=>"多雲",3=>"陰",45 or 48=>"霧",>=51 and <=57=>"毛毛雨",>=61 and <=67=>"雨",>=71 and <=77=>"雪",>=80 and <=82=>"陣雨",85 or 86=>"陣雪",>=95 and <=99=>"雷雨",
_ =>"未知",};}
這個程式一開始將會讀取 API Key 與服務端點的數據,接著如同前面的範例相同,先建立一個 IChatClient 物件。接者建立 AIAgent 物件,這裡將會指定系統提示詞為 "你是穿搭顧問,用繁體中文精簡回答。需要天氣資訊時請使用工具查詢,不要自己猜測天氣" 其中,最後一句話,會讓代理人物件,嘗試到這個系統內,找到合適的工具來取得天氣資訊,而不是自行猜測。
從這個系統提示詞可以看出,這並不是僅僅想要讓 AI Agent 來使用工具來回答內容,而是想要透過工具來取得正確的天氣資訊,並且使用這些天氣預報資訊,讓 AI 模型產生出需要穿搭的建議。這樣的設計可以確保 AI 代理在提供穿搭建議時,所依據的天氣資訊是準確的,而不是憑空猜測,提升了建議的可靠性與實用性。
當在建立這個 AI Agent 的時候,有將 [AIFunctionFactory.Create(GetWeatherForecast)] 傳送給 ChatClientAgent 建構函式內,這個參數為讓 AI Agent 知道與註冊一個可用的工具函式,讓 AI 在需要天氣資訊時,可以呼叫這個工具來取得正確的天氣資料。
這樣的設計讓 AI Agent 能夠在對話過程中,根據使用者的需求,動態地呼叫工具函式來取得最新的天氣資訊,並將這些資訊整合到回應中,提供更精準且實用的建議。
AIFunctionFactory.Create 這個方法宣告在 Microsoft.Extensions.AI 命名空間中,用來建立可供 AI Agent 呼叫的工具函式。而傳入的引述為 GetWeatherForecast 這個方法,該方法的程式碼如下: