2024年9月6日 星期五

Groq Python API 文字聊天測試 (一)

上周為了交 ESP32-CAM 課程作業註冊了 Groq 的 API 金鑰, 用來填入 Arduino C 程式中與 Groq平台上的大語言模型交談, 主要是傳送圖片讓其描述圖片. 本周閒下來想要進一步用 Groq 的 Python API 來測試此模型. 註冊 Grok 金鑰參考 :



1. 安裝 groq 套件 : 

使用 Groq 的 Python API 要先用 pip 安裝 groq 套件 : 

D:\python\test>pip install groq    
Collecting groq
  Downloading groq-0.11.0-py3-none-any.whl.metadata (13 kB)
Requirement already satisfied: anyio<5,>=3.5.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from groq) (3.7.1)
Requirement already satisfied: distro<2,>=1.7.0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from groq) (1.9.0)
Requirement already satisfied: httpx<1,>=0.23.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from groq) (0.24.1)
Requirement already satisfied: pydantic<3,>=1.9.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from groq) (2.5.3)
Requirement already satisfied: sniffio in c:\users\tony1\appdata\roaming\python\python310\site-packages (from groq) (1.3.0)
Requirement already satisfied: typing-extensions<5,>=4.7 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from groq) (4.9.0)
Requirement already satisfied: idna>=2.8 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from anyio<5,>=3.5.0->groq) (3.4)
Requirement already satisfied: exceptiongroup in c:\users\tony1\appdata\roaming\python\python310\site-packages (from anyio<5,>=3.5.0->groq) (1.1.3)
Requirement already satisfied: certifi in c:\users\tony1\appdata\roaming\python\python310\site-packages (from httpx<1,>=0.23.0->groq) (2023.7.22)
Requirement already satisfied: httpcore<0.18.0,>=0.15.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from httpx<1,>=0.23.0->groq) (0.17.3)
Requirement already satisfied: annotated-types>=0.4.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pydantic<3,>=1.9.0->groq) (0.5.0)
Requirement already satisfied: pydantic-core==2.14.6 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pydantic<3,>=1.9.0->groq) (2.14.6)
Requirement already satisfied: h11<0.15,>=0.13 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from httpcore<0.18.0,>=0.15.0->httpx<1,>=0.23.0->groq) (0.14.0)
Downloading groq-0.11.0-py3-none-any.whl (106 kB)
Installing collected packages: groq
Successfully installed groq-0.11.0

檢查版本 : 

>>> import groq   
>>> groq.__version__     
'0.11.0'


2. 建立 Groq 物件呼叫 API :   

首先用自訂的 members 模組檢視 groq 套件內容 : 

>>> from members import list_members   
>>> list_members(groq)    
APIConnectionError <class 'type'>
APIError <class 'type'>
APIResponse <class 'type'>
APIResponseValidationError <class 'type'>
APIStatusError <class 'type'>
APITimeoutError <class 'type'>
AsyncAPIResponse <class 'type'>
AsyncClient <class 'type'>
AsyncGroq <class 'type'>
AsyncStream <class 'type'>
AuthenticationError <class 'type'>
BadRequestError <class 'type'>
BaseModel <class 'pydantic._internal._model_construction.ModelMetaclass'>
Client <class 'type'>
ConflictError <class 'type'>
DEFAULT_CONNECTION_LIMITS <class 'httpx.Limits'>
DEFAULT_MAX_RETRIES <class 'int'>
DEFAULT_TIMEOUT <class 'groq.Timeout'>
DefaultAsyncHttpxClient <class 'type'>
DefaultHttpxClient <class 'type'>
Groq <class 'type'>
GroqError <class 'type'>
InternalServerError <class 'type'>
NOT_GIVEN <class 'groq.NotGiven'>
NoneType <class 'type'>
NotFoundError <class 'type'>
NotGiven <class 'type'>
PermissionDeniedError <class 'type'>
ProxiesTypes <class 'typing._UnionGenericAlias'>
RateLimitError <class 'type'>
RequestOptions <class 'typing_extensions._TypedDictMeta'>
Stream <class 'type'>
Timeout <class 'type'>
Transport <class 'type'>
UnprocessableEntityError <class 'type'>
file_from_path <class 'function'>
resources <class 'module'>
types <class 'module'>

