[學習心得][OpenAI] 關於 OpenAI 新功能: Function Calling

image-20230615115340699

前提

OpenAI 在 06/13 發表了新的功能 “Function calling“,其實對 LLM 的開發上算是一個完整的新發展。 本篇文章將快速解釋一下這個更新將會帶來哪一些變革,並且也透過將 LINE 官方帳號的相關整合為案例,幫你打造一個旅遊小幫手。

關於 OpenAI 新的功能Function Calling 的細節

關於 “Function calling” 主要是拿來處理 Intent 的判斷,並且針對使用者的意圖給予相關的 JSON 輸出給開發者作為處理之用。 換成白話文來說,如果你今天想要做一個「天氣服務的 ChatGPT LINE Bot 」的話,那麼你該如何弄呢?

相關資料:

在 OpenAI Functions Calling 之前,要怎麼做?

根據 “DeepLearning 提供一堂很好的 Prompt Engineering for Developers” 有提到,你可能要這樣做:

你現在是一個協助抓取使用者資訊的小幫手,如果使用者詢問了某個地區的天氣。你就幫我把地區抓出來透過以下格式呈現。 
---
{
   "location": "xxxx"
}

image-20230615123019584

很多地方是聰明的,但是還是沒有處理非相關天氣詢問要拒絕。這裡可以透過 ChatGPT Share 查看結果。如果是一個 NLU 的小幫手,在這個情況下可能要回覆 { "location" : ""} 或是 NULL ,但是這樣會讓你的 Prompt 非常的冗長,而且通常很長的防禦Prompt (咒語)只能防禦一個階段。 那該怎麼辦呢?

那 OpenAI Functions Calling 怎麼幫助你呢?

這裡給一張流程圖: PlantUML

image-20230615152527422

第一步: 呼叫 Chat / Complete Function Calling

從文章內 “Function calling” 可以提供一個很簡單的範例,你可以發現以下得呼叫方式跟原本使用 chat/ completion 沒有差別,但是回傳資訊差很多了。

curl https://api.openai.com/v1/chat/completions -u :$OPENAI_API_KEY -H 'Content-Type: application/json' -d '{
  "model": "gpt-3.5-turbo-0613",
  "messages": [
    {"role": "user", "content": "What is the weather like in Boston?"}
  ],
  "functions": [
    {
      "name": "get_current_weather",
      "description": "Get the current weather in a given location",
      "parameters": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string",
            "description": "The city and state, e.g. San Francisco, CA"
          },
          "unit": {
            "type": "string",
            "enum": ["celsius", "fahrenheit"]
          }
        },
        "required": ["location"]
      }
    }
  ]
}'

也就是你可以透過詢問 "What is the weather like in Boston?" 讓 chatGPT 透過 gpt-3.5-turbo-0613 (這邊要強調是 GPT3.5) 的模型來跑分析,直接回答給你 JSON 檔案。

{
  "id": "chatcmpl-123",
  ...
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": null,
      "function_call": {
        "name": "get_current_weather",
        "arguments": "{ \"location\": \"Boston, MA\"}"
      }
    },
    "finish_reason": "function_call"
  }]
}

這時候, OpenAI 的 API 絕對 會回覆給你 JSON ,不需要透過各種黑魔防禦術(特殊 Prompt) 就可以達成。 如果他找得到相關資料,他就會幫你把資料抽取出來,並且放在 arguments 傳給你。

更多細節可以參考 API 文件的部分:

Function_call / string or object / Optional

Controls how the model responds to function calls. "none" means the model does not call a function, and responds to the end-user. "auto" means the model can pick between an end-user or calling a function. Specifying a particular function via {"name":\ "my_function"} forces the model to call that function. "none" is the default when no functions are present. "auto" is the default if functions are present.

跟原本 Prompt 的差別

那你會想說,這樣跟原本透過特殊的 Prompt 有什麼差別?

不會有 JSON 以外的回傳:

如果你這時候,忽然又插嘴一句說:「給我一首詩」,他還是會回傳給你 JSON 檔案。可能會告訴你沒有相關可以使用的 arguments。

多個 Functions 的處理:

這也是最強大的,最好用的地方。請查看

curl https: //api.openai.com/v1/chat/completions -u :$OPENAI_API_KEY -H 'Content-Type: application/json' -d '{
"model": "gpt-3.5-turbo-0613",
"messages": [
    {
        "role": "user",
        "content": "What is the weather like in Boston?"
    }
],
"functions": [
    {
        "name": "get_current_weather",
        "description": "Get the current weather in a given location",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "The city and state, e.g. San Francisco, CA"
                },
                "unit": {
                    "type": "string",
                    "enum": [
                        "celsius",
                        "fahrenheit"
                    ]
                }
            },
            "required": [
                "location"
            ]
        }
    },
    {
        "name": "get_current_date",
        "description": "Get the current time in a given location",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "The city and state, e.g. San Francisco, CA"
                },
                "unit": {
                    "type": "string",
                    "enum": [
                        "celsius",
                        "fahrenheit"
                    ]
                }
            },
            "required": [
                "location"
            ]
        }
    }
]
}'

