666ghj

Standardize LLM clients and expose configurable base URLs.

... ... @@ -12,7 +12,7 @@ import re
# 添加项目根目录到Python路径以导入config
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from config import GUIJI_QWEN3_API_KEY
from config import GUIJI_QWEN3_API_KEY, GUIJI_QWEN3_BASE_URL
# 添加utils目录到Python路径
current_dir = os.path.dirname(os.path.abspath(__file__))
... ... @@ -30,21 +30,24 @@ class ForumHost:
使用Qwen3-235B模型作为智能主持人
"""
def __init__(self, api_key: str = None):
def __init__(self, api_key: str = None, base_url: Optional[str] = None):
"""
初始化论坛主持人
Args:
api_key: 硅基流动API密钥,如果不提供则从配置文件读取
base_url: 接口基础地址,默认使用配置文件提供的SiliconFlow地址
"""
self.api_key = api_key or GUIJI_QWEN3_API_KEY
if not self.api_key:
raise ValueError("未找到硅基流动API密钥,请在config.py中设置GUIJI_QWEN3_API_KEY")
self.base_url = base_url or GUIJI_QWEN3_BASE_URL
self.client = OpenAI(
api_key=self.api_key,
base_url="https://api.siliconflow.cn/v1"
base_url=self.base_url
)
self.model = "Qwen/Qwen3-235B-A22B-Instruct-2507" # Use larger model variant
... ...
... ... @@ -72,7 +72,8 @@ class DeepSearchAgent:
if self.config.default_llm_provider == "deepseek":
return DeepSeekLLM(
api_key=self.config.deepseek_api_key,
model_name=self.config.deepseek_model
model_name=self.config.deepseek_model,
base_url=self.config.deepseek_base_url
)
elif self.config.default_llm_provider == "openai":
return OpenAILLM(
... ... @@ -82,7 +83,8 @@ class DeepSearchAgent:
elif self.config.default_llm_provider == "kimi":
return KimiLLM(
api_key=self.config.kimi_api_key,
model_name=self.config.kimi_model
model_name=self.config.kimi_model,
base_url=self.config.kimi_base_url
)
else:
raise ValueError(f"不支持的LLM提供商: {self.config.default_llm_provider}")
... ...
... ... @@ -9,6 +9,8 @@ from openai import OpenAI
from .base import BaseLLM
import sys
DEFAULT_DEEPSEEK_BASE_URL = "https://api.deepseek.com"
# 添加utils目录到Python路径
current_dir = os.path.dirname(os.path.abspath(__file__))
root_dir = os.path.dirname(os.path.dirname(current_dir))
... ... @@ -30,13 +32,14 @@ except ImportError:
class DeepSeekLLM(BaseLLM):
"""DeepSeek LLM实现类"""
def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None):
def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None, base_url: Optional[str] = None):
"""
初始化DeepSeek客户端
Args:
api_key: DeepSeek API密钥,如果不提供则从环境变量读取
model_name: 模型名称,默认使用deepseek-chat
base_url: DeepSeek API基础地址
"""
if api_key is None:
api_key = os.getenv("DEEPSEEK_API_KEY")
... ... @@ -45,10 +48,12 @@ class DeepSeekLLM(BaseLLM):
super().__init__(api_key, model_name)
self.base_url = base_url or os.getenv("DEEPSEEK_BASE_URL") or DEFAULT_DEEPSEEK_BASE_URL
# 初始化OpenAI客户端,使用DeepSeek的endpoint
self.client = OpenAI(
api_key=self.api_key,
base_url="https://api.deepseek.com"
base_url=self.base_url
)
self.default_model = model_name or self.get_default_model()
... ... @@ -110,5 +115,5 @@ class DeepSeekLLM(BaseLLM):
return {
"provider": "DeepSeek",
"model": self.default_model,
"api_base": "https://api.deepseek.com"
"api_base": self.base_url
}
... ...
... ... @@ -10,6 +10,8 @@ from openai import OpenAI
# 假设 .base 模块和 BaseLLM 类已存在
from .base import BaseLLM
DEFAULT_KIMI_BASE_URL = "https://api.moonshot.cn/v1"
# 添加utils目录到Python路径并导入重试模块
try:
current_dir = os.path.dirname(os.path.abspath(__file__))
... ... @@ -30,13 +32,14 @@ except ImportError:
class KimiLLM(BaseLLM):
"""Kimi LLM实现类"""
def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None):
def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None, base_url: Optional[str] = None):
"""
初始化Kimi客户端
Args:
api_key: Kimi API密钥,如果不提供则从环境变量读取
model_name: 模型名称,默认使用kimi-k2-0711-preview
base_url: Kimi API基础地址
"""
if api_key is None:
api_key = os.getenv("KIMI_API_KEY")
... ... @@ -45,10 +48,12 @@ class KimiLLM(BaseLLM):
super().__init__(api_key, model_name)
self.base_url = base_url or os.getenv("KIMI_BASE_URL") or DEFAULT_KIMI_BASE_URL
# 初始化OpenAI客户端,使用Kimi的endpoint
self.client = OpenAI(
api_key=self.api_key,
base_url="https://api.moonshot.cn/v1"
base_url=self.base_url
)
self.default_model = model_name or self.get_default_model()
... ... @@ -136,7 +141,7 @@ class KimiLLM(BaseLLM):
return {
"provider": "Kimi",
"model": self.default_model,
"api_base": "https://api.moonshot.cn/v1",
"api_base": self.base_url,
"max_context_length": "长文本支持(200K+ tokens)"
}
... ...
... ... @@ -12,7 +12,7 @@ from dataclasses import dataclass
# 添加项目根目录到Python路径以导入config
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
from config import GUIJI_QWEN3_API_KEY
from config import GUIJI_QWEN3_API_KEY, GUIJI_QWEN3_BASE_URL
# 添加utils目录到Python路径
current_dir = os.path.dirname(os.path.abspath(__file__))
... ... @@ -38,21 +38,24 @@ class KeywordOptimizer:
使用硅基流动的Qwen3模型将Agent生成的搜索词优化为更贴近真实舆情的关键词
"""
def __init__(self, api_key: str = None):
def __init__(self, api_key: str = None, base_url: str = None):
"""
初始化关键词优化器
Args:
api_key: 硅基流动API密钥,如果不提供则从配置文件读取
base_url: 接口基础地址,默认使用配置文件提供的SiliconFlow地址
"""
self.api_key = api_key or GUIJI_QWEN3_API_KEY
if not self.api_key:
raise ValueError("未找到硅基流动API密钥,请在config.py中设置GUIJI_QWEN3_API_KEY")
self.base_url = base_url or GUIJI_QWEN3_BASE_URL
self.client = OpenAI(
api_key=self.api_key,
base_url="https://api.siliconflow.cn/v1"
base_url=self.base_url
)
self.model = "Qwen/Qwen3-30B-A3B-Instruct-2507"
... ...
... ... @@ -15,6 +15,9 @@ class Config:
deepseek_api_key: Optional[str] = None
openai_api_key: Optional[str] = None
kimi_api_key: Optional[str] = None
deepseek_base_url: str = "https://api.deepseek.com"
openai_base_url: Optional[str] = None
kimi_base_url: str = "https://api.moonshot.cn/v1"
# 数据库配置
db_host: Optional[str] = None
... ... @@ -85,6 +88,10 @@ class Config:
return cls(
deepseek_api_key=getattr(config_module, "DEEPSEEK_API_KEY", None),
openai_api_key=getattr(config_module, "OPENAI_API_KEY", None),
kimi_api_key=getattr(config_module, "KIMI_API_KEY", None),
deepseek_base_url=getattr(config_module, "DEEPSEEK_BASE_URL", "https://api.deepseek.com"),
openai_base_url=getattr(config_module, "OPENAI_BASE_URL", None),
kimi_base_url=getattr(config_module, "KIMI_BASE_URL", "https://api.moonshot.cn/v1"),
db_host=getattr(config_module, "DB_HOST", None),
db_user=getattr(config_module, "DB_USER", None),
... ... @@ -131,6 +138,9 @@ class Config:
deepseek_api_key=config_dict.get("DEEPSEEK_API_KEY"),
openai_api_key=config_dict.get("OPENAI_API_KEY"),
kimi_api_key=config_dict.get("KIMI_API_KEY"),
deepseek_base_url=config_dict.get("DEEPSEEK_BASE_URL", "https://api.deepseek.com"),
openai_base_url=config_dict.get("OPENAI_BASE_URL"),
kimi_base_url=config_dict.get("KIMI_BASE_URL", "https://api.moonshot.cn/v1"),
db_host=config_dict.get("DB_HOST"),
db_user=config_dict.get("DB_USER"),
... ...
... ... @@ -60,7 +60,8 @@ class DeepSearchAgent:
if self.config.default_llm_provider == "deepseek":
return DeepSeekLLM(
api_key=self.config.deepseek_api_key,
model_name=self.config.deepseek_model
model_name=self.config.deepseek_model,
base_url=self.config.deepseek_base_url
)
elif self.config.default_llm_provider == "openai":
return OpenAILLM(
... ... @@ -70,7 +71,8 @@ class DeepSearchAgent:
elif self.config.default_llm_provider == "gemini":
return GeminiLLM(
api_key=self.config.gemini_api_key,
model_name=self.config.gemini_model
model_name=self.config.gemini_model,
base_url=self.config.gemini_base_url
)
else:
raise ValueError(f"不支持的LLM提供商: {self.config.default_llm_provider}")
... ...
... ... @@ -9,6 +9,8 @@ from typing import Optional, Dict, Any
from openai import OpenAI
from .base import BaseLLM
DEFAULT_DEEPSEEK_BASE_URL = "https://api.deepseek.com"
# 添加utils目录到Python路径并导入重试模块
try:
current_dir = os.path.dirname(os.path.abspath(__file__))
... ... @@ -29,13 +31,14 @@ except ImportError:
class DeepSeekLLM(BaseLLM):
"""DeepSeek LLM实现类"""
def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None):
def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None, base_url: Optional[str] = None):
"""
初始化DeepSeek客户端
Args:
api_key: DeepSeek API密钥,如果不提供则从环境变量读取
model_name: 模型名称,默认使用deepseek-chat
base_url: DeepSeek API基础地址
"""
if api_key is None:
api_key = os.getenv("DEEPSEEK_API_KEY")
... ... @@ -44,10 +47,12 @@ class DeepSeekLLM(BaseLLM):
super().__init__(api_key, model_name)
self.base_url = base_url or os.getenv("DEEPSEEK_BASE_URL") or DEFAULT_DEEPSEEK_BASE_URL
# 初始化OpenAI客户端,使用DeepSeek的endpoint
self.client = OpenAI(
api_key=self.api_key,
base_url="https://api.deepseek.com"
base_url=self.base_url
)
self.default_model = model_name or self.get_default_model()
... ... @@ -109,5 +114,5 @@ class DeepSeekLLM(BaseLLM):
return {
"provider": "DeepSeek",
"model": self.default_model,
"api_base": "https://api.deepseek.com"
"api_base": self.base_url
}
... ...
... ... @@ -9,6 +9,8 @@ from typing import Optional, Dict, Any
from openai import OpenAI
from .base import BaseLLM
DEFAULT_GEMINI_BASE_URL = "https://www.chataiapi.com/v1"
# 添加utils目录到Python路径并导入重试模块
try:
current_dir = os.path.dirname(os.path.abspath(__file__))
... ... @@ -29,13 +31,14 @@ except ImportError:
class GeminiLLM(BaseLLM):
"""Gemini LLM实现类"""
def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None):
def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None, base_url: Optional[str] = None):
"""
初始化Gemini客户端
Args:
api_key: Gemini API密钥,如果不提供则从环境变量读取
model_name: 模型名称,默认使用gemini-2.5-pro
base_url: Gemini API基础地址
"""
if api_key is None:
api_key = os.getenv("GEMINI_API_KEY")
... ... @@ -44,10 +47,12 @@ class GeminiLLM(BaseLLM):
super().__init__(api_key, model_name)
self.base_url = base_url or os.getenv("GEMINI_BASE_URL") or DEFAULT_GEMINI_BASE_URL
# 初始化OpenAI客户端,使用Gemini的中转endpoint
self.client = OpenAI(
api_key=self.api_key,
base_url="https://www.chataiapi.com/v1"
base_url=self.base_url
)
self.default_model = model_name or self.get_default_model()
... ... @@ -109,5 +114,5 @@ class GeminiLLM(BaseLLM):
return {
"provider": "Gemini",
"model": self.default_model,
"api_base": "https://www.chataiapi.com/v1"
"api_base": self.base_url
}
... ...
... ... @@ -16,6 +16,9 @@ class Config:
openai_api_key: Optional[str] = None
gemini_api_key: Optional[str] = None
bocha_api_key: Optional[str] = None
deepseek_base_url: str = "https://api.deepseek.com"
openai_base_url: Optional[str] = None
gemini_base_url: str = "https://www.chataiapi.com/v1"
# 模型配置
default_llm_provider: str = "deepseek" # deepseek、openai 或 gemini
... ... @@ -72,6 +75,9 @@ class Config:
deepseek_api_key=getattr(config_module, "DEEPSEEK_API_KEY", None),
openai_api_key=getattr(config_module, "OPENAI_API_KEY", None),
gemini_api_key=getattr(config_module, "GEMINI_API_KEY", None),
deepseek_base_url=getattr(config_module, "DEEPSEEK_BASE_URL", "https://api.deepseek.com"),
openai_base_url=getattr(config_module, "OPENAI_BASE_URL", None),
gemini_base_url=getattr(config_module, "GEMINI_BASE_URL", "https://www.chataiapi.com/v1"),
bocha_api_key=getattr(config_module, "BOCHA_API_KEY", None),
default_llm_provider=getattr(config_module, "DEFAULT_LLM_PROVIDER", "deepseek"),
deepseek_model=getattr(config_module, "DEEPSEEK_MODEL", "deepseek-chat"),
... ... @@ -100,6 +106,9 @@ class Config:
deepseek_api_key=config_dict.get("DEEPSEEK_API_KEY"),
openai_api_key=config_dict.get("OPENAI_API_KEY"),
gemini_api_key=config_dict.get("GEMINI_API_KEY"),
deepseek_base_url=config_dict.get("DEEPSEEK_BASE_URL", "https://api.deepseek.com"),
openai_base_url=config_dict.get("OPENAI_BASE_URL"),
gemini_base_url=config_dict.get("GEMINI_BASE_URL", "https://www.chataiapi.com/v1"),
bocha_api_key=config_dict.get("BOCHA_API_KEY"),
default_llm_provider=config_dict.get("DEFAULT_LLM_PROVIDER", "deepseek"),
deepseek_model=config_dict.get("DEEPSEEK_MODEL", "deepseek-chat"),
... ...
... ... @@ -60,7 +60,8 @@ class DeepSearchAgent:
if self.config.default_llm_provider == "deepseek":
return DeepSeekLLM(
api_key=self.config.deepseek_api_key,
model_name=self.config.deepseek_model
model_name=self.config.deepseek_model,
base_url=self.config.deepseek_base_url
)
elif self.config.default_llm_provider == "openai":
return OpenAILLM(
... ...
... ... @@ -9,6 +9,8 @@ from typing import Optional, Dict, Any
from openai import OpenAI
from .base import BaseLLM
DEFAULT_DEEPSEEK_BASE_URL = "https://api.deepseek.com"
# 添加utils目录到Python路径并导入重试模块
try:
current_dir = os.path.dirname(os.path.abspath(__file__))
... ... @@ -29,13 +31,14 @@ except ImportError:
class DeepSeekLLM(BaseLLM):
"""DeepSeek LLM实现类"""
def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None):
def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None, base_url: Optional[str] = None):
"""
初始化DeepSeek客户端
Args:
api_key: DeepSeek API密钥,如果不提供则从环境变量读取
model_name: 模型名称,默认使用deepseek-chat
base_url: DeepSeek API基础地址
"""
if api_key is None:
api_key = os.getenv("DEEPSEEK_API_KEY")
... ... @@ -44,10 +47,12 @@ class DeepSeekLLM(BaseLLM):
super().__init__(api_key, model_name)
self.base_url = base_url or os.getenv("DEEPSEEK_BASE_URL") or DEFAULT_DEEPSEEK_BASE_URL
# 初始化OpenAI客户端,使用DeepSeek的endpoint
self.client = OpenAI(
api_key=self.api_key,
base_url="https://api.deepseek.com"
base_url=self.base_url
)
self.default_model = model_name or self.get_default_model()
... ... @@ -109,5 +114,5 @@ class DeepSeekLLM(BaseLLM):
return {
"provider": "DeepSeek",
"model": self.default_model,
"api_base": "https://api.deepseek.com"
"api_base": self.base_url
}
... ...
... ... @@ -15,6 +15,8 @@ class Config:
deepseek_api_key: Optional[str] = None
openai_api_key: Optional[str] = None
tavily_api_key: Optional[str] = None
deepseek_base_url: str = "https://api.deepseek.com"
openai_base_url: Optional[str] = None
# 模型配置
default_llm_provider: str = "deepseek" # deepseek 或 openai
... ... @@ -66,6 +68,8 @@ class Config:
deepseek_api_key=getattr(config_module, "DEEPSEEK_API_KEY", None),
openai_api_key=getattr(config_module, "OPENAI_API_KEY", None),
tavily_api_key=getattr(config_module, "TAVILY_API_KEY", None),
deepseek_base_url=getattr(config_module, "DEEPSEEK_BASE_URL", "https://api.deepseek.com"),
openai_base_url=getattr(config_module, "OPENAI_BASE_URL", None),
default_llm_provider=getattr(config_module, "DEFAULT_LLM_PROVIDER", "deepseek"),
deepseek_model=getattr(config_module, "DEEPSEEK_MODEL", "deepseek-chat"),
openai_model=getattr(config_module, "OPENAI_MODEL", "gpt-4o-mini"),
... ... @@ -93,6 +97,8 @@ class Config:
deepseek_api_key=config_dict.get("DEEPSEEK_API_KEY"),
openai_api_key=config_dict.get("OPENAI_API_KEY"),
tavily_api_key=config_dict.get("TAVILY_API_KEY"),
deepseek_base_url=config_dict.get("DEEPSEEK_BASE_URL", "https://api.deepseek.com"),
openai_base_url=config_dict.get("OPENAI_BASE_URL"),
default_llm_provider=config_dict.get("DEFAULT_LLM_PROVIDER", "deepseek"),
deepseek_model=config_dict.get("DEEPSEEK_MODEL", "deepseek-chat"),
openai_model=config_dict.get("OPENAI_MODEL", "gpt-4o-mini"),
... ...
<div align="center">
<img src="static/image/logo_compressed.png" alt="Weibo Public Opinion Analysis System Logo" width="800">
<img src="static/image/logo_compressed.png" alt="Weibo Public Opinion Analysis System Logo" width="700">
<a href="https://trendshift.io/repositories/12461" target="_blank"><img src="https://trendshift.io/api/badge/repositories/12461" alt="666ghj%2FWeibo_PublicOpinion_AnalysisSystem | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
<a href="https://leaflow.net/" target="_blank"><img src="static/image/Leaflow_logo.png" alt="666ghj%2FWeibo_PublicOpinion_AnalysisSystem | Leaflow" style="width: 150px;" width="150"/></a>
[![GitHub Stars](https://img.shields.io/github/stars/666ghj/Weibo_PublicOpinion_AnalysisSystem?style=flat-square)](https://github.com/666ghj/Weibo_PublicOpinion_AnalysisSystem/stargazers)
[![GitHub Watchers](https://img.shields.io/github/watchers/666ghj/Weibo_PublicOpinion_AnalysisSystem?style=flat-square)](https://github.com/666ghj/Weibo_PublicOpinion_AnalysisSystem/watchers)
[![GitHub Forks](https://img.shields.io/github/forks/666ghj/Weibo_PublicOpinion_AnalysisSystem?style=flat-square)](https://github.com/666ghj/Weibo_PublicOpinion_AnalysisSystem/network)
[![GitHub Issues](https://img.shields.io/github/issues/666ghj/Weibo_PublicOpinion_AnalysisSystem?style=flat-square)](https://github.com/666ghj/Weibo_PublicOpinion_AnalysisSystem/issues)
[![GitHub Pull Requests](https://img.shields.io/github/issues-pr/666ghj/Weibo_PublicOpinion_AnalysisSystem?style=flat-square)](https://github.com/666ghj/Weibo_PublicOpinion_AnalysisSystem/pulls)
[![GitHub License](https://img.shields.io/github/license/666ghj/Weibo_PublicOpinion_AnalysisSystem?style=flat-square)](https://github.com/666ghj/Weibo_PublicOpinion_AnalysisSystem/blob/main/LICENSE)
[![Version](https://img.shields.io/badge/version-v1.0.0-green.svg?style=flat-square)](https://github.com/666ghj/Weibo_PublicOpinion_AnalysisSystem)
[![Docker](https://img.shields.io/badge/Docker-Build-2496ED?style=flat-square&logo=docker&logoColor=white)](https://hub.docker.com/)
[English](./README-EN.md) | [中文文档](./README.md)
... ... @@ -221,7 +230,7 @@ playwright install chromium
#### 4.1 Configure API Keys
Edit the `config.py` file and fill in your API keys (you can also choose your own models and search proxies):
Edit the `config.py` file and fill in your API keys (you can also choose your own models and search proxies; please see the config file for details):
```python
# MySQL Database Configuration
... ... @@ -283,7 +292,9 @@ conda activate your_conda_name
python app.py
```
> Note: Data crawling requires separate operation, see section 5.3 for guidance
> Note 1: After a run is terminated, the Streamlit app might not shut down correctly and may still be occupying the port. If this occurs, find the process that is holding the port and kill it.
> Note 2: Data scraping needs to be performed as a separate operation. Please refer to the instructions in section 5.3.
Visit http://localhost:5000 to use the complete system
... ...
... ... @@ -230,7 +230,7 @@ playwright install chromium
#### 4.1 配置API密钥
编辑 `config.py` 文件,填入您的API密钥(您也可以选择自己的模型、搜索代理):
编辑 `config.py` 文件,填入您的API密钥(您也可以选择自己的模型、搜索代理,详情见config文件内):
```python
# MySQL数据库配置
... ... @@ -292,7 +292,9 @@ conda activate your_conda_name
python app.py
```
> 注:数据爬取需要单独操作,见5.3指引
> 注1:一次运行终止后,streamlit app可能结束异常仍然占用端口,此时搜索占用端口的进程kill掉即可
> 注2:数据爬取需要单独操作,见5.3指引
访问 http://localhost:5000 即可使用完整系统
... ...
... ... @@ -192,6 +192,7 @@ class ReportAgent:
return GeminiLLM(
api_key=self.config.gemini_api_key,
model_name=self.config.gemini_model,
base_url=self.config.gemini_base_url,
config=self.config # 传入配置对象以支持动态超时设置
)
else:
... ...
... ... @@ -9,6 +9,8 @@ from typing import Optional, Dict, Any
from openai import OpenAI
from .base import BaseLLM
DEFAULT_GEMINI_BASE_URL = "https://www.chataiapi.com/v1"
# 导入根目录的config
try:
current_dir = os.path.dirname(os.path.abspath(__file__))
... ... @@ -50,13 +52,14 @@ except ImportError:
class GeminiLLM(BaseLLM):
"""Report Engine Gemini LLM实现类"""
def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None, config=None):
def __init__(self, api_key: Optional[str] = None, model_name: Optional[str] = None, base_url: Optional[str] = None, config=None):
"""
初始化Gemini客户端
Args:
api_key: Gemini API密钥,如果不提供则从config或环境变量读取
model_name: 模型名称,默认使用gemini-2.5-pro
base_url: Gemini API基础地址
config: 配置对象,用于获取超时设置
"""
if api_key is None:
... ... @@ -78,6 +81,13 @@ class GeminiLLM(BaseLLM):
# 从配置获取超时时间,默认15分钟(适应7分钟平均生成时间)
timeout = config.api_timeout if config and hasattr(config, 'api_timeout') else 900.0
self.base_url = (
base_url
or (getattr(self.config, 'gemini_base_url', None) if self.config else None)
or os.getenv('GEMINI_BASE_URL')
or DEFAULT_GEMINI_BASE_URL
)
# 创建针对此实例的重试配置
self.retry_config = create_report_retry_config(config)
... ... @@ -85,7 +95,7 @@ class GeminiLLM(BaseLLM):
# 专门为报告生成设置长超时(15分钟),适应7分钟平均生成时间
self.client = OpenAI(
api_key=self.api_key,
base_url="https://www.chataiapi.com/v1",
base_url=self.base_url,
timeout=timeout
)
... ... @@ -188,6 +198,6 @@ class GeminiLLM(BaseLLM):
return {
"provider": "Gemini",
"model": self.default_model,
"api_base": "https://www.chataiapi.com/v1",
"api_base": self.base_url,
"purpose": "Report Generation"
}
... ...
... ... @@ -13,6 +13,7 @@ class Config:
"""Report Engine配置类"""
# API密钥
gemini_api_key: Optional[str] = None
gemini_base_url: str = "https://www.chataiapi.com/v1"
# 模型配置
default_llm_provider: str = "gemini"
... ... @@ -56,6 +57,7 @@ class Config:
return cls(
gemini_api_key=getattr(config_module, "GEMINI_API_KEY", None),
gemini_base_url=getattr(config_module, "GEMINI_BASE_URL", "https://www.chataiapi.com/v1"),
default_llm_provider=getattr(config_module, "DEFAULT_LLM_PROVIDER", "gemini"),
gemini_model=getattr(config_module, "GEMINI_MODEL", "gemini-2.5-pro"),
max_content_length=getattr(config_module, "MAX_CONTENT_LENGTH", 200000),
... ... @@ -82,6 +84,7 @@ class Config:
return cls(
gemini_api_key=config_dict.get("GEMINI_API_KEY"),
gemini_base_url=config_dict.get("GEMINI_BASE_URL", "https://www.chataiapi.com/v1"),
default_llm_provider=config_dict.get("DEFAULT_LLM_PROVIDER", "gemini"),
gemini_model=config_dict.get("GEMINI_MODEL", "gemini-2.5-pro"),
max_content_length=int(config_dict.get("MAX_CONTENT_LENGTH", "200000")),
... ...
... ... @@ -27,7 +27,18 @@ except locale.Error:
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from InsightEngine import DeepSearchAgent, Config
from config import DEEPSEEK_API_KEY, KIMI_API_KEY, DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, DB_PORT, DB_CHARSET
from config import (
DEEPSEEK_API_KEY,
DEEPSEEK_BASE_URL,
KIMI_API_KEY,
KIMI_BASE_URL,
DB_HOST,
DB_USER,
DB_PASSWORD,
DB_NAME,
DB_PORT,
DB_CHARSET,
)
def main():
... ... @@ -111,6 +122,8 @@ def main():
deepseek_api_key=None,
openai_api_key=None,
kimi_api_key=KIMI_API_KEY, # 强制使用配置文件中的Kimi Key
deepseek_base_url=DEEPSEEK_BASE_URL,
kimi_base_url=KIMI_BASE_URL,
db_host=db_host,
db_user=db_user,
db_password=db_password,
... ...
... ... @@ -27,7 +27,13 @@ except locale.Error:
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from MediaEngine import DeepSearchAgent, Config
from config import DEEPSEEK_API_KEY, BOCHA_Web_Search_API_KEY, GEMINI_API_KEY
from config import (
DEEPSEEK_API_KEY,
DEEPSEEK_BASE_URL,
BOCHA_Web_Search_API_KEY,
GEMINI_API_KEY,
GEMINI_BASE_URL,
)
def main():
... ... @@ -112,6 +118,8 @@ def main():
openai_api_key=None,
gemini_api_key=gemini_key,
bocha_api_key=bocha_key,
deepseek_base_url=DEEPSEEK_BASE_URL,
gemini_base_url=GEMINI_BASE_URL,
default_llm_provider=llm_provider,
deepseek_model="deepseek-chat", # 保留默认值以兼容
openai_model="gpt-4o-mini", # 保留默认值以兼容
... ...
... ... @@ -27,7 +27,7 @@ except locale.Error:
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from QueryEngine import DeepSearchAgent, Config
from config import DEEPSEEK_API_KEY, TAVILY_API_KEY
from config import DEEPSEEK_API_KEY, DEEPSEEK_BASE_URL, TAVILY_API_KEY
def main():
... ... @@ -110,6 +110,7 @@ def main():
deepseek_api_key=deepseek_key,
openai_api_key=None,
tavily_api_key=tavily_key,
deepseek_base_url=DEEPSEEK_BASE_URL,
default_llm_provider=llm_provider,
deepseek_model=model_name,
openai_model="gpt-4o-mini", # 保留默认值以兼容
... ...
... ... @@ -4,35 +4,52 @@ Intelligence Public Opinion Analysis Platform Configuration File
Stores database connection information and API keys
"""
# ============================== 数据库配置 ==============================
# MySQL Database Configuration
DB_HOST = "your_database_host" # e.g., "localhost" or "127.0.0.1"
DB_PORT = 3306
DB_PORT = 3306 # e.g., 3306
DB_USER = "your_database_user"
DB_PASSWORD = "your_database_password"
DB_NAME = "your_database_name"
DB_CHARSET = "utf8mb4"
# 我们也提供云数据库资源便捷配置,日均10w+数据,目前推广阶段可免费申请,联系我们:670939375@qq.com
# 我们也提供云数据库资源便捷配置,日均10w+数据,学术研究可免费申请,联系我们:670939375@qq.com
# DeepSeek API Key
# 申请地址https://www.deepseek.com/
DEEPSEEK_API_KEY = "your_deepseek_api_key"
# Tavily Search API Key
# 申请地址https://www.tavily.com/
TAVILY_API_KEY = "your_tavily_api_key"
# ============================== LLM配置 ==============================
# 重要提醒:推荐第一次先按照默认模型安排配置,成功跑通后再更改自己的模型!
# Kimi API Key
# 申请地址https://www.kimi.com/
KIMI_API_KEY = "your_kimi_api_key"
# DeepSeek API Key (openai调用格式)
# 用于Query Agent
# 申请地址https://www.deepseek.com/
DEEPSEEK_API_KEY = "sk-xxxxxxxxxxxxxxxxx"
DEEPSEEK_BASE_URL = "https://api.deepseek.com"
# Gemini API Key (via OpenAI format proxy)
# Kimi API Key (openai调用格式)
# 用于Insight Agent
# 申请地址https://platform.moonshot.cn/
KIMI_API_KEY = "sk-xxxxxxxxxxxxxxxxx"
KIMI_BASE_URL = "https://api.moonshot.cn/v1"
# Gemini API Key (openai调用格式)
# 用于Media Agent与Report Agent
# 这里我用了一个中转api来接入Gemini,申请地址https://api.chataiapi.com/,你也可以使用其他
GEMINI_API_KEY = "your_gemini_api_key"
GEMINI_API_KEY = "sk-xxxxxxxxxxxxxxxxx"
GEMINI_BASE_URL = "https://www.chataiapi.com/v1"
# Siliconflow API Key (openai调用格式)
# 用于Forum Host与keyword Optimizer
# 申请地址https://siliconflow.cn/
GUIJI_QWEN3_API_KEY = "sk-xxxxxxxxxxxxxxxxx"
GUIJI_QWEN3_BASE_URL = "https://api.siliconflow.cn/v1"
# 调试阶段出于成本考虑,没有使用ChatGPT与Claude,您也可以接入自己的模型,只要符合openai调用格式即可
# ============================== Web工具配置 ==============================
# Tavily Search API Key
# 申请地址https://www.tavily.com/
TAVILY_API_KEY = "tvly-xxxxxxxxxxxxxxxxx"
# Bocha Search API Key
# 申请地址https://open.bochaai.com/
BOCHA_Web_Search_API_KEY = "your_bocha_web_search_api_key"
# Guiji Flow API Key
# 申请地址https://siliconflow.cn/
GUIJI_QWEN3_API_KEY = "your_guiji_qwen3_api_key"
\ No newline at end of file
BOCHA_Web_Search_API_KEY = "sk-xxxxxxxxxxxxxxxxx"
... ...