其中的 Groq 類別實作了實作了許多可供呼叫的 API 函式, 使用時要先呼叫 Groq 類別的建構式 Groq() 並傳入 api_key 參數來建立一個 Groq 物件 :

>>> api_key='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'   # 此為範例金鑰    
>>> client=Groq(api_key=api_key)      
>>> type(client)      
<class 'groq.Groq'>      

同樣用自訂的 members 模組檢視 Groq 物件內容 : 

>>> list_members(client)    
api_key <class 'str'>
audio <class 'groq.resources.audio.audio.Audio'>
auth_headers <class 'dict'>
base_url <class 'httpx.URL'>
chat <class 'groq.resources.chat.chat.Chat'>
close <class 'method'>
copy <class 'method'>
custom_auth <class 'NoneType'>
default_headers <class 'dict'>
default_query <class 'dict'>
delete <class 'method'>
embeddings <class 'groq.resources.embeddings.Embeddings'>
get <class 'method'>
get_api_list <class 'method'>
is_closed <class 'method'>
max_retries <class 'int'>
models <class 'groq.resources.models.Models'>
patch <class 'method'>
platform_headers <class 'method'>
post <class 'method'>
put <class 'method'>
qs <class 'groq._qs.Querystring'>
request <class 'method'>
timeout <class 'groq.Timeout'>
user_agent <class 'str'>
with_options <class 'method'>
with_raw_response <class 'groq._client.GroqWithRawResponse'>
with_streaming_response <class 'groq._client.GroqWithStreamedResponse'>

Groq 的 API 放在 Chat 物件的子物件 Completions 物件裡面, 只要呼叫  client.chat.completions.create() 方法並傳入 message 與 model 參數即可向 Groq 的指定模型提出請求, 參考 Groq 教學文件 :


我用茶米老師最愛用的 '愛情是甚麼' 來詢問 llama3-8b-8192 模型 :

>>> chat_completion=client.chat.completions.create( 
    messages=[ 
       
            "role": "user", 
            "content": "請問愛情是甚麼?", 
        } 
    ], 
    model="llama3-8b-8192", 
)

傳回值是一個用字典包裹的 ChatCompletion 物件 : 

>>> type(chat_completion)     
<class 'groq.types.chat.chat_completion.ChatCompletion'>     

其內容如下 ; 

>>> chat_completion    
ChatCompletion(id='chatcmpl-a90e34fd-a7f3-4e0d-87fd-56ecb467e955', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content="A question that has puzzled philosophers, psychologists, and poets for centuries! 💕\n\n愛情 (ài qíng) in Chinese, or love in English, is a complex and multifaceted emotion that can be difficult to define precisely. However, I'll try to provide a brief overview:\n\nLove is a strong feeling of affection, attachment, and commitment towards another person, place, or thing. It can manifest in various forms, such as:\n\n1. Romantic love: deep emotional connection and attachment between two people, often accompanied by feelings of passion, intimacy, and a desire to spend time together.\n2. Familial love: bond between family members, such as a parent's love for their child, sibling love, or love between partners who have a close familial relationship.\n3. Friendship love: strong emotional connection and sense of belonging with friends.\n4. Unconditional love: selfless and unwavering dedication to a person, pet, or cause, often characterized by a willingness to sacrifice one's own interests for the benefit of others.\n5. Spiritual love: deep sense of connection to a higher power, nature, or a sense of unity with all existence.\n\nLove can take many forms, and its intensity and expression can vary greatly from person to person. Some common characteristics of love include:\n\n* Tenderness and affection\n* Dedication and commitment\n* Selflessness and willingness to sacrifice\n* Emotional connection and bonding\n* Trust and loyalty\n* Joy and happiness\n\nIn many Eastern cultures, including Chinese, Confucianism and Buddhism emphasize the importance of developing loving and compassionate relationships with others, as well as cultivating a sense of inner peace and balance. In these philosophies, loving relationships are seen as a means to achieve personal growth, happiness, and spiritual fulfillment.\n\nIn summary, love is a complex and multifaceted emotion that encompasses various forms of attachment, affection, and commitment towards others, oneself, or a higher power. Its expression can vary greatly, and its importance is deeply rooted in many cultures and spiritual traditions. 💕", role='assistant', function_call=None, tool_calls=None))], created=1725520655, model='llama3-8b-8192', object='chat.completion', system_fingerprint='fp_179b0f92c9', usage=CompletionUsage(completion_tokens=415, prompt_tokens=18, total_tokens=433, completion_time=0.345833333, prompt_time=0.002827264, queue_time=0.779573253, total_time=0.348660597), x_groq={'id': 'req_01j70gqcnpfc0a81t5vzhht3qm'})