你會發現,上面的程式碼有兩個 function 等著判別。 get_current_dateget_current_weather

  • 如果你的問句是: What is the weather like in Boston? ,那他就會回傳給你 get_current_weather,然後給你 location = Boston
  • 反之,如果你問句是: What time is it in Boston? ,那他就會回傳給你 get_current_date,然後給你 location = Boston

第二步 : 呼叫 3rd Party API

  • 這邊就跳過,可以是各種 Open API 去找資料。
  • 但是,可以透過 ChatGPT Plugin 的資料去找,將自己模擬成 ChatGPT Plugin 。

第三步: Send the summary to OpenAI

原本 https://openai.com/blog/function-calling-and-other-api-updates 資料有錯誒

image-20230615161410297

這裡要注意,如果你去找 Call 3rd API 故意回傳空的,代表 OpenAI 的 Summary 會沒有「參考資料」 參考以下: ` {“role”: “function”, “name”: “get_poi”, “content”: “{}”}` 。

也就是説,他會開始使用自己知道的相關資訊。(但是可能不是你期待的)。

curl https://api.openai.com/v1/chat/completions -u :$OPENAI_API_KEY -H 'Content-Type: application/json' -d '{
  "model": "gpt-3.5-turbo-0613",
  "messages": [
    {"role": "user", "content": "台北好玩地方在哪裡?"},
    {"role": "assistant", "content": null, "function_call": {"name": "get_current_poi", "arguments": "{ \"location\": \"台北\"}"}},
    {"role": "function", "name": "get_poi", "content": "{}"}
  ],
  "functions": [
    {
      "name": "get_current_poi",
      "description": "Get the current point interesting in a given location",
      "parameters": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string",
            "description": "The city and state, e.g. San Francisco, CA"
          }
        },
        "required": ["location"]
      }
    }
  ]
}'

這裡會收到回覆(Response):

{
  "id": "xxx",
  "object": "chat.completion",
  "created": 1686816314,
  "model": "gpt-3.5-turbo-0613",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "台北有很多好玩的地方,以下是一些推薦的地點:\n\n1. 101大樓:台北最著名的地標建築之一,是世界上最高的摩天大樓之一,可以在觀景台欣賞城市全景。\n\n2. 象山:台北的一座山峰,可以從山頂俯瞰整個城市,是非常適合登山和賞景的地方。\n\n3. 士林夜市:台北最著名的夜市之一,可以品嚐到各種美食和購物。\n\n4. 故宮博物院:收藏中國文化藝術品的博物館,展示了大量的歷史文物。\n\n5. 國立自然科學博物館:一個專門展示自然科學知識和展品的博物館,非常適合家庭和學生參觀。\n\n6. 北投溫泉:台北最著名的溫泉區之一,可以享受溫泉浸浴和放鬆身心。\n\n7. 龍山寺:台北最古老的寺廟之一,是信仰佛教的重要地方,也是一個參觀的旅遊景點。\n\n希望這些地方能讓您在台北有一個愉快的旅行!"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 104,
    "completion_tokens": 419,
    "total_tokens": 523
  }
}

本來以為 "finish_reason": "stop" 在回覆後檢查。並且設定, for loop 檢查,但是發現就算把資料傳空的給 OpenAI ,他也會根據他有的資訊開始回覆給你。

使用 Function Calling 需要注意的事情

1. Langchain 也可以用了嗎?

2. 使用 Func Calling 的語意理解能力沒有原來的 Chat 聰明

經過我自己觀察,透過 Func Calling 擷取出來相關 Argument 沒有以前直接在 ChatGPT 測試還聰明。 可能也因為 API GPT3.5 Turbo 其實也是不等於 ChatGPT 的。 所以在使用上,會需要常常去多問一次。來解釋相關內容,再來擷取出相關的 Arguments 。

3. Func Calling Summarized 如果沒資料, ChatGPT 會以他知道的來回覆。

Function Calling 可以帶來的應用

這裡快速摘要幾個可以帶來的新應用:

  • 自幹自己的 ChatGPT Plugin:
    • ChatGPT App在台灣上架!Plugins開放、一次搞懂怎麼用 上架後就受到很多人歡迎,但是他還是相對「少數」,因為需要額外付費 $20 。所以使用的人還是相對少。
    • 透過 Function Calling 就可以打造出自己的 ChatGPT Plugin 在你喜歡的平台(LINE 官方帳號, slack …)
  • 更聰明的 Intent 識別機制 :
    • 因為這個 API 的速度還蠻快的,回覆的 token 也都不多。
    • 作為 NLU 的識別機制會相當的實用。並且可以確保回覆的 JSON format 相當的精確。

