File size: 8,801 Bytes
d0dd276
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import json
import os
import inspect
import pathlib
from app.config import settings
from app.utils.logging import log

# 定义不应该被保存或加载的配置项
EXCLUDED_SETTINGS = [
    "STORAGE_DIR", 
    "ENABLE_STORAGE", 
    "BASE_DIR", 
    "PASSWORD", 
    "WEB_PASSWORD", 
    "WHITELIST_MODELS", 
    "BLOCKED_MODELS", 
    "DEFAULT_BLOCKED_MODELS", 
    "PUBLIC_MODE", 
    "DASHBOARD_URL",
    "version"
]

def save_settings():
    """
    将settings中所有的从os.environ.get获取的配置保存到JSON文件中,
    但排除特定的配置项
    """
    if settings.ENABLE_STORAGE:
        # 确保存储目录存在
        storage_dir = pathlib.Path(settings.STORAGE_DIR)
        storage_dir.mkdir(parents=True, exist_ok=True)
        
        # 设置JSON文件路径
        settings_file = storage_dir / "settings.json"
        
        # 获取settings模块中的所有变量
        settings_dict = {}
        for name, value in inspect.getmembers(settings):
            # 跳过内置和私有变量,以及函数/模块/类,以及排除列表中的配置项
            if (not name.startswith('_') and 
                not inspect.isfunction(value) and 
                not inspect.ismodule(value) and 
                not inspect.isclass(value) and
                name not in EXCLUDED_SETTINGS):
                
                # 尝试将可序列化的值添加到字典中
                try:
                    json.dumps({name: value})  # 测试是否可序列化
                    settings_dict[name] = value
                except (TypeError, OverflowError):
                    # 如果不可序列化,则跳过
                    continue
        log('info', f"保存设置到JSON文件: {settings_file}")
        
        # 保存到JSON文件
        with open(settings_file, 'w', encoding='utf-8') as f:
            json.dump(settings_dict, f, ensure_ascii=False, indent=4)
        
        return settings_file

