Files

1 line
73 KiB
JSON

{"repo": "aken1023/fermi-problem", "files": {"app.py": {"53c6111cf382b4db955e74601a1df884c7ed5c5b": {"t": 1785674056.9738855, "n": 12878, "h": "8cb2bc8f54a2496a", "c": "from flask import Flask, render_template, request, jsonify\nimport os\nfrom dotenv import load_dotenv\nimport requests\nimport csv\nimport datetime\nfrom pathlib import Path\nimport logging\n\n# 設定日誌記錄\nlogging.basicConfig(level=logging.INFO)\nlogger = logging.getLogger(__name__)\n\n# 加载环境变量\nload_dotenv()\n\napp = Flask(__name__)\n\n# 获取 DeepSeek API 密钥\nDEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\n# DeepSeek API URL\nDEEPSEEK_API_URL = \"https://api.deepseek.com/v1/chat/completions\"\n\n# 检查 API 密钥是否存在\nif not DEEPSEEK_API_KEY:\n logger.error(\"DEEPSEEK_API_KEY 環境變數未設定!\")\n logger.error(\"請在 Zeabur 平台設定環境變數 DEEPSEEK_API_KEY\")\n logger.error(\"或在本地建立 .env 檔案並設定\")\nelse:\n # 檢查 API 金鑰格式\n if not DEEPSEEK_API_KEY.startswith('sk-'):\n logger.warning(\"API 金鑰格式可能不正確,應該以 'sk-' 開頭\")\n logger.info(\"API 金鑰已載入\")\n\n# CSV 文件路径\nCSV_FILE = 'qa_records.csv'\n\n# IP 使用次數追蹤\nip_usage = {}\n\n\n# 初始化 CSV 文件\ndef init_csv():\n if not Path(CSV_FILE).exists():\n with open(CSV_FILE, 'w', newline='', encoding='utf-8') as file:\n writer = csv.writer(file)\n writer.writerow(['id', 'question', 'answer', 'timestamp'])\n\n\n# 确保应用启动时初始化 CSV\ninit_csv()\n\n\n# 保存问答记录到 CSV\ndef save_qa_record(question, answer):\n records = []\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.reader(file)\n records = list(reader)\n except FileNotFoundError:\n records = [['id', 'question', 'answer', 'timestamp']]\n \n new_id = len(records)\n timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')\n \n with open(CSV_FILE, 'a', newline='', encoding='utf-8') as file:\n writer = csv.writer(file)\n writer.writerow([new_id, question, answer, timestamp])\n\n\n# 获取历史问题记录\ndef get_history_questions():\n questions = []\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.DictReader(file)\n for row in reader:\n questions.append({\n 'id': row['id'],\n 'question': row['question'],\n 'timestamp': row['timestamp']\n })\n except FileNotFoundError:\n pass\n return questions[-20:] # 只返回最近20條記錄\n\n\n# 获取特定问答记录\ndef get_qa_record(record_id):\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.DictReader(file)\n for row in reader:\n if row['id'] == str(record_id):\n return {\n 'question': row['question'],\n 'answer': row['answer']\n }\n except FileNotFoundError:\n pass\n return None\n\n\n@app.route('/')\ndef index():\n history = get_history_questions()\n return render_template('index.html', history=history)\n\n\n@app.route('/api_test')\ndef api_test():\n \"\"\"API 金鑰檢測頁面\"\"\"\n return render_template('api_test.html')\n\n\n@app.route('/remaining_attempts')\ndef remaining_attempts():\n ip = request.args.get('ip')\n if ip not in ip_usage:\n ip_usage[ip] = 10 # 初始化次數\n\n remaining = ip_usage[ip]\n return jsonify({'remaining': remaining})\n\n\n@app.route('/chat', methods=['POST'])\ndef chat():\n user_message = request.json.get('message', '')\n \n if not user_message:\n return jsonify({\"error\": \"消息不能为空\"}), 400\n \n # 檢查 API 金鑰是否存在\n if not DEEPSEEK_API_KEY:\n logger.error(\"API 金鑰未設定\")\n return jsonify({\n \"error\": \"API 金鑰未設定\",\n \"details\": \"請在 Zeabur 平台設定環境變數 DEEPSEEK_API_KEY\"\n }), 500\n \n # 调用 DeepSeek API\n try:\n headers = {\n \"Authorization\": f\"Bearer {DEEPSEEK_API_KEY}\",\n \"Content-Type\": \"application/json\"\n }\n \n # 系統提示詞\n system_prompt = (\n \"請使用繁體中文回答所有問題,進行費米估算時請遵循以下步驟並完整展示推論過程:\\n\\n\"\n \"1. 分解問題:將大問題分解為可估算的小問題\\n\"\n \"2. 列出假設:明確說明每個假設的依據\\n\"\n \"3. 估算數值:對每個子問題進行合理估算\\n\"\n \"4. 計算過程:詳細展示每一步的計算過程和邏輯\\n\"\n \"5. 單位換算:清楚標示所有單位換算步驟\\n\"\n \"6. 不確定性分析:discussion估算中的不確定因素\\n\"\n \"7. 最終方程式:整理出完整的計算方程式\\n\"\n \"8. 合理性檢查:檢視最終結果是否合理\\n\\n\"\n \"請盡可能詳細地展示每個步驟,讓用戶能夠完全理解整個推論過程。\\n\\n\"\n \"如果用戶提出的問題與費米估算或推論無關,請以幽默風趣的方式拒絕回答,\"\n \"例如:「哎呀!我的大腦只有費米估算模式,其他問題可能會讓我的電路短路!\"\n \"讓我們回到估算的世界吧,例如:『台灣一年消耗多少衛生紙?』或\"\n \"『地球上有多少隻螞蟻?』這類問題才是我的專長!」\"\n )\n \n payload = {\n \"model\": \"deepseek-chat\", # 使用适当的模型名称\n \"messages\": [\n {\"role\": \"system\", \"content\": system_prompt},\n {\"role\": \"user\", \"content\": user_message}\n ],\n \"temperature\": 0.6,\n \"max_tokens\": 3000\n }\n \n logger.info(f\"發送 API 請求到 {DEEPSEEK_API_URL}\")\n response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload, timeout=60)\n \n # 詳細的錯誤處理\n if response.status_code == 401:\n logger.error(\"API 金鑰無效 (401 Unauthorized)\")\n return jsonify({\n \"error\": \"API 金鑰無效或未正確設定\",\n \"details\": \"請檢查 DEEPSEEK_API_KEY 環境變數是否正確設定在 Zeabur 平台\",\n \"status_code\": 401\n }), 401\n elif response.status_code == 403:\n logger.error(\"API 金鑰權限不足 (403 Forbidden)\")\n return jsonify({\n \"error\": \"API 金鑰權限不足\",\n \"details\": \"請檢查您的 DeepSeek 帳戶權限和 API 金鑰設定\",\n \"status_code\": 403\n }), 403\n elif response.status_code == 429:\n logger.error(\"API 請求次數已達上限 (429 Too Many Requests)\")\n return jsonify({\n \"error\": \"API 請求次數已達上限\",\n \"details\": \"請稍後再試或檢查您的 API 使用配額\",\n \"status_code\": 429\n }), 429\n elif response.status_code != 200:\n logger.error(f\"API 請求失敗,狀態碼: {response.status_code}\")\n logger.error(f\"回應內容: {response.text[:500]}\")\n return jsonify({\n \"error\": f\"API 請求失敗 (HTTP {response.status_code})\",\n \"details\": response.text[:500],\n \"status_code\": response.status_code\n }), response.status_code\n \n response.raise_for_status()\n \n ai_response = response.json()\n ai_message = ai_response.get(\"choices\", [{}])[0].get(\"message\", {}).get(\"content\", \"\")\n \n # 保存問答記錄\n save_qa_record(user_message, ai_message)\n \n return jsonify({\"response\": ai_message})\n \n except requests.exceptions.HTTPError as e:\n logger.error(f\"HTTP 錯誤: {e}\")\n status_code = e.response.status_code if hasattr(e, 'response') else 500\n return jsonify({\n \"error\": f\"API 請求失敗: {str(e)}\",\n \"status_code\": status_code\n }), status_code\n except requests.exceptions.RequestException as e:\n logger.error(f\"網路連線錯誤: {e}\")\n return jsonify({\n \"error\": f\"網路連線錯誤: {str(e)}\",\n \"details\": \"請檢查網路連線或稍後再試\"\n }), 500\n except Exception as e:\n logger.error(f\"系統錯誤: {e}\")\n return jsonify({\n \"error\": f\"系統錯誤: {str(e)}\",\n \"details\": \"請聯繫系統管理員\"\n }), 500\n\n\n@app.route('/history', methods=['GET'])\ndef history():\n questions = get_history_questions()\n return jsonify({\"history\": questions})\n\n\n@app.route('/qa/<int:record_id>', methods=['GET'])\ndef get_qa(record_id):\n record = get_qa_record(record_id)\n if record:\n return jsonify(record)\n return jsonify({\"error\": \"記錄不存在\"}), 404\n\n\n@app.route('/reset_attempts', methods=['POST'])\ndef reset_attempts():\n try:\n data = request.json\n ip = data.get('ip')\n password = data.get('password')\n \n # 簡單的密碼驗證(建議使用更安全的方式)\n if password == 'admin123': # 請更改為您的管理密碼\n if ip in ip_usage:\n ip_usage[ip] = 10 # 重置為 10 次\n return jsonify({\n \"success\": True,\n \"remaining\": ip_usage[ip],\n \"message\": \"使用次數已重置\"\n })\n else:\n return jsonify({\n \"success\": False,\n \"error\": \"IP 地址未找到\"\n }), 404\n else:\n return jsonify({\n \"success\": False,\n \"error\": \"密碼錯誤\"\n }), 401\n \n except Exception as e:\n logger.error(f\"重置使用次數時發生錯誤: {e}\")\n return jsonify({\n \"success\": False,\n \"error\": \"重置失敗\"\n }), 500\n\n\n@app.route('/check_api_key', methods=['GET'])\ndef check_api_key():\n \"\"\"檢查 DEEPSEEK_API_KEY 的狀態和有效性\"\"\"\n try:\n # 檢查環境變數是否存在\n if not DEEPSEEK_API_KEY:\n return jsonify({\n \"status\": \"error\",\n \"message\": \"API 金鑰未設定\",\n \"details\": \"請在 Zeabur 平台設定環境變數 DEEPSEEK_API_KEY\",\n \"recommendation\": \"在 Zeabur 控制台中新增環境變數 DEEPSEEK_API_KEY\"\n }), 500\n \n # 檢查 API 金鑰格式\n if not DEEPSEEK_API_KEY.startswith('sk-'):\n return jsonify({\n \"status\": \"warning\",\n \"message\": \"API 金鑰格式可能不正確\",\n \"details\": f\"API 金鑰應該以 'sk-' 開頭,目前格式: {DEEPSEEK_API_KEY[:10]}...\",\n \"recommendation\": \"請檢查 API 金鑰是否正確複製\"\n }), 400\n \n # 測試 API 連線\n headers = {\n \"Authorization\": f\"Bearer {DEEPSEEK_API_KEY}\",\n \"Content-Type\": \"application/json\"\n }\n \n test_payload = {\n \"model\": \"deepseek-chat\",\n \"messages\": [\n {\"role\": \"user\", \"content\": \"測試\"}\n ],\n \"max_tokens\": 10\n }\n \n logger.info(\"開始測試 DeepSeek API 連線\")\n response = requests.post(\n DEEPSEEK_API_URL,\n headers=headers,\n json=test_payload,\n timeout=10\n )\n \n # 分析回應\n if response.status_code == 200:\n return jsonify({\n \"status\": \"success\",\n \"message\": \"API 金鑰有效且連線正常\",\n \"details\": {\n \"api_key_format\": \"正確\",\n \"api_key_length\": len(DEEPSEEK_API_KEY),\n \"api_key_prefix\": DEEPSEEK_API_KEY[:10] + \"...\",\n \"connection_test\": \"成功\",\n \"response_time\": f\"{response.elapsed.total_seconds():.2f}秒\"\n },\n \"recommendation\": \"API 金鑰設定正確,可以正常使用\"\n })\n \n elif response.status_code == 401:\n return jsonify({\n \"status\": \"error\",\n \"message\": \"API 金鑰無效\",\n \"details\": {\n \"status_code\": 401,\n \"error_type\": \"Unauthorized\",\n \"api_key_format\": \"正確\" if DEEPSEEK_API_KEY.startswith('sk-') else \"不正確\"\n },\n \"recommendation\": \"請檢查 API 金鑰是否正確,或重新生成新的 API 金鑰\"\n }), 401\n \n elif response.status_code == 403:\n return jsonify({\n \"status\": \"error\",\n \"message\": \"API 金鑰權限不足\",\n \"details\": {\n \"status_code\": 403,\n \"error_type\": \"Forbidden\"\n },\n \"recommendation\": \"請檢查您的 DeepSeek 帳戶權限和 API 金鑰設定\"\n }), 403\n \n elif response.status_code == 429:\n return jsonify({\n \"status\": \"warning\",\n \"message\": \"API 請求次數已達上限\",\n \"details\": {\n \"status_code\": 429,\n \"error_type\": \"Too Many Requests\"\n },\n \"recommendation\": \"請稍後再試或檢查您的 API 使用配額\"\n }), 429\n \n else:\n return jsonify({\n \"status\": \"error\",\n \"message\": f\"API 測試失敗 (HTTP {response.status_code})\",\n \"details\": {\n \"status_code\": response.status_code,\n \"response_text\": response.text[:200]\n },\n \"recommendation\": \"請檢查網路連線或稍後重試\"\n }), response.status_code\n \n except requests.exceptions.Timeout:\n return jsonify({\n \"status\": \"error\",\n \"message\": \"API 連線超時\",\n \"details\": \"請求在 10 秒內未收到回應\",\n \"recommendation\": \"請檢查網路連線或稍後重試\"\n }), 408\n \n except requests.exceptions.ConnectionError:\n return jsonify({\n \"status\": \"error\",\n \"message\": \"無法連接到 DeepSeek API\",\n \"details\": \"網路連線錯誤\",\n \"recommendation\": \"請檢查網路連線或防火牆設定\"\n }), 503\n \n except Exception as e:\n logger.error(f\"API 金鑰檢查時發生錯誤: {e}\")\n return jsonify({\n \"status\": \"error\",\n \"message\": \"檢查過程中發生未知錯誤\",\n \"details\": str(e),\n \"recommendation\": \"請聯繫系統管理員\"\n }), 500\n\n\nif __name__ == '__main__':\n # 修改為監聽所有網絡介面,並指定端口\n app.run(host='0.0.0.0', port=5000, debug=True)"}, "fd252bc9efe3652de90464e071819362412a0680": {"t": 1785773576.7565305, "n": 12866, "h": "a15630a431a885fe", "c": "from flask import Flask, render_template, request, jsonify\nimport os\nfrom dotenv import load_dotenv\nimport requests\nimport csv\nimport datetime\nfrom pathlib import Path\nimport logging\n\n# 設定日誌記錄\nlogging.basicConfig(level=logging.INFO)\nlogger = logging.getLogger(__name__)\n\n# 加载环境变量\nload_dotenv()\n\napp = Flask(__name__)\n\n# 获取 DeepSeek API 密钥\nDEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\n# DeepSeek API URL\nDEEPSEEK_API_URL = \"https://api.deepseek.com/v1/chat/completions\"\n\n# 检查 API 密钥是否存在\nif not DEEPSEEK_API_KEY:\n logger.error(\"DEEPSEEK_API_KEY 環境變數未設定!\")\n logger.error(\"請在 Zeabur 平台設定環境變數 DEEPSEEK_API_KEY\")\n logger.error(\"或在本地建立 .env 檔案並設定\")\nelse:\n # 檢查 API 金鑰格式\n if not DEEPSEEK_API_KEY.startswith('sk-'):\n logger.warning(\"API 金鑰格式可能不正確,應該以 'sk-' 開頭\")\n logger.info(\"API 金鑰已載入\")\n\n# CSV 文件路径\nCSV_FILE = 'qa_records.csv'\n\n# IP 使用次數追蹤\nip_usage = {}\n\n\n# 初始化 CSV 文件\ndef init_csv():\n if not Path(CSV_FILE).exists():\n with open(CSV_FILE, 'w', newline='', encoding='utf-8') as file:\n writer = csv.writer(file)\n writer.writerow(['id', 'question', 'answer', 'timestamp'])\n\n\n# 确保应用启动时初始化 CSV\ninit_csv()\n\n\n# 保存问答记录到 CSV\ndef save_qa_record(question, answer):\n records = []\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.reader(file)\n records = list(reader)\n except FileNotFoundError:\n records = [['id', 'question', 'answer', 'timestamp']]\n \n new_id = len(records)\n timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')\n \n with open(CSV_FILE, 'a', newline='', encoding='utf-8') as file:\n writer = csv.writer(file)\n writer.writerow([new_id, question, answer, timestamp])\n\n\n# 获取历史问题记录\ndef get_history_questions():\n questions = []\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.DictReader(file)\n for row in reader:\n questions.append({\n 'id': row['id'],\n 'question': row['question'],\n 'timestamp': row['timestamp']\n })\n except FileNotFoundError:\n pass\n return questions[-20:] # 只返回最近20條記錄\n\n\n# 获取特定问答记录\ndef get_qa_record(record_id):\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.DictReader(file)\n for row in reader:\n if row['id'] == str(record_id):\n return {\n 'question': row['question'],\n 'answer': row['answer']\n }\n except FileNotFoundError:\n pass\n return None\n\n\n@app.route('/')\ndef index():\n history = get_history_questions()\n return render_template('index.html', history=history)\n\n\n@app.route('/api_test')\ndef api_test():\n \"\"\"API 金鑰檢測頁面\"\"\"\n return render_template('api_test.html')\n\n\n@app.route('/remaining_attempts')\ndef remaining_attempts():\n ip = request.args.get('ip')\n if ip not in ip_usage:\n ip_usage[ip] = 10 # 初始化次數\n\n remaining = ip_usage[ip]\n return jsonify({'remaining': remaining})\n\n\n@app.route('/chat', methods=['POST'])\ndef chat():\n user_message = request.json.get('message', '')\n \n if not user_message:\n return jsonify({\"error\": \"消息不能为空\"}), 400\n \n # 檢查 API 金鑰是否存在\n if not DEEPSEEK_API_KEY:\n logger.error(\"API 金鑰未設定\")\n return jsonify({\n \"error\": \"API 金鑰未設定\",\n \"details\": \"請在 Zeabur 平台設定環境變數 DEEPSEEK_API_KEY\"\n }), 500\n \n # 调用 DeepSeek API\n try:\n headers = {\n \"Authorization\": f\"Bearer {DEEPSEEK_API_KEY}\",\n \"Content-Type\": \"application/json\"\n }\n \n # 系統提示詞\n system_prompt = (\n \"請使用繁體中文回答所有問題,進行費米估算時請遵循以下步驟並完整展示推論過程:\\n\\n\"\n \"1. 分解問題:將大問題分解為可估算的小問題\\n\"\n \"2. 列出假設:明確說明每個假設的依據\\n\"\n \"3. 估算數值:對每個子問題進行合理估算\\n\"\n \"4. 計算過程:詳細展示每一步的計算過程和邏輯\\n\"\n \"5. 單位換算:清楚標示所有單位換算步驟\\n\"\n \"6. 不確定性分析:discussion估算中的不確定因素\\n\"\n \"7. 最終方程式:整理出完整的計算方程式\\n\"\n \"8. 合理性檢查:檢視最終結果是否合理\\n\\n\"\n \"請盡可能詳細地展示每個步驟,讓用戶能夠完全理解整個推論過程。\\n\\n\"\n \"如果用戶提出的問題與費米估算或推論無關,請以幽默風趣的方式拒絕回答,\"\n \"例如:「哎呀!我的大腦只有費米估算模式,其他問題可能會讓我的電路短路!\"\n \"讓我們回到估算的世界吧,例如:『台灣一年消耗多少衛生紙?』或\"\n \"『地球上有多少隻螞蟻?』這類問題才是我的專長!」\"\n )\n \n payload = {\n \"model\": \"deepseek-chat\", # 使用适当的模型名称\n \"messages\": [\n {\"role\": \"system\", \"content\": system_prompt},\n {\"role\": \"user\", \"content\": user_message}\n ],\n \"temperature\": 0.6,\n \"max_tokens\": 3000\n }\n \n logger.info(f\"發送 API 請求到 {DEEPSEEK_API_URL}\")\n response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload)\n \n # 詳細的錯誤處理\n if response.status_code == 401:\n logger.error(\"API 金鑰無效 (401 Unauthorized)\")\n return jsonify({\n \"error\": \"API 金鑰無效或未正確設定\",\n \"details\": \"請檢查 DEEPSEEK_API_KEY 環境變數是否正確設定在 Zeabur 平台\",\n \"status_code\": 401\n }), 401\n elif response.status_code == 403:\n logger.error(\"API 金鑰權限不足 (403 Forbidden)\")\n return jsonify({\n \"error\": \"API 金鑰權限不足\",\n \"details\": \"請檢查您的 DeepSeek 帳戶權限和 API 金鑰設定\",\n \"status_code\": 403\n }), 403\n elif response.status_code == 429:\n logger.error(\"API 請求次數已達上限 (429 Too Many Requests)\")\n return jsonify({\n \"error\": \"API 請求次數已達上限\",\n \"details\": \"請稍後再試或檢查您的 API 使用配額\",\n \"status_code\": 429\n }), 429\n elif response.status_code != 200:\n logger.error(f\"API 請求失敗,狀態碼: {response.status_code}\")\n logger.error(f\"回應內容: {response.text[:500]}\")\n return jsonify({\n \"error\": f\"API 請求失敗 (HTTP {response.status_code})\",\n \"details\": response.text[:500],\n \"status_code\": response.status_code\n }), response.status_code\n \n response.raise_for_status()\n \n ai_response = response.json()\n ai_message = ai_response.get(\"choices\", [{}])[0].get(\"message\", {}).get(\"content\", \"\")\n \n # 保存問答記錄\n save_qa_record(user_message, ai_message)\n \n return jsonify({\"response\": ai_message})\n \n except requests.exceptions.HTTPError as e:\n logger.error(f\"HTTP 錯誤: {e}\")\n status_code = e.response.status_code if hasattr(e, 'response') else 500\n return jsonify({\n \"error\": f\"API 請求失敗: {str(e)}\",\n \"status_code\": status_code\n }), status_code\n except requests.exceptions.RequestException as e:\n logger.error(f\"網路連線錯誤: {e}\")\n return jsonify({\n \"error\": f\"網路連線錯誤: {str(e)}\",\n \"details\": \"請檢查網路連線或稍後再試\"\n }), 500\n except Exception as e:\n logger.error(f\"系統錯誤: {e}\")\n return jsonify({\n \"error\": f\"系統錯誤: {str(e)}\",\n \"details\": \"請聯繫系統管理員\"\n }), 500\n\n\n@app.route('/history', methods=['GET'])\ndef history():\n questions = get_history_questions()\n return jsonify({\"history\": questions})\n\n\n@app.route('/qa/<int:record_id>', methods=['GET'])\ndef get_qa(record_id):\n record = get_qa_record(record_id)\n if record:\n return jsonify(record)\n return jsonify({\"error\": \"記錄不存在\"}), 404\n\n\n@app.route('/reset_attempts', methods=['POST'])\ndef reset_attempts():\n try:\n data = request.json\n ip = data.get('ip')\n password = data.get('password')\n \n # 簡單的密碼驗證(建議使用更安全的方式)\n if password == 'admin123': # 請更改為您的管理密碼\n if ip in ip_usage:\n ip_usage[ip] = 10 # 重置為 10 次\n return jsonify({\n \"success\": True,\n \"remaining\": ip_usage[ip],\n \"message\": \"使用次數已重置\"\n })\n else:\n return jsonify({\n \"success\": False,\n \"error\": \"IP 地址未找到\"\n }), 404\n else:\n return jsonify({\n \"success\": False,\n \"error\": \"密碼錯誤\"\n }), 401\n \n except Exception as e:\n logger.error(f\"重置使用次數時發生錯誤: {e}\")\n return jsonify({\n \"success\": False,\n \"error\": \"重置失敗\"\n }), 500\n\n\n@app.route('/check_api_key', methods=['GET'])\ndef check_api_key():\n \"\"\"檢查 DEEPSEEK_API_KEY 的狀態和有效性\"\"\"\n try:\n # 檢查環境變數是否存在\n if not DEEPSEEK_API_KEY:\n return jsonify({\n \"status\": \"error\",\n \"message\": \"API 金鑰未設定\",\n \"details\": \"請在 Zeabur 平台設定環境變數 DEEPSEEK_API_KEY\",\n \"recommendation\": \"在 Zeabur 控制台中新增環境變數 DEEPSEEK_API_KEY\"\n }), 500\n \n # 檢查 API 金鑰格式\n if not DEEPSEEK_API_KEY.startswith('sk-'):\n return jsonify({\n \"status\": \"warning\",\n \"message\": \"API 金鑰格式可能不正確\",\n \"details\": f\"API 金鑰應該以 'sk-' 開頭,目前格式: {DEEPSEEK_API_KEY[:10]}...\",\n \"recommendation\": \"請檢查 API 金鑰是否正確複製\"\n }), 400\n \n # 測試 API 連線\n headers = {\n \"Authorization\": f\"Bearer {DEEPSEEK_API_KEY}\",\n \"Content-Type\": \"application/json\"\n }\n \n test_payload = {\n \"model\": \"deepseek-chat\",\n \"messages\": [\n {\"role\": \"user\", \"content\": \"測試\"}\n ],\n \"max_tokens\": 10\n }\n \n logger.info(\"開始測試 DeepSeek API 連線\")\n response = requests.post(\n DEEPSEEK_API_URL,\n headers=headers,\n json=test_payload,\n timeout=10\n )\n \n # 分析回應\n if response.status_code == 200:\n return jsonify({\n \"status\": \"success\",\n \"message\": \"API 金鑰有效且連線正常\",\n \"details\": {\n \"api_key_format\": \"正確\",\n \"api_key_length\": len(DEEPSEEK_API_KEY),\n \"api_key_prefix\": DEEPSEEK_API_KEY[:10] + \"...\",\n \"connection_test\": \"成功\",\n \"response_time\": f\"{response.elapsed.total_seconds():.2f}秒\"\n },\n \"recommendation\": \"API 金鑰設定正確,可以正常使用\"\n })\n \n elif response.status_code == 401:\n return jsonify({\n \"status\": \"error\",\n \"message\": \"API 金鑰無效\",\n \"details\": {\n \"status_code\": 401,\n \"error_type\": \"Unauthorized\",\n \"api_key_format\": \"正確\" if DEEPSEEK_API_KEY.startswith('sk-') else \"不正確\"\n },\n \"recommendation\": \"請檢查 API 金鑰是否正確,或重新生成新的 API 金鑰\"\n }), 401\n \n elif response.status_code == 403:\n return jsonify({\n \"status\": \"error\",\n \"message\": \"API 金鑰權限不足\",\n \"details\": {\n \"status_code\": 403,\n \"error_type\": \"Forbidden\"\n },\n \"recommendation\": \"請檢查您的 DeepSeek 帳戶權限和 API 金鑰設定\"\n }), 403\n \n elif response.status_code == 429:\n return jsonify({\n \"status\": \"warning\",\n \"message\": \"API 請求次數已達上限\",\n \"details\": {\n \"status_code\": 429,\n \"error_type\": \"Too Many Requests\"\n },\n \"recommendation\": \"請稍後再試或檢查您的 API 使用配額\"\n }), 429\n \n else:\n return jsonify({\n \"status\": \"error\",\n \"message\": f\"API 測試失敗 (HTTP {response.status_code})\",\n \"details\": {\n \"status_code\": response.status_code,\n \"response_text\": response.text[:200]\n },\n \"recommendation\": \"請檢查網路連線或稍後重試\"\n }), response.status_code\n \n except requests.exceptions.Timeout:\n return jsonify({\n \"status\": \"error\",\n \"message\": \"API 連線超時\",\n \"details\": \"請求在 10 秒內未收到回應\",\n \"recommendation\": \"請檢查網路連線或稍後重試\"\n }), 408\n \n except requests.exceptions.ConnectionError:\n return jsonify({\n \"status\": \"error\",\n \"message\": \"無法連接到 DeepSeek API\",\n \"details\": \"網路連線錯誤\",\n \"recommendation\": \"請檢查網路連線或防火牆設定\"\n }), 503\n \n except Exception as e:\n logger.error(f\"API 金鑰檢查時發生錯誤: {e}\")\n return jsonify({\n \"status\": \"error\",\n \"message\": \"檢查過程中發生未知錯誤\",\n \"details\": str(e),\n \"recommendation\": \"請聯繫系統管理員\"\n }), 500\n\n\nif __name__ == '__main__':\n # 修改為監聽所有網絡介面,並指定端口\n app.run(host='0.0.0.0', port=5000, debug=True)"}, "32b4b13d7126addca0939d6e3d75317a17831950": {"t": 1785773578.2746475, "n": 8371, "h": "237d3436f3b6800e", "c": "from flask import Flask, render_template, request, jsonify\nimport os\nfrom dotenv import load_dotenv\nimport requests\nimport csv\nimport datetime\nfrom pathlib import Path\nimport logging\n\n# 設定日誌記錄\nlogging.basicConfig(level=logging.INFO)\nlogger = logging.getLogger(__name__)\n\n# 加载环境变量\nload_dotenv()\n\napp = Flask(__name__)\n\n# 获取 DeepSeek API 密钥\nDEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\n# DeepSeek API URL\nDEEPSEEK_API_URL = \"https://api.deepseek.com/v1/chat/completions\"\n\n# 检查 API 密钥是否存在\nif not DEEPSEEK_API_KEY:\n logger.error(\"DEEPSEEK_API_KEY 環境變數未設定!\")\n logger.error(\"請在 Zeabur 平台設定環境變數 DEEPSEEK_API_KEY\")\n logger.error(\"或在本地建立 .env 檔案並設定\")\nelse:\n # 檢查 API 金鑰格式\n if not DEEPSEEK_API_KEY.startswith('sk-'):\n logger.warning(\"API 金鑰格式可能不正確,應該以 'sk-' 開頭\")\n logger.info(\"API 金鑰已載入\")\n\n# CSV 文件路径\nCSV_FILE = 'qa_records.csv'\n\n# IP 使用次數追蹤\nip_usage = {}\n\n\n# 初始化 CSV 文件\ndef init_csv():\n if not Path(CSV_FILE).exists():\n with open(CSV_FILE, 'w', newline='', encoding='utf-8') as file:\n writer = csv.writer(file)\n writer.writerow(['id', 'question', 'answer', 'timestamp'])\n\n\n# 确保应用启动时初始化 CSV\ninit_csv()\n\n\n# 保存问答记录到 CSV\ndef save_qa_record(question, answer):\n records = []\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.reader(file)\n records = list(reader)\n except FileNotFoundError:\n records = [['id', 'question', 'answer', 'timestamp']]\n \n new_id = len(records)\n timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')\n \n with open(CSV_FILE, 'a', newline='', encoding='utf-8') as file:\n writer = csv.writer(file)\n writer.writerow([new_id, question, answer, timestamp])\n\n\n# 获取历史问题记录\ndef get_history_questions():\n questions = []\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.DictReader(file)\n for row in reader:\n questions.append({\n 'id': row['id'],\n 'question': row['question'],\n 'timestamp': row['timestamp']\n })\n except FileNotFoundError:\n pass\n return questions[-20:] # 只返回最近20條記錄\n\n\n# 获取特定问答记录\ndef get_qa_record(record_id):\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.DictReader(file)\n for row in reader:\n if row['id'] == str(record_id):\n return {\n 'question': row['question'],\n 'answer': row['answer']\n }\n except FileNotFoundError:\n pass\n return None\n\n\n@app.route('/')\ndef index():\n history = get_history_questions()\n return render_template('index.html', history=history)\n\n\n@app.route('/remaining_attempts')\ndef remaining_attempts():\n ip = request.args.get('ip')\n if ip not in ip_usage:\n ip_usage[ip] = 10 # 初始化次數\n\n remaining = ip_usage[ip]\n return jsonify({'remaining': remaining})\n\n\n@app.route('/chat', methods=['POST'])\ndef chat():\n user_message = request.json.get('message', '')\n \n if not user_message:\n return jsonify({\"error\": \"消息不能为空\"}), 400\n \n # 檢查 API 金鑰是否存在\n if not DEEPSEEK_API_KEY:\n logger.error(\"API 金鑰未設定\")\n return jsonify({\n \"error\": \"API 金鑰未設定\",\n \"details\": \"請在 Zeabur 平台設定環境變數 DEEPSEEK_API_KEY\"\n }), 500\n \n # 调用 DeepSeek API\n try:\n headers = {\n \"Authorization\": f\"Bearer {DEEPSEEK_API_KEY}\",\n \"Content-Type\": \"application/json\"\n }\n \n # 系統提示詞\n system_prompt = (\n \"請使用繁體中文回答所有問題,進行費米估算時請遵循以下步驟並完整展示推論過程:\\n\\n\"\n \"1. 分解問題:將大問題分解為可估算的小問題\\n\"\n \"2. 列出假設:明確說明每個假設的依據\\n\"\n \"3. 估算數值:對每個子問題進行合理估算\\n\"\n \"4. 計算過程:詳細展示每一步的計算過程和邏輯\\n\"\n \"5. 單位換算:清楚標示所有單位換算步驟\\n\"\n \"6. 不確定性分析:discussion估算中的不確定因素\\n\"\n \"7. 最終方程式:整理出完整的計算方程式\\n\"\n \"8. 合理性檢查:檢視最終結果是否合理\\n\\n\"\n \"請盡可能詳細地展示每個步驟,讓用戶能夠完全理解整個推論過程。\\n\\n\"\n \"如果用戶提出的問題與費米估算或推論無關,請以幽默風趣的方式拒絕回答,\"\n \"例如:「哎呀!我的大腦只有費米估算模式,其他問題可能會讓我的電路短路!\"\n \"讓我們回到估算的世界吧,例如:『台灣一年消耗多少衛生紙?』或\"\n \"『地球上有多少隻螞蟻?』這類問題才是我的專長!」\"\n )\n \n payload = {\n \"model\": \"deepseek-chat\", # 使用适当的模型名称\n \"messages\": [\n {\"role\": \"system\", \"content\": system_prompt},\n {\"role\": \"user\", \"content\": user_message}\n ],\n \"temperature\": 0.6,\n \"max_tokens\": 3000\n }\n \n logger.info(f\"發送 API 請求到 {DEEPSEEK_API_URL}\")\n response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload)\n \n # 詳細的錯誤處理\n if response.status_code == 401:\n logger.error(\"API 金鑰無效 (401 Unauthorized)\")\n return jsonify({\n \"error\": \"API 金鑰無效或未正確設定\",\n \"details\": \"請檢查 DEEPSEEK_API_KEY 環境變數是否正確設定在 Zeabur 平台\",\n \"status_code\": 401\n }), 401\n elif response.status_code == 403:\n logger.error(\"API 金鑰權限不足 (403 Forbidden)\")\n return jsonify({\n \"error\": \"API 金鑰權限不足\",\n \"details\": \"請檢查您的 DeepSeek 帳戶權限和 API 金鑰設定\",\n \"status_code\": 403\n }), 403\n elif response.status_code == 429:\n logger.error(\"API 請求次數已達上限 (429 Too Many Requests)\")\n return jsonify({\n \"error\": \"API 請求次數已達上限\",\n \"details\": \"請稍後再試或檢查您的 API 使用配額\",\n \"status_code\": 429\n }), 429\n elif response.status_code != 200:\n logger.error(f\"API 請求失敗,狀態碼: {response.status_code}\")\n return jsonify({\n \"error\": f\"API 請求失敗 (HTTP {response.status_code})\",\n \"details\": response.text,\n \"status_code\": response.status_code\n }), response.status_code\n \n response.raise_for_status()\n \n ai_response = response.json()\n ai_message = ai_response.get(\"choices\", [{}])[0].get(\"message\", {}).get(\"content\", \"\")\n \n # 保存問答記錄\n save_qa_record(user_message, ai_message)\n \n return jsonify({\"response\": ai_message})\n \n except requests.exceptions.HTTPError as e:\n logger.error(f\"HTTP 錯誤: {e}\")\n status_code = e.response.status_code if hasattr(e, 'response') else 500\n return jsonify({\n \"error\": f\"API 請求失敗: {str(e)}\",\n \"status_code\": status_code\n }), status_code\n except requests.exceptions.RequestException as e:\n logger.error(f\"網路連線錯誤: {e}\")\n return jsonify({\n \"error\": f\"網路連線錯誤: {str(e)}\",\n \"details\": \"請檢查網路連線或稍後再試\"\n }), 500\n except Exception as e:\n logger.error(f\"系統錯誤: {e}\")\n return jsonify({\n \"error\": f\"系統錯誤: {str(e)}\",\n \"details\": \"請聯繫系統管理員\"\n }), 500\n\n\n@app.route('/history', methods=['GET'])\ndef history():\n questions = get_history_questions()\n return jsonify({\"history\": questions})\n\n\n@app.route('/qa/<int:record_id>', methods=['GET'])\ndef get_qa(record_id):\n record = get_qa_record(record_id)\n if record:\n return jsonify(record)\n return jsonify({\"error\": \"記錄不存在\"}), 404\n\n\n@app.route('/reset_attempts', methods=['POST'])\ndef reset_attempts():\n try:\n data = request.json\n ip = data.get('ip')\n password = data.get('password')\n \n # 簡單的密碼驗證(建議使用更安全的方式)\n if password == 'admin123': # 請更改為您的管理密碼\n if ip in ip_usage:\n ip_usage[ip] = 10 # 重置為 10 次\n return jsonify({\n \"success\": True,\n \"remaining\": ip_usage[ip],\n \"message\": \"使用次數已重置\"\n })\n else:\n return jsonify({\n \"success\": False,\n \"error\": \"IP 地址未找到\"\n }), 404\n else:\n return jsonify({\n \"success\": False,\n \"error\": \"密碼錯誤\"\n }), 401\n \n except Exception as e:\n logger.error(f\"重置使用次數時發生錯誤: {e}\")\n return jsonify({\n \"success\": False,\n \"error\": \"重置失敗\"\n }), 500\n\n\nif __name__ == '__main__':\n # 修改為監聽所有網絡介面,並指定端口\n app.run(host='0.0.0.0', port=5000, debug=True)"}, "014c42f845bcf0e74d52e37d376942cf0cbe3d7a": {"t": 1785773580.011394, "n": 7389, "h": "52218bd0f82db799", "c": "from flask import Flask, render_template, request, jsonify\nimport os\nfrom dotenv import load_dotenv\nimport requests\nimport csv\nimport datetime\nfrom pathlib import Path\nimport logging\n\n# 設定日誌記錄\nlogging.basicConfig(level=logging.INFO)\nlogger = logging.getLogger(__name__)\n\n# 加载环境变量\nload_dotenv()\n\napp = Flask(__name__)\n\n# 获取 DeepSeek API 密钥\nDEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\n# DeepSeek API URL\nDEEPSEEK_API_URL = \"https://api.deepseek.com/v1/chat/completions\"\n\n# 检查 API 密钥是否存在\nif not DEEPSEEK_API_KEY:\n logger.error(\"DEEPSEEK_API_KEY 環境變數未設定!\")\n logger.error(\"請在 Zeabur 平台設定環境變數 DEEPSEEK_API_KEY\")\n logger.error(\"或在本地建立 .env 檔案並設定\")\nelse:\n # 檢查 API 金鑰格式\n if not DEEPSEEK_API_KEY.startswith('sk-'):\n logger.warning(\"API 金鑰格式可能不正確,應該以 'sk-' 開頭\")\n logger.info(\"API 金鑰已載入\")\n\n# CSV 文件路径\nCSV_FILE = 'qa_records.csv'\n\n# IP 使用次數追蹤\nip_usage = {}\n\n\n# 初始化 CSV 文件\ndef init_csv():\n if not Path(CSV_FILE).exists():\n with open(CSV_FILE, 'w', newline='', encoding='utf-8') as file:\n writer = csv.writer(file)\n writer.writerow(['id', 'question', 'answer', 'timestamp'])\n\n\n# 确保应用启动时初始化 CSV\ninit_csv()\n\n\n# 保存问答记录到 CSV\ndef save_qa_record(question, answer):\n records = []\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.reader(file)\n records = list(reader)\n except FileNotFoundError:\n records = [['id', 'question', 'answer', 'timestamp']]\n \n new_id = len(records)\n timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')\n \n with open(CSV_FILE, 'a', newline='', encoding='utf-8') as file:\n writer = csv.writer(file)\n writer.writerow([new_id, question, answer, timestamp])\n\n\n# 获取历史问题记录\ndef get_history_questions():\n questions = []\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.DictReader(file)\n for row in reader:\n questions.append({\n 'id': row['id'],\n 'question': row['question'],\n 'timestamp': row['timestamp']\n })\n except FileNotFoundError:\n pass\n return questions[-20:] # 只返回最近20條記錄\n\n\n# 获取特定问答记录\ndef get_qa_record(record_id):\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.DictReader(file)\n for row in reader:\n if row['id'] == str(record_id):\n return {\n 'question': row['question'],\n 'answer': row['answer']\n }\n except FileNotFoundError:\n pass\n return None\n\n\n@app.route('/')\ndef index():\n history = get_history_questions()\n return render_template('index.html', history=history)\n\n\n@app.route('/remaining_attempts')\ndef remaining_attempts():\n ip = request.args.get('ip')\n if ip not in ip_usage:\n ip_usage[ip] = 10 # 初始化次數\n\n remaining = ip_usage[ip]\n return jsonify({'remaining': remaining})\n\n\n@app.route('/chat', methods=['POST'])\ndef chat():\n user_message = request.json.get('message', '')\n \n if not user_message:\n return jsonify({\"error\": \"消息不能为空\"}), 400\n \n # 檢查 API 金鑰是否存在\n if not DEEPSEEK_API_KEY:\n logger.error(\"API 金鑰未設定\")\n return jsonify({\n \"error\": \"API 金鑰未設定\",\n \"details\": \"請在 Zeabur 平台設定環境變數 DEEPSEEK_API_KEY\"\n }), 500\n \n # 调用 DeepSeek API\n try:\n headers = {\n \"Authorization\": f\"Bearer {DEEPSEEK_API_KEY}\",\n \"Content-Type\": \"application/json\"\n }\n \n # 系統提示詞\n system_prompt = (\n \"請使用繁體中文回答所有問題,進行費米估算時請遵循以下步驟並完整展示推論過程:\\n\\n\"\n \"1. 分解問題:將大問題分解為可估算的小問題\\n\"\n \"2. 列出假設:明確說明每個假設的依據\\n\"\n \"3. 估算數值:對每個子問題進行合理估算\\n\"\n \"4. 計算過程:詳細展示每一步的計算過程和邏輯\\n\"\n \"5. 單位換算:清楚標示所有單位換算步驟\\n\"\n \"6. 不確定性分析:discussion估算中的不確定因素\\n\"\n \"7. 最終方程式:整理出完整的計算方程式\\n\"\n \"8. 合理性檢查:檢視最終結果是否合理\\n\\n\"\n \"請盡可能詳細地展示每個步驟,讓用戶能夠完全理解整個推論過程。\\n\\n\"\n \"如果用戶提出的問題與費米估算或推論無關,請以幽默風趣的方式拒絕回答,\"\n \"例如:「哎呀!我的大腦只有費米估算模式,其他問題可能會讓我的電路短路!\"\n \"讓我們回到估算的世界吧,例如:『台灣一年消耗多少衛生紙?』或\"\n \"『地球上有多少隻螞蟻?』這類問題才是我的專長!」\"\n )\n \n payload = {\n \"model\": \"deepseek-chat\", # 使用适当的模型名称\n \"messages\": [\n {\"role\": \"system\", \"content\": system_prompt},\n {\"role\": \"user\", \"content\": user_message}\n ],\n \"temperature\": 0.6,\n \"max_tokens\": 3000\n }\n \n logger.info(f\"發送 API 請求到 {DEEPSEEK_API_URL}\")\n response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload)\n \n # 詳細的錯誤處理\n if response.status_code == 401:\n logger.error(\"API 金鑰無效 (401 Unauthorized)\")\n return jsonify({\n \"error\": \"API 金鑰無效或未正確設定\",\n \"details\": \"請檢查 DEEPSEEK_API_KEY 環境變數是否正確設定在 Zeabur 平台\",\n \"status_code\": 401\n }), 401\n elif response.status_code == 403:\n logger.error(\"API 金鑰權限不足 (403 Forbidden)\")\n return jsonify({\n \"error\": \"API 金鑰權限不足\",\n \"details\": \"請檢查您的 DeepSeek 帳戶權限和 API 金鑰設定\",\n \"status_code\": 403\n }), 403\n elif response.status_code == 429:\n logger.error(\"API 請求次數已達上限 (429 Too Many Requests)\")\n return jsonify({\n \"error\": \"API 請求次數已達上限\",\n \"details\": \"請稍後再試或檢查您的 API 使用配額\",\n \"status_code\": 429\n }), 429\n elif response.status_code != 200:\n logger.error(f\"API 請求失敗,狀態碼: {response.status_code}\")\n return jsonify({\n \"error\": f\"API 請求失敗 (HTTP {response.status_code})\",\n \"details\": response.text,\n \"status_code\": response.status_code\n }), response.status_code\n \n response.raise_for_status()\n \n ai_response = response.json()\n ai_message = ai_response.get(\"choices\", [{}])[0].get(\"message\", {}).get(\"content\", \"\")\n \n # 保存問答記錄\n save_qa_record(user_message, ai_message)\n \n return jsonify({\"response\": ai_message})\n \n except requests.exceptions.HTTPError as e:\n logger.error(f\"HTTP 錯誤: {e}\")\n status_code = e.response.status_code if hasattr(e, 'response') else 500\n return jsonify({\n \"error\": f\"API 請求失敗: {str(e)}\",\n \"status_code\": status_code\n }), status_code\n except requests.exceptions.RequestException as e:\n logger.error(f\"網路連線錯誤: {e}\")\n return jsonify({\n \"error\": f\"網路連線錯誤: {str(e)}\",\n \"details\": \"請檢查網路連線或稍後再試\"\n }), 500\n except Exception as e:\n logger.error(f\"系統錯誤: {e}\")\n return jsonify({\n \"error\": f\"系統錯誤: {str(e)}\",\n \"details\": \"請聯繫系統管理員\"\n }), 500\n\n\n@app.route('/history', methods=['GET'])\ndef history():\n questions = get_history_questions()\n return jsonify({\"history\": questions})\n\n\n@app.route('/qa/<int:record_id>', methods=['GET'])\ndef get_qa(record_id):\n record = get_qa_record(record_id)\n if record:\n return jsonify(record)\n return jsonify({\"error\": \"記錄不存在\"}), 404\n\n\nif __name__ == '__main__':\n # 修改為監聽所有網絡介面,並指定端口\n app.run(host='0.0.0.0', port=5000, debug=True)"}, "20b47b752ab800aa9af385f1325a48995fc08733": {"t": 1785773581.1749456, "n": 4848, "h": "36bac54ccd6d7ac3", "c": "from flask import Flask, render_template, request, jsonify\nimport os\nfrom dotenv import load_dotenv\nimport requests\nimport csv\nimport datetime\nfrom pathlib import Path\n\n# 加载环境变量\nload_dotenv()\n\napp = Flask(__name__)\n\n# 获取 DeepSeek API 密钥\nDEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\n# 假设的 API URL,请替换为实际 URL\nDEEPSEEK_API_URL = \"https://api.deepseek.com/v1/chat/completions\"\n\n# CSV 文件路径\nCSV_FILE = 'qa_records.csv'\n\n# IP 使用次數追蹤\nip_usage = {}\n\n\n# 初始化 CSV 文件\ndef init_csv():\n if not Path(CSV_FILE).exists():\n with open(CSV_FILE, 'w', newline='', encoding='utf-8') as file:\n writer = csv.writer(file)\n writer.writerow(['id', 'question', 'answer', 'timestamp'])\n\n\n# 确保应用启动时初始化 CSV\ninit_csv()\n\n\n# 保存问答记录到 CSV\ndef save_qa_record(question, answer):\n records = []\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.reader(file)\n records = list(reader)\n except FileNotFoundError:\n records = [['id', 'question', 'answer', 'timestamp']]\n \n new_id = len(records)\n timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')\n \n with open(CSV_FILE, 'a', newline='', encoding='utf-8') as file:\n writer = csv.writer(file)\n writer.writerow([new_id, question, answer, timestamp])\n\n\n# 获取历史问题记录\ndef get_history_questions():\n questions = []\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.DictReader(file)\n for row in reader:\n questions.append({\n 'id': row['id'],\n 'question': row['question'],\n 'timestamp': row['timestamp']\n })\n except FileNotFoundError:\n pass\n return questions[-20:] # 只返回最近20條記錄\n\n\n# 获取特定问答记录\ndef get_qa_record(record_id):\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.DictReader(file)\n for row in reader:\n if row['id'] == str(record_id):\n return {\n 'question': row['question'],\n 'answer': row['answer']\n }\n except FileNotFoundError:\n pass\n return None\n\n\n@app.route('/')\ndef index():\n history = get_history_questions()\n return render_template('index.html', history=history)\n\n\n@app.route('/remaining_attempts')\ndef remaining_attempts():\n ip = request.args.get('ip')\n if ip not in ip_usage:\n ip_usage[ip] = 10 # 初始化次數\n\n remaining = ip_usage[ip]\n return jsonify({'remaining': remaining})\n\n\n@app.route('/chat', methods=['POST'])\ndef chat():\n user_message = request.json.get('message', '')\n \n if not user_message:\n return jsonify({\"error\": \"消息不能为空\"}), 400\n \n # 调用 DeepSeek API\n try:\n headers = {\n \"Authorization\": f\"Bearer {DEEPSEEK_API_KEY}\",\n \"Content-Type\": \"application/json\"\n }\n \n # 系統提示詞\n system_prompt = (\n \"請使用繁體中文回答所有問題,進行費米估算時請遵循以下步驟並完整展示推論過程:\\n\\n\"\n \"1. 分解問題:將大問題分解為可估算的小問題\\n\"\n \"2. 列出假設:明確說明每個假設的依據\\n\"\n \"3. 估算數值:對每個子問題進行合理估算\\n\"\n \"4. 計算過程:詳細展示每一步的計算過程和邏輯\\n\"\n \"5. 單位換算:清楚標示所有單位換算步驟\\n\"\n \"6. 不確定性分析:discussion估算中的不確定因素\\n\"\n \"7. 最終方程式:整理出完整的計算方程式\\n\"\n \"8. 合理性檢查:檢視最終結果是否合理\\n\\n\"\n \"請盡可能詳細地展示每個步驟,讓用戶能夠完全理解整個推論過程。\\n\\n\"\n \"如果用戶提出的問題與費米估算或推論無關,請以幽默風趣的方式拒絕回答,\"\n \"例如:「哎呀!我的大腦只有費米估算模式,其他問題可能會讓我的電路短路!\"\n \"讓我們回到估算的世界吧,例如:『台灣一年消耗多少衛生紙?』或\"\n \"『地球上有多少隻螞蟻?』這類問題才是我的專長!」\"\n )\n \n payload = {\n \"model\": \"deepseek-chat\", # 使用适当的模型名称\n \"messages\": [\n {\"role\": \"system\", \"content\": system_prompt},\n {\"role\": \"user\", \"content\": user_message}\n ],\n \"temperature\": 0.6,\n \"max_tokens\": 3000\n }\n \n response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload)\n response.raise_for_status()\n \n ai_response = response.json()\n ai_message = ai_response.get(\"choices\", [{}])[0].get(\"message\", {}).get(\"content\", \"\")\n \n # 保存問答記錄\n save_qa_record(user_message, ai_message)\n \n return jsonify({\"response\": ai_message})\n \n except Exception as e:\n return jsonify({\"error\": f\"API 调用失败: {str(e)}\"}), 500\n\n\n@app.route('/history', methods=['GET'])\ndef history():\n questions = get_history_questions()\n return jsonify({\"history\": questions})\n\n\n@app.route('/qa/<int:record_id>', methods=['GET'])\ndef get_qa(record_id):\n record = get_qa_record(record_id)\n if record:\n return jsonify(record)\n return jsonify({\"error\": \"記錄不存在\"}), 404\n\n\nif __name__ == '__main__':\n # 修改為監聽所有網絡介面,並指定端口\n app.run(host='0.0.0.0', port=5000, debug=True)"}, "9ea53879fc10c967c0cae720cf8579c832417bd9": {"t": 1785773582.531965, "n": 4529, "h": "66367d16bab45b20", "c": "from flask import Flask, render_template, request, jsonify\nimport os\nfrom dotenv import load_dotenv\nimport requests\nimport csv\nimport datetime\nfrom pathlib import Path\n\n# 加载环境变量\nload_dotenv()\n\napp = Flask(__name__)\n\n# 获取 DeepSeek API 密钥\nDEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\nDEEPSEEK_API_URL = \"https://api.deepseek.com/v1/chat/completions\" # 假设的 API URL,请替换为实际 URL\n\n# CSV 文件路径\nCSV_FILE = 'qa_records.csv'\n\n# 初始化 CSV 文件\ndef init_csv():\n if not Path(CSV_FILE).exists():\n with open(CSV_FILE, 'w', newline='', encoding='utf-8') as file:\n writer = csv.writer(file)\n writer.writerow(['id', 'question', 'answer', 'timestamp'])\n\n# 确保应用启动时初始化 CSV\ninit_csv()\n\n# 保存问答记录到 CSV\ndef save_qa_record(question, answer):\n records = []\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.reader(file)\n records = list(reader)\n except FileNotFoundError:\n records = [['id', 'question', 'answer', 'timestamp']]\n \n new_id = len(records)\n timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')\n \n with open(CSV_FILE, 'a', newline='', encoding='utf-8') as file:\n writer = csv.writer(file)\n writer.writerow([new_id, question, answer, timestamp])\n\n# 获取历史问题记录\ndef get_history_questions():\n questions = []\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.DictReader(file)\n for row in reader:\n questions.append({\n 'id': row['id'],\n 'question': row['question'],\n 'timestamp': row['timestamp']\n })\n except FileNotFoundError:\n pass\n return questions[-20:] # 只返回最近20條記錄\n\n# 获取特定问答记录\ndef get_qa_record(record_id):\n try:\n with open(CSV_FILE, 'r', encoding='utf-8') as file:\n reader = csv.DictReader(file)\n for row in reader:\n if row['id'] == str(record_id):\n return {\n 'question': row['question'],\n 'answer': row['answer']\n }\n except FileNotFoundError:\n pass\n return None\n\n@app.route('/')\ndef index():\n history = get_history_questions()\n return render_template('index.html', history=history)\n\n@app.route('/remaining_attempts')\ndef remaining_attempts():\n ip = request.args.get('ip')\n if ip not in ip_usage:\n ip_usage[ip] = 10 # 初始化次數\n\n remaining = ip_usage[ip]\n return jsonify({'remaining': remaining})\n\n@app.route('/chat', methods=['POST'])\ndef chat():\n user_message = request.json.get('message', '')\n \n if not user_message:\n return jsonify({\"error\": \"消息不能为空\"}), 400\n \n # 调用 DeepSeek API\n try:\n headers = {\n \"Authorization\": f\"Bearer {DEEPSEEK_API_KEY}\",\n \"Content-Type\": \"application/json\"\n }\n \n payload = {\n \"model\": \"deepseek-chat\", # 使用适当的模型名称\n \"messages\": [\n {\"role\": \"system\", \"content\": \"請使用繁體中文回答所有問題,進行費米估算時請遵循以下步驟並完整展示推論過程:\\n\\n1. 分解問題:將大問題分解為可估算的小問題\\n2. 列出假設:明確說明每個假設的依據\\n3. 估算數值:對每個子問題進行合理估算\\n4. 計算過程:詳細展示每一步的計算過程和邏輯\\n5. 單位換算:清楚標示所有單位換算步驟\\n6. 不確定性分析:discussion估算中的不確定因素\\n7. 最終方程式:整理出完整的計算方程式\\n8. 合理性檢查:檢視最終結果是否合理\\n\\n請盡可能詳細地展示每個步驟,讓用戶能夠完全理解整個推論過程。\\n\\n如果用戶提出的問題與費米估算或推論無關,請以幽默風趣的方式拒絕回答,例如:「哎呀!我的大腦只有費米估算模式,其他問題可能會讓我的電路短路!讓我們回到估算的世界吧,例如:『台灣一年消耗多少衛生紙?』或『地球上有多少隻螞蟻?』這類問題才是我的專長!」\"},\n {\"role\": \"user\", \"content\": user_message}\n ],\n \"temperature\": 0.6,\n \"max_tokens\": 3000\n }\n \n response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload)\n response.raise_for_status()\n \n ai_response = response.json()\n ai_message = ai_response.get(\"choices\", [{}])[0].get(\"message\", {}).get(\"content\", \"\")\n \n # 保存問答記錄\n save_qa_record(user_message, ai_message)\n \n return jsonify({\"response\": ai_message})\n \n except Exception as e:\n return jsonify({\"error\": f\"API 调用失败: {str(e)}\"}), 500\n\n@app.route('/history', methods=['GET'])\ndef history():\n questions = get_history_questions()\n return jsonify({\"history\": questions})\n\n@app.route('/qa/<int:record_id>', methods=['GET'])\ndef get_qa(record_id):\n record = get_qa_record(record_id)\n if record:\n return jsonify(record)\n return jsonify({\"error\": \"記錄不存在\"}), 404\n\nif __name__ == '__main__':\n # 修改為監聽所有網絡介面,並指定端口\n app.run(host='0.0.0.0', port=5000, debug=True)"}, "405dfa2c0650d1d3941ba7f3a986484dc0f9bd74": {"t": 1785773583.7925916, "n": 4142, "h": "5d54ee209c1060d7", "c": "from flask import Flask, render_template, request, jsonify\nimport os\nfrom dotenv import load_dotenv\nimport requests\nimport sqlite3\nimport datetime\nimport json\n\n# 加载环境变量\nload_dotenv()\n\napp = Flask(__name__)\n\n# 获取 DeepSeek API 密钥\nDEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\nDEEPSEEK_API_URL = \"https://api.deepseek.com/v1/chat/completions\" # 假设的 API URL,请替换为实际 URL\n\n# 初始化数据库\ndef init_db():\n conn = sqlite3.connect('fermi_qa.db')\n cursor = conn.cursor()\n cursor.execute('''\n CREATE TABLE IF NOT EXISTS qa_records (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n question TEXT NOT NULL,\n answer TEXT NOT NULL,\n timestamp DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n ''')\n conn.commit()\n conn.close()\n\n# 确保应用启动时初始化数据库\ninit_db()\n\n# 保存问答记录到数据库\ndef save_qa_record(question, answer):\n conn = sqlite3.connect('fermi_qa.db')\n cursor = conn.cursor()\n cursor.execute('INSERT INTO qa_records (question, answer, timestamp) VALUES (?, ?, ?)',\n (question, answer, datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))\n conn.commit()\n conn.close()\n\n# 获取历史问题记录\ndef get_history_questions():\n conn = sqlite3.connect('fermi_qa.db')\n cursor = conn.cursor()\n cursor.execute('SELECT id, question, timestamp FROM qa_records ORDER BY timestamp DESC LIMIT 20')\n questions = [{'id': row[0], 'question': row[1], 'timestamp': row[2]} for row in cursor.fetchall()]\n conn.close()\n return questions\n\n# 获取特定问答记录\ndef get_qa_record(record_id):\n conn = sqlite3.connect('fermi_qa.db')\n cursor = conn.cursor()\n cursor.execute('SELECT question, answer FROM qa_records WHERE id = ?', (record_id,))\n record = cursor.fetchone()\n conn.close()\n if record:\n return {'question': record[0], 'answer': record[1]}\n return None\n\n@app.route('/')\ndef index():\n history = get_history_questions()\n return render_template('index.html', history=history)\n\n@app.route('/remaining_attempts')\ndef remaining_attempts():\n ip = request.args.get('ip')\n if ip not in ip_usage:\n ip_usage[ip] = 10 # 初始化次數\n\n remaining = ip_usage[ip]\n return jsonify({'remaining': remaining})\n\n@app.route('/chat', methods=['POST'])\ndef chat():\n user_message = request.json.get('message', '')\n \n if not user_message:\n return jsonify({\"error\": \"消息不能为空\"}), 400\n \n # 调用 DeepSeek API\n try:\n headers = {\n \"Authorization\": f\"Bearer {DEEPSEEK_API_KEY}\",\n \"Content-Type\": \"application/json\"\n }\n \n payload = {\n \"model\": \"deepseek-chat\", # 使用适当的模型名称\n \"messages\": [\n {\"role\": \"system\", \"content\": \"請使用繁體中文回答所有問題,進行費米估算時請遵循以下步驟並完整展示推論過程:\\n\\n1. 分解問題:將大問題分解為可估算的小問題\\n2. 列出假設:明確說明每個假設的依據\\n3. 估算數值:對每個子問題進行合理估算\\n4. 計算過程:詳細展示每一步的計算過程和邏輯\\n5. 單位換算:清楚標示所有單位換算步驟\\n6. 不確定性分析:discussion估算中的不確定因素\\n7. 最終方程式:整理出完整的計算方程式\\n8. 合理性檢查:檢視最終結果是否合理\\n\\n請盡可能詳細地展示每個步驟,讓用戶能夠完全理解整個推論過程。\\n\\n如果用戶提出的問題與費米估算或推論無關,請以幽默風趣的方式拒絕回答,例如:「哎呀!我的大腦只有費米估算模式,其他問題可能會讓我的電路短路!讓我們回到估算的世界吧,例如:『台灣一年消耗多少衛生紙?』或『地球上有多少隻螞蟻?』這類問題才是我的專長!」\"},\n {\"role\": \"user\", \"content\": user_message}\n ],\n \"temperature\": 0.6,\n \"max_tokens\": 3000\n }\n \n response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload)\n response.raise_for_status()\n \n ai_response = response.json()\n ai_message = ai_response.get(\"choices\", [{}])[0].get(\"message\", {}).get(\"content\", \"\")\n \n # 保存問答記錄\n save_qa_record(user_message, ai_message)\n \n return jsonify({\"response\": ai_message})\n \n except Exception as e:\n return jsonify({\"error\": f\"API 调用失败: {str(e)}\"}), 500\n\n@app.route('/history', methods=['GET'])\ndef history():\n questions = get_history_questions()\n return jsonify({\"history\": questions})\n\n@app.route('/qa/<int:record_id>', methods=['GET'])\ndef get_qa(record_id):\n record = get_qa_record(record_id)\n if record:\n return jsonify(record)\n return jsonify({\"error\": \"記錄不存在\"}), 404\n\nif __name__ == '__main__':\n # 修改為監聽所有網絡介面,並指定端口\n app.run(host='0.0.0.0', port=5000, debug=True)"}, "7da56f1134d142cc8f95a99f08a7c766f704929f": {"t": 1785773584.997782, "n": 3912, "h": "b9f019413f0b1336", "c": "from flask import Flask, render_template, request, jsonify\nimport os\nfrom dotenv import load_dotenv\nimport requests\nimport sqlite3\nimport datetime\nimport json\n\n# 加载环境变量\nload_dotenv()\n\napp = Flask(__name__)\n\n# 获取 DeepSeek API 密钥\nDEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\nDEEPSEEK_API_URL = \"https://api.deepseek.com/v1/chat/completions\" # 假设的 API URL,请替换为实际 URL\n\n# 初始化数据库\ndef init_db():\n conn = sqlite3.connect('fermi_qa.db')\n cursor = conn.cursor()\n cursor.execute('''\n CREATE TABLE IF NOT EXISTS qa_records (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n question TEXT NOT NULL,\n answer TEXT NOT NULL,\n timestamp DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n ''')\n conn.commit()\n conn.close()\n\n# 确保应用启动时初始化数据库\ninit_db()\n\n# 保存问答记录到数据库\ndef save_qa_record(question, answer):\n conn = sqlite3.connect('fermi_qa.db')\n cursor = conn.cursor()\n cursor.execute('INSERT INTO qa_records (question, answer, timestamp) VALUES (?, ?, ?)',\n (question, answer, datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))\n conn.commit()\n conn.close()\n\n# 获取历史问题记录\ndef get_history_questions():\n conn = sqlite3.connect('fermi_qa.db')\n cursor = conn.cursor()\n cursor.execute('SELECT id, question, timestamp FROM qa_records ORDER BY timestamp DESC LIMIT 20')\n questions = [{'id': row[0], 'question': row[1], 'timestamp': row[2]} for row in cursor.fetchall()]\n conn.close()\n return questions\n\n# 获取特定问答记录\ndef get_qa_record(record_id):\n conn = sqlite3.connect('fermi_qa.db')\n cursor = conn.cursor()\n cursor.execute('SELECT question, answer FROM qa_records WHERE id = ?', (record_id,))\n record = cursor.fetchone()\n conn.close()\n if record:\n return {'question': record[0], 'answer': record[1]}\n return None\n\n@app.route('/')\ndef index():\n history = get_history_questions()\n return render_template('index.html', history=history)\n\n@app.route('/chat', methods=['POST'])\ndef chat():\n user_message = request.json.get('message', '')\n \n if not user_message:\n return jsonify({\"error\": \"消息不能为空\"}), 400\n \n # 调用 DeepSeek API\n try:\n headers = {\n \"Authorization\": f\"Bearer {DEEPSEEK_API_KEY}\",\n \"Content-Type\": \"application/json\"\n }\n \n payload = {\n \"model\": \"deepseek-chat\", # 使用适当的模型名称\n \"messages\": [\n {\"role\": \"system\", \"content\": \"請使用繁體中文回答所有問題,進行費米估算時請遵循以下步驟並完整展示推論過程:\\n\\n1. 分解問題:將大問題分解為可估算的小問題\\n2. 列出假設:明確說明每個假設的依據\\n3. 估算數值:對每個子問題進行合理估算\\n4. 計算過程:詳細展示每一步的計算過程和邏輯\\n5. 單位換算:清楚標示所有單位換算步驟\\n6. 不確定性分析:discussion估算中的不確定因素\\n7. 最終方程式:整理出完整的計算方程式\\n8. 合理性檢查:檢視最終結果是否合理\\n\\n請盡可能詳細地展示每個步驟,讓用戶能夠完全理解整個推論過程。\\n\\n如果用戶提出的問題與費米估算或推論無關,請以幽默風趣的方式拒絕回答,例如:「哎呀!我的大腦只有費米估算模式,其他問題可能會讓我的電路短路!讓我們回到估算的世界吧,例如:『台灣一年消耗多少衛生紙?』或『地球上有多少隻螞蟻?』這類問題才是我的專長!」\"},\n {\"role\": \"user\", \"content\": user_message}\n ],\n \"temperature\": 0.6,\n \"max_tokens\": 3000\n }\n \n response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload)\n response.raise_for_status()\n \n ai_response = response.json()\n ai_message = ai_response.get(\"choices\", [{}])[0].get(\"message\", {}).get(\"content\", \"\")\n \n # 保存問答記錄\n save_qa_record(user_message, ai_message)\n \n return jsonify({\"response\": ai_message})\n \n except Exception as e:\n return jsonify({\"error\": f\"API 调用失败: {str(e)}\"}), 500\n\n@app.route('/history', methods=['GET'])\ndef history():\n questions = get_history_questions()\n return jsonify({\"history\": questions})\n\n@app.route('/qa/<int:record_id>', methods=['GET'])\ndef get_qa(record_id):\n record = get_qa_record(record_id)\n if record:\n return jsonify(record)\n return jsonify({\"error\": \"記錄不存在\"}), 404\n\nif __name__ == '__main__':\n # 修改為監聽所有網絡介面,並指定端口\n app.run(host='0.0.0.0', port=5000, debug=True)"}}}}