八月下旬上徐爸的 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')
>>> api_key
'API KEY 在此'
然後呼叫 configure() 函式並傳入此金鑰 :
>>> genai.configure(api_key=api_key)
如果沒出現錯誤訊息表示金鑰認證成功.
3. 建立 GenerativeModel 物件 :
接下來就可以呼叫 GenerativeModel 類別的建構式 GenerativeModel() 並傳入模型名稱來建立 GenerativeModel 物件, 目前常用的模型如下 :
模型名稱 | 說明 |
gemini-1.5-pro | 中型多模態模型, 可處理視訊/音訊/圖片/程式/文本, 可免費使用 |
gemini-1.5-flash | 輕量快速多模態模型, 可處理視訊/音訊/圖片/程式/文本, 可免費使用 |
參考 :
Flash 模型支援多達 40 種語言, 主打輕量快速, 雖然不似 Pro 版強大, 但在摘要生成, 聊天, 圖像與影片生成等功能上並沒有打多少折扣, 而且上下文窗口擴大為 32K 字元, 可與 Gemini 進行更長的對話. 免費帳戶 Pro 版每分鐘只能呼叫 2 次, Flash 版則是每秒 1500 次, 參考 :
例如 :
>>> 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)
愛情是一個非常複雜的情感,很難用簡單的定義概括。它可以包含以下一些元素:
* **親密感:** 對彼此的深切了解和信任,願意分享內心世界和感受。
* **激情:** 強烈的吸引力和慾望,包括生理上的吸引和情感上的渴望。
* **承諾:** 對彼此的長期承诺,願意共同面對人生的挑戰。
但是,愛情不只是一個抽象的概念,它也是一種主觀體驗,每个人对爱意的理解和感受都不同。它可以是:
* **浪漫的愛:** 充滿了激情和浪漫的愛情,常伴隨著心動和悸動。
* **友愛的愛:** 建立在共同興趣、價值觀和互相支持的基础上的愛情,充滿着理解和尊重。
* **家庭的愛:** 親人之間的愛,包含著無私的奉獻和無條件的包容。
總之,愛情是一種多樣且複雜的情感,它可以帶來幸福、快樂、痛苦和成長。它沒有標準答案,每個人生命中的愛情故事都獨一無二。
以下是一些哲學家和作家對愛情的看法:
* **柏拉圖:** 認為愛情是通往真理和美善的道路。
* **莎士比亞:** 以其作品中的爱情故事而闻名,他将爱情描绘成一种强烈的激情和痛苦的折磨。
* **弗洛伊德:** 认为爱情是一种本能的驱动力,是性欲和亲密感的结合。
最終,愛情的定義需要由每個人自己去探索和感受。
2024-09-17 補充 :
我在之前為了簡化 Grok 聊天寫的 ask_llm.py 模組內添加了 ask_gemini_text() 方法 :
# ask_llm.py
# Please install the following packages in advance:
# !pip install groq
# !pip install google-generativeai
import base64
from groq import Client
import google.generativeai as genai
from openai import OpenAI
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
def ask_gemini_text(prompt, api_key, model='gemini-1.5-flash'):
genai.configure(api_key=api_key)
model=genai.GenerativeModel(model)
safety_settings={
'HATE': 'BLOCK_NONE',
'HARASSMENT': 'BLOCK_NONE',
'SEXUAL' : 'BLOCK_NONE',
'DANGEROUS' : 'BLOCK_NONE'
}
reply=model.generate_content(prompt, safety_settings=safety_settings)
return reply.text
首先從隱藏檔 .env 讀取 GROQ_API_KEY 變數 :
>>> import os
>>> from dotenv import load_dotenv
>>> load_dotenv()
True
>>> gemini_api_key=os.environ.get('GEMINI_API_KEY')
使用時先從 ask_llm 模組匯入所有函式 :
>>> from ask_llm import *
設定提示詞後即可呼叫 ask_gemini() 聊天 :
>>> prompt='甚麼是量子糾纏? 請以能讓小學生了解的程度簡述並以繁體中文 (zh_Hant) 回答'
>>> print(ask_gemini_text(prompt, gemini_api_key))
想像一下,你有兩個特別的彈珠,它們是雙胞胎,雖然分開了,卻有一種神奇的聯繫。
當你把其中一個彈珠塗成紅色,另一個彈珠瞬間就會變成藍色!而且,無論它們相隔多遠,這個神奇的顏色變化都會瞬間發生。
這就是量子糾纏,兩個粒子即使相隔很遠,也能互相影響,就像兩個心靈相通的雙胞胎一樣。
不過,量子糾纏的粒子不像彈珠一樣只有紅藍兩種顏色,它們可以有很多不同的狀態,例如,它們可以同時像波一樣擴散,也可以像粒子一樣集中,而當其中一個粒子的狀態改變時,另一個粒子也會瞬間跟著改變。
量子糾纏是一個非常奇妙的現象,科學家們還在研究它的更多秘密,希望未來可以利用它來開發更先進的科技,例如量子電腦。
-------------------------------------------------
如果要呼叫 Pro 模型 model 要傳入 'gemini-pro' (每分鐘只能呼叫 2 次) :
>>> print(ask_gemini_text(prompt, gemini_api_key, 'gemini-pro'))
量子糾纏就像兩個特別的朋友,即使相隔很遠,他們也能心有靈犀。
想像一下你有兩個盒子,每個盒子裡都有一個小球。如果你打開一個盒子,發現裡面的球是紅色的,那麼你不用打開另一個盒子,你也知道另一個盒子裡的小球一定是紅色的。這兩個球就像量子糾纏的朋友,它們之間有種特別的聯繫,即使它們分開很遠,也能「感應」到彼此。
這個現象很神奇,就像魔術一樣,但它真的是自然界裡真實存在的現象。科學家們已經做過很多實驗,證明了量子糾纏是真實的。
參考 :
沒有留言 :
張貼留言