[學習心得][Golang] 透過 ChatGPT 來做 REGEX 的事情

image-20230611001729736

前提

大家應該都跟我一樣,經常使用 ChatGPT 來協助一些 coding 上的問題。尤其是對於 Regular Expression 的問題。最近在處理上發現,需要透過「正向表列」,而非跟他講哪些不可以的方向比較容易成功。也應該說, Regular Expression 本來就要透過正向表來才對。

原本:

// AddLineBreaksAroundURLs takes a string as input, finds URLs,
// and inserts a newline character before and after each URL.
// It returns the modified string.
func AddLineBreaksAroundURLs(input string) string {
	re := regexp.MustCompile(`(https?:\/\/[^\s\p{Han}]+)`)
	return re.ReplaceAllString(input, "\n$1\n")
}

發現無法處理:

 https://voyager.minedojo.org/。

當我發現我一直跟 ChatGPT 講要排除 ` https://voyager.minedojo.org/。` 這個案例的時候,往往會一直卡住無法向前。 但是寫多個測試案例倒是真的蠻好的。

Unit Testing code

func TestAddLineBreaksAroundURLs(t *testing.T) {
	tests := []struct {
		input    string
		expected string
	}{
		{
			input:    "Check out this website https://example.com and this one http://another-example.com",
			expected: "Check out this website \nhttps://example.com\n and this one \nhttp://another-example.com\n",
		},
		{
			input:    "Here is an URL with dot at the end https://voyager.minedojo.org/。",
			expected: "Here is an URL with dot at the end \nhttps://voyager.minedojo.org/\n。",
		},
		{
			input:    "This is another test 可在https://voyager.minedojo.org/上訪問。",
			expected: "This is another test 可在\nhttps://voyager.minedojo.org/\n上訪問。",
		},
		// Add more test cases here as needed
	}

	for _, tt := range tests {
		res := AddLineBreaksAroundURLs(tt.input)
		assert.Equal(t, tt.expected, res, "Should correctly insert line breaks around URLs")
	}
}

正面表列

後來決定,透過正面表列來解決這個問題。

// AddLineBreaksAroundURLs takes a string as input, finds URLs,
// and inserts a newline character before and after each URL.
// It returns the modified string.
func AddLineBreaksAroundURLs(input string) string {
    re := regexp.MustCompile(`(https?:\/\/[\w\/\?\&\.\-]+)`)
    matches := re.FindAllString(input, -1)
    for _, match := range matches {
        input = strings.Replace(input, match, "\n" + match + "\n", 1)
    }
    return input
}

大家可以透過以下方式分享 ChatGPT link

image-20230611002225533

[TIL] 關於 WWDC 2023 身為開發者你應該知道的事情

image-20230606091609243

我如何看待 WWDC23 ?

身為技術研討會主辦人,我看的是:

  • 整體錄影方式與收音技巧
  • 每一個講者的職稱(可以看出內部分工與架構)
  • 平台想要規劃出的生態圈

職稱相關

image-20230606172229878image-20230606172232338

應該跟許多公司一樣:

  • Engineering Progam Manager - 技術專案經理
  • Engineering Manage - 技術開發的經理

職稱其實也代表部門的多寡,對外部而言很嶄新的 visionOS 部門卻有那麼多清楚分工,而且能演講的人還蠻多的。不愧是 Apple 。

硬體相關

  • New Mac Studio 可以有六顆螢幕(原來之前的不行啊?!)

iOS 17 帶來軟體開發新變化

Name Drop 近場溝通新應用

image-20230606094035126

  • 取代掉所有名片應用 (LINE OA 其實有類似做法)
  • 不知道會用到哪個 SDK ,應該會開放給其他 App 使用。

更智能的鍵盤輸入

Image

可能是使用 local 「In-line predictive text API」

Image

TV OS 相關變革

透過 iPhone 直接在 Apple TV 開會

image-20230606114817277

image-20230606114820316image-20230606114822745

走 Continuity Camera API

Vision Pro 帶來的軟體開發變化

img

(要接線~~~~~ Orz)

image-20230606120805201

果然要另外接電池

image-20230606121309156

Apple Vision Pro 帶來新的生物識別系統「Optic ID」

image-20230606151548290

