2025年3月12日 星期三

OpenAI API 學習筆記 : API 參數測試 (四)

今天繼續來測試 OpenAI API 的常用參數, 本系列前兩篇測試文章參考 :


本系列全部文章索引參考 : 


本篇主要測試 OpenAI API 的 json_format 參數. 


10. json_format 參數 : 

此參數用來指定 API 回應的格式, 其值唯一個鍵為 type 的字典, 預設為 {'type': 'text'}, 表示模型會生成純文字結果, 但可以設定為 {'type': 'json_object'} 來要求模型生成 JSON 格式的回應, 當應用程式需要 JSON 這種結構化資料時就很方便. 但使用時須注意, prompt 中必須明白提到回應要以 JSON 格式回覆才行, 否則會出現例外錯誤. 

首先同樣匯入 OpenAI 類別與建立物件 :

>>> from openai import OpenAI   
>>> api_key='填入 API key'    
>>> client=OpenAI(api_key=api_key)  

如果不傳入 json_format 參數的話, 預設就是 {'type': 'text'}, API 會傳回純文字結果 : 

>>> chat_completion=client.chat.completions.create(
    messages=[{'role': 'user', 'content': '合歡山北峰經緯度是多少?'}],
    model='gpt-3.5-turbo'
    )
>>> print(chat_completion.choices[0].message.content)    
合歡山北峰的經度為120.957250,緯度為24.144128。

這跟傳入 response_format={'type': 'text'} 結果是一樣的 : 

>>> chat_completion=client.chat.completions.create(
    model='gpt-3.5-turbo',
    messages=[
        {'role': 'user', 'content': '合歡山北峰經緯度是多少?'}
        ],
    response_format={'type': 'text'}
    )   
>>> print(chat_completion.choices[0].message.content)   
合歡山北峰的經度為120.842639度,緯度為24.155528度。

如果要讓模型回應 JSON 格式之結果, 除了要傳送 response_format 字典參數外, 還要在 prompt 中指名使用 JSON 格式回覆 :

>>> chat_completion=client.chat.completions.create(
    model='gpt-3.5-turbo',
    messages=[
        {'role': 'system', 'content': '請用 JSON 格式回答'},
        {'role': 'user', 'content': '合歡山北峰經緯度是多少?'}
        ],
    response_format={'type': 'json_object'}
    )    
>>> print(chat_completion.choices[0].message.content)    
{
    "緯度": "24.1381°N",
    "經度": "121.2739°E"
}  

這樣就能取得 JSON 格式的結構化回應了. 其實 prompt 中的 JSON 格式說明也不一定要放在 role=system 中, 直接放在 role=user 中也可以, 例如 : 

>>> chat_completion=client.chat.completions.create(
    model='gpt-3.5-turbo',
    messages=[{'role': 'user', 'content': '合歡山北峰經緯度是多少(以 json 格式)?'}],
    response_format={'type': 'json_object'}
    )   
>>> print(chat_completion.choices[0].message.content)    
{
    "latitude": "24.1586",
    "longitude": "121.2747"
}

結果鍵變成英文, 這是隨機的, 再問一次可能就回應中文了, 可以用 '以繁體中文 json 格式' 來要求 API 回覆鍵為中文的經緯度 : 

>>> chat_completion=client.chat.completions.create(
    model='gpt-3.5-turbo',
    messages=[{'role': 'user', 'content': '合歡山北峰經緯度是多少(以繁體中文 json 格式)?'}],
    response_format={'type': 'json_object'}
    )   
>>> print(chat_completion.choices[0].message.content)   
{
    "經度": "121.2715",
    "緯度": "24.1741"
}

但如果傳入 response_format={'type': 'json_object'} 參數卻沒有在 prompt 中提到要用 json 格式回覆, 那麼就會觸發 BadRequestError 例外 : 

>>> chat_completion=client.chat.completions.create(
    model='gpt-3.5-turbo',
    messages=[{'role': 'user', 'content': '合歡山北峰經緯度是多少?'}],
    response_format={'type': 'json_object'}
    )    

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\tony1\AppData\Local\Programs\Thonny\lib\site-packages\openai\_utils\_utils.py", line 275, in wrapper
    return func(*args, **kwargs)
  File "C:\Users\tony1\AppData\Local\Programs\Thonny\lib\site-packages\openai\resources\chat\completions.py", line 829, in create
    return self._post(
  File "C:\Users\tony1\AppData\Local\Programs\Thonny\lib\site-packages\openai\_base_client.py", line 1280, in post
    return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
  File "C:\Users\tony1\AppData\Local\Programs\Thonny\lib\site-packages\openai\_base_client.py", line 957, in request
    return self._request(
  File "C:\Users\tony1\AppData\Local\Programs\Thonny\lib\site-packages\openai\_base_client.py", line 1061, in _request
    raise self._make_status_error_from_response(err.response) from None
openai.BadRequestError: Error code: 400 - {'error': {'message': "'messages' must contain the word 'json' in some form, to use 'response_format' of type 'json_object'.", 'type': 'invalid_request_error', 'param': 'messages', 'code': None}}

錯誤訊息指出 : 'must contain the word 'json' in some form', 亦即一定要在 prompt 中有提及 json 這個字眼才可以. 

PS : 問了這麼多次同樣問題, GPT 模型給出的合歡山北峰經緯度數據都有些微差異, 我查詢維基百科得到的正確經緯度是北緯 24°10′53″N, 東經 121°16′54″E. 

沒有留言 :