千呼萬喚的 Assistants API 終於趕在農曆年假期前一天上線了!我絕對不會說隔壁棚已經上線超過兩個月,趕緊記錄下來試用的心得。
Assistants API 這次增加了託管上下文的線程管理功能,終於不用再每次都把對話紀錄全部塞進 Prompt 了,同時也整合 Function calling、Code Interpreter 與讀取多種格式文件等功能,最後再加上允許圖表輸出,讓開發者可以輕鬆在應用中打造出個人助理。
這次參考了官方的範例程式,其中使用的是 Python SDK 與 2024-02-15-preview 的 API,並且結合目前工作上遇到的一個場景,來演示這次推出的新功能,完整程式碼歡迎查看下方 GitHub。
相關連結:https://github.com/charliewei0716/azure-openai-assistant-data-engineer
Assistants API 概念
在過去 OpenAI 的 API 一直都是無狀態的設計,所以如果希望 GPT 的回答是朔及前文的,就必須在每次的對話中,將所有歷史對話紀錄都塞進 API 內,常用的做法是塞入最新的 10 筆對話紀錄,以減少 Token 爆量的問題發生。
而 Assistants API 新增了 Thread 的概念,Thread 支援上下文的持久儲存,這使 API 變成是有狀態的,同時 Thread 將自動管理存入的對話紀錄,雖然這部份就像是黑盒子,官方並沒有明確說明對話的保留機制,但從此以後終於不用再自己搞個 DB 把對話都記錄下來,只需要一直無腦的新增訊息就好。
當一個 Thread 被建立後,可以將每一次對話視為一個 Run,其中我們可以定義 Function calling 與 Code Interpreter 兩類工具:Function calling 就像平常寫程式一樣,可以客製化編寫自己的邏輯,一般常用來做第三方串接,讓自然語言可以轉化為實際的動作;另一項 Code Interpreter 會在背後啟動一個 Python 沙盒環境,Assistants API 會在環境中編輯運行程式碼,藉此提升程式碼回答的正確性。而最終在每一次的 Run 中,GPT 將根據對話自動判斷是否呼叫這些定義好的工具。
同時 Assistants API 也接受非常多類型的文件上傳,一樣只要在對話內容中,被 GPT 認為是與文件相關的,他就會自己去參考這些文件內容,並給出相應的回覆。
接著我們將會舉一個情境範例,進一步了解對話的生命週期與各項功能。
情境說明
我們將使用 Assistants API 搭建一個資料工程師助手,這位助手具備以下功能:
- 分析上傳的 CSV 文件並給出其見解
- 根據需求繪製視覺化報表
- 協助使用者將這個 CSV 文件在 Databricks 上建立一張 Table
事前準備
主程式是一個 Jupyter Notebook,可以直接在我的 GitHub 上找到,接著你還需要以下:
- 一個可以使用 Azure OpenAI 的 Azure 訂閱
- 佈署一個符合地區規定可使用 Assistants API 的模型,範例中使用的是瑞典中部的 gpt-4-1106-preview
- 可以執行 Jupyter Notebook 的環境,歡迎直接使用儲存庫中的 Codespaces,適合懶得自己處理套件版本的朋友
建立 Azure OpenAI client
重要的第一步,使用 Azure OpenAI 的各項連線資訊建立 client,這邊的 API 版本是 2024-02-15-preview。
Function calling
首先編寫一個模擬在 Databricks 建表的 Function,直接視需求寫邏輯就好,這邊沒有太多規定的寫法
根據需求將 Function 設定進 Function calling,整理成規定格式的 tools_list。
需要注意的是目前如果沒有包含 {"type": "code_interpreter"} 會直接報錯,也就是強制使用 Code Interpreter,還不確定是不是正常設定。
上傳檔案
這邊我們會上傳一個帶有風力發電廠資料的 CSV,後續交由 GPT 來幫忙分析這組資料。
每個文件上傳完成會分配一組 id。
建立 Assistant and a Thread
接著就能用以上定義好的各項資訊來建立 Assistant,其中 instructions 可以當成 system prompt 來使用,其他東西就依序照著填入,再建立 Thread 就好。
處理 Function calling
這邊編寫一個處理 Function calling 的函數,方便後續對話時重複使用。
基本上就是用 Assistants API 判斷出的 input 放入 create_databricks_table 完成建表動作,至於何時會使用到這個函數,我們後面會看到。
呈現對話與圖片
一樣編寫成函數,方便後續對話時重複使用。這邊看起來似乎複雜了一點,但其實只是做了一些文字與圖片的格式整理,建議直接用就好有需要再來看這段。
處理對話
最後這個就是主程式了,他會往 thread 內放入一句對話並開始執行 run,因為目前執行一次 run 可能會到 1 分鐘以上,所以這邊就先簡單用 while True 與 time.sleep(5) 處理了。
比較重要的兩個狀態,當狀態是 completed 會去呼叫呈現對話與圖片的函數 format_messages,狀態是 completed 會去呼叫處理 Function calling 的函數 call_functions。
實際使用
完成以上,我們終於可以使用 Assistants API 來跟助手對話了,直接呼叫主程式 process_message。
這是什麼資料?
測試是否可以讀取上傳的檔案。
幫我畫一張漂亮的圖表
測試圖表輸出的功能。
幫我在能源 schema 上建立一張 Databricks table
測試 Function calling。
用 PySpark 查找表中前十筆資料
測試 Code Interpreter。
結論
Assistants API 可說是階段性的集大成者,2023 一整年我們可能都在搭建整合 ChatGPT 的應用,並且花費大量時間在歷史對話儲存、資料上傳後的 Embedding 與向量搜尋,但 Assistants API 的出現短短數行程式就能達到類似效果,看起來又再次打破了整個架構。
但我認為目前還沒必要把辛苦建立的系統全部打掉重練,一方面 Assistants API 還在預覽階段本來就不建議整進上線系統,再加上有了 Function calling 和 Code Interpreter 等功能後,本來 GPT-4 就被詬病的反應時間似乎又更難處理了,對於一些即時性需求這樣的反應速度還不是能被接受的。
留言
張貼留言