File size: 4,580 Bytes
a783ac1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | import os
import urllib.request
import json
import ssl
# 1. 讀取 .env 檔案中的金鑰
def load_env_variables():
# 優先嘗試使用 python-dotenv
try:
from dotenv import load_dotenv
load_dotenv('.env')
except ImportError:
pass
# 手動備用解析 .env,確保在任何環境下都能正常讀取
env_path = '.env'
if os.path.exists(env_path):
with open(env_path, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#') and '=' in line:
parts = line.split('=', 1)
key = parts[0].strip()
val = parts[1].strip().strip('\'"')
os.environ[key] = val
load_env_variables()
GEMINI_KEY = os.getenv("GEMINI_KEY") or os.getenv("GEMINI_API_KEY")
def query_gemini_with_search(prompt: str) -> dict:
"""
使用 Python 標準庫 urllib 呼叫 Gemini API,並開啟 Google Search Grounding 工具來進行實時/地圖查詢。
"""
if not GEMINI_KEY:
raise ValueError("❌ 錯誤:找不到 GEMINI_KEY 或 GEMINI_API_KEY,請確認您的 .env 檔案設定。")
# 使用支援 Google 搜尋 Grounding 的主流模型
model_name = "gemini-2.5-flash"
url = f"https://generativelanguage.googleapis.com/v1beta/models/{model_name}:generateContent?key={GEMINI_KEY}"
# 準備 Payload,啟用 Google 搜尋工具
# print('prompt', prompt)
prompt += '\n回覆請用 2 句話簡短的話回覆。'
print('prompt', prompt)
payload = {
"contents": [{
"parts": [{"text": prompt}]
}],
"tools": [{
"google_search": {}
}]
}
data = json.dumps(payload).encode('utf-8')
req = urllib.request.Request(
url,
data=data,
headers={"Content-Type": "application/json"},
method="POST"
)
# 忽略 SSL 憑證警告 (防止特定本機網路環境異常)
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
try:
with urllib.request.urlopen(req, context=ctx, timeout=30) as response:
res_data = response.read().decode('utf-8')
return json.loads(res_data)
except urllib.error.HTTPError as e:
error_msg = e.read().decode('utf-8')
print(f"\n❌ API 請求失敗:{e.code} {e.reason}")
print(f"詳細錯誤資訊:{error_msg}")
return {}
except Exception as e:
print(f"\n❌ 連線失敗:{e}")
return {}
def main():
print("=" * 60)
print("🗺️ Gemini 地圖/實時地理資訊查詢工具")
print("=" * 60)
if not GEMINI_KEY:
print("❌ 未在環境變數或 .env 中偵測到 API 金鑰。")
print("請在專案目錄下的 .env 檔案中加入:")
print("GEMINI_API_KEY=您的_API_金鑰")
return
masked_key = f"{GEMINI_KEY[:6]}...{GEMINI_KEY[-6:]}" if len(GEMINI_KEY) > 12 else "已讀取"
print(f"🔑 已載入 API 金鑰:{masked_key}")
print("💡 輸入 'exit' 或 'quit' 即可退出。")
print("-" * 60)
while True:
try:
prompt = input("\n💬 請輸入您的問題(如:尋找台北車站附近的露營用品店、大直捷運站附近的餐廳):\n👉 ").strip()
if not prompt:
continue
if prompt.lower() in ['exit', 'quit']:
print("\n👋 感謝使用,再見!")
break
print("⏳ 正在由 Gemini 查詢並搜尋地圖/網路資訊...")
result = query_gemini_with_search(prompt)
if not result:
continue
try:
candidate = result['candidates'][0]
text = candidate['content']['parts'][0]['text']
print("\n🤖 Gemini 回覆:")
print(text)
except (KeyError, IndexError) as e:
print(f"\n❌ 解析 API 回傳資料時發生錯誤:{e}")
print("原始回傳內容:", json.dumps(result, ensure_ascii=False, indent=2))
except KeyboardInterrupt:
print("\n\n👋 偵測到中斷指令,結束程式。")
break
except Exception as e:
print(f"\n❌ 發生未預期的錯誤:{e}")
if __name__ == "__main__":
main()
|