發表文章

讓 LINE Bot 對談機器人顯示 "Loading..." 動畫

圖片
LINE 在日前推出了一個功能,恰恰好適合現在許多開發人員正在設計的 - 搭配LLM(大型語言模型AI) - 的 AI 對談機器人。 這個功能 ‘Display Loading Animation’ 讓開發人員可以在LINE Bot回覆訊息前,先出現個幾秒底下這樣的圖示: 這個圖示可以設定最長顯示時間,從 5~ 60秒 之間的5的倍數均可,時間到了,會自動消失。而即便時間還沒到,如果LINE Bot(不是用戶)後面有訊息發送,動畫也會自動消失。 要讓你的 LINE Bot 出現這樣的動畫非常簡單,我們的 LineBotSDK 也在第一時間更新了,使用我們 SDK 的 C# 開發人員,現在可將 LineBotSDK更新到最新版,即可輕鬆的透過底下的程式碼,來顯示出這樣的 Loading 動畫: using isRock . LineBot ; // create bot instance var bot = new Bot ( channelAccessToken ) ; // show ladding animation var ret = bot . DisplayLoadingAnimation ( chatId , 15 ) ; // display the result Console . Write ( ret ) ; 特別是對於現在需要串接LLM(大語言模型)的Chat Bot來說,呼叫LLM的API,回應時間往往都比較長,因此,我們在 Reply 用戶的訊息前,可以先讓用戶看到這樣的,然後再呼叫LLM相關的API(像是OpenAI API),如此一來,假設 LLM API 回覆的時間較長,用戶也比較不會有空等不耐煩的感覺。 而且這個指令執行之後,如果有 Push/Reply 的訊息發送,Loading 圖示就會自動消失,讓整個用戶的體驗不至於有突兀感。 適當的使用,會讓你的 Chat Bot 有更生動擬真的感覺,有需要的朋友可以立刻試試看。 Enjoy it. 😊

使用Qdrant向量資料庫實作語意相似度比對

圖片
什麼是向量資料庫? 在許多的AI實作當中,都有向量資料庫的使用需求。例如RAG(檢索增強生成)、或是資料的相關性比對、相似性搜尋…等,這些應用情境中,我們都會用到向量資料庫。 向量資料庫主要的任務,當然就是存儲和查詢向量數據。被儲存的向量數據通常是高維度的資料,以陣列(集合)的形式呈現。 例如,OpenAI就有提供一組Embedding API,讓我們可以把文字給向量化。你可以透過該 API,把一句話(一段文字)轉換成向量數據,類似底下這樣: OpenAI 的這組 Embedding API,在預設狀況下,會把資料轉成 1536 維度的向量數據,其背後的行為是把文字送給一個訓練好的模型,透過該模型跑出這組向量數據,再回傳給用戶。 然而,把一段文字給向量化的目的是什麼呢? 當我們把文字做了這種轉換後,在 1536 維度的座標空間(向量數據)中,愈相似的文字,透過Embedding API會得到距離愈接近的座標點,藉此,我們得以迅速的判斷兩段文字在語意上的相似性。 而向量資料庫中所謂的查詢功能,主要就是向量的檢索,像是『近鄰搜索(Nearest Neighbor Search)』,當用戶或應用程式提交一個向量查詢時,向量資料庫會幫我們找出資料庫中,與之最相似(接近)的向量座標點。 因此,開發人員只需要透過 Embedding API,把文字轉成向量,再把轉換好的向量座標值,儲存到向量資料庫之中,未來就可以透過向量資料庫來查詢相似(接近)的文字。 關於這個部分,如果讀者有興趣,前陣子有段網路上的影片把多維度向量資料庫的概念介紹的蠻清楚的: https://www.youtube.com/watch?v=W_ZUUDJsUtA https://www.youtube.com/watch?v=ct20Kv8yn0U 為何需要? 向量資料庫最實務上的應用,就是找到類似的特徵值。 例如,當我們把人臉的特徵值以向量資料的形式儲存到向量資料庫中之後,我們就可以透過資料庫本身提供的搜尋功能,快速地尋找出相似的人臉,這也是許多AI應用實現的基礎。 我們底下的程式碼範例,則是找出最接近的問題。(呃…什麼意思?🤔 請往下繼續看) 我們在建立對談機器人時候,常常需要讓機器人回答用戶的問題。這時,我們會讓用戶輸入問句,然後透過 Embedding API

極速ChatGPT開發者兵器指南 - 推薦序

圖片
這是出乎我意料之外的事情。 今(2024)年2月中旬的一個晚上,那時才開工沒多久,大家估計還在農曆年節的休假氣氛中。我邀請了本書的三位作者,一同來我的線上直播節目接受專訪。 談論的主題,當然是過去一整年資訊界無人可忽視的 --『生成式AI』。當天精彩的訪問與對談,在這邊我暫不贅述,有興趣的朋友可以在YT頻道搜尋 『.net walker - 與微軟AI MVP大神漫談生成式AI的發展與未來』,或掃描底下QR Code觀賞。 讓我出乎我意料的是,當天即時觀看的線上人數和日後點閱的人數,雙雙突破過去的紀錄,這還是在年假剛過、開工不久、加上沒有任何廣宣的狀況下。 當時,現場網友詢問問題之熱情,讓我和三位受訪者(也就是本書的三位作者),幾乎無法結束訪談,即便早已超過原本預定的受訪時間。 在節目現場,我的這三位好友,在我和線上網友的聯合提問夾擊之下,分享了生成式AI相關的許多重要技術概念,包含Embedding、RAG(檢索增強生成)、Semantic Kernel、向量資料庫…等,整個對談暢快淋漓、欲罷不能。 由於時間的限制,即便明知還有許多議題和網友提出的問題都還沒談到,身為主持人的我,也不得不讓三位作者暫時喘口氣。但讓人興奮的是,當天作者們分享的內容,以及後來來不及談論到的更多深入議題,都出現在您現在所看到的這本書當中。 這本書,有技術、有實務,而且有為數不少的實作範例,由三位身為微軟MVP、在AI領域首屈一指的專家們共同著作,相信對需要深入了解生成式AI應用與相關技術的你,是絕佳的選擇。 如果您遺漏了他們合著的上一本著作,這次,千萬別再錯過。 Microsoft Regional Director / Microsoft MVP / 光岩資訊資深技術顧問 董大偉

周末讀書會 - 一如既往

圖片
一般來說,我都是看完整本書之後,才會決定要不要推薦,能讓我還沒看完就忍不住推薦的書極少。 但『一如既往』,就是這極少中的之一。 這本書的主題很難界定,你既可以說它是在談投資、也可以說他在談經營或企管、有些內容說的是競爭、但有時候你會覺得他講的是人生。 然而重點在於,這本書寫得非常好看。 我超愛的科幻小說家倪匡,曾說過:『好看的小說非常簡單,必定要有豐富的情節、鮮活的人物,小說寫得不好看,裏面有再多的學問、道理、藝術價值,都沒有用。』 一如既往,這本書的作者厲害之處,就是他能夠把每一篇都寫得環環相扣、異常好看,然而即便我知道每篇文章的pattern,想要模仿也是很難(這是個苦功來著)。 基本上那個pattern就是…以引人入勝的故事開頭,使用對照法讓故事撐托出主題,以極具說服力的文字或數據讓主題凸顯出價值,讓讀者有所收穫,最後在最短的文字內把一篇文章總結,然後預告下一篇作者想要接著談論什麼。 就這樣,你會一篇接著一篇,不由自主的閱讀下去,每一篇,你都會有一些驚訝、會有一些省思、接著會有一些take a way。 整本書,看似信手拈來、行雲流水,一氣呵成。但我知道,這是精心設計與編排後的結果。 一本書,最要緊是好看。 好看,讓人讀得下去,裡面豐富的內容才對身為讀者的你有意義。 『一如既往』這本書做到了,而且做得很徹底。 我快看完了,看完之後,如果有時間,我還想針對裡面某幾篇特別分享,如果你等不及,不妨先找來看看。

