Download app/config.py from Himankpro/Sub: direct link, hf CLI and curl.
- Browser
- Download file 5.86 kB
-
https://huggingface.co/spaces/Himankpro/Sub/resolve/main/app/config.py
- Command line
-
hf download hf://spaces/Himankpro/Sub/app/config.py
-
curl -L -o config.py https://huggingface.co/spaces/Himankpro/Sub/resolve/main/app/config.py
5.86 kB
| """ | |
| 配置管理 | |
| 统一从项目根目录的 .env 文件加载配置 | |
| """ | |
| import os | |
| from dotenv import load_dotenv | |
| # 加载项目根目录的 .env 文件 | |
| # 路径: MiroFish/.env (相对于 backend/app/config.py) | |
| project_root_env = os.path.join(os.path.dirname(__file__), '../../.env') | |
| if os.path.exists(project_root_env): | |
| load_dotenv(project_root_env, override=True) | |
| else: | |
| # 如果根目录没有 .env,尝试加载环境变量(用于生产环境) | |
| load_dotenv(override=True) | |
| class Config: | |
| """Flask配置类""" | |
| # Flask配置 | |
| SECRET_KEY = os.environ.get('SECRET_KEY', 'mirofish-secret-key') | |
| DEBUG = os.environ.get('FLASK_DEBUG', 'True').lower() == 'true' | |
| # JSON配置 - 禁用ASCII转义,让中文直接显示(而不是 \uXXXX 格式) | |
| JSON_AS_ASCII = False | |
| # LLM(OpenAI 兼容)。优先使用 LLM_1 / LLM_2,避免逗号拼接误配 | |
| LLM_1 = os.environ.get("LLM_1", "").strip() | |
| LLM_2 = os.environ.get("LLM_2", "").strip() | |
| LLM_API_KEY = os.environ.get('LLM_API_KEY') | |
| LLM_BASE_URL = os.environ.get('LLM_BASE_URL', 'https://api.openai.com/v1') | |
| LLM_MODEL_NAME = os.environ.get('LLM_MODEL_NAME', 'gpt-4o-mini') | |
| # Zep:优先 ZEP_1 / ZEP_2 | |
| ZEP_1 = os.environ.get("ZEP_1", "").strip() | |
| ZEP_2 = os.environ.get("ZEP_2", "").strip() | |
| ZEP_API_KEY = os.environ.get('ZEP_API_KEY') | |
| def get_zep_api_keys(cls): | |
| keys = [k for k in (cls.ZEP_1, cls.ZEP_2) if k] | |
| if keys: | |
| return keys | |
| raw = (cls.ZEP_API_KEY or "").strip() | |
| if not raw: | |
| return [] | |
| if "," in raw: | |
| return [k.strip() for k in raw.split(",") if k.strip()] | |
| return [raw] | |
| def get_llm_api_keys(cls): | |
| keys = [k for k in (cls.LLM_1, cls.LLM_2) if k] | |
| if keys: | |
| return keys | |
| raw = (cls.LLM_API_KEY or "").strip() | |
| if not raw: | |
| return [] | |
| if "," in raw: | |
| return [k.strip() for k in raw.split(",") if k.strip()] | |
| return [raw] | |
| # Razorpay + simulation unlock (website) | |
| RAZORPAY_KEY_ID = os.environ.get("RAZORPAY_KEY_ID", "").strip() | |
| RAZORPAY_KEY_SECRET = os.environ.get("RAZORPAY_KEY_SECRET", "").strip() | |
| RAZORPAY_AMOUNT_PAISE = int(os.environ.get("RAZORPAY_AMOUNT_PAISE", "49900")) | |
| RAZORPAY_CURRENCY = os.environ.get("RAZORPAY_CURRENCY", "INR").strip() or "INR" | |
| PAYMENT_COUPON_CODES = os.environ.get("PAYMENT_COUPON_CODES", "").strip() | |
| PAYMENT_JWT_SECRET = os.environ.get("PAYMENT_JWT_SECRET", "").strip() | |
| def payment_coupon_set(cls): | |
| if not cls.PAYMENT_COUPON_CODES: | |
| return set() | |
| return {c.strip().lower() for c in cls.PAYMENT_COUPON_CODES.split(",") if c.strip()} | |
| def billing_enabled(cls) -> bool: | |
| razorpay_ok = bool(cls.RAZORPAY_KEY_ID and cls.RAZORPAY_KEY_SECRET) | |
| return razorpay_ok or bool(cls.payment_coupon_set()) | |
| def payment_signing_secret(cls) -> str: | |
| return (cls.PAYMENT_JWT_SECRET or cls.PIPELINE_CLIENT_SECRET or cls.SECRET_KEY or "mirofish-pay").strip() | |
| # 文件上传配置 | |
| MAX_CONTENT_LENGTH = 50 * 1024 * 1024 # 50MB | |
| UPLOAD_FOLDER = os.path.join(os.path.dirname(__file__), '../uploads') | |
| ALLOWED_EXTENSIONS = {'pdf', 'md', 'txt', 'markdown'} | |
| # 文本处理配置 | |
| DEFAULT_CHUNK_SIZE = 500 # 默认切块大小 | |
| DEFAULT_CHUNK_OVERLAP = 50 # 默认重叠大小 | |
| # OASIS模拟配置 | |
| OASIS_DEFAULT_MAX_ROUNDS = int(os.environ.get('OASIS_DEFAULT_MAX_ROUNDS', '10')) | |
| OASIS_SIMULATION_DATA_DIR = os.path.join(os.path.dirname(__file__), '../uploads/simulations') | |
| # OASIS平台可用动作配置 | |
| OASIS_TWITTER_ACTIONS = [ | |
| 'CREATE_POST', 'LIKE_POST', 'REPOST', 'FOLLOW', 'DO_NOTHING', 'QUOTE_POST' | |
| ] | |
| OASIS_REDDIT_ACTIONS = [ | |
| 'LIKE_POST', 'DISLIKE_POST', 'CREATE_POST', 'CREATE_COMMENT', | |
| 'LIKE_COMMENT', 'DISLIKE_COMMENT', 'SEARCH_POSTS', 'SEARCH_USER', | |
| 'TREND', 'REFRESH', 'DO_NOTHING', 'FOLLOW', 'MUTE' | |
| ] | |
| # 全自动流水线(website → /api/pipeline/start) | |
| PIPELINE_MAX_ROUNDS = os.environ.get('PIPELINE_MAX_ROUNDS') # optional cap on OASIS rounds | |
| PIPELINE_PARALLEL_PROFILES = int(os.environ.get('PIPELINE_PARALLEL_PROFILES', '5')) | |
| # Supabase: report storage + simulation_runs table (free tier friendly) | |
| SUPABASE_URL = os.environ.get('SUPABASE_URL', '').rstrip('/') | |
| SUPABASE_SERVICE_ROLE_KEY = os.environ.get('SUPABASE_SERVICE_ROLE_KEY', '') | |
| # Project Settings → API → JWT Secret (verify user access tokens from the website) | |
| SUPABASE_JWT_SECRET = os.environ.get('SUPABASE_JWT_SECRET', '') | |
| SUPABASE_REPORTS_BUCKET = os.environ.get('SUPABASE_REPORTS_BUCKET', 'reports') | |
| # Optional: signing secret for legacy MiroFish Bearer JWTs. Defaults to SECRET_KEY. | |
| MIROFISH_SESSION_JWT_SECRET = os.environ.get('MIROFISH_SESSION_JWT_SECRET', '').strip() | |
| # Same value as website VITE_PIPELINE_CLIENT_SECRET (browser sends X-Mirofish-User-Id + X-Pipeline-Client-Secret). | |
| PIPELINE_CLIENT_SECRET = os.environ.get('PIPELINE_CLIENT_SECRET', '').strip() | |
| # Report Agent配置 | |
| REPORT_AGENT_MAX_TOOL_CALLS = int(os.environ.get('REPORT_AGENT_MAX_TOOL_CALLS', '5')) | |
| REPORT_AGENT_MAX_REFLECTION_ROUNDS = int(os.environ.get('REPORT_AGENT_MAX_REFLECTION_ROUNDS', '2')) | |
| REPORT_AGENT_TEMPERATURE = float(os.environ.get('REPORT_AGENT_TEMPERATURE', '0.5')) | |
| def validate(cls): | |
| """验证必要配置""" | |
| errors = [] | |
| if not cls.get_llm_api_keys(): | |
| errors.append("LLM_1 / LLM_2 or LLM_API_KEY 未配置") | |
| if not cls.get_zep_api_keys(): | |
| errors.append("ZEP_1 / ZEP_2 or ZEP_API_KEY 未配置") | |
| return errors | |