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()