可見此模型預設都用英文回答, 我修改提示詞, 添加 "請用繁體中文 (zh_Hant) 回答" 要求它用中文回答, 注意, 這裡用 W3C 最新的繁中代號 zh_Hant 取代較舊的 zh_TW, 參考 :


也可用 zh_Hant_TW 來區別港澳台. 

>>> chat_completion=client.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": "請問愛情是甚麼? 請用繁體中文(zh_Hant)回答",
        }
    ],
    model="llama3-8b-8192",
)

結果就會用中文回答了 (但有些詞彙仍是英文) :

>>> chat_completion    
ChatCompletion(id='chatcmpl-4e1aaa7e-2407-444b-8d7d-ad002a6c840f', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='😊\n\n愛情(Love)是指兩個人之間的 emotions 和 sentiments,係由深沉的情 attachment 和 nurturing  mutual caring towards each other所產生。它是一種複雜的複合體,包括ged of strong feelings of affection, attachment, and commitment towards the other person.\n\n愛情通常有以下幾個特質:\n\n1. Compassion(同情):對对方的感受和需要,願意包容和理解。\n2. Communication(溝通):分享思想、感受和經驗,築造緊密的關係。\n3. Trust(信任):相信对方的意圖和承諾,願意共享秘密和分享生活中的喜樂和困難。\n4. Intimacy(親密):體會对方的溫柔和感受,建立著情感上的連接。\n5. Devotion(效忠):並肩作戰,共度生命的喜樂和困難,維持關係的強度和暖度。\n\n總之,愛情是一種深沉、崇高、溫柔和承擔的情感體驗,能將兩個人連接在一起,共享生命的喜樂和困難。', role='assistant', function_call=None, tool_calls=None))], created=1725520825, model='llama3-8b-8192', object='chat.completion', system_fingerprint='fp_179b0f92c9', usage=CompletionUsage(completion_tokens=261, prompt_tokens=30, total_tokens=291, completion_time=0.2175, prompt_time=0.003804458, queue_time=0.009506011, total_time=0.221304458), x_groq={'id': 'req_01j70gwk6rfcv9z9v472pn5p0b'})

可見回應內容是放在 choices 屬性值 choices 的索引 0 物件的 message 屬性值 content 內 :

>>> chat_completion.choices[0].message.content    
'😊\n\n愛情(Love)是指兩個人之間的 emotions 和 sentiments,係由深沉的情 attachment 和 nurturing  mutual caring towards each other所產生。它是一種複雜的複合體,包括ged of strong feelings of affection, attachment, and commitment towards the other person.\n\n愛情通常有以下幾個特質:\n\n1. Compassion(同情):對对方的感受和需要,願意包容和理解。\n2. Communication(溝通):分享思想、感受和經驗,築造緊密的關係。\n3. Trust(信任):相信对方的意圖和承諾,願意共享秘密和分享生活中的喜樂和困難。\n4. Intimacy(親密):體會对方的溫柔和感受,建立著情感上的連接。\n5. Devotion(效忠):並肩作戰,共度生命的喜樂和困難,維持關係的強度和暖度。\n\n總之,愛情是一種深沉、崇高、溫柔和承擔的情感體驗,能將兩個人連接在一起,共享生命的喜樂和困難。'

