Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/chopinau_nexuspulse-influence-project.json
T
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
39 KiB
JSON
Raw 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": "chopinau/nexuspulse-influence-project", "files": {"python_backend/config.py": {"359daa4d119dc1551d99bc2bffda7e7afd49cae6": {"t": 1785746497.6138878, "n": 8324, "h": "70994016b7e6ee74", "c": "# -*- coding: utf-8 -*-\n\"\"\"\n微舆配置文件\n\n此模块使用 pydantic-settings 管理全局配置,支持从环境变量和 .env 文件自动加载。\n数据模型定义位置:\n- 本文件 - 配置模型定义\n\"\"\"\n\nfrom pathlib import Path\nfrom pydantic_settings import BaseSettings\nfrom pydantic import Field, ConfigDict\nfrom typing import Optional, Literal\nfrom loguru import logger\n\n\n# 计算 .env 优先级:优先当前工作目录,其次项目根目录\nPROJECT_ROOT: Path = Path(__file__).resolve().parent\nCWD_ENV: Path = Path.cwd() / \".env\"\nENV_FILE: str = str(CWD_ENV if CWD_ENV.exists() else (PROJECT_ROOT / \".env\"))\n\n\nclass Settings(BaseSettings):\n \"\"\"\n 全局配置;支持 .env 和环境变量自动加载。\n 变量名与原 config.py 大写一致,便于平滑过渡。\n \"\"\"\n # ================== Flask 服务器配置 ====================\n HOST: str = Field(\"0.0.0.0\", description=\"BETTAFISH 主机地址,例如 0.0.0.0 或 127.0.0.1\")\n PORT: int = Field(5000, description=\"Flask服务器端口号,默认5000\")\n\n # ================== 日志配置 ====================\n LOG_FILE: str = Field(\"logs/app.log\", description=\"日志文件路径\")\n\n # ================== 报告输出配置 ====================\n OUTPUT_DIR: str = Field(\"final_reports\", description=\"最终报告输出目录\")\n CHAPTER_OUTPUT_DIR: str = Field(\"final_reports/chapters\", description=\"章节中间文件输出目录\")\n DOCUMENT_IR_OUTPUT_DIR: str = Field(\"final_reports/ir\", description=\"文档中间表示输出目录\")\n\n TEMPLATE_DIR: str = Field(\"ReportEngine/report_template\", description=\"报告模板目录\")\n JSON_ERROR_LOG_DIR: str = Field(\"logs/json_errors\", description=\"JSON解析错误日志目录\")\n CHAPTER_JSON_MAX_ATTEMPTS: int = Field(3, description=\"章节JSON生成最大尝试次数\")\n\n # ====================== 数据库配置 ======================\n DB_DIALECT: str = Field(\"postgresql\", description=\"数据库类型,可选 mysql 或 postgresql;请与其他连接信息同时配置\")\n DB_HOST: str = Field(\"your_db_host\", description=\"数据库主机,例如localhost 或 127.0.0.1\")\n DB_PORT: int = Field(3306, description=\"数据库端口号,默认为3306\")\n DB_USER: str = Field(\"your_db_user\", description=\"数据库用户名\")\n DB_PASSWORD: str = Field(\"your_db_password\", description=\"数据库密码\")\n DB_NAME: str = Field(\"your_db_name\", description=\"数据库名称\")\n DB_CHARSET: str = Field(\"utf8mb4\", description=\"数据库字符集,推荐utf8mb4,兼容emoji\")\n \n # ======================= LLM 相关 =======================\n # 我们的LLM模型API赞助商有:https://aihubmix.com/?aff=8Ds9,提供了非常全面的模型api\n \n # Insight Agent(推荐Kimi,申请地址:https://platform.moonshot.cn/)\n INSIGHT_ENGINE_API_KEY: Optional[str] = Field(None, description=\"Insight Agent(推荐 kimi-k2,官方申请地址:https://platform.moonshot.cn/)API 密钥,用于主 LLM。🚩请先按推荐配置申请并跑通,再根据需要调整 KEY、BASE_URL 与 MODEL_NAME。\")\n INSIGHT_ENGINE_BASE_URL: Optional[str] = Field(\"https://api.moonshot.cn/v1\", description=\"Insight Agent LLM BaseUrl,可根据厂商自定义\")\n INSIGHT_ENGINE_MODEL_NAME: str = Field(\"kimi-k2-0711-preview\", description=\"Insight Agent LLM 模型名称,例如 kimi-k2-0711-preview\")\n \n # Media Agent(推荐Gemini,推荐中转厂商:https://aihubmix.com/?aff=8Ds9)\n MEDIA_ENGINE_API_KEY: Optional[str] = Field(None, description=\"Media Agent(推荐 gemini-2.5-pro,中转厂商申请地址:https://aihubmix.com/?aff=8Ds9)API 密钥\")\n MEDIA_ENGINE_BASE_URL: Optional[str] = Field(\"https://aihubmix.com/v1\", description=\"Media Agent LLM BaseUrl,可根据中转服务调整\")\n MEDIA_ENGINE_MODEL_NAME: str = Field(\"gemini-2.5-pro\", description=\"Media Agent LLM 模型名称,如 gemini-2.5-pro\")\n \n # Query Agent(推荐DeepSeek,申请地址:https://www.deepseek.com/)\n QUERY_ENGINE_API_KEY: Optional[str] = Field(None, description=\"Query Agent(推荐 deepseek,官方申请地址:https://platform.deepseek.com/)API 密钥\")\n QUERY_ENGINE_BASE_URL: Optional[str] = Field(\"https://api.deepseek.com\", description=\"Query Agent LLM BaseUrl\")\n QUERY_ENGINE_MODEL_NAME: str = Field(\"deepseek-chat\", description=\"Query Agent LLM 模型名称,如 deepseek-reasoner\")\n \n # Report Agent(推荐Gemini,推荐中转厂商:https://aihubmix.com/?aff=8Ds9)\n REPORT_ENGINE_API_KEY: Optional[str] = Field(None, description=\"Report Agent(推荐 gemini-2.5-pro,中转厂商申请地址:https://aihubmix.com/?aff=8Ds9)API 密钥\")\n REPORT_ENGINE_BASE_URL: Optional[str] = Field(\"https://aihubmix.com/v1\", description=\"Report Agent LLM BaseUrl,可根据中转服务调整\")\n REPORT_ENGINE_MODEL_NAME: str = Field(\"gemini-2.5-pro\", description=\"Report Agent LLM 模型名称,如 gemini-2.5-pro\")\n\n # MindSpider Agent(推荐Deepseek,官方申请地址:https://platform.deepseek.com/)\n MINDSPIDER_API_KEY: Optional[str] = Field(None, description=\"MindSpider Agent(推荐 deepseek,官方申请地址:https://platform.deepseek.com/)API 密钥\")\n MINDSPIDER_BASE_URL: Optional[str] = Field(None, description=\"MindSpider Agent BaseUrl,可按所选服务配置\")\n MINDSPIDER_MODEL_NAME: Optional[str] = Field(None, description=\"MindSpider Agent 模型名称,例如 deepseek-reasoner\")\n \n # Forum Host(Qwen3最新模型,这里我使用了硅基流动这个平台,申请地址:https://cloud.siliconflow.cn/)\n FORUM_HOST_API_KEY: Optional[str] = Field(None, description=\"Forum Host(推荐 qwen-plus,官方申请地址:https://www.aliyun.com/product/bailian)API 密钥\")\n FORUM_HOST_BASE_URL: Optional[str] = Field(None, description=\"Forum Host LLM BaseUrl,可按所选服务配置\")\n FORUM_HOST_MODEL_NAME: Optional[str] = Field(None, description=\"Forum Host LLM 模型名称,例如 qwen-plus\")\n \n # SQL keyword Optimizer(小参数Qwen3模型,这里我使用了硅基流动这个平台,申请地址:https://cloud.siliconflow.cn/)\n KEYWORD_OPTIMIZER_API_KEY: Optional[str] = Field(None, description=\"SQL Keyword Optimizer(推荐 qwen-plus,官方申请地址:https://www.aliyun.com/product/bailian)API 密钥\")\n KEYWORD_OPTIMIZER_BASE_URL: Optional[str] = Field(None, description=\"Keyword Optimizer BaseUrl,可按所选服务配置\")\n KEYWORD_OPTIMIZER_MODEL_NAME: Optional[str] = Field(None, description=\"Keyword Optimizer LLM 模型名称,例如 qwen-plus\")\n \n # ================== GraphRAG 配置 ====================\n GRAPHRAG_ENABLED: bool = Field(False, description=\"是否启用GraphRAG知识图谱功能(true/false)\")\n GRAPHRAG_MAX_QUERIES: int = Field(3, description=\"GraphRAG每个章节生成前的最大查询次数\")\n \n # ================== 网络工具配置 ====================\n # Tavily API(申请地址:https://www.tavily.com/)\n TAVILY_API_KEY: Optional[str] = Field(None, description=\"Tavily API(申请地址:https://www.tavily.com/)API密钥,用于Tavily网络搜索\")\n\n SEARCH_TOOL_TYPE: Literal[\"AnspireAPI\", \"BochaAPI\"] = Field(\"AnspireAPI\", description=\"网络搜索工具类型,支持BochaAPI或AnspireAPI两种,默认为AnspireAPI\")\n # Bocha API(申请地址:https://open.bochaai.com/)\n BOCHA_BASE_URL: Optional[str] = Field(\"https://api.bocha.cn/v1/ai-search\", description=\"Bocha AI 搜索BaseUrl或博查网页搜索BaseUrl\")\n BOCHA_WEB_SEARCH_API_KEY: Optional[str] = Field(None, description=\"Bocha API(申请地址:https://open.bochaai.com/)API密钥,用于Bocha搜索\")\n\n # Anspire AI Search API(申请地址:https://open.anspire.cn/?share_code=3E1FUOUH)\n ANSPIRE_BASE_URL: Optional[str] = Field(\"https://plugin.anspire.cn/api/ntsearch/search\", description=\"Anspire AI 搜索BaseUrl\")\n ANSPIRE_API_KEY: Optional[str] = Field(None, description=\"Anspire AI Search API(申请地址:https://open.anspire.cn/?share_code=3E1FUOUH)API密钥,用于Anspire搜索\")\n\n # ================== 飞书配置 ====================\n FEISHU_APP_ID: Optional[str] = Field(None, description=\"飞书应用 App ID,用于飞书多维表格API认证\")\n FEISHU_APP_SECRET: Optional[str] = Field(None, description=\"飞书应用 App Secret,用于飞书多维表格API认证\")\n FEISHU_APP_TOKEN: Optional[str] = Field(None, description=\"飞书多维表格 App Token,用于指定默认操作的Bitable\")\n\n \n # ================== Insight Engine 搜索配置 ====================\n DEFAULT_SEARCH_HOT_CONTENT_LIMIT: int = Field(100, description=\"热榜内容默认最大数\")\n DEFAULT_SEARCH_TOPIC_GLOBALLY_LIMIT_PER_TABLE: int = Field(50, description=\"按表全局话题最大数\")\n DEFAULT_SEARCH_TOPIC_BY_DATE_LIMIT_PER_TABLE: int = Field(100, description=\"按日期话题最大数\")\n DEFAULT_GET_COMMENTS_FOR_TOPIC_LIMIT: int = Field(500, description=\"单话题评论最大数\")\n DEFAULT_SEARCH_TOPIC_ON_PLATFORM_LIMIT: int = Field(200, description=\"平台搜索话题最大数\")\n MAX_SEARCH_RESULTS_FOR_LLM: int = Field(0, description=\"供LLM用搜索结果最大数\")\n MAX_HIGH_CONFIDENCE_SENTIMENT_RESULTS: int = Field(0, description=\"高置信度情感分析最大数\")\n MAX_REFLECTIONS: int = Field(3, description=\"最大反思次数\")\n MAX_PARAGRAPHS: int = Field(6, description=\"最大段落数\")\n SEARCH_TIMEOUT: int = Field(240, description=\"单次搜索请求超时\")\n MAX_CONTENT_LENGTH: int = Field(500000, description=\"搜索最大内容长度\")\n \n model_config = ConfigDict(\n env_file=ENV_FILE,\n env_prefix=\"\",\n case_sensitive=False,\n extra=\"allow\"\n )\n\n\n# 创建全局配置实例\nsettings = Settings()\n\n\ndef reload_settings() -> Settings:\n \"\"\"\n 重新加载配置\n \n 从 .env 文件和环境变量重新加载配置,更新全局 settings 实例。\n 用于在运行时动态更新配置。\n \n Returns:\n Settings: 新创建的配置实例\n \"\"\"\n \n global settings\n settings = Settings()\n return settings\n"}, "7a674841724d4f84a48b940bd38ca59a7d5c5598": {"t": 1785764973.657902, "n": 8324, "h": "70994016b7e6ee74", "c": "# -*- coding: utf-8 -*-\n\"\"\"\n微舆配置文件\n\n此模块使用 pydantic-settings 管理全局配置,支持从环境变量和 .env 文件自动加载。\n数据模型定义位置:\n- 本文件 - 配置模型定义\n\"\"\"\n\nfrom pathlib import Path\nfrom pydantic_settings import BaseSettings\nfrom pydantic import Field, ConfigDict\nfrom typing import Optional, Literal\nfrom loguru import logger\n\n\n# 计算 .env 优先级:优先当前工作目录,其次项目根目录\nPROJECT_ROOT: Path = Path(__file__).resolve().parent\nCWD_ENV: Path = Path.cwd() / \".env\"\nENV_FILE: str = str(CWD_ENV if CWD_ENV.exists() else (PROJECT_ROOT / \".env\"))\n\n\nclass Settings(BaseSettings):\n \"\"\"\n 全局配置;支持 .env 和环境变量自动加载。\n 变量名与原 config.py 大写一致,便于平滑过渡。\n \"\"\"\n # ================== Flask 服务器配置 ====================\n HOST: str = Field(\"0.0.0.0\", description=\"BETTAFISH 主机地址,例如 0.0.0.0 或 127.0.0.1\")\n PORT: int = Field(5000, description=\"Flask服务器端口号,默认5000\")\n\n # ================== 日志配置 ====================\n LOG_FILE: str = Field(\"logs/app.log\", description=\"日志文件路径\")\n\n # ================== 报告输出配置 ====================\n OUTPUT_DIR: str = Field(\"final_reports\", description=\"最终报告输出目录\")\n CHAPTER_OUTPUT_DIR: str = Field(\"final_reports/chapters\", description=\"章节中间文件输出目录\")\n DOCUMENT_IR_OUTPUT_DIR: str = Field(\"final_reports/ir\", description=\"文档中间表示输出目录\")\n\n TEMPLATE_DIR: str = Field(\"ReportEngine/report_template\", description=\"报告模板目录\")\n JSON_ERROR_LOG_DIR: str = Field(\"logs/json_errors\", description=\"JSON解析错误日志目录\")\n CHAPTER_JSON_MAX_ATTEMPTS: int = Field(3, description=\"章节JSON生成最大尝试次数\")\n\n # ====================== 数据库配置 ======================\n DB_DIALECT: str = Field(\"postgresql\", description=\"数据库类型,可选 mysql 或 postgresql;请与其他连接信息同时配置\")\n DB_HOST: str = Field(\"your_db_host\", description=\"数据库主机,例如localhost 或 127.0.0.1\")\n DB_PORT: int = Field(3306, description=\"数据库端口号,默认为3306\")\n DB_USER: str = Field(\"your_db_user\", description=\"数据库用户名\")\n DB_PASSWORD: str = Field(\"your_db_password\", description=\"数据库密码\")\n DB_NAME: str = Field(\"your_db_name\", description=\"数据库名称\")\n DB_CHARSET: str = Field(\"utf8mb4\", description=\"数据库字符集,推荐utf8mb4,兼容emoji\")\n \n # ======================= LLM 相关 =======================\n # 我们的LLM模型API赞助商有:https://aihubmix.com/?aff=8Ds9,提供了非常全面的模型api\n \n # Insight Agent(推荐Kimi,申请地址:https://platform.moonshot.cn/)\n INSIGHT_ENGINE_API_KEY: Optional[str] = Field(None, description=\"Insight Agent(推荐 kimi-k2,官方申请地址:https://platform.moonshot.cn/)API 密钥,用于主 LLM。🚩请先按推荐配置申请并跑通,再根据需要调整 KEY、BASE_URL 与 MODEL_NAME。\")\n INSIGHT_ENGINE_BASE_URL: Optional[str] = Field(\"https://api.moonshot.cn/v1\", description=\"Insight Agent LLM BaseUrl,可根据厂商自定义\")\n INSIGHT_ENGINE_MODEL_NAME: str = Field(\"kimi-k2-0711-preview\", description=\"Insight Agent LLM 模型名称,例如 kimi-k2-0711-preview\")\n \n # Media Agent(推荐Gemini,推荐中转厂商:https://aihubmix.com/?aff=8Ds9)\n MEDIA_ENGINE_API_KEY: Optional[str] = Field(None, description=\"Media Agent(推荐 gemini-2.5-pro,中转厂商申请地址:https://aihubmix.com/?aff=8Ds9)API 密钥\")\n MEDIA_ENGINE_BASE_URL: Optional[str] = Field(\"https://aihubmix.com/v1\", description=\"Media Agent LLM BaseUrl,可根据中转服务调整\")\n MEDIA_ENGINE_MODEL_NAME: str = Field(\"gemini-2.5-pro\", description=\"Media Agent LLM 模型名称,如 gemini-2.5-pro\")\n \n # Query Agent(推荐DeepSeek,申请地址:https://www.deepseek.com/)\n QUERY_ENGINE_API_KEY: Optional[str] = Field(None, description=\"Query Agent(推荐 deepseek,官方申请地址:https://platform.deepseek.com/)API 密钥\")\n QUERY_ENGINE_BASE_URL: Optional[str] = Field(\"https://api.deepseek.com\", description=\"Query Agent LLM BaseUrl\")\n QUERY_ENGINE_MODEL_NAME: str = Field(\"deepseek-chat\", description=\"Query Agent LLM 模型名称,如 deepseek-reasoner\")\n \n # Report Agent(推荐Gemini,推荐中转厂商:https://aihubmix.com/?aff=8Ds9)\n REPORT_ENGINE_API_KEY: Optional[str] = Field(None, description=\"Report Agent(推荐 gemini-2.5-pro,中转厂商申请地址:https://aihubmix.com/?aff=8Ds9)API 密钥\")\n REPORT_ENGINE_BASE_URL: Optional[str] = Field(\"https://aihubmix.com/v1\", description=\"Report Agent LLM BaseUrl,可根据中转服务调整\")\n REPORT_ENGINE_MODEL_NAME: str = Field(\"gemini-2.5-pro\", description=\"Report Agent LLM 模型名称,如 gemini-2.5-pro\")\n\n # MindSpider Agent(推荐Deepseek,官方申请地址:https://platform.deepseek.com/)\n MINDSPIDER_API_KEY: Optional[str] = Field(None, description=\"MindSpider Agent(推荐 deepseek,官方申请地址:https://platform.deepseek.com/)API 密钥\")\n MINDSPIDER_BASE_URL: Optional[str] = Field(None, description=\"MindSpider Agent BaseUrl,可按所选服务配置\")\n MINDSPIDER_MODEL_NAME: Optional[str] = Field(None, description=\"MindSpider Agent 模型名称,例如 deepseek-reasoner\")\n \n # Forum Host(Qwen3最新模型,这里我使用了硅基流动这个平台,申请地址:https://cloud.siliconflow.cn/)\n FORUM_HOST_API_KEY: Optional[str] = Field(None, description=\"Forum Host(推荐 qwen-plus,官方申请地址:https://www.aliyun.com/product/bailian)API 密钥\")\n FORUM_HOST_BASE_URL: Optional[str] = Field(None, description=\"Forum Host LLM BaseUrl,可按所选服务配置\")\n FORUM_HOST_MODEL_NAME: Optional[str] = Field(None, description=\"Forum Host LLM 模型名称,例如 qwen-plus\")\n \n # SQL keyword Optimizer(小参数Qwen3模型,这里我使用了硅基流动这个平台,申请地址:https://cloud.siliconflow.cn/)\n KEYWORD_OPTIMIZER_API_KEY: Optional[str] = Field(None, description=\"SQL Keyword Optimizer(推荐 qwen-plus,官方申请地址:https://www.aliyun.com/product/bailian)API 密钥\")\n KEYWORD_OPTIMIZER_BASE_URL: Optional[str] = Field(None, description=\"Keyword Optimizer BaseUrl,可按所选服务配置\")\n KEYWORD_OPTIMIZER_MODEL_NAME: Optional[str] = Field(None, description=\"Keyword Optimizer LLM 模型名称,例如 qwen-plus\")\n \n # ================== GraphRAG 配置 ====================\n GRAPHRAG_ENABLED: bool = Field(False, description=\"是否启用GraphRAG知识图谱功能(true/false)\")\n GRAPHRAG_MAX_QUERIES: int = Field(3, description=\"GraphRAG每个章节生成前的最大查询次数\")\n \n # ================== 网络工具配置 ====================\n # Tavily API(申请地址:https://www.tavily.com/)\n TAVILY_API_KEY: Optional[str] = Field(None, description=\"Tavily API(申请地址:https://www.tavily.com/)API密钥,用于Tavily网络搜索\")\n\n SEARCH_TOOL_TYPE: Literal[\"AnspireAPI\", \"BochaAPI\"] = Field(\"AnspireAPI\", description=\"网络搜索工具类型,支持BochaAPI或AnspireAPI两种,默认为AnspireAPI\")\n # Bocha API(申请地址:https://open.bochaai.com/)\n BOCHA_BASE_URL: Optional[str] = Field(\"https://api.bocha.cn/v1/ai-search\", description=\"Bocha AI 搜索BaseUrl或博查网页搜索BaseUrl\")\n BOCHA_WEB_SEARCH_API_KEY: Optional[str] = Field(None, description=\"Bocha API(申请地址:https://open.bochaai.com/)API密钥,用于Bocha搜索\")\n\n # Anspire AI Search API(申请地址:https://open.anspire.cn/?share_code=3E1FUOUH)\n ANSPIRE_BASE_URL: Optional[str] = Field(\"https://plugin.anspire.cn/api/ntsearch/search\", description=\"Anspire AI 搜索BaseUrl\")\n ANSPIRE_API_KEY: Optional[str] = Field(None, description=\"Anspire AI Search API(申请地址:https://open.anspire.cn/?share_code=3E1FUOUH)API密钥,用于Anspire搜索\")\n\n # ================== 飞书配置 ====================\n FEISHU_APP_ID: Optional[str] = Field(None, description=\"飞书应用 App ID,用于飞书多维表格API认证\")\n FEISHU_APP_SECRET: Optional[str] = Field(None, description=\"飞书应用 App Secret,用于飞书多维表格API认证\")\n FEISHU_APP_TOKEN: Optional[str] = Field(None, description=\"飞书多维表格 App Token,用于指定默认操作的Bitable\")\n\n \n # ================== Insight Engine 搜索配置 ====================\n DEFAULT_SEARCH_HOT_CONTENT_LIMIT: int = Field(100, description=\"热榜内容默认最大数\")\n DEFAULT_SEARCH_TOPIC_GLOBALLY_LIMIT_PER_TABLE: int = Field(50, description=\"按表全局话题最大数\")\n DEFAULT_SEARCH_TOPIC_BY_DATE_LIMIT_PER_TABLE: int = Field(100, description=\"按日期话题最大数\")\n DEFAULT_GET_COMMENTS_FOR_TOPIC_LIMIT: int = Field(500, description=\"单话题评论最大数\")\n DEFAULT_SEARCH_TOPIC_ON_PLATFORM_LIMIT: int = Field(200, description=\"平台搜索话题最大数\")\n MAX_SEARCH_RESULTS_FOR_LLM: int = Field(0, description=\"供LLM用搜索结果最大数\")\n MAX_HIGH_CONFIDENCE_SENTIMENT_RESULTS: int = Field(0, description=\"高置信度情感分析最大数\")\n MAX_REFLECTIONS: int = Field(3, description=\"最大反思次数\")\n MAX_PARAGRAPHS: int = Field(6, description=\"最大段落数\")\n SEARCH_TIMEOUT: int = Field(240, description=\"单次搜索请求超时\")\n MAX_CONTENT_LENGTH: int = Field(500000, description=\"搜索最大内容长度\")\n \n model_config = ConfigDict(\n env_file=ENV_FILE,\n env_prefix=\"\",\n case_sensitive=False,\n extra=\"allow\"\n )\n\n\n# 创建全局配置实例\nsettings = Settings()\n\n\ndef reload_settings() -> Settings:\n \"\"\"\n 重新加载配置\n \n 从 .env 文件和环境变量重新加载配置,更新全局 settings 实例。\n 用于在运行时动态更新配置。\n \n Returns:\n Settings: 新创建的配置实例\n \"\"\"\n \n global settings\n settings = Settings()\n return settings\n"}, "8987f47d1f1c54bb008f7bbe164da39444ad5996": {"t": 1785764975.122001, "n": 7989, "h": "8eac2567330019bb", "c": "# -*- coding: utf-8 -*-\n\"\"\"\n微舆配置文件\n\n此模块使用 pydantic-settings 管理全局配置,支持从环境变量和 .env 文件自动加载。\n数据模型定义位置:\n- 本文件 - 配置模型定义\n\"\"\"\n\nfrom pathlib import Path\nfrom pydantic_settings import BaseSettings\nfrom pydantic import Field, ConfigDict\nfrom typing import Optional, Literal\nfrom loguru import logger\n\n\n# 计算 .env 优先级:优先当前工作目录,其次项目根目录\nPROJECT_ROOT: Path = Path(__file__).resolve().parent\nCWD_ENV: Path = Path.cwd() / \".env\"\nENV_FILE: str = str(CWD_ENV if CWD_ENV.exists() else (PROJECT_ROOT / \".env\"))\n\n\nclass Settings(BaseSettings):\n \"\"\"\n 全局配置;支持 .env 和环境变量自动加载。\n 变量名与原 config.py 大写一致,便于平滑过渡。\n \"\"\"\n # ================== Flask 服务器配置 ====================\n HOST: str = Field(\"0.0.0.0\", description=\"BETTAFISH 主机地址,例如 0.0.0.0 或 127.0.0.1\")\n PORT: int = Field(5000, description=\"Flask服务器端口号,默认5000\")\n\n # ================== 日志配置 ====================\n LOG_FILE: str = Field(\"logs/app.log\", description=\"日志文件路径\")\n\n # ================== 报告输出配置 ====================\n OUTPUT_DIR: str = Field(\"final_reports\", description=\"最终报告输出目录\")\n CHAPTER_OUTPUT_DIR: str = Field(\"final_reports/chapters\", description=\"章节中间文件输出目录\")\n DOCUMENT_IR_OUTPUT_DIR: str = Field(\"final_reports/ir\", description=\"文档中间表示输出目录\")\n\n TEMPLATE_DIR: str = Field(\"ReportEngine/report_template\", description=\"报告模板目录\")\n JSON_ERROR_LOG_DIR: str = Field(\"logs/json_errors\", description=\"JSON解析错误日志目录\")\n CHAPTER_JSON_MAX_ATTEMPTS: int = Field(3, description=\"章节JSON生成最大尝试次数\")\n\n # ====================== 数据库配置 ======================\n DB_DIALECT: str = Field(\"postgresql\", description=\"数据库类型,可选 mysql 或 postgresql;请与其他连接信息同时配置\")\n DB_HOST: str = Field(\"your_db_host\", description=\"数据库主机,例如localhost 或 127.0.0.1\")\n DB_PORT: int = Field(3306, description=\"数据库端口号,默认为3306\")\n DB_USER: str = Field(\"your_db_user\", description=\"数据库用户名\")\n DB_PASSWORD: str = Field(\"your_db_password\", description=\"数据库密码\")\n DB_NAME: str = Field(\"your_db_name\", description=\"数据库名称\")\n DB_CHARSET: str = Field(\"utf8mb4\", description=\"数据库字符集,推荐utf8mb4,兼容emoji\")\n \n # ======================= LLM 相关 =======================\n # 我们的LLM模型API赞助商有:https://aihubmix.com/?aff=8Ds9,提供了非常全面的模型api\n \n # Insight Agent(推荐Kimi,申请地址:https://platform.moonshot.cn/)\n INSIGHT_ENGINE_API_KEY: Optional[str] = Field(None, description=\"Insight Agent(推荐 kimi-k2,官方申请地址:https://platform.moonshot.cn/)API 密钥,用于主 LLM。🚩请先按推荐配置申请并跑通,再根据需要调整 KEY、BASE_URL 与 MODEL_NAME。\")\n INSIGHT_ENGINE_BASE_URL: Optional[str] = Field(\"https://api.moonshot.cn/v1\", description=\"Insight Agent LLM BaseUrl,可根据厂商自定义\")\n INSIGHT_ENGINE_MODEL_NAME: str = Field(\"kimi-k2-0711-preview\", description=\"Insight Agent LLM 模型名称,例如 kimi-k2-0711-preview\")\n \n # Media Agent(推荐Gemini,推荐中转厂商:https://aihubmix.com/?aff=8Ds9)\n MEDIA_ENGINE_API_KEY: Optional[str] = Field(None, description=\"Media Agent(推荐 gemini-2.5-pro,中转厂商申请地址:https://aihubmix.com/?aff=8Ds9)API 密钥\")\n MEDIA_ENGINE_BASE_URL: Optional[str] = Field(\"https://aihubmix.com/v1\", description=\"Media Agent LLM BaseUrl,可根据中转服务调整\")\n MEDIA_ENGINE_MODEL_NAME: str = Field(\"gemini-2.5-pro\", description=\"Media Agent LLM 模型名称,如 gemini-2.5-pro\")\n \n # Query Agent(推荐DeepSeek,申请地址:https://www.deepseek.com/)\n QUERY_ENGINE_API_KEY: Optional[str] = Field(None, description=\"Query Agent(推荐 deepseek,官方申请地址:https://platform.deepseek.com/)API 密钥\")\n QUERY_ENGINE_BASE_URL: Optional[str] = Field(\"https://api.deepseek.com\", description=\"Query Agent LLM BaseUrl\")\n QUERY_ENGINE_MODEL_NAME: str = Field(\"deepseek-chat\", description=\"Query Agent LLM 模型名称,如 deepseek-reasoner\")\n \n # Report Agent(推荐Gemini,推荐中转厂商:https://aihubmix.com/?aff=8Ds9)\n REPORT_ENGINE_API_KEY: Optional[str] = Field(None, description=\"Report Agent(推荐 gemini-2.5-pro,中转厂商申请地址:https://aihubmix.com/?aff=8Ds9)API 密钥\")\n REPORT_ENGINE_BASE_URL: Optional[str] = Field(\"https://aihubmix.com/v1\", description=\"Report Agent LLM BaseUrl,可根据中转服务调整\")\n REPORT_ENGINE_MODEL_NAME: str = Field(\"gemini-2.5-pro\", description=\"Report Agent LLM 模型名称,如 gemini-2.5-pro\")\n\n # MindSpider Agent(推荐Deepseek,官方申请地址:https://platform.deepseek.com/)\n MINDSPIDER_API_KEY: Optional[str] = Field(None, description=\"MindSpider Agent(推荐 deepseek,官方申请地址:https://platform.deepseek.com/)API 密钥\")\n MINDSPIDER_BASE_URL: Optional[str] = Field(None, description=\"MindSpider Agent BaseUrl,可按所选服务配置\")\n MINDSPIDER_MODEL_NAME: Optional[str] = Field(None, description=\"MindSpider Agent 模型名称,例如 deepseek-reasoner\")\n \n # Forum Host(Qwen3最新模型,这里我使用了硅基流动这个平台,申请地址:https://cloud.siliconflow.cn/)\n FORUM_HOST_API_KEY: Optional[str] = Field(None, description=\"Forum Host(推荐 qwen-plus,官方申请地址:https://www.aliyun.com/product/bailian)API 密钥\")\n FORUM_HOST_BASE_URL: Optional[str] = Field(None, description=\"Forum Host LLM BaseUrl,可按所选服务配置\")\n FORUM_HOST_MODEL_NAME: Optional[str] = Field(None, description=\"Forum Host LLM 模型名称,例如 qwen-plus\")\n \n # SQL keyword Optimizer(小参数Qwen3模型,这里我使用了硅基流动这个平台,申请地址:https://cloud.siliconflow.cn/)\n KEYWORD_OPTIMIZER_API_KEY: Optional[str] = Field(None, description=\"SQL Keyword Optimizer(推荐 qwen-plus,官方申请地址:https://www.aliyun.com/product/bailian)API 密钥\")\n KEYWORD_OPTIMIZER_BASE_URL: Optional[str] = Field(None, description=\"Keyword Optimizer BaseUrl,可按所选服务配置\")\n KEYWORD_OPTIMIZER_MODEL_NAME: Optional[str] = Field(None, description=\"Keyword Optimizer LLM 模型名称,例如 qwen-plus\")\n \n # ================== GraphRAG 配置 ====================\n GRAPHRAG_ENABLED: bool = Field(False, description=\"是否启用GraphRAG知识图谱功能(true/false)\")\n GRAPHRAG_MAX_QUERIES: int = Field(3, description=\"GraphRAG每个章节生成前的最大查询次数\")\n \n # ================== 网络工具配置 ====================\n # Tavily API(申请地址:https://www.tavily.com/)\n TAVILY_API_KEY: Optional[str] = Field(None, description=\"Tavily API(申请地址:https://www.tavily.com/)API密钥,用于Tavily网络搜索\")\n\n SEARCH_TOOL_TYPE: Literal[\"AnspireAPI\", \"BochaAPI\"] = Field(\"AnspireAPI\", description=\"网络搜索工具类型,支持BochaAPI或AnspireAPI两种,默认为AnspireAPI\")\n # Bocha API(申请地址:https://open.bochaai.com/)\n BOCHA_BASE_URL: Optional[str] = Field(\"https://api.bocha.cn/v1/ai-search\", description=\"Bocha AI 搜索BaseUrl或博查网页搜索BaseUrl\")\n BOCHA_WEB_SEARCH_API_KEY: Optional[str] = Field(None, description=\"Bocha API(申请地址:https://open.bochaai.com/)API密钥,用于Bocha搜索\")\n\n # Anspire AI Search API(申请地址:https://open.anspire.cn/?share_code=3E1FUOUH)\n ANSPIRE_BASE_URL: Optional[str] = Field(\"https://plugin.anspire.cn/api/ntsearch/search\", description=\"Anspire AI 搜索BaseUrl\")\n ANSPIRE_API_KEY: Optional[str] = Field(None, description=\"Anspire AI Search API(申请地址:https://open.anspire.cn/?share_code=3E1FUOUH)API密钥,用于Anspire搜索\")\n\n \n # ================== Insight Engine 搜索配置 ====================\n DEFAULT_SEARCH_HOT_CONTENT_LIMIT: int = Field(100, description=\"热榜内容默认最大数\")\n DEFAULT_SEARCH_TOPIC_GLOBALLY_LIMIT_PER_TABLE: int = Field(50, description=\"按表全局话题最大数\")\n DEFAULT_SEARCH_TOPIC_BY_DATE_LIMIT_PER_TABLE: int = Field(100, description=\"按日期话题最大数\")\n DEFAULT_GET_COMMENTS_FOR_TOPIC_LIMIT: int = Field(500, description=\"单话题评论最大数\")\n DEFAULT_SEARCH_TOPIC_ON_PLATFORM_LIMIT: int = Field(200, description=\"平台搜索话题最大数\")\n MAX_SEARCH_RESULTS_FOR_LLM: int = Field(0, description=\"供LLM用搜索结果最大数\")\n MAX_HIGH_CONFIDENCE_SENTIMENT_RESULTS: int = Field(0, description=\"高置信度情感分析最大数\")\n MAX_REFLECTIONS: int = Field(3, description=\"最大反思次数\")\n MAX_PARAGRAPHS: int = Field(6, description=\"最大段落数\")\n SEARCH_TIMEOUT: int = Field(240, description=\"单次搜索请求超时\")\n MAX_CONTENT_LENGTH: int = Field(500000, description=\"搜索最大内容长度\")\n \n model_config = ConfigDict(\n env_file=ENV_FILE,\n env_prefix=\"\",\n case_sensitive=False,\n extra=\"allow\"\n )\n\n\n# 创建全局配置实例\nsettings = Settings()\n\n\ndef reload_settings() -> Settings:\n \"\"\"\n 重新加载配置\n \n 从 .env 文件和环境变量重新加载配置,更新全局 settings 实例。\n 用于在运行时动态更新配置。\n \n Returns:\n Settings: 新创建的配置实例\n \"\"\"\n \n global settings\n settings = Settings()\n return settings\n"}}, "patch_report_engine_deepseek.py": {"359daa4d119dc1551d99bc2bffda7e7afd49cae6": {"t": 1785809880.3838441, "n": 2649, "h": "b6695d7e0f3a9d22", "c": "import os\n\ntarget_file = r\"D:\\my-web-app\\BettaFish\\report_engine_only.py\"\n\ntry:\n with open(target_file, \"r\", encoding=\"utf-8\") as f:\n content = f.read()\n\n old_code = \"\"\"def build_agent_config(args) -> Settings:\n \\\"\\\"\\\"基于 .env 配置并融合命令行覆盖项生成最终配置\\\"\\\"\\\"\n config_overrides: Dict[str, Any] = {}\n\n if args.graphrag_enabled is not None:\n config_overrides[\"GRAPHRAG_ENABLED\"] = args.graphrag_enabled\n if args.graphrag_max_queries is not None:\n if args.graphrag_max_queries <= 0:\n logger.warning(\"GRAPHRAG_MAX_QUERIES 必须大于 0,本次将继续使用 .env/默认值\")\n else:\n config_overrides[\"GRAPHRAG_MAX_QUERIES\"] = args.graphrag_max_queries\n\n if not config_overrides:\n return global_settings\n\n return global_settings.model_copy(update=config_overrides)\"\"\"\n\n new_code = \"\"\"def build_agent_config(args) -> Settings:\n \\\"\\\"\\\"基于 .env 配置并融合命令行覆盖项生成最终配置\\\"\\\"\\\"\n # 强制重新加载配置,确保获取最新的环境变量\n try:\n current_settings = Settings()\n except Exception as e:\n logger.warning(f\"重新加载配置失败,使用默认配置: {e}\")\n current_settings = global_settings\n\n config_overrides: Dict[str, Any] = {}\n\n # 自动适配 DeepSeek (如果用户只配了 Key 没改 URL)\n # 假设 DeepSeek Key 以 sk- 开头,且当前 Base URL 是默认的 aihubmix\n api_key = current_settings.REPORT_ENGINE_API_KEY\n base_url = current_settings.REPORT_ENGINE_BASE_URL\n \n if api_key and api_key.startswith(\"sk-\") and \"aihubmix\" in (base_url or \"\"):\n logger.info(\"🔧 检测到 DeepSeek 风格 API Key,自动切换至 DeepSeek 官方节点\")\n config_overrides[\"REPORT_ENGINE_BASE_URL\"] = \"https://api.deepseek.com\"\n config_overrides[\"REPORT_ENGINE_MODEL_NAME\"] = \"deepseek-chat\"\n\n if args.graphrag_enabled is not None:\n config_overrides[\"GRAPHRAG_ENABLED\"] = args.graphrag_enabled\n if args.graphrag_max_queries is not None:\n if args.graphrag_max_queries <= 0:\n logger.warning(\"GRAPHRAG_MAX_QUERIES 必须大于 0,本次将继续使用 .env/默认值\")\n else:\n config_overrides[\"GRAPHRAG_MAX_QUERIES\"] = args.graphrag_max_queries\n\n if not config_overrides:\n return current_settings\n\n return current_settings.model_copy(update=config_overrides)\"\"\"\n\n if old_code in content:\n new_content = content.replace(old_code, new_code)\n with open(target_file, \"w\", encoding=\"utf-8\") as f:\n f.write(new_content)\n print(\"Success: Patched report_engine_only.py\")\n else:\n print(\"Error: Could not find target code block. Content length:\", len(content))\n # Optional: Print a snippet to verify\n print(\"Snippet:\", content[539:600])\n\nexcept Exception as e:\n print(f\"File operation failed: {e}\")\n"}}, "python_backend/news_engine.py": {"359daa4d119dc1551d99bc2bffda7e7afd49cae6": {"t": 1786067732.5665877, "n": 4002, "h": "38cf9897ec3dd8d8", "c": "# -*- coding: utf-8 -*-\nimport os\nimport json\nimport random\nimport requests\nfrom typing import List, Dict\nfrom tavily import TavilyClient\nfrom dotenv import load_dotenv\nfrom pathlib import Path\n\n# Load environment\ncurrent_file_path = Path(__file__).resolve()\nproject_root_dir = current_file_path.parent.parent\nload_dotenv(dotenv_path=project_root_dir / '.env')\n\nTAVILY_API_KEY = os.getenv(\"TAVILY_API_KEY\")\nDEEPSEEK_API_KEY = os.getenv(\"DEEPSEEK_API_KEY\")\n\ndef fetch_market_news(topic: str) -> List[Dict]:\n \"\"\"\n Fetch real-time news using Tavily or fallback to AI Synthesis.\n Strictly returns JSON format: [{ \"title\": str, \"source\": str, \"sentiment\": str }]\n \"\"\"\n news_items = []\n \n # ATTEMPT 1: REAL TAVILY DATA\n if TAVILY_API_KEY:\n try:\n client = TavilyClient(api_key=TAVILY_API_KEY)\n response = client.search(query=f\"{topic} market news business\", search_depth=\"basic\", max_results=5)\n \n for res in response.get('results', []):\n # Map URL to cleaner source name\n url = res.get('url', '')\n source = \"Web Source\"\n if \"bloomberg\" in url: source = \"Bloomberg\"\n elif \"reuters\" in url: source = \"Reuters\"\n elif \"cnbc\" in url: source = \"CNBC\"\n elif \"wsj\" in url: source = \"WSJ\"\n elif \"techcrunch\" in url: source = \"TechCrunch\"\n else: \n # Extract domain roughly\n try:\n source = url.split('//')[1].split('/')[0].replace('www.', '').split('.')[0].capitalize()\n except:\n source = \"Industry Web\"\n\n news_items.append({\n \"title\": res.get('title', 'Market Update'),\n \"source\": source,\n \"sentiment\": \"Neutral\" # Default, hard to analyze without LLM\n })\n except Exception as e:\n print(f\"⚠️ Tavily fetch failed: {e}\")\n\n # If Tavily returned items, return them (maybe enhance sentiment later)\n if news_items:\n return news_items[:5]\n\n # ATTEMPT 2: AI SYNTHESIS (FALLBACK)\n # If no API key or fetch failed, generate realistic headlines based on the topic.\n print(\"🤖 Engaging AI News Synthesis...\")\n \n if not DEEPSEEK_API_KEY:\n # ABSOLUTE FALLBACK if no keys at all - MUST be removed in production\n # But keeping it for now as a last resort to prevent crash, but warning loudly\n print(\"⚠️ CRITICAL: No API keys found. Returning empty list instead of static mocks.\")\n return []\n\n system_prompt = \"\"\"\n You are a financial news generator. \n Generate 3 REALISTIC, PROFESSIONAL news headlines about the user's topic based on GENERAL MARKET KNOWLEDGE.\n Do NOT use \"Mock\" or \"Placeholder\". Make it sound like a real headline from today.\n RETURN ONLY JSON. Format: [{\"title\": \"...\", \"source\": \"...\", \"sentiment\": \"Bullish\"|\"Bearish\"|\"Neutral\", \"url\": \"#\"}]\n Sources should be reputable (Bloomberg, Reuters, FT, WSJ, TechCrunch).\n \"\"\"\n \n try:\n api_url = \"https://api.deepseek.com/v1/chat/completions\"\n headers = {\"Authorization\": f\"Bearer {DEEPSEEK_API_KEY}\", \"Content-Type\": \"application/json\"}\n payload = {\n \"model\": \"deepseek-chat\",\n \"messages\": [{\"role\": \"system\", \"content\": system_prompt}, {\"role\": \"user\", \"content\": f\"Topic: {topic}\"}],\n \"temperature\": 0.7\n }\n \n response = requests.post(api_url, json=payload, headers=headers, timeout=10)\n content = response.json()[\"choices\"][0][\"message\"][\"content\"]\n \n # Parse JSON from LLM\n # Use regex to find JSON array if mixed with text\n import re\n match = re.search(r'\\[.*\\]', content, re.DOTALL)\n if match:\n return json.loads(match.group(0))\n \n except Exception as e:\n print(f\"❌ AI Synthesis failed: {e}\")\n\n return []\n"}}}}