def load_settings():
    """
    从JSON文件中加载设置并更新settings模块,
    排除特定的配置项,并合并GEMINI_API_KEYS
    """
    if settings.ENABLE_STORAGE:
        # 设置JSON文件路径
        storage_dir = pathlib.Path(settings.STORAGE_DIR)
        settings_file = storage_dir / "settings.json"
        
        # 如果文件不存在,则返回
        if not settings_file.exists():
            return False
        
        # 从JSON文件中加载设置
        try:
            with open(settings_file, 'r', encoding='utf-8') as f:
                loaded_settings = json.load(f)
            
            # 保存当前环境变量中的GEMINI_API_KEYS
            current_api_keys = []
            if hasattr(settings, 'GEMINI_API_KEYS') and settings.GEMINI_API_KEYS:
                current_api_keys = settings.GEMINI_API_KEYS.split(',')
                current_api_keys = [key.strip() for key in current_api_keys if key.strip()]
            
            # 保存当前环境变量中的GOOGLE_CREDENTIALS_JSON和VERTEX_EXPRESS_API_KEY
            current_google_credentials_json = settings.GOOGLE_CREDENTIALS_JSON if hasattr(settings, 'GOOGLE_CREDENTIALS_JSON') else ""
            current_vertex_express_api_key = settings.VERTEX_EXPRESS_API_KEY if hasattr(settings, 'VERTEX_EXPRESS_API_KEY') else ""
            
            # 更新settings模块中的变量,但排除特定配置项
            for name, value in loaded_settings.items():
                if hasattr(settings, name) and name not in EXCLUDED_SETTINGS:
                    # 特殊处理GEMINI_API_KEYS,进行合并去重
                    if name == "GEMINI_API_KEYS":
                        loaded_api_keys = value.split(',') if value else []
                        loaded_api_keys = [key.strip() for key in loaded_api_keys if key.strip()]
                        all_keys = list(set(current_api_keys + loaded_api_keys))
                        setattr(settings, name, ','.join(all_keys))
                    # 特殊处理GOOGLE_CREDENTIALS_JSON,如果当前环境变量中有值,则优先使用环境变量中的值
                    elif name == "GOOGLE_CREDENTIALS_JSON":
                        # 检查当前值是否为空(None、空字符串、只有空白字符,或者是"''"这样的空引号)
                        is_empty = (not current_google_credentials_json or 
                                   not current_google_credentials_json.strip() or 
                                   current_google_credentials_json.strip() in ['""', "''"])
                        log('debug', f"is_empty检查结果: {is_empty}")
                        if is_empty:
                            log('debug', f"当前GOOGLE_CREDENTIALS_JSON为空,将使用持久化的值")
                            setattr(settings, name, value)
                            # 更新环境变量,确保其他模块能够访问到
                            if value:  # 只有当value不为空时才设置环境变量
                                os.environ["GOOGLE_CREDENTIALS_JSON"] = value
                                log('info', f"从持久化存储加载了GOOGLE_CREDENTIALS_JSON配置")
                            else:
                                log('warning', f"持久化的GOOGLE_CREDENTIALS_JSON值为空")
                        else:
                            log('debug', f"当前GOOGLE_CREDENTIALS_JSON不为空,保持现有值")
                    # 特殊处理VERTEX_EXPRESS_API_KEY,如果当前环境变量中有值,则优先使用环境变量中的值
                    elif name == "VERTEX_EXPRESS_API_KEY":
                        # 检查当前值是否为空(None、空字符串或只有空白字符)
                        if not current_vertex_express_api_key or not current_vertex_express_api_key.strip():
                            setattr(settings, name, value)
                            # 更新环境变量,确保其他模块能够访问到
                            if value:  # 只有当value不为空时才设置环境变量
                                os.environ["VERTEX_EXPRESS_API_KEY"] = value
                                log('info', f"从持久化存储加载了VERTEX_EXPRESS_API_KEY配置")
                    else:
                        setattr(settings, name, value)
            
            # 在加载完设置后,检查是否需要刷新模型配置
            try:
                # 如果加载了Google Credentials JSON或Vertex Express API Key,需要刷新模型配置
                if (hasattr(settings, 'GOOGLE_CREDENTIALS_JSON') and settings.GOOGLE_CREDENTIALS_JSON) or \
                   (hasattr(settings, 'VERTEX_EXPRESS_API_KEY') and settings.VERTEX_EXPRESS_API_KEY):
                    log('info', "检测到Google Credentials JSON或Vertex Express API Key,准备更新配置")
                    
                    # 更新配置
                    import app.vertex.config as app_config
                    
                    # 重新加载vertex配置
                    app_config.reload_config()
                    
                    # 更新app_config中的GOOGLE_CREDENTIALS_JSON
                    if hasattr(settings, 'GOOGLE_CREDENTIALS_JSON') and settings.GOOGLE_CREDENTIALS_JSON:
                        app_config.GOOGLE_CREDENTIALS_JSON = settings.GOOGLE_CREDENTIALS_JSON
                        # 同时更新环境变量,确保其他模块能够访问到
                        os.environ["GOOGLE_CREDENTIALS_JSON"] = settings.GOOGLE_CREDENTIALS_JSON
                        log('info', "已更新app_config和环境变量中的GOOGLE_CREDENTIALS_JSON")
                    
                    # 更新app_config中的VERTEX_EXPRESS_API_KEY_VAL
                    if hasattr(settings, 'VERTEX_EXPRESS_API_KEY') and settings.VERTEX_EXPRESS_API_KEY:
                        app_config.VERTEX_EXPRESS_API_KEY_VAL = [key.strip() for key in settings.VERTEX_EXPRESS_API_KEY.split(',') if key.strip()]
                        # 同时更新环境变量
                        os.environ["VERTEX_EXPRESS_API_KEY"] = settings.VERTEX_EXPRESS_API_KEY
                        log('info', f"已更新app_config和环境变量中的VERTEX_EXPRESS_API_KEY_VAL,共{len(app_config.VERTEX_EXPRESS_API_KEY_VAL)}个有效密钥")
                    
                    log('info', "配置更新完成,Vertex AI将在下次请求时重新初始化")
                    
            except Exception as e:
                log('error', f"更新配置时出错: {str(e)}")
            
            log('info', f"加载设置成功")
            return True
        except Exception as e:
            log('error', f"加载设置时出错: {e}")
            return False