可見與 ChatGPT 比起來, llama3-8b-8192 模型的中文似乎不太行. 

但是如果改用 llama3-70b-8192 模型的話就會好很多 : 

>>> chat_completion=client.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": "請問愛情是甚麼? 請用繁體中文(zh_Hant)回答",
        }
    ],
    model="llama3-70b-8192",   
)  
>>> chat_completion.choices[0].message.content    
'愛情是一種複雜的情感體驗,它的定義和解釋隨著文化、時代和個人而異。但以下是對愛情的一些看法和描述:\n\n愛情是一種強烈的情感連結,它使人們之間產生深入的依戀、信賴和關心。它可以出現在親密關係、友誼、家人或其他社會關係中。\n\n愛情可以是 романтик(romantic love)的形式,即伴侶之間的情感聯繫,帶來甜蜜、溫暖和幸福的感覺。它也可以是無條件的愛(unconditional love),例如父母對孩子的愛、友人的情誼或對社會的慈悲。\n\n愛情可以根據不同的理論和模型進行解釋,例如:\n\n1. 生物學模型:愛情是一種生物化學反應,受到腦内多巴胺和OXTOCIN等激素的影響。\n2. 進化理论模型:愛情是一種演化策略,旨在提高生育和存續的機會。\n3. Attachment理论模型:愛情是一種依戀關係,與他人之間的安全感和信任感相關。\n4. 精神分析理论模型:愛情是一種潛意識的需求和慾望,反映了人格的發展和成長。\n\n無論愛情的定義和解釋如何,它都是人類生活中最重要和美麗的事情之一,它給我們帶來情感上的滿足、幸福和成長。\n\n總之,愛情是一種情感體驗,它可以跨越時間、空間和人際關係,使我們感受到情感上的連結和依戀。它是人類最基本和重要的情感之一,是我們生活中不可或缺的一部分。'

模型參數的大小果然與回應文本的品質息息相關啊!


3. 將聊天程式碼寫成函式 :   

為了簡化聊天介面, 我將上面的程式碼寫成 ask_groq() 函式 :

# ask_llm.py  
from groq import Groq

def ask_groq(prompt, api_key, model='llama3-70b-8192'):
    client=Groq(api_key=api_key)
    chat_completion=client.chat.completions.create(
        messages=[
            {"role": "user",
             "content": prompt,
             }],
        model=model,   
        )
    return chat_completion.choices[0].message.content

此函式預設使用 llama3-70b-8192 模型, 也可以傳入其他可用模型 :




例如 :

>>> from ask_llm import *    
>>> api_key='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'   # 此為範例金鑰 
>>> question='請問愛情是甚麼? 請用繁體中文(zh_Hant)回答'     
>>> answer=ask_groq(question, api_key)      
>>> answer   
'love! ❤️\n\n愛情是一種強烈的情感體驗,是人際之間的밀착和連結。它是一種複雜的感受,包含了情感、情感、承諾、信任、依賴、奉獻和回報等多種內容。\n\n愛情可以是 romance 的愛情,指的是男女之間的浪漫關係,包括戀愛、婚姻等。也可以是 familia 的愛情,指的是家人之間的親情,如父母對子女的愛、兄弟姊妹之間的感情。\n\n愛情也可以是 Platonic 的愛情,指的是不帶性情的友情,例如朋友之間的深厚情誼。甚至愛情也可以是自己對自己的愛,指的是自我acceptance 和自我接納。\n\n愛情是一種自發的感情,無法強迫或假裝。它是一種自然而然的感情流露,讓我們感受到被需要、被理解、被支持和被愛。愛情讓我們感到安全、溫暖和幸福。\n\n然而,愛情也可以是一種allenges 的感情。它可以讓我們感受到不安全、嫉妒、挫折和失去。愛情需要我們付出,放棄一些利益,和面對些挑戰和危險。\n\n總之,愛情是一種美麗而又複雜的情感體驗,是人生中最重要和最美好的部分之一。 💕'

改用 Mixtral 的 mixtral-8x7b-32768 模型 : 

