開始
幾個月前,在參加 Databricks 與 R 的工作坊時,我發現了他們的一些自訂 SQL 函數。這些特定的函數以 “ai_” 開頭,並且可以通過簡單的 SQL 調用來運行 NLP:
正面
> SELECT ai_analyze_sentiment(‘我很傷心’);
負面
這對我來說是一個啟示。它展示了在我們的日常工作中以分析師的身份使用 LLM 的新方法。到目前為止,我主要將 LLM 用於代碼補全和開發任務。然而,這種新方法則專注於直接使用 LLM 對我們的數據進行操作。
我第一個反應是嘗試通過 R 訪問這些自訂函數。通過 dbplyr,我們可以在 R 中訪問 SQL 函數,看到它們的運作非常棒:
mutate(
sentiment = ai_analyze_sentiment(o_comment)
)
#> # 來源: SQL [6 x 2]
#> o_comment sentiment
#> <chr> <chr>
#> 1 “, pending theodolites … 中立
#> 2 “uriously special foxes … 中立
#> 3 “sleep. courts after the … 中立
#> 4 “ess foxes may sleep … 中立
#> 5 “ts wake blithely unusual … 混合
#> 6 “hins sleep. fluffily … 中立
這種集成的一個缺點是,儘管可以通過 R 訪問,但我們需要與 Databricks 保持實時連接才能以這種方式利用 LLM,從而限制了能夠受益於此的使用者人數。
根據他們的文檔,Databricks 正在利用 Llama 3.1 70B 模型。雖然這是一個高效的大型語言模型,但其龐大的體積對大多數用戶的機器來說是一個重大挑戰,讓其在標準硬件上運行變得不切實際。
實現可行性
LLM 的開發正在迅速加速。最初,只有在線大型語言模型 (LLMs) 可以用於日常使用。這引發了公司在共享數據方面的顧慮。此外,使用在線 LLM 的成本可能是相當可觀的,按 token 收費可能會迅速累積。
理想的解決方案是將 LLM 整合到我們自己的系統中,這需要三個基本組件:
一個可以舒適地存放在內存中的模型
一個能夠達到足夠準確性的模型以進行 NLP 任務
模型與用戶筆記本之間的直觀介面
在過去的一年中,擁有這三個元素幾乎是不可能的。能夠存入內存的模型要麼不準確,要麼過於緩慢。然而,最近的進展,例如 Meta 的 Llama 以及像 Ollama 這樣的跨平台互動引擎,使得部署這些模型成為可能,為希望將 LLM 整合到其工作流中的公司提供了有希望的解決方案。
該項目
這個項目始於一次探索,源於我對利用“通用” LLM 產生與 Databricks AI 函數可比結果的興趣。主要挑戰是確定這樣的模型需要多少設置和準備才能提供可靠且一致的結果。
在沒有訪問設計文檔或開源代碼的情況下,我僅依賴於 LLM 的輸出作為測試基礎。這帶來了幾個障礙,包括可用於微調模型的眾多選項。即使在提示工程中,可能性也是廣泛的。為了確保模型不會過於專門化或集中於特定主題或結果,我需要在準確性和通用性之間找到微妙的平衡。
幸運的是,經過 extensive 測試,我發現簡單的“一次性”提示能夠產生最佳結果。所謂“最佳”,是指答案對於給定的行既準確又在多行之間一致。穩定性至關重要,因為這意味著提供的答案必須是指定的選項之一(正面、負面或中立),不需要任何額外的解釋。
以下是一個對 Llama 3.2 可靠工作的提示示例:
>>> 你是一個有用的情感引擎。僅返回以下答案之一:正面、負面、中立。無需大寫。無需解釋。答案是基於以下文本:… 我很高興
正面
作為旁註,我嘗試一次提交多行的嘗試未能成功。事實上,我花了大量時間探索不同的方法,例如同時提交 10 行或 2 行,並將其格式化為 JSON 或 CSV 格式。結果往往不一致,似乎並沒有加速過程到值得付出的努力。
一旦我對這種方法感到舒適,下一步就是將功能包裝在 R 包中。
方法
我的一個目標是使 mall 包盡可能“人性化”。換句話說,我希望確保在 R 和 Python 中使用該包能無縫整合數據分析師在日常工作中使用其首選語言的方式。
對於 R 來說,這相對簡單。我只需要驗證這些函數是否能很好地與管道 (%>% 和 |>) 一起工作,並且可以輕鬆地納入像 tidyverse 這樣的包中:
llm_sentiment(review) |>
filter(.sentiment == “正面”) |>
select(review)
#> review
#> 1 這是我用過的最好的電視。螢幕和聲音都很棒。
然而,對於 Python 來說,作為一種非母語的語言,這意味著我必須調整我的數據操作思維。具體來說,我學到在 Python 中,對象(如 pandas DataFrame)設計上“包含”轉換函數。
這一洞察使我調查 Pandas API 是否允許擴展,幸運的是,它確實如此!在探索可能性後,我決定從 Polar 開始,這使我能夠通過創建新的命名空間來擴展其 API。這一簡單的添加使得用戶能輕鬆訪問所需的函數:
>>> import mall
>>> df = pl.DataFrame(dict(x = [“我很高興”, “我很傷心”]))
>>> df.llm.sentiment(“x”)
shape: (2, 2)
┌────────────┬───────────┐
│ x ┆ sentiment │
│ — ┆ — │
│ str ┆ str │
╞════════════╪═══════════╡
│ 我很高興 ┆ 正面 │
│ 我很傷心 ┆ 負面 │
└────────────┴───────────┘
通過將所有新函數保留在 llm 命名空間中,用戶可以很容易找到並利用他們所需的函數:
接下來是什麼
我認為社區使用 mall 並提供反饋後,了解未來的發展將變得更加容易。我預計添加更多 LLM 後端將是主要需求。另一個可能的增強是當可用的新更新模型出現時,則可能需要更新針對該模型的提示。我在從 Llama 3.1 過渡到 Llama 3.2 時經歷了這一點。需要微調其中一個提示。該包的結構使得未來的這種微調將是包的附加功能,而不是對提示的替換,以保持向後兼容性。
這是我第一次撰寫有關項目的歷史和結構的文章。這一特定的努力因為 R + Python 和 LLM 的方面而如此獨特,我認為值得分享。
如果您希望了解更多關於 mall 的信息,請隨時訪問其官方網站:https://mlverse.github.io/mall/