🚜iOS 本地 AI:用 LM Studio 把 AnyLanguageModel 接上本地 LLM
我們發現 AnyLanguageModel 還沒有 100% 實現 Foundation Models framework 的功能,但我們已經可以透過它替換成其他模型。本文以 LM Studio 的伺服器功能,讓 App 可以去呼叫 Mac 上的開源 LLM,生成結果。
這是踩坑 AnyLanguageModel 以來的第三篇。AnyLanguageModel 宣稱能從 import FoundationModels 無縫替換成 import AnyLanguageModel。
一般來說,這種語法及功能的完全相容套件,會被宣稱為 drop-in replacement。AnyLanguageModel 也確實朝這個目的在開發中。
不過,除了上一篇提到的 Identifiable 問題以外,它目前(0.5.2 版)還有多個問題,使我們無法做到 100% 替換成功。
當我們把 AIPlayground 0.2.0 版的 enabledTraits 加上 anyLanguageModelTrait(具體作法請參考前一篇文章)以後,會發現有幾個 build errors。
這些問題我們可以暫時繞過不管,但我還是列出來如下:
- 在
#Playground中,@Generablemacro 產生的 memberwise init 方法會無法使用。我已經回報了 Issue #74。這個問題會影響到我們的Prompt Builder.swift,或是在#Playground裡面新增範例Generabletype 的需求,workaround 就是搬到#Playground以外來寫 @Generablemacro 沒有支援PromptRepresentable,所以會無法放入PromptBuilderclosure@Generablemacro 沒有把 property 的 type 正確設定成Type.PartiallyGenerated。這個問題會影響到我們的extension CatProfiles.PartiallyGenerated: View實作- 傳入
SystemLanguageModel.default時,幾個 structured output 的範例會出現 type mismatch 的錯誤。也就是說,AnyLanguageModel還沒有做到完全複製 Foundation Models 該有的行為
除了前一篇提到的 Identifiable 問題我發了 PR、上述第一個問題有回報 Issue 以外,其餘問題我讀了程式碼以後,無法在短時間內解決,所以只好先修改 AIPlayground。當你在專案中看到 // XXX,就表示是 workaround。
AnyLanguageModel 目前仍在積極開發 structured output 與 @Generable 相關的功能。雖然上述問題說不定很快就能獲得解決,至少現在還沒。
那麼,到這篇文章發表為止,AnyLanguageModel 有什麼真正的實用性嗎?
有的。到目前為止,我們可以先暫時放棄 structured output。先來試試看串接第三方的模型,並且先專注在接收純文字的回傳。
讓我們先調整一下的 AIPlayground,好讓替換模型更方便。
讓 BenchmarkingView 支援顯示 Markdown 文字
讓模型生成的字串顯示在 SwiftUI 很容易,因為我們已經有 BenchmarkingView 了。
extension String: GenerableView {}
extension String: @retroactive View {
public var body: some View {
if let text = try? AttributedString(
markdown: self,
options: .init(interpretedSyntax: .inlineOnlyPreservingWhitespace)
) {
Text(text)
} else {
Text(self)
}
}
}
多數語言模型會回傳 Markdown 格式,所以如果字串能被正確解析,就照格式來顯示。
值得注意的是這行:extension String: @retroactive View
- 照理來說我們應該要
extension String.PartiallyGenerated,不過它們是相同的型別,所以就寫extension String即可 - 加上
@retroactive,是因為我們「宣告一個不歸我們掌控的 type,去 conform 某個不歸我們掌控的 protocol」。通常來說這是個壞主意,因為我們不知道那個 type 未來會不會也宣告支援該 protocol,並且有不同的實作,那就有可能會造成意外。Swift 6 開始會警告我們。要手動標記@retroactive才能消除警告。詳情請參考 SE-0364
除了增加顯示 Markdown 字串以外,我還進行了一些調整:
- 在
BenchmarkingView增加顯示錯誤訊息的功能 - 讓
BenchmarkingView與BenchmarkingGenerator支援傳入模型參數any LanguageModel,方便我們使用AnyLanguageModel提供的各種模型設定
以上範例程式碼的更新,我已經上傳到 AIPlayground 的 0.3.0 版了。
使用 LM Studio 作為本地 LLM 伺服器
為了讓讀者體會 AnyLanguageModel 替換成其他模型的效果,我認為最快速且免費的方式,是在 Mac 上安裝一個能執行本地語言模型的程式,並且作為本地端伺服器的方式來使用。
這次,我設計了一個 weak self podcast 節目的假想逐字稿生成範例。雖然我從來不會想要用 AI 工具來生成節目大綱,但是看看語言模型對於我熟悉的東西會生出什麼東西來,還滿好玩的。
讀者當然可以替換成自己想要的 instructions 與 prompt。
先看最終效果: