# Chapter2. 使用 Python 呼叫 API :+1: 完整程式碼在 https://github.com/iamalex33329/chatgpt-develop-guide-zhtw ## 其他章節 [Chapter1. OpenAI API 入門](https://hackmd.io/@U3f2IzHERbymAst2-lDdjA/S1cNMYi6T) [Chapter3. API 參數解析與錯誤處理](https://hackmd.io/@U3f2IzHERbymAst2-lDdjA/BJWNtsh6p) [Chapter4. 打造自己的 ChatGPT](https://hackmd.io/@112356044/Hk81U96Tp) [Chapter5. 突破時空限制 - 整合搜尋功能](https://hackmd.io/@112356044/HkbVM-ApT) [Chapter6. 讓 AI 幫 AI - 自動串接流程](https://hackmd.io/@112356044/r1Ke-GR6T) [Chapter7. 網頁版聊天程式與文字生圖 Image API](https://hackmd.io/@112356044/Hyf-AvgAT) [Chapter8. 設計 LINE AI 聊天機器人](https://hackmd.io/@112356044/r1d6HsgAa) [Chapter9. 自媒體業者必看!使用 AI 自動生成高品質字幕](https://hackmd.io/@112356044/rJ2T37V0T) [Chapter10. 把 AI 帶到 Discord](https://hackmd.io/@112356044/Sy_L-B40T) [Chapter11. AI 客製化投資理財應用實戰](https://hackmd.io/@112356044/HkUE0rER6) [Chapter12. 用 LangChain 實作新書宣傳自動小編](https://hackmd.io/@112356044/SybvbdN0p) ## 目錄結構 [TOC] ## 使用官方 openai 套件 ### 安裝與使用 openai 套件 ``` python= !pip install openai import openai openai.api_key = "XXXXXXXXXXX" ``` #### openai 套件有三種設定金鑰的方法: 1. 透過套件本身的 `openai.api_key` 來設定 2. 將金鑰儲存在某個檔案,並透過 `openai.api_key_path` 指定路徑 3. 若不使用上述兩個設定方式,預設會自動尋找 `OPENAI_API_KEY` 的**環境變數** #### 接著透過 `openai.ChatCompletion.create()` 連線使用 API,這個函式有兩個必要參數 1. model: 指定採用的模型,這裡使用穩定的 gpt-3.5-turbo 2. messages: 這是訊息串,每個元素都是 **dict**,`role` 是發言角色(**user**, **assistant**, **system** 其中之一);`content` 是訊息內容 ``` python= import openai openai.api_key = "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" reply = openai.ChatCompletion.create( model='gpt-3.5-turbo', messages=[ {'role': 'user', 'content': 'how are you'} ] ) print(reply) ``` 這時會傳回一個 OpenAIObject 類別的物件,可以直接以 `dict` 來操作 ``` json= { "id": "chatcmpl-91JjP1r7ol57AMszxbDTlkrCqNlz9", "object": "chat.completion", "created": 1710101203, // 實際使用的模型 "model": "gpt-3.5-turbo-0125", "choices": [ { "index": 0, "message": { "role": "assistant", // API 回覆的訊息內容 "content": "I'm just a computer program, so I don't have feelings or emotions, but I'm here to help you with any questions or tasks you have. How can I assist you today?" }, "logprobs": null, // 訊息終止的原因 "finish_reason": "stop" } ], "usage": { "prompt_tokens": 10, "completion_tokens": 38, // 本次 API 的 token 用量 "total_tokens": 48 }, "system_fingerprint": "fp_4f0b692a78" } ``` - model: 本次使用 API 的模型 - usage: 本次 API 的用量 | 項目 | 說明 | | -------- | -------- | | prompt_tokens | 傳送 API 訊息的 token 數量 | | completion_tokens | API 回覆訊息的 token 數量 | | total_tokens | prompt_tokens + completion_tokens | - choices: 是 list type,代表 API 回覆的訊息 - finish_reason: 表示該回覆訊息是否完整,有兩種可能 - stop: 正常結束,回覆內容為完整語句 - length: 因長度限制,回覆內容並不完整 [查詢 OpenAI 各個模型價格 ::: Pricing](https://openai.com/pricing) ### 傳送多筆訊息 ``` python= reply = openai.ChatCompletion.create( model='gpt-3.5-turbo', messages=[ {'role': 'system', 'content': 'Your name is Alex.'}, {'role': 'user', 'content': 'how are you, what\'s your name?'} ] ) ``` 我們可以發現,API 確實有按照 `system` 暗示,名稱變成 Alex ## 認識 token > OpenAI API 的計價單位就是 **token**,不論是傳送給 API 的文字,或是回傳的內容都是以 token 為單位 ### 使用 tokenizer 頁面檢視 token [OpenAI Platform ::: Tokenizer](https://platform.openai.com/tokenizer) ![Screenshot 2024-03-11 at 4.33.41 AM](https://hackmd.io/_uploads/H1WNKqjpT.png) - 每個字段都有其 Token ID,而中文字的 token 會比英文還來得多! - 大略的計算方式為:length of words = total_token * 0.75 ### 使用 tokenizer 套件計算精確 token 數 取得模型的編碼器名稱 ``` python= !pip install tiktoken import tiktoken encoder = tiktoken.encoding_for_model('gpt-3.5-turbo') print(encoder.name) encoder = tiktoken.encoding_for_model('gpt-4') print(encoder.name) ``` 利用 `encode()` 轉為 token,可以看到是一樣的 ``` python= tokens = encoder.encode('how are you') print('tokens: ' + str(tokens)) print('length of token: ' + str(len(tokens))) print('decode tokens: ' + encoder.decode(tokens)) # tokens: [5269, 527, 499, 30] # length of token: 4 # decode tokens: how are you? ``` ![Screenshot 2024-03-11 at 4.42.33 AM](https://hackmd.io/_uploads/rJVrocs6T.png) ### ChatML 標記語言 以前面示範的 `how are you` 為例,透過查詢 token 數量可以發現僅有 3 個單位,但 API 所傳回的 token 卻有 10 個單位,是什麼造成的? ``` json= "prompt_tokens": 10 ``` 實際上在傳送字串時,模型會轉換成 Chat Markup Language(ChatML)的格式,會轉換成以下格式: ``` = <|im_start|>角色\n訊息內容<|im_end|> ``` `<|im_start|>` 與 `<|im_end|>` 都是特殊的 token,代表單一訊息的開頭/結尾。`"\n"` 以及各個角色都會被轉換成 1 個 token。 因此上述例子會轉換成: ``` {'role': 'user', 'content': 'how are you'} ``` ``` <|im_start|>user\nhow are you<|im_end|> ``` 最後還會加上結尾,表示接下來交給 AI 回覆 ``` <|start|>assistant\n ``` 也就是說,每一則訊息除了本身內容轉換的 token 之外,還會加上 4 個(2 個特殊 token、1 個換行符號、1 個角色)token,以及 3 個 token 的結尾訊息。 3 (how are you) + 4 (2 + 1 + 1) + 3 = 10 ## 使用 Python requests 模組呼叫 API OpenAI API 是走 http protocol,因此也不一定要透過 openai 模組才能使用,甚至只要簡單的 command line,就可以取用 OpenAI 的 API。 ### OpenAI API 的 HTTP 規格 OpenAI Chat API 主要透過 HTTP POST 方法提供服務,API 存取網址為 :link: https://api.openai.com/v1/chat/completions 使用時必須在 header 加上以下兩項資料 | 表頭 | 內容 | 說明 | | -------- | -------- | -------- | | Content-Type | application/json | 表實際傳輸的內容(JSON) | | Authorization | Bearer 金鑰 | 金鑰來提供 API 認證 | ### 使用 Python requests 模組 在 Python 中透過 http 協定傳輸資料,最簡單的方式就是用 `requests` 套件 ``` python= !pip install requests import requests import apikey openai_api_url = 'https://api.openai.com/v1/chat/completions' response = requests.post( openai_api_url, headers={ 'Content-Type': 'application/json', 'Authorization': f'Bearer {apikey.OPENAI_API_KEY}' }, json={ 'model': 'gpt-3.5-turbo', 'messages': [ {'role': 'user', 'content': 'how are you'} ] } ) reply = response.json() print(reply['choices'][0]['message']['content']) ``` > 通常在一些無法下載 openai 套件的環境,或是沒有足夠空間安裝的嵌入式系統,會直接透過 HTTP POST 來呼叫。 ### 利用 curl 工具快速測試 API ``` bash= curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_OPENAI_API_KEY" \ -d '{ "model": "gpt-3.5-turbo", "messages": [ {"role": "user", "content": "how are you"} ] }' \ https://api.openai.com/v1/chat/completions ``` ![Screenshot 2024-03-12 at 12.04.54 AM](https://hackmd.io/_uploads/BJvTjo2Tp.png)