---
# System prepended metadata

title: Chapter2. 使用 Python 呼叫 API
tags: [ChatGPT 開發手冊]

---

# 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)