使用Azure AI Question Answering 快速建立客服機器人

圖片
還記得疫情那時候嗎? 有一段時間,醫療院所內的護理師面對應接不暇的來電,都是為了詢問跟疫苗有關的問題。像是: 疫苗施打的順序? 何時可以輪到我? 如果有過敏該如何選擇? 注射時應該要注意些甚麼? 我能不能不打疫苗? 諸如此類的詢問,塞爆了正常的電話掛號系統,導致許多真正需要幫忙的病患,無法得到該有的醫療資源以及諮詢,而護理師也無法專注於本來應該進行的護理工作。 這時,有些醫院開始導入對談機器人,透過手機APP或是網頁,可以讓一般民眾詢問疫苗相關的問題,並且提供正確的回覆。 當時,還沒有 ChatGPT 這樣的大型語言模型,醫院的資訊單位也不是AI領域的專家,要如何在極短的時間內,建構出一個可以準確回答用戶疫苗相關QA問題的對談機器人? 來幫助醫院在面對突乎其來的詢問電話時,可以透過分流來舒緩客服壓力? 答案,就在底下這個影片裡。我們從這個影片中可以看到,要如何在幾分鐘內,將既有的 知識庫 轉換成對談機器人,讓用戶可以直接透過網頁或手機問問題: 底下這個影片,加碼介紹如何把這個QA對談機器人,變成LINE Bot(也就是LINE官方帳號),讓用戶只需要用LINE就可以直接得到答案: 參考 課程: https://www.studyhost.tw/NewCourses/LineBot

使用 GitHub Copilot 建立單元測試

圖片
過去,只要上到 DevOps 課程,我就會強調單元測試在 CI/CD Pipeline中的重要性,絕對是屬於必須的(must have)。自動化頻繁交付想要不斷的交付(產生)價值,而不是不斷的產生bug,那單元測試絕對不可或缺。 你可能會想,那最近幾年,敏捷開發與DevOps這麼普及,大家都號稱能夠頻繁交付,那想必單元測試實施的比例肯定也很高,對吧? 答案是:『不,並沒有』。 因為,開發團隊不寫單元測試的理由,比寫單元測試的理由實在多太多了,例如: 測試程式本身需要花額外的時間 寫功能/趕進度 的時間都不夠了,怎麼有時間寫單元測試 不是每一個人都知道怎麼開始寫 方法(Mrthod)或類別的 相依性/耦合度 太高,難以撰寫單元測試 團隊中沒有這個氛圍,推動沒多久就無疾而終 PM或老闆不認為單元測試有價值 … 隨手都可以舉出一大堆,這些都是上課時問學員,學員真實的回答。沒辦法,每個團隊都有各自難念的經,我尊重。 不過,那是去年。 今年開始,有一個非常大的理由,讓我覺得,可以重新要求開發人員,把 Unit Test 的建立視為標配,並且放入每一個 CI Pipeline當中。 沒錯,又是AI。 現在,透過 GitHub Copilot 你可以更輕鬆的建立單元測試,你可以用 GitHub Copilot 幫你產生測試案例,也可以用 GitHub Copilot 幫你重構,或是調整主程式,以配合單元測試的運行… 過去覺得需要花費大把時間、耗費許多工夫的作業,如今 GitHub Copilot 可以幫我省去近一半的時間。卡關不知道該怎麼做的時候,還能跟 GitHub Copilot Chat 聊聊,技術問題迎刃而解。 我底下錄了一段影片,展示了如何使用 GitHub Copilot 建立單元測試。如果,你的團隊過去也屬於(有諸多原因導致)無法傳寫單元測試的一族,不妨看一下影片,或許在新的一年,將有不同的可能性出現? 參考 課程: https://www.studyhost.tw/NewCourses/ALM

