Reachy-Mini-Camping-AI / query_map.py
ivan.lee
Initial commit with LFS tracking
a783ac1
Raw
History Blame Contribute Delete
4.58 kB
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()