可能帶來影響:

  • 虹膜辨識會變成是基本 OAuth 的認證設備(搭配 Passkey (a.k.a. FiDO2)
  • 比起 WorldCoin 可能因為 AirDrop 產生盜用 ,但是 Vision Pro 更可以取得更多人的虹膜資訊。
  • 雖然依照 Apple 的個性,不可能有任何取得方式。但是代表 Optic ID 可以更加的準確, Passkey 的未來更令人期待。

iOS SDK

Accessibility SDK

image-20230606153541003

Privacy API

image-20230606153526487

[TIL] 換 iPhone 需要注意的小事項

image-20230604204741307

為何更換手機

最近因為要出國,因為讓小孩子避免走失。買了 Apple Watch ,卻發現沒有辦法漫遊。只好弄一隻支援 ESIM 卡片的手機給他。 這樣一來,最方便的方式就是把我的手機(iPhone XR) 給他,然後我換一隻最新的 iPhone 14 Pro (明明 15 就快出了)

大部分的軟體使用「iCloud 備份與復原」應該可以搞定。

iPhone 系統軟體,需要注意的部分

  • 舊手機:

    • 記得把 Find My Device 關閉
    • 記得登出 iCloud (先將以下都做完,先將以下都做完,先將以下都做完)
  • Apple Watch

    • 需要先解除配對(就算忘記也沒關係,就重新配對洗掉)
  • Apple Pay

    • 全部要重新認證(到新手機)

    • Apple Watch 的 Apple Pay 也要重新認證(也是在新手機上操作)

不要急著洗掉就手機 iCloud 備份與復原後,有一些 App 可能需要他。

大部分的應用程式都可以走 iCloud 復原來安裝(開啟的時候,也通常可以無痛轉移)。但是有一些應用程式需要舊手機轉換。

  • Steam App
    • 需要舊手機認證,才能轉換。
  • WeChat
    • 一樣,需要舊手機掃描 QR-Code
  • VPN 軟體
    • 每個公司可能不同,有的管制更嚴格。
  • LINE 的部分,完整可以參考【LINE換機官方懶人包】帶您一步一步操作~ iOS與安卓都適用
    • 舊手機:
      • 先去備份起來(可以透過 iCloud)
      • 要確保有備份完整,確保有備份完整,確保有備份完整
    • 打開手機裝 LINE
      • 掃描舊手機 QR Code 登入,並且轉換手機。
      • 這時候,選擇從備份恢復。
      • 如果,發現沒有完整恢復回來?(也就是備份有失敗)
        • 想要打開舊手機,會發現已經轉換過來,無法開啟。
        • 刪除舊手機的 LINE ,重新安裝。
        • 重新以上步驟,將新手機帳號轉換回來就手機。
        • 這時候發現對話都回來了,再來重新備份一次。這次要注意有沒有備份完成。
        • 然後重複手續,轉換到新手機。

大概就這樣,本來以為換手機很方便。結果也是卡蠻久,最重要的還是 LINE 卡住(嗚著臉)。

[TIL] Microsoft Build 2023 Day2- 資訊整理

image-20230525100950428

影片:

(官方直播,可能會下架)

Plugin 會是新世代的 Fontend

前一天 CTO Kevin Scott 在 “The era of the AI Copilot”

image-20230525101053577

image-20230525102351165

關於 IDE 對於 Plugin 開發的支持

image-20230525134906708

  • Web IDE 支援很快速建立 Copilot Plugin

這裡有個 Jira Copilot Plugin 案例

image-20230525135841131

image-20230525135904283

image-20230525135931099

商業用語部分 - Syntex Plugin

image-20230525140354258

image-20230525140413639

  • Docu sign flow with Copilot

Copilot 總結

image-20230525140520001

關於 Plugin - Developer Success

image-20230525140619283

  • Productivity:

    • 完整的說明,有相關的 “Team Toolkit”
    • 有個人化體驗
    • 可以很方便開發跟 Deploy

    image-20230525140815459

Dev Home: 快速建置開發者的相關環境

image-20230525142557183

  • 透過帳號登入
  • 相關設置都有
  • 今天有 Preview 版本在 Windows Store

Build and maintain your company Copilot with Azure ML and GPT-4 | BRK211H

整個流程相當清楚,又能完整呈現 Azure Copilot 與 Azure ML 的強大。

image-20230526153901836

  • 先建立一個情境,幫生意擴展找客戶挑選 TA
  • 透過 Copilot 給予相關的信件:
    • 這裡想要給予更多更貼近 TA 的資訊,尋找過去信件與相關資料。

image-20230526153841220

[TIL] Microsoft Build 2023 Day1- 資訊整理

image-20230525101507051

這一屆有很多重要消息:

  • Windows Copilot (Windows 內建 chatgpt)
  • ChatGPT with Bing Search (include free tier)
  • Azure AI Studio
  • Dev Home : 登入帳號直接連接 github (windows 相關)

  • Microsoft Fabric : all-in-one BI platform

同步也分享一下,不論是 MSFT CEO 跟 CTO 都有強調關於 Plugin 生態圈的重要。以後微軟許多環境,應該都有 GPT 的存在。 但是又開放許多 3rd Party 開發 Plugin 系統。 來客製化自己的搜尋體驗。這就再次呼應到「生態系競爭策略」這本書。