在POC或迷你專案中使用 LiteDB

圖片
3/24,我發了篇FB 貼文 ,提到我很久沒有在撰寫範例的時候使用關聯式資料庫了。這不是因為關聯式資料庫不好,而是使用場景和情境的問題。 大部分的教學文章或範例,為求讓主題專注不要失焦,我會讓範例盡可能地簡單。例如,用Console App 取代 Web 架構,用file取代DB。這樣學員的進入障礙會再降低一點,畢竟,我們不能假設每一位學員都對MVC框架或是資料庫存取的ORM有認識。 那篇貼文得到不少迴響,其中有位讀者建議,也可以考慮用 LiteDB ,我當時回覆說我會找個時間來試試看。既然說了出口,肯定是必須要測試一下的。 LiteDB 技術上來說,LiteDB 是一個嵌入式的 NoSQL 資料庫,特別是針對 .NET 開發者設計。其本質上是一個檔案,但它提供了類似於傳統關聯式資料庫管理系統的功能,包括存儲、檢索、更新和刪除資料操作。LiteDB 以單一檔案的形式儲存在專案資料夾中,這使得它非常適合於輕量級應用。不管是desktop app、mobile app或任何需要資料庫但又不希望安裝重量級資料庫伺服器的情境,都很適合。 你只需要針對專案安裝 NuGet 套件就可以使用: dotnet add package LiteDB 不需要伺服器、不用管帳號密碼、可以跨平台,所有的資料都存儲在單一檔案,便於管理和分發、佈署。簡單的說,當我寫好範例,在裡面放一些資料,丟上GitHub,你不管在哪一個平台(Windows, Linux),Clone下來之後,無須任何配置、設定,就可使用,資料也不會消失,無須重建。 確實,這對做範例非常方便。 你可以看看我在GitHub上的這個範例: git clone https://github.com/isdaviddong/TestLiteDB.git 下載下來之後,無須任何設定,直接 dotnet run 就可以執行: 專案中,包含了一個MyData.db檔案,就是資料庫實際儲存的位置: 你可以透過底下這樣的程式碼,即可使用: var db = new LiteDatabase ( "MyData.db" ) var col = db . GetCollection < Person > ( "persons" ) ; 其

使用 Airtable 在小型需求上取代傳統資料庫

圖片
我好幾年沒有用傳統的關聯式資料庫了。 老實說,傳統的關聯式資料庫,其實對於教育訓練和小型的專案來說,是一種負擔。 如果你想讓學員清楚的掌握一門技術,就好比說,對談機器人的開發吧,在整個教學的過程中,若是範例用到SQL或MySQL資料庫,無疑是一種節外生枝,把問題變得更複雜。因為,在對談機器人當中,儲存只是一種迫不得已的額外需求,是枝微末節,而非對談機器人技術的主體。 同樣的,如果你做一個小型專案或POC的話,『儲存』也往往不是重點,儲存只是『必要之惡』。其實,若是從這個角度廣義的來說,軟體開發的GUI、資料庫,都只是細節(枝微末節),都應該要是可以隨時被抽換或取代的部分,而非系統核心。 一套軟體或解決方案的真正核心,是商業邏輯。它(商業邏輯)才是一個應用程式真正展現價值的部分。 我們把主題拉回來。所以,我最近這幾年在上課的時候,盡量不讓範例程式碼涉及資料庫存取,特別是關聯式資料庫的存取。因為這對讀者或學員來說,變成了另一種必須學習的負擔。 但說的容易,如果範例中有碰到需要儲存資料的時候該怎麼辦呢? 有沒有什麼最簡單的儲存機制可以在程式碼中替代傳統資料庫? 這也是我最近幾年寫範例的時候,常常碰到的問題。因此,我特別花了一段時間,找看看有沒有什麼好用的『類』資料庫儲存體? 最後,我選擇了 Airtable。 Airtable Airtable 是一個靈活的雲端資料庫產品,結合了資料庫的功能和電子表格(data grid)的簡易性。它允許用戶以視覺化的方式存儲、組織和協作各種資訊: 白話一點說,就是它可以很自由的在Web畫面上設計欄位和維護(輸入、編輯)資料。 對我來說,它還有另一個重點,就是它擁有非常簡單的REST API,透過呼叫API就可以直接來讀寫資料。 它的API在使用上很簡單,只需要在設計好資料表之後,透過 https://airtable.com/create/tokens 站台建立一個 PAT(Personal Access Token): 建立PAT的時候,可以選擇要針對所有資料表,還是特定資料表,要只給這個token 讀取(Read)權限,還是要寫入(Write)權限: 有了token之後,可以透過很標準的REST API呼叫,進行連線的建立與資料的寫入: string ID = "👉air_tabl

