手把手教會你如何透過ChatGPT API實現上下文對話

coding進階發表於2023-04-03

前言

ChatGPT最近熱度持續高漲,已經成為網際網路和金融投資領域最熱門的話題。

有的小夥伴可能需要在公司搭建一套ChatGPT系統,那使用ChatGPT的API顯然是最好的選擇。

不過ChatGPT的API都是無狀態的,沒有對話管理的功能。

你呼叫API傳送一個問題(prompt)給ChatGPT,它就根據你傳送的問題返回一個結果(completion)。

那如何透過ChatGPT的API實現帶上下文功能的對話呢。

ChatGPT API

ChatGPT的API實際上是對標準的HTTP介面做了一層封裝,HTTP請求的url地址如下:

https://api.openai.com/v1/chat/completions

官方封裝了Python和Node.js庫,可以直接使用。

我們來看一段Python程式碼示例:

import os
import openai
# 設定API key
openai.api_key = os.getenv("OPENAI_API_KEY")

# 給ChatGPT傳送請求
completion = openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
    {"role": "user", "content": "Hello!"}
  ]
)

# 列印請求結果
print(completion.choices[0].message)

這段程式碼很簡單,傳送一條訊息"Hello!"給ChatGPT,然後列印結果。

這裡有3個注意事項:

​ 其中,openai.ChatCompletion用於對話。

Role角色

細心的同學可能已經發現,給ChatGPT傳送訊息的時候,引數message是個陣列,陣列裡每個dict有role這個欄位。

role目前有3個取值:

  • user。表示提交prompt的一方。
  • assistant。表示給出completion響應的一方,實際上就是ChatGPT本身。
  • system。message裡role為system,是為了讓ChatGPT在對話過程中設定自己的行為,目前role為system的訊息沒有太大的實際作用,官方說法如下:
gpt-3.5-turbo-0301 does not always pay strong attention to system messages. Future models will be trained to pay stronger attention to system messages.
# Note: you need to be using OpenAI Python v0.27.0 for the code below to work
import openai

openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Who won the world series in 2020?"},
        {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
        {"role": "user", "content": "Where was it played?"}
    ]
)

上面這段程式碼裡,使用了3種角色的role,這個messages傳送給ChatGPT後,ChatGPT就有了上下文,知道作為user的我們說了什麼,也知道作為assistant的自己回答了什麼。

想透過API實現包含上下文資訊的多輪對話的關鍵就是用好role欄位。

不含上下文的對話

import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")

while True:
    content = input("User: ")
    messages = [{"role": "user", "content": content}]
    
    completion = openai.ChatCompletion.create(
      model="gpt-3.5-turbo",
      messages=messages
    )

    chat_response = completion
    answer = chat_response.choices[0].message.content
    print(f'ChatGPT: {answer}')

上面這個實現裡,每次只傳送了當前輸入的資訊,並沒有傳送對話的歷史記錄,所以ChatGPT無法知道上下文。

我們來看對話效果如下:

$ python3 chatgpt1.py 
User: 你好
ChatGPT: 你好!我是AI助手,有什麼可以幫到您的嗎?
User: 我剛才說了什麼
ChatGPT: 很抱歉,由於我是AI語音助手,無法得知您剛才說了什麼,請您再次告知。

包含上下文的對話

import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")

messages = []
while True:
    content = input("User: ")
    messages.append({"role": "user", "content": content})
    
    completion = openai.ChatCompletion.create(
      model="gpt-3.5-turbo",
      messages=messages
    )

    chat_response = completion
    answer = chat_response.choices[0].message.content
    print(f'ChatGPT: {answer}')
    messages.append({"role": "assistant", "content": answer})

上面這個實現裡,每次傳送請求給ChatGPT時,把歷史對話記錄也一起傳送,所以ChatGPT知道對話的上下文。

我們來看對話效果如下:

$ python3 chatgpt2.py 
User: 你好
ChatGPT: 你好!我是AI助手,有什麼需要幫忙的嗎?
User: 我剛才說了什麼
ChatGPT: 你剛才說了 "你好"。

潛在的坑

目前透過API實現上下文對話有2個潛在的坑:

  • token數量問題。每次要把歷史對話記錄傳過去,會導致後續單次請求和響應消耗的token數量越來越多,超過ChatGPT模型支援的最大上下文長度,ChatGPT就無法繼續往下處理了。比如gpt-3.5-turbo支援的最大上下文長度是4097個token,如果單次請求和響應裡包含的token數量超過這個數,ChatGPT就會返回如下錯誤:

    This model's maximum context length is 4097 tokens. However, you requested 4103 tokens (2066 in the messages, 2037 in the completion). Please reduce the length of the messages or completion.
  • 費用問題。API是按照token數量收費的,這個token計算是prompt和completion的token數量總和。由於後續的請求包含的token數量越來越多,導致每次呼叫API的收費也越來越高。

那如何解決這個問題呢?

  • 第一種方式就是每次傳送請求時,不用帶上全部歷史對話記錄,只帶上最近幾輪對話的記錄。比如就帶上最近6條對話記錄(3條prompt,3條completion),減少單次請求裡包含的token數量,避免超過ChatGPT模型的最大上下文長度。
  • 第二種方式是在呼叫API的時候,限制使用者提問內容長度,以及限制返回的completion的token數量。後者可以透過給API呼叫指定max_token引數來實現,該引數的含義如下:

    The maximum number of tokens to generate in the chat completion.

    The total length of input tokens and generated tokens is limited by the model's context length.

總結

官網和ChatGPT對話的同學可能會發現,API返回的completion結果其實沒有官網的好,


透過檢視官網對話的請求資訊,發現普通使用者(非ChatGPT Plus會員)用的模型是text-davinci-002-render-sha,而這個模型在API裡無法使用。

開源地址

想知道如何註冊ChatGPT賬號以及API使用教程的可以參考我的開源教程: ChatGPT模型教程。包含ChatGPT和百度文心一言的入門和實戰教程。

公眾號:coding進階。

個人網站:Jincheng's Blog

知乎:無忌

福利

我為大家整理了一份後端開發學習資料禮包,包含程式語言入門到進階知識(Go、C++、Python)、後端開發技術棧、面試題等。

關注公眾號「coding進階」,傳送訊息 backend 領取資料禮包,這份資料會不定期更新,加入我覺得有價值的資料。還可以傳送訊息「進群」,和同行一起交流學習,答疑解惑。

References

相關文章