---
# System prepended metadata

title: 《OpenAI API 開發手冊》服務專區
tags: [F5762]

---

# 《OpenAI API 開發手冊》服務專區

{%youtube eEqi1Qxc5AE%}

- [本書範例檔案](#%E6%9C%AC%E6%9B%B8%E7%AF%84%E4%BE%8B%E6%AA%94%E6%A1%88)
- [旗標官網頁面](https://www.flag.com.tw/books/product/F5762)
- [勘誤](https://hackmd.io/cixa-XYvSW22UGcz6flVGA#%E5%8B%98%E8%AA%A4)

## 本書範例檔案

### 第 1 章

- [Colab 筆記本](https://colab.research.google.com/drive/1g2StUAFx5Ev3pKnr7xM66OFHTN0qm4X3?usp=sharing)
- [OpenAI API 註冊與申請金鑰流程](https://hackmd.io/@flagmaker/BJuxF7bkye)
- [OpenAI Tokenizer 網站](https://platform.openai.com/tokenizer)
- [tiktokenizer 網站](https://tiktokenizer.vercel.app/)

### 第 2 章

- [Colab 筆記本](https://colab.research.google.com/drive/1tZhG0mCG4s4S3DbgzqfSZPeEaC3QXvvb?usp=sharing)
- [驗證組織的網頁](https://platform.openai.com/settings/organization/general)

#### 輸入圖片的計費

計費方式相關資訊：

- [輸入圖片的計費方式](https://platform.openai.com/docs/guides/images#calculating-costs)
- [Pricing 頁面](https://openai.com/api/pricing/) FAQ 區最後有輸入圖片的費用計算機
- [驗算用的輔助函式](https://colab.research.google.com/drive/15UqEWFWyRKOSnm7UzgplW4pJ7xYV8t29?usp=sharing)
### 第 3 章

- [Colab 筆記本](https://colab.research.google.com/drive/1xREEYvkOMppizk5WorSF_nQU80A-LGrt?usp=sharing)

### 第 4 章

- [Colab 筆記本](https://colab.research.google.com/drive/1EXEpkyxETc1Sn7_2BMdKd6brasmINwDL?usp=sharing)
- [搜尋工具的計價方式](https://platform.openai.com/docs/pricing#web-search)
- [檔案檢索工具的計費方式](https://platform.openai.com/docs/pricing#built-in-tools)

### 第 5 章

- [Colab 筆記本](https://colab.research.google.com/drive/1GGomc4iwTq3ohX_cx16P5dT1mI0O6MV0?usp=sharing)

### 第 6 章

- [Colab 筆記本](https://colab.research.google.com/drive/1pVisiBOP3iCqWxhXvw_OHUP9NUq-gLvx?usp=sharing)
- [最後版本的 Chat 類別](https://colab.research.google.com/drive/1wqyPtoddd7xG-TC3JtNqee6aIJaiIXFc?usp=sharing)

### 第 7 章

- [範例下載](https://github.com/FlagTech/F5762_mcp/archive/refs/heads/master.zip)
- [uv 工具教學](https://reurl.cc/YYmamx)
- uv 工具安裝：
    - Windows：
        
        ```
        powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
        ```
        
    - Mac 或是 Linux：

        ```
        curl -LsSf https://astral.sh/uv/install.sh | sh
        ```
        
#### 7-2 MCP 伺服器開發

:::info
請記得修改 MCP 伺服器程式檔路徑為你自己專案的路徑。
:::

##### 測試 MCP 伺服器：

```json
{
    "mcpServers": {
        "shell_helper": {
            "command": "uv",
            "args": [
                "--directory",
                "C:/temp/mcp_test",
                "run",
                "server_shell_helper.py"
            ]
        }           
    }
}
```

##### 多個 MCP 伺服器共同運作

```json
{
    "mcpServers": {
        "shell_helper": {
            "command": "uv",
            "args": [
                "--directory",
                "C:/temp/mcp_test",
                "run",
                "server_shell_helper.py"
            ]
        },
         "google_search": {
            "command": "uv",
            "args": [
                "--directory",
                "C:/temp/mcp_test",
                "run",
                "server_google_search.py"
            ]
        }          
    }
}
```
    
#### 7-3 MCP 用戶端

##### 使用單一 MCP 伺服器的應用程式

```json
{
    "mcpServers": {
        "shell_helper": {
            "command": "uv",
            "args": [
                "--directory",
                "C:/temp/mcp_test",
                "run",
                "server_shell_helper.py"
            ]
        },
    }
}
```


##### 同時使用多個 MCP 伺服器

```json
{
    "mcpServers": {
        "shell_helper": {
            "command": "uv",
            "args": [
                "--directory",
                "C:/temp/mcp_test",
                "run",
                "server_shell_helper.py"
            ]
        },
         "google_search": {
            "command": "uv",
            "args": [
                "--directory",
                "C:/temp/mcp_test",
                "run",
                "server_google_search.py"
            ]
        }
    }
}
```

##### 使用其他人設計的 MCP 伺服器

```json
{
    "mcpServers": {
        "shell_helper": {
            "command": "uv",
            "args": [
                "--directory",
                "C:/temp/mcp_test",
                "run",
                "server_shell_helper.py"
            ]
        },
         "google_search": {
            "command": "uv",
            "args": [
                "--directory",
                "C:/temp/mcp_test",
                "run",
                "server_google_search.py"
            ]
        },
        "fetch": {
            "command": "uvx",
            "args": ["mcp-server-fetch"]
        }
    }
}
```

###### JSON Schema 相容問題

```json
{
    "mcpServers": {
        "pan-doc": {
            "command": "uvx",
            "args": ["pan-doc"]
        }
    }
}
```

### 第 8 章

本章範例與第 7 章是同一個專案，沿用即可。若有需要，再重新下載：

- [範例下載](https://github.com/FlagTech/F5762_mcp/archive/refs/heads/master.zip)

本章大部分都是在本機端執行的程式範例，但 8-2 節會使用到單獨的 Colab 筆記本：

- [Colab 筆記本](https://colab.research.google.com/drive/1qvaIlGVAZWEITFyW8WbgPYfQgA6dEJmW?usp=sharing)

#### 8-1 使用 SSE 將 MCP 伺服器部署在網路上

##### 使用 SSE 傳輸的 MCP 用戶端：

```json
{
    "mcpServers": {
        "sse_google_search": {
            "url": "http://localhost:8000/sse"
        }
    }
}
```

##### 使用 Streamable HTTP 在網路上部署 MCP 伺服器：

```json
{
    "mcpServers": {
        "http_google_search": {
            "type": "http",
            "url": "http://localhost:8000/mcp"
        }
    }
}
```

#### 8-2  使用公開在網路上的 MCP 伺服器

##### GitMCP 使用方法

```json
{
    "mcpServers": {
        "sse_google_search": {
            "url": "http://localhost:8000/sse"
        },
        "gitmcp": {
            "type": "openai",
            "url": "https://gitmcp.io/idosal/git-mcp"
        }

    }
}
```

##### 使用 OpenAI 內建工具連接部署在公開網路上的 MCP 伺服器

- [Colab 筆記本](https://colab.research.google.com/drive/1qvaIlGVAZWEITFyW8WbgPYfQgA6dEJmW?usp=sharing)

#### 8-3  使用環境變數傳遞機密資訊給 MCP 伺服器

:::warning
請記得修改 MCP 伺服器執行檔的路徑為你自己專案的路徑。
:::

##### 預設揭露給 MCP 伺服器的環境變數

```json
{
    "mcpServers": {
         "show environ": {
            "command": "uv",
            "args": [
                "--directory",
                "C:/temp/mcp_test",
                "run",
                "server_environ.py"
            ]
        }
    }
}
```

##### 使用 env 項目傳遞環境變數給 MCP 伺服器

```json
{
    "mcpServers": {
         "show environ": {
            "command": "uv",
            "args": [
                "--directory",
                "C:/temp/mcp_test",
                "run",
                "server_environ.py"
            ],
			"env": {
			"FAKE_API_KEY": "my_fake_api_key"
			}
        }
    }
}
```

#### 8-4 操控其他應用程式的 MCP 伺服器

##### 測試控制 Spotify 的 MCP 伺服器

```json
{
    "mcpServers": {
        "spotify": {
            "command": "uv",
            "args": [
                "--directory",
                "C:/temp/mcp_test",
                "run",
                "server_spotify.py"
            ],
            "env": {
                "SPOTIFY_CLIENT_ID": "你的 Client id",
                "SPOTIFY_CLIENT_SECRET": "你的 Client secret"
            }
        }
    }
}
```

### 第 9 章

- [範例下載](https://github.com/FlagTech/F5762_realtime/archive/refs/heads/master.zip)

#### 9-3 進入 Realtime API 的語音世界

##### 用語音控制 MCP 伺服器

```json
{
    "mcpServers": {
        "spotify": {
            "command": "uv",
            "args": [
                "--directory",
                "C:/temp/mcp_test",
                "run",
                "server_spotify.py"
            ],
            "env": {
                "SPOTIFY_CLIENT_ID": "你的 Client id",
                "SPOTIFY_CLIENT_SECRET": "你的 Client secret"
            }
        }
    }
}
```

### 第 10 章

- [Colab 筆記本](https://colab.research.google.com/drive/1n1VkVBxfO54GEbJ6EIEOagopU3aMuxyy?usp=sharing)
- [範例檔案下載](https://github.com/FlagTech/F5762_agents_sdk/archive/refs/heads/master.zip)

## 勘誤

### 第 2 章

#### 2-29 頁輸入圖片的計費方式

- gpt-4.1 的計費方式比照 gpt-4o
- gpt-4.1 mini 與 gpt-4.1-nano 說明中『以短邊縮小到 32 的倍數』，實際上會以短邊及長邊都各試算一次，最後**以區塊數少**的為準，再轉換成 token 數

### 第 5 章

#### 5-23 頁最下方 FunctionCallingCommand 類別的 make_tool_msg 函式

原本的程式碼如下：

```python=25
    # 叫用單一函式並且將函式執行結果組成訊息後傳回
    def make_tool_msg(self, tool_call):
        tool_info = f'{tool_call.name}(**{tool_call.arguments})'
        if self.verbose: print(f'叫用：{tool_info}')
        result = eval(tool_info)
        return {   # 建立可傳回函式執行結果的字典
            "type": "function_call_output", # 以工具角色送出回覆
            "call_id": tool_call.call_id, # 叫用函式的識別碼
            "output": result # 函式傳回值
        }
```

但因為 API 回覆的引數內容是 JSON 格式，會遇到像是 true/false 與 Python 的 True/False 大小寫不同的問題，最好先從 JSON 轉回 Python 後再執行函式，如下所示：

```python=25
    # 叫用單一函式並且將函式執行結果組成訊息後傳回
    def make_tool_msg(self, tool_call):
        tool_info = f'{tool_call.name}(**{tool_call.arguments})'
        if self.verbose: print(f'叫用：{tool_info}')
        func = eval(tool_call.name)
        args = json.loads(tool_call.arguments)
        result = func(**args)
        return {   # 建立可傳回函式執行結果的字典
            "type": "function_call_output", # 以工具角色送出回覆
            "call_id": tool_call.call_id, # 叫用函式的識別碼
            "output": result # 函式傳回值
        }
```

### 第 6 章

#### 6-3 頁最下方儲存格程式碼

這裡程式碼與上一段重複，應該是如下[整理執行結果為 markdown 格式](https://colab.research.google.com/drive/1pVisiBOP3iCqWxhXvw_OHUP9NUq-gLvx?authuser=1#scrollTo=TAcv3QqeZPok&line=1&uniqifier=1)：

```python=1
output_md = (
    f'執行結果\n\n```\n'
    f'{result.stdout.decode("utf8")}\n'
    f'```\n\n錯誤訊息\n\n```\n'
    f'{result.stderr.decode("utf8")}\n'
    f'```\n\n結束碼：{result.returncode}'
)
print(output_md)
```

#### 6-32 頁

- 中間的程式碼：

    ```python=27
        def handle_command(self, chat, cmd):
            if not super().handle_command(chat, cmd):
                return False
            idx = chat.find_tool_index(self.tool_name)
            if idx == -1:
                chat.tools.append({
                    'type': self.tool_name,
                    'partial_images': 3 if self.verbose else 0
                })
            else:
                chat.tools.pop(idx)
            return True
    ```
    
    中間第 34 行原本在非 verbose 模式時設定變化圖為 0 張，不過因為會採用串流方式，必須設定至少為 1 張，因此這裡改為 1：

    ```python=27
        def handle_command(self, chat, cmd):
            if not super().handle_command(chat, cmd):
                return False
            idx = chat.find_tool_index(self.tool_name)
            if idx == -1:
                chat.tools.append({
                    'type': self.tool_name,
                    'partial_images': 3 if self.verbose else 1
                })
            else:
                chat.tools.pop(idx)
            return True
    ```

- 最下方程式碼：

    ```python=40
        def handle_event(self, chat, stream, event):
            if event.type == 'response.completed':
                b64_data = self.get_img_b64(event.response.output)
                if not b64_data: return None
            elif event.type == (
                'response.image_generation_call.partial_image'
            ):
                b64_data = event.partial_image_b64
            else: return None
            return get_img_obj(b64_data)
    ```

    最後一行漏掉了 `self.`，應該為：

    ```python=40
        def handle_event(self, chat, stream, event):
            if event.type == 'response.completed':
                b64_data = self.get_img_b64(event.response.output)
                if not b64_data: return None
            elif event.type == (
                'response.image_generation_call.partial_image'
            ):
                b64_data = event.partial_image_b64
            else: return None
            return self.get_img_obj(b64_data)
    ```
