Files

1 line
21 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "chatgpt3a01/open-notebookllm", "files": {"backend/controllers/settings_controller.py": {"7199ae5757f3c37c27314f11bb1ad6cb0565e8a2": {"t": 1785745416.8607957, "n": 7063, "h": "edbc459821e9507f", "c": "\"\"\"\n設定控制器 - 支援多 AI 提供商\n\"\"\"\nimport os\nfrom flask import request, jsonify\nfrom . import settings_bp\nfrom services.ai_service_manager import get_ai_service, clear_ai_service\nfrom config import get_config\n\n\n@settings_bp.route('', methods=['GET'])\ndef get_settings():\n \"\"\"取得設定\"\"\"\n config = get_config()\n ai_service = get_ai_service()\n\n return jsonify({\n 'success': True,\n 'data': {\n 'ai_provider': config.AI_PROVIDER,\n 'gemini_model': config.GEMINI_MODEL,\n 'openai_model': config.OPENAI_MODEL,\n 'has_gemini_key': bool(config.GEMINI_API_KEY),\n 'has_openai_key': bool(config.OPENAI_API_KEY),\n 'has_anthropic_key': bool(os.getenv('ANTHROPIC_API_KEY', '')),\n 'has_groq_key': bool(os.getenv('GROQ_API_KEY', '')),\n 'has_deepseek_key': bool(os.getenv('DEEPSEEK_API_KEY', '')),\n 'provider_ready': ai_service.is_ready,\n 'current_provider': ai_service.provider_type,\n 'current_config': ai_service.get_current_config()\n }\n })\n\n\n@settings_bp.route('/providers', methods=['GET'])\ndef get_providers():\n \"\"\"取得可用的 AI 提供商列表\"\"\"\n ai_service = get_ai_service()\n providers = ai_service.get_available_providers()\n\n return jsonify({\n 'success': True,\n 'data': {\n 'current_provider': ai_service.provider_type,\n 'providers': providers\n }\n })\n\n\n@settings_bp.route('', methods=['PUT'])\ndef update_settings():\n \"\"\"更新設定(運行時切換 Provider)\"\"\"\n data = request.get_json()\n\n provider = data.get('provider')\n api_key = data.get('api_key')\n model = data.get('model')\n\n if not provider:\n return jsonify({'success': False, 'error': 'provider 為必填'}), 400\n\n # Ollama 不需要 API Key\n if provider.lower() != 'ollama' and not api_key:\n # 檢查是否已有 API Key 在環境變數中\n env_key_map = {\n 'gemini': 'GEMINI_API_KEY',\n 'openai': 'OPENAI_API_KEY',\n 'anthropic': 'ANTHROPIC_API_KEY',\n 'groq': 'GROQ_API_KEY',\n 'deepseek': 'DEEPSEEK_API_KEY',\n }\n env_key = env_key_map.get(provider.lower())\n if env_key and not os.getenv(env_key):\n return jsonify({'success': False, 'error': f'{provider} API Key 未設定'}), 400\n\n try:\n ai_service = get_ai_service()\n ai_service.switch_provider(provider, api_key, model)\n\n return jsonify({\n 'success': True,\n 'message': f'已切換至 {provider}',\n 'data': {\n 'provider': provider,\n 'provider_ready': ai_service.is_ready,\n 'config': ai_service.get_current_config()\n }\n })\n\n except Exception as e:\n return jsonify({'success': False, 'error': str(e)}), 400\n\n\n@settings_bp.route('/test-api', methods=['POST'])\ndef test_api():\n \"\"\"測試 API 連線\"\"\"\n data = request.get_json()\n\n provider = data.get('provider')\n api_key = data.get('api_key')\n\n if not provider:\n return jsonify({'success': False, 'error': 'provider 為必填'}), 400\n\n try:\n test_provider = None\n provider_lower = provider.lower()\n\n if provider_lower == 'gemini':\n from services.ai_providers.gemini_provider import GeminiProvider\n test_provider = GeminiProvider(api_key=api_key)\n\n elif provider_lower == 'openai':\n from services.ai_providers.openai_provider import OpenAIProvider\n test_provider = OpenAIProvider(api_key=api_key)\n\n elif provider_lower == 'anthropic':\n from services.ai_providers.anthropic_provider import AnthropicProvider\n test_provider = AnthropicProvider(api_key=api_key)\n\n elif provider_lower == 'ollama':\n from services.ai_providers.ollama_provider import OllamaProvider\n test_provider = OllamaProvider()\n if not test_provider.is_available():\n return jsonify({'success': False, 'error': 'Ollama 服務不可用,請確認已啟動'}), 400\n\n elif provider_lower == 'groq':\n from services.ai_providers.groq_provider import GroqProvider\n test_provider = GroqProvider(api_key=api_key)\n\n elif provider_lower == 'deepseek':\n from services.ai_providers.deepseek_provider import DeepSeekProvider\n test_provider = DeepSeekProvider(api_key=api_key)\n\n else:\n return jsonify({'success': False, 'error': f'不支援的提供商: {provider}'}), 400\n\n # 簡單測試\n result = test_provider.generate(\"Hello, please reply with 'OK' only.\")\n\n return jsonify({\n 'success': True,\n 'message': f'{provider} API 連線成功',\n 'response': result[:100]\n })\n\n except Exception as e:\n return jsonify({'success': False, 'error': f'API 連線失敗: {str(e)}'}), 400\n\n\n@settings_bp.route('/reset', methods=['POST'])\ndef reset_service():\n \"\"\"重置 AI 服務\"\"\"\n try:\n clear_ai_service()\n ai_service = get_ai_service(force_new=True)\n\n return jsonify({\n 'success': True,\n 'message': 'AI 服務已重置',\n 'data': {\n 'provider_ready': ai_service.is_ready,\n 'current_provider': ai_service.provider_type,\n 'config': ai_service.get_current_config()\n }\n })\n\n except Exception as e:\n return jsonify({'success': False, 'error': str(e)}), 400\n\n\n@settings_bp.route('/models/<provider>', methods=['GET'])\ndef get_provider_models(provider):\n \"\"\"取得指定提供商的可用模型列表\"\"\"\n provider_lower = provider.lower()\n\n models = []\n\n if provider_lower == 'gemini':\n models = ['gemini-2.5-flash', 'gemini-2.5-pro', 'gemini-2.0-flash', 'gemini-1.5-pro', 'gemini-1.5-flash']\n\n elif provider_lower == 'openai':\n models = ['gpt-4o', 'gpt-4.1', 'gpt-4-turbo', 'gpt-4', 'gpt-3.5-turbo']\n\n elif provider_lower == 'anthropic':\n from services.ai_providers.anthropic_provider import AnthropicProvider\n models = AnthropicProvider.AVAILABLE_MODELS\n\n elif provider_lower == 'ollama':\n # 嘗試取得本地已安裝的模型\n try:\n from services.ai_providers.ollama_provider import OllamaProvider\n ollama = OllamaProvider()\n if ollama.is_available():\n models = ollama.list_local_models()\n if not models:\n models = ['llama3.2', 'llama3.1', 'mistral', 'mixtral', 'qwen2.5', 'phi3']\n except:\n models = ['llama3.2', 'llama3.1', 'mistral', 'mixtral', 'qwen2.5', 'phi3']\n\n elif provider_lower == 'groq':\n from services.ai_providers.groq_provider import GroqProvider\n models = GroqProvider.AVAILABLE_MODELS\n\n elif provider_lower == 'deepseek':\n from services.ai_providers.deepseek_provider import DeepSeekProvider\n models = DeepSeekProvider.AVAILABLE_MODELS\n\n else:\n return jsonify({'success': False, 'error': f'不支援的提供商: {provider}'}), 400\n\n return jsonify({\n 'success': True,\n 'data': {\n 'provider': provider,\n 'models': models\n }\n })\n"}, "68123f2d38ac6632021ba569aa4bbc61862309e4": {"t": 1785752963.6402078, "n": 7063, "h": "edbc459821e9507f", "c": "\"\"\"\n設定控制器 - 支援多 AI 提供商\n\"\"\"\nimport os\nfrom flask import request, jsonify\nfrom . import settings_bp\nfrom services.ai_service_manager import get_ai_service, clear_ai_service\nfrom config import get_config\n\n\n@settings_bp.route('', methods=['GET'])\ndef get_settings():\n \"\"\"取得設定\"\"\"\n config = get_config()\n ai_service = get_ai_service()\n\n return jsonify({\n 'success': True,\n 'data': {\n 'ai_provider': config.AI_PROVIDER,\n 'gemini_model': config.GEMINI_MODEL,\n 'openai_model': config.OPENAI_MODEL,\n 'has_gemini_key': bool(config.GEMINI_API_KEY),\n 'has_openai_key': bool(config.OPENAI_API_KEY),\n 'has_anthropic_key': bool(os.getenv('ANTHROPIC_API_KEY', '')),\n 'has_groq_key': bool(os.getenv('GROQ_API_KEY', '')),\n 'has_deepseek_key': bool(os.getenv('DEEPSEEK_API_KEY', '')),\n 'provider_ready': ai_service.is_ready,\n 'current_provider': ai_service.provider_type,\n 'current_config': ai_service.get_current_config()\n }\n })\n\n\n@settings_bp.route('/providers', methods=['GET'])\ndef get_providers():\n \"\"\"取得可用的 AI 提供商列表\"\"\"\n ai_service = get_ai_service()\n providers = ai_service.get_available_providers()\n\n return jsonify({\n 'success': True,\n 'data': {\n 'current_provider': ai_service.provider_type,\n 'providers': providers\n }\n })\n\n\n@settings_bp.route('', methods=['PUT'])\ndef update_settings():\n \"\"\"更新設定(運行時切換 Provider)\"\"\"\n data = request.get_json()\n\n provider = data.get('provider')\n api_key = data.get('api_key')\n model = data.get('model')\n\n if not provider:\n return jsonify({'success': False, 'error': 'provider 為必填'}), 400\n\n # Ollama 不需要 API Key\n if provider.lower() != 'ollama' and not api_key:\n # 檢查是否已有 API Key 在環境變數中\n env_key_map = {\n 'gemini': 'GEMINI_API_KEY',\n 'openai': 'OPENAI_API_KEY',\n 'anthropic': 'ANTHROPIC_API_KEY',\n 'groq': 'GROQ_API_KEY',\n 'deepseek': 'DEEPSEEK_API_KEY',\n }\n env_key = env_key_map.get(provider.lower())\n if env_key and not os.getenv(env_key):\n return jsonify({'success': False, 'error': f'{provider} API Key 未設定'}), 400\n\n try:\n ai_service = get_ai_service()\n ai_service.switch_provider(provider, api_key, model)\n\n return jsonify({\n 'success': True,\n 'message': f'已切換至 {provider}',\n 'data': {\n 'provider': provider,\n 'provider_ready': ai_service.is_ready,\n 'config': ai_service.get_current_config()\n }\n })\n\n except Exception as e:\n return jsonify({'success': False, 'error': str(e)}), 400\n\n\n@settings_bp.route('/test-api', methods=['POST'])\ndef test_api():\n \"\"\"測試 API 連線\"\"\"\n data = request.get_json()\n\n provider = data.get('provider')\n api_key = data.get('api_key')\n\n if not provider:\n return jsonify({'success': False, 'error': 'provider 為必填'}), 400\n\n try:\n test_provider = None\n provider_lower = provider.lower()\n\n if provider_lower == 'gemini':\n from services.ai_providers.gemini_provider import GeminiProvider\n test_provider = GeminiProvider(api_key=api_key)\n\n elif provider_lower == 'openai':\n from services.ai_providers.openai_provider import OpenAIProvider\n test_provider = OpenAIProvider(api_key=api_key)\n\n elif provider_lower == 'anthropic':\n from services.ai_providers.anthropic_provider import AnthropicProvider\n test_provider = AnthropicProvider(api_key=api_key)\n\n elif provider_lower == 'ollama':\n from services.ai_providers.ollama_provider import OllamaProvider\n test_provider = OllamaProvider()\n if not test_provider.is_available():\n return jsonify({'success': False, 'error': 'Ollama 服務不可用,請確認已啟動'}), 400\n\n elif provider_lower == 'groq':\n from services.ai_providers.groq_provider import GroqProvider\n test_provider = GroqProvider(api_key=api_key)\n\n elif provider_lower == 'deepseek':\n from services.ai_providers.deepseek_provider import DeepSeekProvider\n test_provider = DeepSeekProvider(api_key=api_key)\n\n else:\n return jsonify({'success': False, 'error': f'不支援的提供商: {provider}'}), 400\n\n # 簡單測試\n result = test_provider.generate(\"Hello, please reply with 'OK' only.\")\n\n return jsonify({\n 'success': True,\n 'message': f'{provider} API 連線成功',\n 'response': result[:100]\n })\n\n except Exception as e:\n return jsonify({'success': False, 'error': f'API 連線失敗: {str(e)}'}), 400\n\n\n@settings_bp.route('/reset', methods=['POST'])\ndef reset_service():\n \"\"\"重置 AI 服務\"\"\"\n try:\n clear_ai_service()\n ai_service = get_ai_service(force_new=True)\n\n return jsonify({\n 'success': True,\n 'message': 'AI 服務已重置',\n 'data': {\n 'provider_ready': ai_service.is_ready,\n 'current_provider': ai_service.provider_type,\n 'config': ai_service.get_current_config()\n }\n })\n\n except Exception as e:\n return jsonify({'success': False, 'error': str(e)}), 400\n\n\n@settings_bp.route('/models/<provider>', methods=['GET'])\ndef get_provider_models(provider):\n \"\"\"取得指定提供商的可用模型列表\"\"\"\n provider_lower = provider.lower()\n\n models = []\n\n if provider_lower == 'gemini':\n models = ['gemini-2.5-flash', 'gemini-2.5-pro', 'gemini-2.0-flash', 'gemini-1.5-pro', 'gemini-1.5-flash']\n\n elif provider_lower == 'openai':\n models = ['gpt-4o', 'gpt-4.1', 'gpt-4-turbo', 'gpt-4', 'gpt-3.5-turbo']\n\n elif provider_lower == 'anthropic':\n from services.ai_providers.anthropic_provider import AnthropicProvider\n models = AnthropicProvider.AVAILABLE_MODELS\n\n elif provider_lower == 'ollama':\n # 嘗試取得本地已安裝的模型\n try:\n from services.ai_providers.ollama_provider import OllamaProvider\n ollama = OllamaProvider()\n if ollama.is_available():\n models = ollama.list_local_models()\n if not models:\n models = ['llama3.2', 'llama3.1', 'mistral', 'mixtral', 'qwen2.5', 'phi3']\n except:\n models = ['llama3.2', 'llama3.1', 'mistral', 'mixtral', 'qwen2.5', 'phi3']\n\n elif provider_lower == 'groq':\n from services.ai_providers.groq_provider import GroqProvider\n models = GroqProvider.AVAILABLE_MODELS\n\n elif provider_lower == 'deepseek':\n from services.ai_providers.deepseek_provider import DeepSeekProvider\n models = DeepSeekProvider.AVAILABLE_MODELS\n\n else:\n return jsonify({'success': False, 'error': f'不支援的提供商: {provider}'}), 400\n\n return jsonify({\n 'success': True,\n 'data': {\n 'provider': provider,\n 'models': models\n }\n })\n"}}, ".env.example": {"7199ae5757f3c37c27314f11bb1ad6cb0565e8a2": {"t": 1785747111.956564, "n": 2542, "h": "b331930b18c32442", "c": "# NoteBookLLM 環境變數配置\n# ================================================\n\n# AI Provider 設定\n# 可選: gemini, openai, anthropic, ollama, groq, deepseek\nAI_PROVIDER=gemini\n\n# ================================================\n# Gemini API 配置 (Google)\n# ================================================\nGEMINI_API_KEY=your-gemini-api-key-here\nGEMINI_MODEL=gemini-2.0-flash\nGEMINI_EMBEDDING_MODEL=models/embedding-001\nGEMINI_IMAGE_MODEL=gemini-2.0-flash-exp-image-generation\n\n# ================================================\n# OpenAI API 配置\n# ================================================\nOPENAI_API_KEY=your-openai-api-key-here\nOPENAI_MODEL=gpt-4o\nOPENAI_EMBEDDING_MODEL=text-embedding-3-small\nOPENAI_IMAGE_MODEL=dall-e-3\n\n# ================================================\n# Anthropic API 配置 (Claude)\n# ================================================\nANTHROPIC_API_KEY=your-anthropic-api-key-here\nANTHROPIC_MODEL=claude-sonnet-4-20250514\n\n# ================================================\n# Ollama 本地模型配置\n# ================================================\nOLLAMA_HOST=http://localhost:11434\nOLLAMA_MODEL=llama3.2\nOLLAMA_EMBEDDING_MODEL=nomic-embed-text\n\n# ================================================\n# Groq API 配置 (高速推理)\n# ================================================\nGROQ_API_KEY=your-groq-api-key-here\nGROQ_MODEL=llama-3.3-70b-versatile\n\n# ================================================\n# DeepSeek API 配置 (推理模型)\n# ================================================\nDEEPSEEK_API_KEY=your-deepseek-api-key-here\nDEEPSEEK_MODEL=deepseek-chat\n# 推理模型: deepseek-reasoner\n\n# ================================================\n# Flask 配置\n# ================================================\nFLASK_ENV=development\nFLASK_DEBUG=1\nSECRET_KEY=your-secret-key-change-this-in-production\n\n# ================================================\n# 資料庫配置\n# ================================================\nDATABASE_URL=sqlite:///database.db\n\n# ================================================\n# 上傳配置\n# ================================================\nUPLOAD_FOLDER=../uploads\nMAX_CONTENT_LENGTH=52428800\n\n# ================================================\n# CORS 配置\n# ================================================\nCORS_ORIGINS=http://localhost:3000,http://localhost:5173\n\n# ================================================\n# RAG 配置\n# ================================================\nCHUNK_SIZE=1000\nCHUNK_OVERLAP=200\nTOP_K_RESULTS=5\n\n# ================================================\n# 日誌等級\n# ================================================\nLOG_LEVEL=INFO\n"}, "68123f2d38ac6632021ba569aa4bbc61862309e4": {"t": 1785752960.7980795, "n": 2542, "h": "b331930b18c32442", "c": "# NoteBookLLM 環境變數配置\n# ================================================\n\n# AI Provider 設定\n# 可選: gemini, openai, anthropic, ollama, groq, deepseek\nAI_PROVIDER=gemini\n\n# ================================================\n# Gemini API 配置 (Google)\n# ================================================\nGEMINI_API_KEY=your-gemini-api-key-here\nGEMINI_MODEL=gemini-2.0-flash\nGEMINI_EMBEDDING_MODEL=models/embedding-001\nGEMINI_IMAGE_MODEL=gemini-2.0-flash-exp-image-generation\n\n# ================================================\n# OpenAI API 配置\n# ================================================\nOPENAI_API_KEY=your-openai-api-key-here\nOPENAI_MODEL=gpt-4o\nOPENAI_EMBEDDING_MODEL=text-embedding-3-small\nOPENAI_IMAGE_MODEL=dall-e-3\n\n# ================================================\n# Anthropic API 配置 (Claude)\n# ================================================\nANTHROPIC_API_KEY=your-anthropic-api-key-here\nANTHROPIC_MODEL=claude-sonnet-4-20250514\n\n# ================================================\n# Ollama 本地模型配置\n# ================================================\nOLLAMA_HOST=http://localhost:11434\nOLLAMA_MODEL=llama3.2\nOLLAMA_EMBEDDING_MODEL=nomic-embed-text\n\n# ================================================\n# Groq API 配置 (高速推理)\n# ================================================\nGROQ_API_KEY=your-groq-api-key-here\nGROQ_MODEL=llama-3.3-70b-versatile\n\n# ================================================\n# DeepSeek API 配置 (推理模型)\n# ================================================\nDEEPSEEK_API_KEY=your-deepseek-api-key-here\nDEEPSEEK_MODEL=deepseek-chat\n# 推理模型: deepseek-reasoner\n\n# ================================================\n# Flask 配置\n# ================================================\nFLASK_ENV=development\nFLASK_DEBUG=1\nSECRET_KEY=your-secret-key-change-this-in-production\n\n# ================================================\n# 資料庫配置\n# ================================================\nDATABASE_URL=sqlite:///database.db\n\n# ================================================\n# 上傳配置\n# ================================================\nUPLOAD_FOLDER=../uploads\nMAX_CONTENT_LENGTH=52428800\n\n# ================================================\n# CORS 配置\n# ================================================\nCORS_ORIGINS=http://localhost:3000,http://localhost:5173\n\n# ================================================\n# RAG 配置\n# ================================================\nCHUNK_SIZE=1000\nCHUNK_OVERLAP=200\nTOP_K_RESULTS=5\n\n# ================================================\n# 日誌等級\n# ================================================\nLOG_LEVEL=INFO\n"}}}}