1 line
21 KiB
JSON
1 line
21 KiB
JSON
{"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"}}}} |