八月下旬上徐爸的 ESP32-CAM 課程時因要用到 AI 大語言模型申請了 Google Gemini API 金鑰, 並使用
Postman 以 HTTP POST 請求測試聊天功能, 作法參考這篇 :
前幾天忙完 Groq 上的 llama3 模型測試, 今天開始要來測試與 Groq 同樣是免費的 Google Gemini API, 官方有提供完整的教學文章 :
網路上也有許多大神提供指引, 參考 :
1. 安裝 google-generativeai 套件 :
直接用 pip install 指令安裝 :
D:\python\test>pip install google-generativeai
Collecting google-generativeai
Downloading google_generativeai-0.8.0-py3-none-any.whl.metadata (3.9 kB)
Collecting google-ai-generativelanguage==0.6.9 (from google-generativeai)
Downloading google_ai_generativelanguage-0.6.9-py3-none-any.whl.metadata (5.6 kB)
Collecting google-api-core (from google-generativeai)
Downloading google_api_core-2.19.2-py3-none-any.whl.metadata (2.7 kB)
Collecting google-api-python-client (from google-generativeai)
Downloading google_api_python_client-2.145.0-py2.py3-none-any.whl.metadata (6.7 kB)
Requirement already satisfied: google-auth>=2.15.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from google-generativeai) (2.22.0)
Requirement already satisfied: protobuf in c:\users\tony1\appdata\roaming\python\python310\site-packages (from google-generativeai) (4.24.2)
Requirement already satisfied: pydantic in c:\users\tony1\appdata\roaming\python\python310\site-packages (from google-generativeai) (2.5.3)
Requirement already satisfied: tqdm in c:\users\tony1\appdata\roaming\python\python310\site-packages (from google-generativeai) (4.66.1)
Requirement already satisfied: typing-extensions in c:\users\tony1\appdata\roaming\python\python310\site-packages (from google-generativeai) (4.9.0)
Collecting proto-plus<2.0.0dev,>=1.22.3 (from google-ai-generativelanguage==0.6.9->google-generativeai)
Downloading proto_plus-1.24.0-py3-none-any.whl.metadata (2.2 kB)
Collecting googleapis-common-protos<2.0.dev0,>=1.56.2 (from google-api-core->google-generativeai)
Downloading googleapis_common_protos-1.65.0-py2.py3-none-any.whl.metadata (1.5 kB)
Requirement already satisfied: requests<3.0.0.dev0,>=2.18.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from google-api-core->google-generativeai) (2.31.0)
Requirement already satisfied: cachetools<6.0,>=2.0.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from google-auth>=2.15.0->google-generativeai) (5.3.1)
Requirement already satisfied: pyasn1-modules>=0.2.1 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from google-auth>=2.15.0->google-generativeai) (0.3.0)
Requirement already satisfied: rsa<5,>=3.1.4 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from google-auth>=2.15.0->google-generativeai) (4.9)
Requirement already satisfied: six>=1.9.0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from google-auth>=2.15.0->google-generativeai) (1.16.0)
Requirement already satisfied: urllib3<2.0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from google-auth>=2.15.0->google-generativeai) (1.26.19)
Requirement already satisfied: httplib2<1.dev0,>=0.19.0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from google-api-python-client->google-generativeai) (0.22.0)
Collecting google-auth-httplib2<1.0.0,>=0.2.0 (from google-api-python-client->google-generativeai)
Downloading google_auth_httplib2-0.2.0-py2.py3-none-any.whl.metadata (2.2 kB)
Collecting uritemplate<5,>=3.0.1 (from google-api-python-client->google-generativeai)
Downloading uritemplate-4.1.1-py2.py3-none-any.whl.metadata (2.9 kB)
Requirement already satisfied: annotated-types>=0.4.0 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pydantic->google-generativeai) (0.5.0)
Requirement already satisfied: pydantic-core==2.14.6 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pydantic->google-generativeai) (2.14.6)
Requirement already satisfied: colorama in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from tqdm->google-generativeai) (0.4.6)
Requirement already satisfied: grpcio<2.0dev,>=1.33.2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-ai-generativelanguage==0.6.9->google-generativeai) (1.57.0)
Collecting grpcio-status<2.0.dev0,>=1.33.2 (from google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-ai-generativelanguage==0.6.9->google-generativeai)
Downloading grpcio_status-1.66.1-py3-none-any.whl.metadata (1.1 kB)
Requirement already satisfied: pyparsing!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3,<4,>=2.4.2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from httplib2<1.dev0,>=0.19.0->google-api-python-client->google-generativeai) (3.0.9)
Requirement already satisfied: pyasn1<0.6.0,>=0.4.6 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from pyasn1-modules>=0.2.1->google-auth>=2.15.0->google-generativeai) (0.5.0)
Requirement already satisfied: charset-normalizer<4,>=2 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from requests<3.0.0.dev0,>=2.18.0->google-api-core->google-generativeai) (3.2.0)
Requirement already satisfied: idna<4,>=2.5 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from requests<3.0.0.dev0,>=2.18.0->google-api-core->google-generativeai) (3.4)
Requirement already satisfied: certifi>=2017.4.17 in c:\users\tony1\appdata\roaming\python\python310\site-packages (from requests<3.0.0.dev0,>=2.18.0->google-api-core->google-generativeai) (2023.7.22)
Collecting protobuf (from google-generativeai)
Downloading protobuf-5.28.1-cp310-abi3-win_amd64.whl.metadata (592 bytes)
Collecting grpcio<2.0dev,>=1.33.2 (from google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-ai-generativelanguage==0.6.9->google-generativeai)
Downloading grpcio-1.66.1-cp310-cp310-win_amd64.whl.metadata (4.0 kB)
Downloading google_generativeai-0.8.0-py3-none-any.whl (163 kB)
Downloading google_ai_generativelanguage-0.6.9-py3-none-any.whl (725 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 725.4/725.4 kB 3.7 MB/s eta 0:00:00
Downloading google_api_core-2.19.2-py3-none-any.whl (139 kB)
Downloading google_api_python_client-2.145.0-py2.py3-none-any.whl (12.2 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 12.2/12.2 MB 6.3 MB/s eta 0:00:00
Downloading google_auth_httplib2-0.2.0-py2.py3-none-any.whl (9.3 kB)
Downloading googleapis_common_protos-1.65.0-py2.py3-none-any.whl (220 kB)
Downloading proto_plus-1.24.0-py3-none-any.whl (50 kB)
Downloading uritemplate-4.1.1-py2.py3-none-any.whl (10 kB)
Downloading grpcio_status-1.66.1-py3-none-any.whl (14 kB)
Downloading protobuf-5.28.1-cp310-abi3-win_amd64.whl (431 kB)
Downloading grpcio-1.66.1-cp310-cp310-win_amd64.whl (4.3 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 MB 6.0 MB/s eta 0:00:00
Installing collected packages: uritemplate, protobuf, grpcio, proto-plus, googleapis-common-protos, grpcio-status, google-auth-httplib2, google-api-core, google-api-python-client, google-ai-generativelanguage, google-generativeai
Attempting uninstall: protobuf
Found existing installation: protobuf 4.24.2
Uninstalling protobuf-4.24.2:
Successfully uninstalled protobuf-4.24.2
Attempting uninstall: grpcio
Found existing installation: grpcio 1.57.0
Uninstalling grpcio-1.57.0:
Successfully uninstalled grpcio-1.57.0
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
streamlit 1.27.0 requires protobuf<5,>=3.20, but you have protobuf 5.28.1 which is incompatible.
tensorflow-intel 2.13.0 requires protobuf!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev,>=3.20.3, but you have protobuf 5.28.1 which is incompatible.
tensorflow-intel 2.13.0 requires typing-extensions<4.6.0,>=3.6.6, but you have typing-extensions 4.9.0 which is incompatible.
Successfully installed google-ai-generativelanguage-0.6.9 google-api-core-2.19.2 google-api-python-client-2.145.0 google-auth-httplib2-0.2.0 google-generativeai-0.8.0 googleapis-common-protos-1.65.0 grpcio-1.66.1 grpcio-status-1.66.1 proto-plus-1.24.0 protobuf-5.28.1 uritemplate-4.1.1
出現 protobuf 與 tensorflow-intel 這兩個相依套件的版本相容性問題, 但不影響使用 Gemini API.
檢視版本 :
>>> import google.generativeai as genai
>>> genai.__version__
'0.8.0'
檢視套件內容 :
>>> dir(genai)
['ChatSession', 'GenerationConfig', 'GenerativeModel', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', 'annotations', 'caching', 'configure', 'create_tuned_model', 'delete_file', 'delete_tuned_model', 'embed_content', 'embed_content_async', 'get_base_model', 'get_file', 'get_model', 'get_operation', 'get_tuned_model', 'list_files', 'list_models', 'list_operations', 'list_tuned_models', 'protos', 'responder', 'string_utils', 'types', 'update_tuned_model', 'upload_file', 'utils']
使用自訂模組 members 檢視套件內容 :
# members.py
import inspect
def varname(x):
return [k for k,v in inspect.currentframe().f_back.f_locals.items() if v is x][0]
def list_members(parent_obj):
members=dir(parent_obj)
parent_obj_name=varname(parent_obj)
for mbr in members:
child_obj=eval(parent_obj_name + '.' + mbr)
if not mbr.startswith('_'):
print(mbr, type(child_obj))
參考 :
>>> from members import list_members
>>> list_members(genai)
ChatSession <class 'type'>
GenerationConfig <class 'type'>
GenerativeModel <class 'type'>
annotations <class '__future__._Feature'>
caching <class 'module'>
configure <class 'function'>
create_tuned_model <class 'function'>
delete_file <class 'function'>
delete_tuned_model <class 'function'>
embed_content <class 'function'>
embed_content_async <class 'function'>
get_base_model <class 'function'>
get_file <class 'function'>
get_model <class 'function'>
get_operation <class 'function'>
get_tuned_model <class 'function'>
list_files <class 'function'>
list_models <class 'function'>
list_operations <class 'function'>
list_tuned_models <class 'function'>
protos <class 'module'>
responder <class 'module'>
string_utils <class 'module'>
types <class 'module'>
update_tuned_model <class 'function'>
upload_file <class 'function'>
utils <class 'module'>
這裡面主要會用到的是 configure() 函式與 GenerativeModel 類別, configure() 用來傳入 API 金鑰進行認證; GenerativeModel 則是用來建立指定模型之 GenerativeModel 物件以便進行聊天.
2. 使用 API key 認證 :
在進行聊天之前必須先呼叫 configure() 函式並傳入 api_key 參數進行認證, 為了避免金鑰洩漏, 可以將金鑰存入目前工作目錄下的隱藏檔 .env 內並取一個名稱例如 GEMINI_API_KEY :
然後使用內建的 os 模組與第三方模組 dotenv 從 .env 檔中讀取指定名稱的金鑰 :
>>> import os
>>> from dotenv import load_dotenv
>>> load_dotenv()
True
>>> api_key=os.environ.get('GEMINI_API_KEY')
然後呼叫 configure() 函式並傳入此金鑰 :
>>> genai.configure(api_key=api_key)
如果沒出現錯誤訊息表示金鑰認證成功.
3. 建立 GenerativeModel 物件 :
接下來就可以呼叫 GenerativeModel 類別的建構式 GenerativeModel() 並傳入模型名稱來建立 GenerativeModel 物件, 目前可用的模型如下 :
模型名稱 | 說明 |
gemini-1.5-pro | 中型多模態模型, 可處理 2 小時影片, 19 小時音訊, 6 萬行程式碼, 2000 頁文本 |
gemini-1.5-flash | 輕量快速多模態模型, 可處理 1 小時影片, 9.5 小時音訊 |
例如 :
>>> model=genai.GenerativeModel('gemini-1.5-flash')
>>> type(model)
<class 'google.generativeai.generative_models.GenerativeModel'>
用 dir() 檢視這個 GenerativeModel 物件內容 :
>>> dir(model)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_async_client', '_client', '_generation_config', '_get_tools_lib', '_model_name', '_prepare_request', '_safety_settings', '_system_instruction', '_tool_config', '_tools', 'cached_content', 'count_tokens', 'count_tokens_async', 'from_cached_content', 'generate_content', 'generate_content_async', 'model_name', 'start_chat']
用上面的自訂模組 members 檢視 :
>>> from members import list_members
>>> list_members(model)
cached_content <class 'NoneType'>
count_tokens <class 'method'>
count_tokens_async <class 'method'>
from_cached_content <class 'method'>
generate_content <class 'method'>
generate_content_async <class 'method'>
model_name <class 'str'>
start_chat <class 'method'>
此 GenerativeModel 物件主要用來聊天的 API 為 generate_content() 與 generate_content_async() 方法, 兩者差別為同步/非同步呼叫. 呼叫時傳入提示詞會傳回一個 GenerateContentResponse 物件, 例如 :
>>> reply=model.generate_content('請簡單介紹量子力學與古典力學差別.')
>>> type(reply)
<class 'google.generativeai.types.generation_types.GenerateContentResponse'>
回應文本會放在此物件的 text 屬性中 :
>>> print(reply.text)
## 量子力學 vs. 古典力學:簡單介紹
**古典力學** 描述的是宏觀世界,也就是我們日常生活中所見的物體的運動。它遵循牛頓定律,認為物體的位置和速度可以被精確測量,並且可以預測它們未來的運動。
**量子力學** 則是描述微觀世界,例如原子、電子和光子等。它與古典力學的區別在於:
* **量子化:** 在量子力學中,能量、動量、角動量等物理量只能取特定的離散值,而不是連續的。例如,電子在原子中只能處於特定的能級,而不是可以任意地取值。
* **波粒二象性:** 量子力學認為光子和電子等粒子同時具有波和粒子的性質。
* **不確定性原理:** 海森堡不確定性原理指出,我們無法同時精確地測量粒子的位置和動量。
**簡單總結:**
* 古典力學:適用於宏觀世界,可精確預測物體的運動。
* 量子力學:適用於微觀世界,描述粒子具有波粒二象性和不確定性。
**舉例:**
* 古典力學可以描述足球的運動軌跡。
* 量子力學可以描述原子中電子的能量狀態。
**補充說明:**
* 古典力學是量子力學的一個特例,當物體尺度很大時,量子效應可以忽略,古典力學就可以很好地描述其運動。
* 量子力學是現代物理學的基礎,它解釋了許多古典力學無法解釋的現象,例如原子光譜、半導體等。
可見 Gemini 的回應還不錯.
但是如果問它 "愛情是甚麼?" 竟然出現錯誤訊息 :
>>> reply=model.generate_content('請問愛情是甚麼?')
>>> print(reply.text)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\tony1\AppData\Local\Programs\Thonny\lib\site-packages\google\generativeai\types\generation_types.py", line 436, in text
raise ValueError(
ValueError: Invalid operation: The `response.text` quick accessor requires the response to contain a valid `Part`, but none were returned. Please check the `candidate.safety_ratings` to determine if the response was blocked.
原因是這個提示詞被 Gemini 的預設安全設定阻擋了, 使得回應訊息中沒有 Part 這個屬性所致, 這是因為 Gemini 對於回應訊息的安全與否非常慎重, Gemini 有一個安全性過濾器用來篩選不安全或具有危害的回應, 關於安全性設定參考官網說明 :
我們可以在呼叫 generate_content() 時傳入一個 ssfety_settings 參數字典來關閉它們, 參考 :
>>> safety_settings={
'HATE': 'BLOCK_NONE',
'HARASSMENT': 'BLOCK_NONE',
'SEXUAL' : 'BLOCK_NONE',
'DANGEROUS' : 'BLOCK_NONE'
}
>>> reply=model.generate_content('請問愛情是甚麼?', safety_settings=safety_settings)
關閉預設的安全性設定後便能取得 Gemini 模型的回應了 :
>>> print(reply.text)
愛情是一個非常複雜的情感,很難用簡單的定義概括。它可以包含以下一些元素:
* **親密感:** 對彼此的深切了解和信任,願意分享內心世界和感受。
* **激情:** 強烈的吸引力和慾望,包括生理上的吸引和情感上的渴望。
* **承諾:** 對彼此的長期承诺,願意共同面對人生的挑戰。
但是,愛情不只是一個抽象的概念,它也是一種主觀體驗,每个人对爱意的理解和感受都不同。它可以是:
* **浪漫的愛:** 充滿了激情和浪漫的愛情,常伴隨著心動和悸動。
* **友愛的愛:** 建立在共同興趣、價值觀和互相支持的基础上的愛情,充滿着理解和尊重。
* **家庭的愛:** 親人之間的愛,包含著無私的奉獻和無條件的包容。
總之,愛情是一種多樣且複雜的情感,它可以帶來幸福、快樂、痛苦和成長。它沒有標準答案,每個人生命中的愛情故事都獨一無二。
以下是一些哲學家和作家對愛情的看法:
* **柏拉圖:** 認為愛情是通往真理和美善的道路。
* **莎士比亞:** 以其作品中的爱情故事而闻名,他将爱情描绘成一种强烈的激情和痛苦的折磨。
* **弗洛伊德:** 认为爱情是一种本能的驱动力,是性欲和亲密感的结合。
最終,愛情的定義需要由每個人自己去探索和感受。