2024年9月21日 星期六

MicroPython 學習筆記 : 用 urequests 串接 OpenAI 大語言模型

這周本來都在測試 OpenAI 與 Gemini 等 LLM, 周四突然想到 ESP8266/ESP32 用 MicroPython 不知道能否串接 OpenAI 等模型, 於是找出開發板, 複習 2022~2023 年鑽研一陣子的 xtools 函式庫, 經過這幾天的把玩, MicroPython 大致回魂了. 

不過卻發現了 xtools 的一個問題, 由於 MicroPython 在 v1.23 版用 tsl 模組替換了 ussl 模組, 使得 xtools 在呼叫 urequests 與 xrequests 的函式時會出現找不到 ussl 的錯誤, 所以我又把韌體刷回 1.19 或 1.22 版, 順便改寫 xtoold 函式庫增加了傳貼圖的 line_sticker() 與傳圖片的 line_image() 函式 (但圖片不知為何傳不出來). 

晚飯後開始來嚐試參考將之前用 requests 串接 OpenAI 模型的函式改寫為 MicroPython 版 :

def ask_gpt(prompt, api_key, model='gpt-4o-mini'):
    url='https://api.openai.com/v1/chat/completions'
    headers={'Content-Type': 'application/json',
             'Authorization': f'Bearer {api_key}'}
    json={'model': model,
          'messages': [{'role': 'user', 'content': prompt}]} 
    response=xrequests.post(url=url,headers=headers, json=json)
    reply=response.json()
    return reply['choices'][0]['message']['content']

參考 : 


但不管使用 urequests 或 xrequests 的 post() 函式提出請求都出現錯誤, 紀錄如下 : 

>>> import xrequests   
>>> def ask_gpt(prompt, api_key, model='gpt-4o-mini'):
    url='https://api.openai.com/v1/chat/completions'
    headers={'Content-Type': 'application/json',
             'Authorization': f'Bearer {api_key}'}
    json={'model': model,
          'messages': [{'role': 'user', 'content': prompt}]} 
    response=xrequests.post(url=url,headers=headers, json=json)
    reply=response.json()
    return reply['choices'][0]['message']['content']
>>> api_key='在此輸入 OpenAI API key'    
>>> prompt='Hello!'    
>>> ask_gpt(prompt, api_key)    
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in ask_gpt
  File "xrequests.py", line 124, in post
  File "xrequests.py", line 61, in request
OSError: -40   

查詢 ChatGPT 得知 OSError: -40 通常是指 SSL/TLS 連線錯誤, 有可能是把韌體刷回 v1.23 以前版本之故, 因為 MicroPython v1.23 就是用 TLS 取代 SSL 來解決安全連線問題. 

搜尋谷歌找到下面這篇文章 : 


其範例程式碼如下 :


作者直接使用 urequests 模組的 post() 就能順利地得到回應, 我在想 v1.23 版韌體的 urequests 應該也有修改, 於是把一顆 ESP32 刷回最新版 v1.23 來測試. 不使用 xtools 函式庫, 用基本的 network 連上 WiFi :

MicroPython v1.23.0 on 2024-06-02; Generic ESP32 module with ESP32
Type "help()" for more information.

>>> import network   
>>> import time    
>>> def connect_wifi(ssid, password):  
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(ssid, password)    
    while not wlan.isconnected():
        print('Connecting to WiFi...')
        time.sleep(1)    
    print('Network Config:', wlan.ifconfig())
    
>>> ssid="ASUS-RT-AX3000"    
>>> password="123456"       
>>> connect_wifi(ssid, password)   
True
Connecting to WiFi...
Connecting to WiFi...
Connecting to WiFi...
Network Config: ('192.168.50.48', '255.255.255.0', '192.168.50.1', '192.168.50.1')

連網成功後匯入 urequests, 然後修改上面的 ask_gpt() 函式, 改用 urequests.post() :

>>> import urequests
>>> def ask_gpt(prompt, api_key, model='gpt-4o-mini'):
    url='https://api.openai.com/v1/chat/completions'
    headers={'Content-Type': 'application/json',
             'Authorization': f'Bearer {api_key}'}
    json={'model': model,
          'messages': [{'role': 'user', 'content': prompt}]} 
    response=urequests.post(url=url,headers=headers, json=json)
    reply=response.json()
    return reply['choices'][0]['message']['content']

>>> prompt='Who are you?'     
>>> api_key='在此輸入 OpenAI API key'  
>>> ask_gpt(prompt, api_key)  
'I am an AI language model created by OpenAI, designed to assist with a variety of tasks, including answering questions, providing information, and generating text based on prompts. How can I help you today?'

跟它打招呼 : 

>>> prompt='Hello'   
>>> ask_gpt(prompt, api_key)      
'Hello! How can I assist you today?'   

但提示詞不能用英文以外的語言, 因為 MicroPython 只支援英文 : 

>>> prompt='嗨'     
>>> ask_gpt(prompt, api_key)    
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in ask_gpt
KeyError: choices

真不錯, 這樣一來跑 MicroPython 的開發板也能藉助 AI 增強功能了. 

補充 :

我拿一顆 ESP8266 刷 v1.23 版韌體如法炮製卻不行 : 

>>> ask_gpt(prompt, api_key)   
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in ask_gpt
  File "requests/__init__.py", line 186, in post
  File "requests/__init__.py", line 95, in request
OSError: -40

詢問 ChatGPT 答覆為 ESP8266 的硬體與其 MicroPython 堆疊對 SSL/TSL 的支援有限. 所以要用 MicroPython 作 AI 應用必須採用 ESP32, 一般 4MB Flash 的就可以, 需要處理音訊或圖片則可用 16MB Flash 的 ESP32. 

沒有留言 :