>>> model='mixtral-8x7b-32768'    
>>> question='請問愛情是甚麼? 請用繁體中文(zh_Hant)回答'  
>>> answer=ask_groq(question, api_key, model)     
>>> answer   
'愛情是一種情感,是兩人之間的深刻同情、歡樂和願景的共享。愛情可以帶來極大的快樂和滋潤,也可以幫助人們在困難時aland providing support and comfort. Love often involves strong feelings of affection, attraction, and commitment to another person, and it can take many forms, such as romantic love, familial love, and platonic love. Ultimately, love is a powerful and essential human experience that can enrich our lives in many ways.'

哈哈, 只有前兩句是用中文回答. 


2024-09-17 補充 :

今天將 Groq 的文字與圖片聊天程式碼寫成一個 ask_llm.py 模組方便呼叫 : 

# ask_llm.py 
# Please install the following packages in advance:
# !pip install groq

import base64
from groq import Client

def ask_groq_text(prompt, api_key, model='llama3-70b-8192'):
    client=Client(api_key=api_key)
    chat_completion=client.chat.completions.create(
        messages=[
            {"role": "user",
             "content": prompt,
             }],
        model=model,   
        )
    return chat_completion.choices[0].message.content

def ask_groq_vision_file(prompt, file, api_key):
    client=Client(api_key=api_key)
    with open(file, 'rb') as image_file:  
        base64_image=base64.b64encode(image_file.read()).decode('utf-8')
    image_url=f'data:image/jpeg;base64,{base64_image}' 
    content=[{'type': 'text', 'text': prompt}, 
             {'type': 'image_url', 'image_url': {'url': image_url}}]
    chat_completion=client.chat.completions.create(
         messages=[{'role': 'user', 'content': content}],
         model='llava-v1.5-7b-4096-preview'
         )
    return chat_completion.choices[0].message.content

def ask_groq_vision_url(prompt, url, api_key):
    client=Client(api_key=api_key)
    content=[{'type': 'text', 'text': prompt},  
             {'type': 'image_url', 'image_url': {'url': url}}] 
    chat_completion=client.chat.completions.create(
         messages=[{'role': 'user', 'content': content}],
         model='llava-v1.5-7b-4096-preview'
         )
    return chat_completion.choices[0].message.content

使用時先從 ask_llm 模組匯入所有函式 :

>>> from ask_llm import *    

首先從隱藏檔 .env 讀取 GROQ_API_KEY 變數 :

>>> import os      
>>> from dotenv import load_dotenv   
>>> load_dotenv()   
True
>>> groq_api_key=os.environ.get('GROQ_API_KEY')   

設定提示詞後呼叫 ask_groq_text(prompt, api_key) 進行文字聊天 :

>>> prompt='甚麼是量子糾纏? 請以小學生能了解的程度簡述且用繁體中文 (zh_Hant) 回答'    
>>> print(ask_groq(prompt, groq_api_key))   
😊

量子糾纏(Quantum Entanglement)是一個非常奇怪、有趣的現象,它發生在量子世界中。

在我們日常生活中,兩個物體之間的距離越遠,牽扯的關聯就越少。例如,你和你的朋友站在兩端的街口,你做出一個動作,朋友不會馬上知道。

但是,在量子世界中,事情就不同了。當兩個粒子( tiny particles)處於量子糾纏的狀態時,無論牽扯的距離有多遠,它們之間的關聯都會保持著。

舉個簡單的例子:

想像你和你的朋友各拿了一個小球,球的顏色可能是紅色或藍色。你們站在兩端的街口,隨機翻開球,看到自己的球的顏色就是什麼顏色。

但是,如果這兩個球處於量子糾纏的狀態,你翻開球,看到自己的球是紅色的,瞬間,你朋友那端的球也一定是紅色的,無論距離有多遠 !

這是因為量子糾纏使得這兩個粒子之間的關聯非常緊密,遠遠超過我們日常生活中理解的範圍。

量子糾纏這種現象讓科學家們感到非常驚奇和困惑,但它也開啟了我們對於量子世界的理解和認識的一扇門。

Hope you understand! 😊

沒有留言 :