---
# System prepended metadata

title: ChatGPT
tags: [說明文件]

---

# ChatGPT
###### tags: `ChatGPT to Llama`
# INTRODUCTION
ChatGPT是由OpenAI開發釋出的聊天型助手，目前廣大使用者皆可透過[網頁介面](https://chat.openai.com/)來使用，我們可以請ChatGPT做各式各樣的事情，舉凡聊天、寫程式、創作等等都可以做到，甚至還可以透過下指示（prompt/ instruction）命令ChatGPT角色扮演式地替人類執行特定的任務（[點我看網路上中文prompt範例](https://softnshare.com/chatgpt-prompts/)）。先看一個上述連結的例子：
- **充當講故事的人**
    - 以下為在聊天框給ChatGPT下的prompt:
    :::warning
    我想讓你充當講故事的人。你要想出有趣的故事，這些故事要有吸引力，要有想象力，要吸引觀眾。它可以是童話故事、教育故事或任何其他類型的故事，有可能吸引人們的注意力和想象力。根據目標受眾，你可以為你的故事會選擇特定的主題或話題，例如，如果是兒童，那麼你可以談論動物；如果是成年人，那麼基於歷史的故事可能會更好地吸引他們等等。我的第一個要求是 “我需要一個關於毅力的有趣故事“。
    :::
    - 以下為ChatGPT的回應:
    :::success
    **毅力的小石頭**

    在一個遙遠的山谷裡，每顆石頭都有自己的故事。但有一顆小石頭，名叫「斯頓」，他認為自己是整個山谷中最不特別的。因為其他石頭都巨大、色彩鮮艷，或是有特殊的形狀，而他只是一顆普通的小石頭。

    一天，山谷中的動物們決定舉行一場比賽，看誰能夠在最短的時間內爬到山的頂端。所有的石頭都被邀請參加。斯頓覺得自己太小，沒有機會勝出，但他還是決定參加，因為他想嘗試一下。

    比賽開始後，斯頓發現自己比想象中要快很多。由於他的體型小，他可以輕易地從裂縫和障礙物中穿越。其他的石頭，尤其是大石頭，都因為太重或形狀不適合而受到困擾。

    但是，當他爬到快要達到山頂時，他遇到了一道大河。這條河對於其他的大石頭來說只是一條小溪，但對斯頓來說，它就像一個巨大的障礙。他幾次試圖穿越河流，但每次都被洪水沖走。

    就在斯頓快要放棄的時候，一只老鷹飛了過來，問他是否需要幫忙。斯頓說：“我不想因為別人的幫助而贏得比賽，但我真的想到達山頂。”老鷹微笑著說：“你已經證明了你的毅力，現在讓我給你一些建議。”

    老鷹教斯頓如何利用河流中的石頭作為踏腳石，逐一越過。經過多次嘗試，斯頓終於成功穿越河流，並最終成為第一個到達山頂的石頭。

    比賽結束後，所有的動物和石頭都為斯頓喝彩。他成為了一名英雄，不是因為他贏得了比賽，而是因為他不放棄，並展現出了真正的毅力。

    從此，每當山谷中的居民談起毅力時，他們都會想起斯頓的故事，並將他當作毅力的象徵。
    :::
    以上例子ChatGPT成功遵從了我們的指示說了一個小故事，由此可以看到，ChatGPT所具備的知識使他有閱讀理解並遵從指示的能力，至於ChatGPT腦中的知識是哪裡來的呢？這個故事是他自己想的還是去網路上找的？試著搜尋一下「毅力的小石頭」：![](https://hackmd.io/_uploads/HyaFZc8kp.png)
    我們初步假設這個故事是ChatGPT自己寫的，那ChatGPT又是怎麼編故事的呢？在下一節我們將初步介紹一下語言模型。

# 語言模型如何運作？
由我們使用ChatGPT的經驗來看，我們透過文字輸入得到ChatGPT的文字輸出，可以想像其背後經過了某種神秘力量的作用。
## 自然語言 VS. 數學模型
近幾年在使用深度學習方法來處理自然語言的生成式模型，會需要**tokenizer**與**embedding layer**搭配使用才可以將自然語言轉換成模型可以運算的矩陣形式：
- **Tokenizer**：不同模型會搭配不同的tokenizer，其作用是將所有訓練資料中的輸入段落或文句使用不同方法切割成最小文字單位(**token**)後將一段文字視作數個小元素來處理。常見的方法如GPT使用的Byte-Pair Encoding，**BPE**，以下為tokenize後的範例：
    ```
    "the</w>" -> ["the</w>"]
    "highest</w>" -> ["high", "est</w>"]
    "mountain</w>" -> ["moun", "tain</w>"]
    ```
    我們會為訓練資料中出現過的每個不同token建立專屬的index，以供後續查找使用。
- **Embedding Layer**：用一串向量(**embedding**)代表一個token的意義是很常見的手法，而要取得一個好的表示法(embedding)，在NLP領域有數種訓練方式，這裡不多作敘述，將其想像成模型中可訓練參數的一部分即可。假設我們使用$E$維的向量來表示一個token的意義，出現過的token數為$N$，我們的embedding layer即為大小為$N*E$的大字典$D$，每一次模型取得輸入段落經過tokenizer取得切割後的token序列的index後，會從字典$D$中對應index的位置抽取出對應向量後拼接成輸入矩陣以便後續運算（如下圖）。我們會期望語意相近的token轉換成embedding後，在空間向量中的距離可以相近。
<div style="text-align:center">
    <img src="https://hackmd.io/_uploads/SJduzpLyp.png" width="100%" >
    
[REF：知乎HeptaAI- 从词到数：Tokenizer与Embedding串讲](https://zhuanlan.zhihu.com/p/631463712)
</div>


輸入的自然語言段落透過**tokenizer**與**embedding layer**餵入model經過一連串的矩陣運算後，會輸出預測結果是落在embedding表中每個token的機率分布，預測結果即為機率最大的token，我們最後會取出該token的index由tokenizer反向對應回去查找該token轉換回人類可讀的語言。

## 深度學習
一般我們在訓練深度學習模型時會有以下基本元素：
- **模型（model）**：先將模型的預測過程簡單的表達為為$\hat{Y}=f(X)$，$X$為**輸入特徵**，即我們想要讓模型參考什麼東西來做預測；$f$表示模型，為設計好的運算方式（**模型架構**）其中包含數量不等的**可訓練的模型參數**；$\hat{Y}$為**模型輸出結果**。
- **目標函數（loss function/ objective function）**：在訓練模型時，我們會提供給模型一個參考答案（**ground truth**），目標是訓練模型想辦法將輸出的結果靠近參考答案。首先我們會需要一個帶有模型預測結果與參考答案的可微分目標函數來評估每一次模型的預測好壞，並對該函數使用最佳化方法，來尋找模型參數應該要調整的方向，通常我們會以極小化為到$0$為主，因為極大化的值會發散到無限大，電腦沒辦法處理。
    - 最佳化方法－極小化函數：
        1. 對目標函數中$L$的欲更新參數$X_i$做偏微分，得到$X_i$的偏微量$\Delta{X_{i}}$
            - **反向傳播**：![](https://hackmd.io/_uploads/SJlIkdAy6.png)
            [REF：反向傳播算法（ Backpropagation Algorithm ）](https://medium.com/%E4%BA%BA%E5%B7%A5%E6%99%BA%E6%85%A7-%E5%80%92%E5%BA%95%E6%9C%89%E5%A4%9A%E6%99%BA%E6%85%A7/%E5%8F%8D%E5%90%91%E5%82%B3%E6%92%AD%E7%AE%97%E6%B3%95-backpropagation-algorithm-71a1845100cf)
            如上圖例子所示，對目標函數$L$中的$W_{11}$做偏微分，可分解成由$L$的最外層出發，對上一層的輸出做偏微分，在向前運算時有經過的路（紅色圈圈及線）在向後傳播時都要計算，直到拆解到欲更新的$W_{11}$為止。
        2. $\Delta{X_{i}}$的意義為$X_i$移動一單位，目標函數值會移動多少單位，欲將目標函數值極小化到$0$，對$X_i$的更新為：
            $$X_i\gets X_i - \gamma \Delta{X_{i}}$$
        其中$\gamma$為學習率（**learning rate**），為設置之每一次參數要更新的步長。
    
    不同訓練方式會搭配很多不同的目標函式，例如我們會想要讓模型預測結果與正確答案的距離越小越好，使用Mean Square Error，MSE ($L=E(Y, f(X))=MSE={(Y-f(X))}^2$)作為我們的目標函數；再舉一個例子，例如提供2種標籤，一為希望模型預測靠近正樣本$S_{pos}$，二為希望模型預測要遠離的負樣本$S_{neg}$，我簡單把目標函數設計為$L={MSE}_{(S_{pos},\ \hat{Y})}-{MSE}_{(S_{neg},\ \hat{Y})}$，其中我們希望${MSE}_{(S_{pos},\ \hat{Y})}$越小越好，${MSE}_{(S_{neg},\ \hat{Y})}$越大越好，透過為${MSE}_{(S_{neg},\ \hat{Y})}$加上負號的方式，使得該函數的目標同樣為最小化。
- **訓練資料**：深度學習模型是**Data Driven**的決策過程，我們用什麼資料訓練模型，模型的能力有很大一部份會取決於他看過多少資料以及資料形式。而資料又分為**標註資料**及**未標註資料**，使用標註資料訓練模型我們稱為**監督式學習**（**supervised learning**），使用未標註資料的訓練方式則稱為**無監督式學習**（**unsupervised learning**）。我們在訓練特定任務時，由人類為每一個樣本標註（**label**）我們希望讓模型輸出的參考答案，而不同任務的資料與標註型態又有所不同，舉常見的鳶尾花資料集為例，樣本輸入模型的特徵為花瓣花萼的長寬等等，而我們希望模型輸出樣本屬於三種鳶尾花類型的哪一種；而如果要訓練如ChatGPT的生成式模型，我們的標註方式則是針對user輸入的prompt，對其做後續回應作為標註。資料標註的過程需要耗費較多的人力，而能力越好的模型通常就會需要較大量的資料，在有限的人力資源下，研究者們致力於發展出許多方法來淋漓盡致地使用未標註資料，透過設計未標註資料的模型輸入與輸出部分，使用資料自有結構來進行**無監督式學習**。
# GPT的模型架構
我們在上一節介紹了文字如何轉換成模型可運算的向量形式，我們接著來理解一下GPT是如何生成文字的，可以觀察到，在與ChatGPT對話時，他的回應並不會一次全數輸出，這就與GPT使用的架構有關，GPT系列模型是使用Google於2017年發布的[Transformer](https://arxiv.org/abs/1706.03762)中的decoder架構堆疊而成大型語言模型，以下簡單介紹：
## Transformers Decoder
Transformers的decoder用的是masked self-attention機制，self-attention是一種適合用來處理語言序列的模型架構，簡單描述他的概念就是，我們在理解一句話的時候，可以發現句子中有些字組合在一起時會有特定的意思，而self-attention的機制就是讓句子中的每一個字的可訓練參數都與其他字的可訓練參數做運算，可直接利用矩陣運算達成平行化訓練，藉此抓取出句子中文字組合的意義。接著我們來關注一下"masked"的部分，我們使用self-attention來「理解」一個句子段落的意義，但例如ChatGPT在「生成」文字時，模型一開始只會有user輸入的prompt資訊，並不能預知他未來會產出什麼文字，所以在訓練transformer decoder時，例如輸入句子長度為$4$，在self-attention進行到一半初步得到每個字與句中其他字的相關性矩陣時，會加上以下的**look-ahead mask**來確保模型的每一個字在查找與他有關聯的文字的時候，是不會看到還沒生成的文字的：$$\begin{bmatrix}
0 & 1 & 1 & 1 \\
0 & 0 & 1 & 1 \\
0 & 0 & 0 & 1 \\
0 & 0 & 0 & 0 \\
\end{bmatrix}$$

其中$1$的位置（欲遮住的位置）會設置成$-\infty$，經過以下$Softmax$公式計算，被遮罩的地方就會是$0$：
$$Softmax(z_i) = \frac{e^{z_{i}}}{\sum_{j=1}^K e^{z_{j}}} \ \ \ for\ i=1,2,\dots,K$$
上式會先將每一項的值先經過指數函數拉到0到無限大，如下**指數函數**圖（橫軸為輸入值，縱軸為輸出值），接著對每一項藉由除上轉換後之序列總和來得到總和為$1$的序列，該比例是用來進一步計算每個字與其他字的加權平均來形成新的文字組合語意。
<div style="text-align:center">
    <img src="https://hackmd.io/_uploads/rJtJ2OC16.png" width="40%">

[REF：wikipedia](https://zh.wikipedia.org/zh-tw/%E6%8C%87%E6%95%B0%E5%87%BD%E6%95%B0)
</div>

如此一來，在分配每一個字的語意比例時，只有輸入模型的prompt還有已生成的token會被列入考慮（如下圖）：
<div style="text-align:center">
    <img src="https://hackmd.io/_uploads/ryZEWYq1T.png" width="40%" >
    
[REF：知乎 @盛源车](https://zhangruochi.com/ML-Interview-Natural-Language-Processing/2020/05/28/)
</div>


接著試想我們正在跟訓練好的GPT玩文字接龍請他輸出文字，如同訓練時只能看到過去token的概念一樣，但由於我們一開始並不能預知所有的輸出文字，所以在這裡是遞迴式的輸出，與訓練時平行化的運算不同。如以下示意圖，首先我們輸入第一個字"life"，而後模型要輸出"is"，接著準備要生成第三個位置時的字時，我們會連同上一個生成的字一併餵入模型，即"life is"，接著模型輸出"life is too"，就這樣反覆生成下去，直到出現代表一句話結束的"<EOS>" token。
<div style="text-align:center">
    <img src="https://hackmd.io/_uploads/HkT3O1uy6.png" width="80%" >
    
[REF：Sebastian Raschka in Twitter](https://x.com/rasbt/status/1631286616596652032?s=20)
</div>


# ChatGPT的成長史
ChatGPT的強大大家有目共睹，接著我們來看看ChatGPT是如何走到今天這一步的：
<div style="text-align:center">
    <img src="https://hackmd.io/_uploads/HJsWlLbk6.png" width="100%" >
    
[REF：GPT / GPT-2 / GPT-3 / InstructGPT 进化之路](https://zhuanlan.zhihu.com/p/609716668)
</div>


如圖所示，圖中的每一個節點皆是Open AI發布過的系列模型，我們可以把模型參數量想像成GPT的大腦容量，訓練資料想像成老師想要傳授給學生的所有知識，從GPT-1到ChatGPT經歷了不停地增加**模型可訓練參數**以及**訓練資料量**，以下分別介紹系列模型的主要特色與在上圖中出現的一些名詞概念：
## GPT-1(2018)
GPT-1使用==大量的未標註資料==（如Wikipedia、Twitter上的文本等等）來預先訓練模型(**pretrain**)，使用文字本身上下文的意義來訓練模型以理解語言本身，接著使用==少量的標註資料==來對預訓練模型進行微調(**fine-tune**)以便更切合的執行其他任務。

## GPT-2(2019)、GPT-3(2020)
首先我們先看一些名詞意義：
- **zero-shot**：GPT-1發布後，接著被BERT打敗（BERT是Google發布的語言模型，主打不同型態的任務微調），然而，OpenAI的信念為，只要給模型看的文本夠多，不需過多需要標註的微調，就可以達到很好的效能，於是主打zero-shot的GPT-2出世，即完全使用pretrain模型來直接執行其他任務，不另外給新樣本給模型學習。該模型同樣達到很好的效果。
- **one-shot/ few-shot learning**：GPT-3測試了zero-shot、one-shot與few-shot，one與few-shot是指在解其他任務時，藉由給預訓練模型1個/數個樣本來使模型學習新任務，結果顯示few-shot的效果較好。
- **in-context learning**：GPT-3的one-shot/ few-shot並非是對pretrain模型的fine-tune，而是將樣本直接加在prompt裡面供模型學習，該作法稱in-context learning，in-context learning需要的樣本數遠小於fine-tune模型需要的樣本數。

截至GPT-3的發布，模型規模已達到175B的參數量（GPT-1的1750倍），訓練了570G（GPT-1的154倍）的資料。儘管GPT-3模型已經有很好的閱讀理解能力與生成能力，但受到訓練資料的影響，生成的文字中並不是很貼近人類希望他輸出的東西，以下為GPT-3最為詬病的問題：
- **making up facts**：捏造事實。
- **generating biased or toxic text**：回應訓練資料中不那麼主流的部分，或是產出一些帶有偏見歧視意義的有毒文字，如歧視黑人、女性偏見等等。
- **simply not following user instructions**：自顧自地玩文字接龍，就像我們訓練模型時做的事情一樣，不遵照prompt下的指示。
## [InstructGPT(2022)](https://arxiv.org/abs/2203.02155)
InstructGPT為解決上一節GPT-3出現的一些問題而生，這一版本的GPT又再走回監督式學習的老路，在GPT-3的基底模型下透過人類標註的優質資料來fine-tune。
- **InstructGPT三大目標**：欲使模型更加貼近(**align**)人類需求：
<div style="text-align:center">
    <img src="https://hackmd.io/_uploads/r1Csg4SJp.png" width="80%" >
    
[REF：GPT / GPT-2 / GPT-3 / InstructGPT 进化之路](https://zhuanlan.zhihu.com/p/609716668)
</div>

### InstructGPT三階段的訓練方式![](https://hackmd.io/_uploads/Sy9TXEBkT.png)

<span style="background-color: #FFE4B5; padding: 1px 10px; border-radius: 2px; border: 2px solid #FFA500; color: #333; font-weight: bold;">STEP-1</span><span style="background-color: #FFFACD; padding: 1px 10px; border-radius: 2px; border: 2px solid #FFA500; color: #333; font-weight: bold;">SFT (Supervised Fine-Tuning)</span>：中文為**監督式微調**，使用由標註人員對prompt親自解答(demonstrations)的資料進行監督式訓練。
<span style="background-color: #FFE4B5; padding: 1px 10px; border-radius: 2px; border: 2px solid #FFA500; color: #333; font-weight: bold;">STEP-2</span><span style="background-color: #FFFACD; padding: 1px 10px; border-radius: 2px; border: 2px solid #FFA500; color: #333; font-weight: bold;">**RM (Reward Model)**</span>：中文為**獎勵模型**，由於SFT的資料十分昂貴，標註人員要耗費較多心力來對一個prompt寫解答，因此OpenAI決定訓練一個獎勵模型搭配第三階段的RL方法來輔助訓練第一階段的模型。訓練獎勵模型的資料只須由標註人員對模型回覆的優劣進行排列，期望可以出少少的力得到大大的效果。
<span style="background-color: #FFE4B5; padding: 1px 10px; border-radius: 2px; border: 2px solid #FFA500; color: #333; font-weight: bold;">STEP-3</span><span style="background-color: #FFFACD; padding: 1px 10px; border-radius: 2px; border: 2px solid #FFA500; color: #333; font-weight: bold;">**RLHF (Reinforcement Learning from Human Feedback)**</span>：中文為**基於人類反饋的強化學習**，用Human Feedback訓練的SFT model、Reward Model，拿SFT model、Reward Model沒看過的資料，以RL的方式訓練。**※無另外使用標註資料**。
- **Reinforcement Learning，RL**：用簡單的比喻來看RL中**Actor Agent**、**Policy**、**Reward**、**Envorinment**的概念，今天要來訓練狗狗（Actor Agent）玩接飛盤遊戲，我們會用不同力氣朝不同方向丟（Environment Factor 1），根據當天天氣風速（Environment Factor 2），飛盤的運動方向速度也會有所不同，當狗狗成功接到飛盤時，我們會給他零食獎勵（Reward），狗狗收到零食很開心，之後當飛盤又飛出去的時候，為了想要再得到零食，狗狗就會想盡辦法（調整Policy）讓自己接到那個飛盤。
    
在InstructGPT的訓練中，於STEP-1經過SFT微調後的GPT-3.0 model作為Actor Agent，於STEP-2訓練的RM model作為計算Reward的Reward Agent，user輸入的prompt即為Actor Agent要觀察後做出反應的Environment。
    
### InstructGPT的數據集生成
1. 首先蒐集40個博士作為labelers來生成優質的標註資料。
2. 接著由標註資料訓練一版初步的InstructGPT後上線到playground，並於user使用該模型時不停地告知user他們的使用足跡會供訓練使用。
3. 最後labelers會自己寫prompt，並搭配playground上蒐集到的prompt，欲產出具有多樣性主題的樣本，如腦力激盪類的、創造性的、改寫類的等等，以下為論文中的列出的樣本種類：![](https://hackmd.io/_uploads/Sy9wx69JT.png)
    
結合playground與標註者自己寫的prompt，共產出了以下這些資料集：
- **dataset for SFT (13k)**：含有prompt的解答（demonstrations）的資料，直接由人工標註的資料來達到align目的。
- **dataset for RM (33k)**：為了進一步使用RL自動訓練模型，首先需要一個Reward Model用來評價模型生成的回覆優劣。在這一階段的資料準備，使用同第一階段訓練的那些prompt，由第一階段的模型輸出的數個不同的回覆（模型中含有一些機率性隨機性的部分，會使模型在每一次產生回應時不會完全相同），接著由labeler對這些回應做排序的標註。
- **dataset for RLHF (31k)**：第三階段為RL訓練，使用的是第一、二階段模型沒看過也未經標註的資料。

## [ChatGPT(2022.11)](https://openai.com/blog/chatgpt)
ChatGPT與InstrucGPT的訓練方式大抵上相同（如下第2張、第3張圖），OpenAI並未釋出ChatGPT的paper但有[Blog](https://openai.com/blog/chatgpt)，與其不同的是：
1. 使用GPT-3.5進行微調，模型由Codex（使用github上的程式訓練）、InstructGPT發展而來，具有編程能力
2. 除InstructGPT的資料集外，另外使用多輪對話的資料（包含AI trainer (user)與model (AI assistant)的雙向對話互動資料，AI trainer對model的下的建議等等）訓練初版的ChatGPT來加強聊天式回應的訓練


<div style="text-align:center">
    <img src="https://hackmd.io/_uploads/HJsWlLbk6.png" width="100%" >
    
[REF：GPT / GPT-2 / GPT-3 / InstructGPT 进化之路](https://zhuanlan.zhihu.com/p/609716668)
</div>

- [InstructGPT](https://arxiv.org/abs/2203.02155): fine-tune GPT-3
<div style="text-align:center">
    <img src="https://hackmd.io/_uploads/ryWA7VHyp.png" width="100%" >
    
[REF：paper- InstructGPT(2022)](https://arxiv.org/abs/2203.02155)
</div>

- [ChatGPT](https://openai.com/blog/chatgpt): fine-tune GPT-3.5、多輪對話
<div style="text-align:center">
    <img src="https://hackmd.io/_uploads/SkkqGNBya.png" width="100%" >
    
[REF：OpenAI Blog- ChatGPT](https://openai.com/blog/chatgpt)
</div>

    
## ChatGPT-4(2023.3.15)
- 比ChatGPT3.5強多了
- 比較貴
- 只有[技術報告](https://cdn.openai.com/papers/gpt-4.pdf)，訓練方式與模型規模不明

# ChatGPT的限制
我們從前幾節理解到了ChatGPT的模型架構與訓練方式，大概對ChatGPT會有的行為模式有初步的理解，ChatGPT雖然強大，但仍有一些限制，我們直接用一些例子來看：
:::spoiler **使用其他工具**
以下為Introduction提供的[連結](https://softnshare.com/chatgpt-prompts/)中的一個例子
- 以在聊天框給ChatGPT下的prompt:
    :::warning
    我想讓你充當一個人工智慧輔助的醫生。我將向你提供一個病人的詳細資料，你的任務是==使用最新的人工智慧工具，如醫學成像軟體和其他機器學習程式==，以便診斷出最有可能導致其症狀的原因。你還應將傳統的方法，如體檢、實驗室測試等，納入你的評估過程，以確保準確性。我的第一個請求是 “我需要幫助診斷一個嚴重腹痛的病例“。
    :::
- ChatGPT的回應:
    :::success
    好的，我將盡量協助您。請您提供以下資料，以便進行初步評估：
    1. 病人的年齡、性別和體重。
    2. 腹痛的具體位置（例如：右上腹、左下腹等）。
    3. 疼痛的性質（例如：刺痛、絞痛、鈍痛等）。
    4. 疼痛開始的時間和持續時間。
    5. 是否有任何引發或緩解疼痛的因素。
    6. 病人是否有其他症狀，如噁心、嘔吐、發熱、腹脹、排便或排尿問題等。
    7. 病人近期是否曾旅行或吃了任何不尋常的食物。
    8. 病人是否有任何已知的健康問題或正在服用的藥物。
    9. 是否進行了任何醫學檢查或實驗室測試，如果有，結果如何。

    提供上述資料後，我將基於目前的知識來進行初步的評估。請注意，這僅供參考，並不替代專業醫生的診斷和建議。在確定病因之前，建議您最好尋求醫生的幫助。
    :::
我們已經理解到了GPT為基於輸入序列開始循環生成之後的字，該prompt要求ChatGPT使用最新的醫學成像軟體和其他機器學習程式，這是一件非常不合理的事情，ChatGPT安全地回應他會「盡量」，但並未提到能或是不能使用其他工具來幫助您。

:::
    

:::spoiler **未來資訊**
我們用2023年5月[黑人牙膏改名的新聞](https://tw.news.yahoo.com/news/%E9%BB%91%E4%BA%BA%E7%89%99%E8%86%8F%E6%AD%A3%E5%90%8D%E4%BA%86-%E6%AD%A3%E5%BC%8F%E6%94%B9%E5%90%8D%E7%82%BAdarlie%E5%A5%BD%E4%BE%86-%E9%82%84%E9%82%80%E8%AB%8B%E5%89%B5%E4%BD%9C%E6%89%8D%E5%AD%90%E9%9F%8B%E7%A6%AE%E5%AE%89%E9%87%8D%E6%96%B0%E8%A9%AE%E9%87%8B%E7%9A%84%E8%80%B3%E7%86%9F%E8%83%BD%E8%A9%B3%E7%9A%84%E5%BB%A3%E5%91%8A%E4%B8%BB%E9%A1%8C%E6%9B%B2-043802063.html)來跟ChatGPT聊聊：
![](https://hackmd.io/_uploads/SyyeRVOya.png)

可以看得出來ChatGPT對於時間性的內容有受過特別訓練，他明確的告知user他的訓練數據只到2022年1月。

:::
:::spoiler **幻覺**
![](https://hackmd.io/_uploads/HJHMfSd1T.png)
    
由以上例子可以看到ChatGPT一本正經地在胡說八道，首先客戶沒有提到他是公務員，再者客戶只提到他的月薪，ChatGPT在回應中也有說到6萬是投保薪資，但實際上投保薪資並不等於應付健保費，接著我問問ChatGPT本人為何會亂回答：

![](https://hackmd.io/_uploads/ryAr8B_ya.png)

看來ChatGPT犯了他所提到第3點的錯誤，**過度推斷**客戶的問題了。通常我們會希望客服不要肯定地回應錯誤的資訊，所以我接著問：

![](https://hackmd.io/_uploads/ryJoBBdkp.png)

根據ChaGPT提示我應該要怎麼指示他：

![](https://hackmd.io/_uploads/H1fP5SuJp.png)

看起來效果好了一些，但還有一個問題是客戶並沒有提到他是公務員。
:::

:::spoiler **錯誤資訊**
請ChatGPT幫我生成4*4的look-ahead mask
![](https://hackmd.io/_uploads/BkJZAoAyT.png)

如果讀者還記得的話，我們在[先前的內容](##Transformers-Decoder)介紹了look-ahead mask的內容，抓到ChatGPT犯錯：

![](https://hackmd.io/_uploads/SkfqCj0ya.png)

索性離開當前對話，開啟新的對話再問一次：

![](https://hackmd.io/_uploads/Sy1sx30JT.png)

ChatGPT自行對他之前答錯的表示方式做了相反的解釋，雖然意義上沒有錯，但與在論文中的表示法是相反的。

於是我斥責了一下ChatGPT：

![](https://hackmd.io/_uploads/BJwWz20kT.png)

他擷取了論文中的code，論文中的code是將mask值為$1$（要屏蔽的）的部分設定為$-inf$，但ChatGPT仍堅持使用0來作為要屏蔽的地方，我暫時不想再跟他解釋。

:::

:::spoiler **ChatGPT的記憶**
我在上面的敘述請ChatGPT幫我生成4*4的mask矩陣，接著補述想要讓他用HackMD展現，顯示他有進行多輪對話的能力：
![](https://hackmd.io/_uploads/Ski2WncJa.png)
然而ChatGPT的記憶也不是永無止盡，ChatGPT-4的最大token數限制是8,192個token，ChatGPT可以記住前幾輪對話的方式是在當前訊息的之前放入歷史對話，當超過token數的限制時，我們就得再複製一次想要給ChatGPT看的內容在當前的訊息以免重要訊息因超過token數限制而沒被模型看到：
![](https://hackmd.io/_uploads/SkPycT5ka.png)
:::

:::spoiler **總結**
以上一些例子大概點出一些使用ChatGPT需要注意的地方及他的回應可能會出現的問題。最後再請ChatGPT本人幫我們複習一下：
![](https://hackmd.io/_uploads/ByggrAqJp.png)
:::



## 調整prompt的技巧
調整prompt是一門博大精深的學問，以下提供一些資源供參：
- [思維鏈](https://domyweb.org/chatgpt-questioning-skills/)
- [ShareGPT](https://sharegpt.com/)為一個共享平台，上面可以看得到大家都怎麼使用ChatGPT。
- [古倫維老師- ChatGPT系列Ep11](https://youtu.be/TYW2rLPIFCE?si=OZNnGqd7XNCZ9s4b)中有介紹一些調整prompt的小技巧。

# ChatGPT可以幫我做什麼？
筆者任職於文境資科AI技術部，依筆者本人使用習慣簡單舉一些可以用到ChatGPT的地方：
:::spoiler **為程式碼加註解**
    
我在github上隨意找了一段[RL的範例程式](https://github.com/pytorch/examples/blob/main/reinforcement_learning/actor_critic.py)複製給ChatGPT，並在最後下了以下指示：
![](https://hackmd.io/_uploads/Ske6-vYk6.png)

以下是完整ChatGPT的回應：
<div style="height: 300px; overflow: auto;">

```python=
import argparse
import gym  # 強化學習環境
import numpy as np
from itertools import count
from collections import namedtuple

import torch  # 深度學習框架
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.distributions import Categorical

# 解決CartPole問題

# 命令行參數解析
parser = argparse.ArgumentParser(description='PyTorch actor-critic example')
# 添加參數
parser.add_argument('--gamma', type=float, default=0.99, metavar='G',
                    help='discount factor (default: 0.99)')
parser.add_argument('--seed', type=int, default=543, metavar='N',
                    help='random seed (default: 543)')
parser.add_argument('--render', action='store_true',
                    help='render the environment')
parser.add_argument('--log-interval', type=int, default=10, metavar='N',
                    help='interval between training status logs (default: 10)')
args = parser.parse_args()

# 初始化CartPole環境
env = gym.make('CartPole-v1')
env.reset(seed=args.seed)
torch.manual_seed(args.seed)

# 用於儲存動作的數據結構
SavedAction = namedtuple('SavedAction', ['log_prob', 'value'])

# 定義政策網絡，同時包含行動者(Actor)和評價者(Critic)
class Policy(nn.Module):
    """
    implements both actor and critic in one model
    """
    def __init__(self):
        super(Policy, self).__init__()
        self.affine1 = nn.Linear(4, 128)

        # actor's layer
        self.action_head = nn.Linear(128, 2)

        # critic's layer
        self.value_head = nn.Linear(128, 1)

        # action & reward buffer
        self.saved_actions = []
        self.rewards = []

    def forward(self, x):
        """
        forward of both actor and critic
        """
        x = F.relu(self.affine1(x))
        action_prob = F.softmax(self.action_head(x), dim=-1)
        state_values = self.value_head(x)
        return action_prob, state_values

# 初始化模型和優化器
model = Policy()
optimizer = optim.Adam(model.parameters(), lr=3e-2)
eps = np.finfo(np.float32).eps.item()

# 根據當前狀態選擇動作
def select_action(state):
    state = torch.from_numpy(state).float()
    probs, state_value = model(state)
    m = Categorical(probs)
    action = m.sample()
    model.saved_actions.append(SavedAction(m.log_prob(action), state_value))
    return action.item()

# 完成一個回合後的訓練流程
def finish_episode():
    R = 0
    saved_actions = model.saved_actions
    policy_losses = []
    value_losses = []
    returns = []

    for r in model.rewards[::-1]:
        R = r + args.gamma * R
        returns.insert(0, R)

    returns = torch.tensor(returns)
    returns = (returns - returns.mean()) / (returns.std() + eps)

    for (log_prob, value), R in zip(saved_actions, returns):
        advantage = R - value.item()
        policy_losses.append(-log_prob * advantage)
        value_losses.append(F.smooth_l1_loss(value, torch.tensor([R])))

    optimizer.zero_grad()
    loss = torch.stack(policy_losses).sum() + torch.stack(value_losses).sum()
    loss.backward()
    optimizer.step()

    del model.rewards[:]
    del model.saved_actions[:]

# 主執行流程
def main():
    running_reward = 10

    for i_episode in count(1):
        state, _ = env.reset()
        ep_reward = 0

        for t in range(1, 10000):
            action = select_action(state)
            state, reward, done, _, _ = env.step(action)

            if args.render:
                env.render()

            model.rewards.append(reward)
            ep_reward += reward
            if done:
                break

        running_reward = 0.05 * ep_reward + (1 - 0.05) * running_reward
        finish_episode()

        if i_episode % args.log_interval == 0:
            print('Episode {}\tLast reward: {:.2f}\tAverage reward: {:.2f}'.format(
                  i_episode, ep_reward, running_reward))

        if running_reward > env.spec.reward_threshold:
            print("Solved! Running reward is now {} and "
                  "the last episode runs to {} time steps!".format(running_reward, t))
            break

if __name__ == '__main__':
    main() 

```

</div>

上面這段程式碼實在是太長了，想要將這段程式碼縮小排版，在HackMD筆記上使用滾輪捲動，我在網路上搜尋了一下，沒有看懂到底該怎麼做，所以我問了ChatGPT：
![](https://hackmd.io/_uploads/HJG4xDFkp.png)

我在網路上有看到別人提到Html語法，但我並不知道該怎麼做，ChatGPT清楚地演示可以直接在HackMD上加入Html元素，雖然ChatGPT提供的語法有小小的順序錯誤，但大抵上方向就是我要做的事情，以下是我修改後ChatGPT給的範例後成功把code block加入scroll bar的作法：
![](https://hackmd.io/_uploads/HkG2mDFkp.png)
:::

:::spoiler **寫程式**
![](https://hackmd.io/_uploads/ByHE0tqJT.png)

![](https://hackmd.io/_uploads/r1cFRKckT.png)
![](https://hackmd.io/_uploads/SJpqJ5q1a.png)
使用該程式碼，出現了第一個錯誤：
![](https://hackmd.io/_uploads/HJxEWq9ka.png)
![](https://hackmd.io/_uploads/HyVIsicyp.png)

照著做之後跑成功了：
![](https://hackmd.io/_uploads/SyRGojqJ6.png)
:::

:::spoiler **翻譯**
- 簡體中文 ---> 繁體中文
![](https://hackmd.io/_uploads/rkLCPFqJp.png)
- 數學表示 ---> latex語法
先前我請ChatGPT生成了look-ahead mask，現在我請他幫我在HackMD上表示，該結果就如同之前章節的樣子。
![](https://hackmd.io/_uploads/Ski2WncJa.png)
:::

:::spoiler **詢問資訊、尋求建議**
![](https://hackmd.io/_uploads/SJ2KFtc1a.png)

![](https://hackmd.io/_uploads/Hy45ot5ka.png)

![](https://hackmd.io/_uploads/H1Hu5i0ya.png)

:::

:::spoiler **搜尋HackMD圖片置中做法**
![](https://hackmd.io/_uploads/BycPAdA1T.png)
![](https://hackmd.io/_uploads/Syc5COA16.png)

以下是before-after示意圖：

![](https://hackmd.io/_uploads/S1piyFRk6.png)

以下的紅框為before指令，黃框為after指令：

![](https://hackmd.io/_uploads/Sy_ggK0Jp.png)
:::

:::spoiler **花式使用HackMD做標題標籤**
![](https://hackmd.io/_uploads/H1ZrlRCka.png)
![](https://hackmd.io/_uploads/Hkm8eCCkT.png)
![](https://hackmd.io/_uploads/Bk7PgCA1T.png)
![](https://hackmd.io/_uploads/BJvOlRA1a.png)
![](https://hackmd.io/_uploads/ryOtxCCkp.png)
![](https://hackmd.io/_uploads/B1gsl0RJ6.png)
![](https://hackmd.io/_uploads/ryh2lCCJT.png)
![](https://hackmd.io/_uploads/HylAx0A1T.png)

經過了多輪的調校，最後成果如讀者在[內文](##InstructGPT(2022))看到的樣子：

![](https://hackmd.io/_uploads/Hkm1e0016.png)

距離漂亮可能還有一段距離，但至少已經達到我想要讓他看起來是標籤的樣子了。
:::



:::spoiler **模仿格式（改寫格式）**
本來我舉例的排版格式如下圖的紅框，最後整理時想要讓排版改成如下圖的黃框，但是我又不想要一個一個手動改。
![](https://hackmd.io/_uploads/r1wUh50JT.png)
我下了以下prompt請萬能的ChatGPT幫幫我：
1. 提供了目標排版格式
2. 提供我想要轉換成目標排版格式的原文
3. 提示ChatGPT把第二段原文轉換為第一段的目標格式
<div style="height: 300px; overflow: auto;">

```
    以下是目標排版

    :::spoiler **未來資訊**
    我們用2023年5月[黑人牙膏改名的新聞](https://tw.news.yahoo.com/news/%E9%BB%91%E4%BA%BA%E7%89%99%E8%86%8F%E6%AD%A3%E5%90%8D%E4%BA%86-%E6%AD%A3%E5%BC%8F%E6%94%B9%E5%90%8D%E7%82%BAdarlie%E5%A5%BD%E4%BE%86-%E9%82%84%E9%82%80%E8%AB%8B%E5%89%B5%E4%BD%9C%E6%89%8D%E5%AD%90%E9%9F%8B%E7%A6%AE%E5%AE%89%E9%87%8D%E6%96%B0%E8%A9%AE%E9%87%8B%E7%9A%84%E8%80%B3%E7%86%9F%E8%83%BD%E8%A9%B3%E7%9A%84%E5%BB%A3%E5%91%8A%E4%B8%BB%E9%A1%8C%E6%9B%B2-043802063.html)來跟ChatGPT聊聊：
    ![](https://hackmd.io/_uploads/SyyeRVOya.png)

    可以看得出來ChatGPT對於時間性的內容有受過特別訓練，他明確的告知user他的訓練數據只到2022年1月。

    :::
    :::spoiler **幻覺**
    ![](https://hackmd.io/_uploads/HJHMfSd1T.png)

    由以上例子可以看到ChatGPT一本正經地在胡說八道，首先客戶沒有提到他是公務員，再者客戶只提到他的月薪，ChatGPT在回應中也有說到6萬是投保薪資，但實際上投保薪資並不等於應付健保費，接著我問問ChatGPT本人為何會亂回答：

    ![](https://hackmd.io/_uploads/ryAr8B_ya.png)

    看來ChatGPT犯了他所提到第3點的錯誤，**過度推斷**客戶的問題了。通常我們會希望客服不要肯定地回應錯誤的資訊，所以我接著問：

    ![](https://hackmd.io/_uploads/ryJoBBdkp.png)

    根據ChaGPT提示我應該要怎麼指示他：

    ![](https://hackmd.io/_uploads/H1fP5SuJp.png)

    看起來效果好了一些，但還有一個問題是客戶並沒有提到他是公務員。
    :::
    :::spoiler **ChatGPT的記憶**
    我在上面的敘述請ChatGPT幫我生成4*4的mask矩陣，接著補述想要讓他用HackMD展現，顯示他有進行多輪對話的能力：
    ![](https://hackmd.io/_uploads/Ski2WncJa.png)
    然而ChatGPT的記憶也不是永無止盡，ChatGPT-4的最大token數限制是8,192個token，ChatGPT可以記住前幾輪對話的方式是在當前訊息的之前放入歷史對話，當超過token數的限制時，我們就得再複製一次想要給ChatGPT看的內容在當前的訊息以免重要訊息因超過token數限制而沒被模型看到：
    ![](https://hackmd.io/_uploads/SkPycT5ka.png)
    :::


    :::spoiler 總結
    以上一些例子大概點出一些使用ChatGPT需要注意的地方及他的回應可能會出現的問題。最後再請ChatGPT本人幫我們複習一下：
    ![](https://hackmd.io/_uploads/ByggrAqJp.png)
    :::

    請幫我把以下文字轉換成目標排版

    - **寫程式**
        :::spoiler 
        ![](https://hackmd.io/_uploads/ByHE0tqJT.png)

        ![](https://hackmd.io/_uploads/r1cFRKckT.png)
        ![](https://hackmd.io/_uploads/SJpqJ5q1a.png)
        使用該程式碼，出現了第一個錯誤：
        ![](https://hackmd.io/_uploads/HJxEWq9ka.png)
        ![](https://hackmd.io/_uploads/HyVIsicyp.png)

        照著做之後跑成功了：
        ![](https://hackmd.io/_uploads/SyRGojqJ6.png)

    - **翻譯**
        :::spoiler 
        - 簡體中文 ---> 繁體中文
        ![](https://hackmd.io/_uploads/rkLCPFqJp.png)
        - 數學表示 ---> latex語法
        ![](https://hackmd.io/_uploads/Ski2WncJa.png)
        :::
    - **詢問資訊、尋求建議**
        :::spoiler 
        ![](https://hackmd.io/_uploads/SJ2KFtc1a.png)

        ![](https://hackmd.io/_uploads/Hy45ot5ka.png)
        :::
    - **HackMD語法**
        :::spoiler
        ![](https://hackmd.io/_uploads/BycPAdA1T.png)
        ![](https://hackmd.io/_uploads/Syc5COA16.png)

        以下是before-after示意圖：

        ![](https://hackmd.io/_uploads/S1piyFRk6.png)

        以下的紅框為before指令，黃框為after指令：

        ![](https://hackmd.io/_uploads/Sy_ggK0Jp.png)

        :::
```
</div>
接著ChatGPT成功幫我轉換了格式，我複製貼上就好：

![](https://hackmd.io/_uploads/SkqvvjCyT.png)

整理好的排版就如讀者現在可以開啟又收合的選單。我發現每一個選單都太長了，於是我問ChatGPT：

![](https://hackmd.io/_uploads/H1OgKsCkT.png)

讀者們還是暫且自己回到選單標題吧:P

:::

    
# CONCLUSION
ChatGPT大大衝擊了人類日常生活工作的模式，我們透過理解他的運作模式可以更聰明的使用他，增加我們的工作效率。
    然而，像ChatGPT-4.0的模型規模於一般使用者的設備並無法直接使用，且OpenAI也沒有將模型公開釋出，目前只能使用透過OpenAI的playground使用或是透過API呼叫，要使用ChatGPT-4.0會收取些許費用。在大型語言模型界仍有其他選擇可以深入研究，如LLaMa2在今年釋出，主打可免費商用，搭配目前正火紅的模型量化技術，一般研究者可於自己的設備上使用嘗試fine-tune，這是目前我們研究的另外一個主要領域。


# REFERENCES
1. [[Blog] ChatGPT的進化足跡](https://www.techbang.com/posts/102473-openai-footprint-chatgpt)
2. [[Blog] ChatGPT&GPT-3](https://ithelp.ithome.com.tw/articles/10310593)
3. [[Blog] GPT/GPT-2/GPT-3(判别式模型&自回歸模型AutoRegressive)](https://blog.csdn.net/hxxjxw/article/details/115391791)
4. [[Blog] GPT / GPT-2 / GPT-3 / InstructGPT 進化之路](https://zhuanlan.zhihu.com/p/609716668)
5. [[Blog] InstructGPT：Training language models to follow instructions with human feedback](https://blog.csdn.net/weixin_50833696/article/details/129712193)
6. [[Blog] 读懂chatgpt背后的原理 -- InstructGPT](https://reurl.cc/NyZRy6)
7. [[Blog] NLP 預訓練模型](https://ithelp.ithome.com.tw/articles/10304910)
8. [[Blog] GPT3.5, InstructGPT和ChatGPT的關係]( https://aitechtogether.com/python/111769.html)
9. [[OpenAI][paper] InstructGPT](https://arxiv.org/pdf/2203.02155.pdf)
10. [[OpenAI][Blog] ChatGPT](https://openai.com/blog/chatgpt)