Azure Web App 的基本驗證被停止了!

圖片
如果先不管自動化CD Pipeline,習慣使用Visual Studio的開發人員,若要對 Azure Web App 佈署網站,大概最喜歡採用的佈署方式,莫過於『發行設定檔』。這一招用很久了,直到最近你可能會發現,建立Azure Web App 的時候,會看到底下這樣的警告: 這也意味著,你無法下載發行設定檔了: 如此一來,Visual Studio 當然也無法佈署了! Azure 這個調整,當然是為了安全性提升。 使用基本驗證不安全嗎? 對,相對來說是的。 因為基本驗證只透過一組帳號密碼來做佈署,再加上發行設定檔還把這組帳密直接給放在裡面,誰拿到了這組帳密都能夠更新網站,沒有進一步的身分驗證,對一般個體戶小型專案的開發人員來說還行,但對企業來說顯然不是一個理想的選擇。 好吧,但這樣比較簡單啊。假設,你只是要快速的進行佈署,我們是否可以先把這個被 disabled 掉的功能暫時開啟呢? 可以的,在 Azure WebApp 的組態設定,將『基本驗證發佈認證』給開啟即可: 如此一來,發行設定檔又可以下載了(記得把網站 reload 一下): 下載到發行設定檔之後,我們在Visual Studio當中可以透過底下這樣的方式佈署網站: 然後選擇剛才下載的發行設定檔即可。 這種佈署方式雖然方便,但就如同前面說過的,發佈的過程並沒有嚴謹的身分驗證,也不支援AAD帳號或是RBAC等權限配置。因此,短期暫時將傳統的基本驗證開啟,取得發行設定檔佈署即便可行,建議未來還是採用AAD(Entra ID)驗證是比較理想的做法:

Semantic Kernel Plugin 的錯誤處理

圖片
先前我們 提到了 透過Semantic Kernel,可以讓AI/LLM在與用戶對談的過程中,自動在需要的時候去呼叫 PlugIn 物件的方法(Method),特別的事情是,這個呼叫並非是我們寫程式去做的,而是 AI 自己做的,我們並沒有寫這部分程式碼的邏輯,我們寫的只是提示(prompt)而已。 那問題來了,如果不是我們寫程式去呼叫這個方法,而是AI自己去呼叫的,那假設,這個被呼叫的方法裡面發生了 Exception ,那會發生什麼事情!? 我們看底下這段程式碼: public class LeaveRequestPlugin { [KernelFunction] [Description("取得請假天數")] public int GetLeaveRecordAmount([Description("要查詢請假天數的員工名稱")] string employeeName) { isRock.LineBot.Bot bot = new LineBot.Bot(ChannelAccessToken); bot.PushMessage(AdminUserId, $"[action : 查詢 {employeeName} 假單]"); if (employeeName.ToLower() == "david") return 3; else if (employeeName.ToLower() == "mary") throw new System.ArgumentOutOfRangeException("無法取得假單資料"); else return 5; } (...略...) } 請注意上面這段查詢員工請假天數的程式碼,你會發現,我們刻意在程式碼裡面,加入了底下這段 code: (...略...) else if (employeeName.ToLower() == "mary") throw new System.Ar