Spaces:
Sleeping
Sleeping
| import pandas as pd | |
| import requests | |
| import google.generativeai as genai | |
| import os | |
| import csv | |
| from datetime import datetime | |
| import streamlit as st | |
| import base64 | |
| import io | |
| # Streamlit 配置 | |
| st.set_page_config( | |
| page_title="台南開放資料 Gemini 分析", | |
| page_icon="📊", | |
| layout="wide", | |
| initial_sidebar_state="expanded", | |
| ) | |
| # 設定 Gemini API 金鑰 | |
| GEMINI_API_KEY = st.sidebar.text_input("Gemini API Key", "AIzaSyBxrwdxgs6JemK25piF_RFnxJ9SqKuqhEE", type="password") | |
| if GEMINI_API_KEY: | |
| # 設定 API 金鑰 | |
| genai.configure(api_key=GEMINI_API_KEY) | |
| model = genai.GenerativeModel("gemini-1.5-flash") | |
| # 準備 Session State | |
| if 'df' not in st.session_state: | |
| st.session_state.df = None | |
| if 'data_summary' not in st.session_state: | |
| st.session_state.data_summary = "" | |
| if 'chat_history' not in st.session_state: | |
| st.session_state.chat_history = [] | |
| if 'csv_log' not in st.session_state: | |
| st.session_state.csv_log = [] | |
| # 添加標題行 | |
| st.session_state.csv_log.append(["Timestamp", "User", "Gemini"]) | |
| # 函數: 記錄對話到 CSV | |
| def log_to_csv(user_message, gemini_response): | |
| timestamp = datetime.now().isoformat() | |
| st.session_state.csv_log.append([timestamp, user_message, gemini_response]) | |
| # 函數: 發送訊息到 Gemini | |
| def send_to_gemini(prompt): | |
| if not GEMINI_API_KEY: | |
| return "請先設定 Gemini API Key" | |
| try: | |
| # 組合提示詞,加入上下文 | |
| context = "" | |
| if st.session_state.df is not None: | |
| context = f"基於前面提供的台南市資料:\n{st.session_state.data_summary}\n\n" | |
| full_prompt = context + prompt | |
| # 請求 Gemini API | |
| response = model.generate_content(full_prompt) | |
| reply = response.text.strip() | |
| # 記錄到 CSV | |
| log_to_csv(prompt, reply) | |
| return reply | |
| except Exception as e: | |
| return f"⚠️ 錯誤:{str(e)}" | |
| # 函數: 抓取資料 | |
| def fetch_data(url): | |
| try: | |
| response = requests.get(url) | |
| response.raise_for_status() # 檢查是否有錯誤 | |
| # 儲存為臨時檔案 | |
| temp_file = io.BytesIO(response.content) | |
| # 讀取 CSV | |
| df = pd.read_csv(temp_file, encoding="utf-8-sig") | |
| # 更新 session state | |
| st.session_state.df = df | |
| # 準備資料摘要 | |
| st.session_state.data_summary = f""" | |
| 資料維度: {df.shape[0]} 列 x {df.shape[1]} 欄 | |
| 欄位名稱: {', '.join(df.columns)} | |
| 資料範例: | |
| {df.head(3).to_string()} | |
| """ | |
| return df | |
| except Exception as e: | |
| st.error(f"獲取資料時發生錯誤: {str(e)}") | |
| return None | |
| # 函數: 分析資料 | |
| def analyze_data(): | |
| if st.session_state.df is None: | |
| st.warning("請先獲取資料") | |
| return | |
| prompt = f"請分析以下台南市政府公開資料,說明這是什麼類型的資料,有什麼重要資訊,以及可能的應用。資料如下:\n\n{st.session_state.data_summary}" | |
| with st.spinner("Gemini 正在分析資料..."): | |
| response = send_to_gemini(prompt) | |
| # 添加到聊天歷史 | |
| st.session_state.chat_history.append(("系統", prompt)) | |
| st.session_state.chat_history.append(("Gemini", response)) | |
| # 自動切換到聊天頁籤 | |
| st.session_state.active_tab = "chat" | |
| # 側邊欄 | |
| with st.sidebar: | |
| st.title("台南開放資料 Gemini 分析") | |
| st.markdown("---") | |
| # 下載 CSV 按鈕 - 使用原生 download_button 代替 HTML 連結 | |
| st.markdown("### 下載對話記錄") | |
| # 準備 CSV 資料 | |
| csv_string = io.StringIO() | |
| writer = csv.writer(csv_string) | |
| for row in st.session_state.csv_log: | |
| writer.writerow(row) | |
| csv_bytes = csv_string.getvalue().encode('utf-8-sig') | |
| # 使用原生下載按鈕 | |
| st.download_button( | |
| label="下載對話記錄 CSV", | |
| data=csv_bytes, | |
| file_name="chat_log.csv", | |
| mime="text/csv", | |
| ) | |
| st.markdown("---") | |
| st.markdown("### 關於") | |
| st.markdown(""" | |
| 這是一個整合台南市政府開放資料和 Gemini AI 的應用程式。 | |
| - 抓取和分析台南市政府的開放資料 | |
| - 使用 Google Gemini AI 進行資料解析 | |
| - 以 CSV 格式下載分析結果和對話記錄 | |
| """) | |
| # 主頁面 - 標籤導航 | |
| if 'active_tab' not in st.session_state: | |
| st.session_state.active_tab = "data" | |
| # 標籤選擇器 | |
| tabs = ["資料展示", "Gemini 聊天"] | |
| active_tab_index = 0 if st.session_state.active_tab == "data" else 1 | |
| active_tab = st.tabs(tabs)[active_tab_index] | |
| # 資料展示頁籤 | |
| if active_tab_index == 0: | |
| with active_tab: | |
| st.header("台南市政府開放資料") | |
| # URL 輸入區 | |
| default_url = "https://data.tainan.gov.tw/dataset/c4e00530-6367-4b7d-a4ac-085965915c78/resource/fc1990ec-f94f-4845-9cfd-214072d4fbf8/download/eeb5b8ad-a10a-4f6e-a064-f4d6ead73d9d.csv" | |
| url = st.text_input("資料 URL", value=default_url) | |
| col1, col2 = st.columns([1, 5]) | |
| with col1: | |
| if st.button("獲取資料"): | |
| with st.spinner("正在獲取資料..."): | |
| fetch_data(url) | |
| with col2: | |
| if st.session_state.df is not None: | |
| if st.button("使用 Gemini 分析資料"): | |
| analyze_data() | |
| st.session_state.active_tab = "chat" | |
| st.rerun() # 修改這裡,從 experimental_rerun() 改為 rerun() | |
| # 顯示資料預覽 | |
| if st.session_state.df is not None: | |
| st.subheader("資料預覽") | |
| st.dataframe(st.session_state.df.head(10), use_container_width=True) | |
| # 顯示數據統計 | |
| st.subheader("資料統計") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.metric("資料列數", st.session_state.df.shape[0]) | |
| with col2: | |
| st.metric("資料欄數", st.session_state.df.shape[1]) | |
| # 欄位列表 | |
| st.subheader("欄位列表") | |
| st.write(", ".join(st.session_state.df.columns)) | |
| # 下載原始資料的按鈕 | |
| csv_data = st.session_state.df.to_csv(index=False).encode('utf-8-sig') | |
| st.download_button( | |
| label="下載原始資料 CSV", | |
| data=csv_data, | |
| file_name="tainan_data.csv", | |
| mime="text/csv", | |
| ) | |
| # Gemini 聊天頁籤 | |
| else: | |
| with active_tab: | |
| st.header("與 Gemini AI 對話") | |
| # 顯示聊天歷史 | |
| chat_container = st.container() | |
| with chat_container: | |
| for role, message in st.session_state.chat_history: | |
| if role == "系統": | |
| st.info(f"系統: {message}") | |
| elif role == "使用者": | |
| st.success(f"您: {message}") | |
| else: # Gemini | |
| st.markdown(f"**Gemini**: {message}") | |
| # 使用者輸入區 | |
| with st.form(key="chat_form", clear_on_submit=True): | |
| user_input = st.text_area("您的問題:", height=100) | |
| submit_button = st.form_submit_button("送出") | |
| if submit_button and user_input: | |
| # 添加使用者訊息到歷史 | |
| st.session_state.chat_history.append(("使用者", user_input)) | |
| # 獲取 Gemini 回覆 | |
| with st.spinner("Gemini 正在回應..."): | |
| response = send_to_gemini(user_input) | |
| # 添加 Gemini 回覆到歷史 | |
| st.session_state.chat_history.append(("Gemini", response)) | |
| # 重新加載頁面以顯示新消息 | |
| st.rerun() # 修改這裡,從 experimental_rerun() 改為 rerun() |