File size: 13,890 Bytes
342e4c4
 
 
c74debe
342e4c4
a0357aa
342e4c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
896a9c8
342e4c4
 
 
 
 
 
 
 
 
a0357aa
c74debe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a0357aa
 
 
 
 
 
 
 
342e4c4
 
 
495d32d
 
 
 
 
 
342e4c4
 
 
 
a0357aa
342e4c4
 
 
 
 
a0357aa
342e4c4
 
 
 
 
a0357aa
342e4c4
 
 
 
 
a0357aa
342e4c4
 
 
 
 
a0357aa
342e4c4
 
 
 
 
a0357aa
342e4c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a0357aa
 
 
 
 
 
 
 
 
 
 
342e4c4
 
 
a0357aa
342e4c4
 
 
 
 
 
 
a0357aa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cde5342
 
 
 
 
 
 
a0357aa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342e4c4
a0357aa
 
 
2944529
 
 
 
 
 
 
 
 
 
 
342e4c4
a0357aa
 
 
 
 
342e4c4
 
 
 
 
a0357aa
342e4c4
 
 
 
a0357aa
342e4c4
 
 
 
a0357aa
342e4c4
 
 
 
a0357aa
342e4c4
 
 
 
a0357aa
342e4c4
 
 
 
a0357aa
342e4c4
 
 
 
 
 
 
495d32d
 
 
 
 
 
 
 
 
 
 
 
a0357aa
495d32d
 
 
342e4c4
 
 
 
 
 
 
495d32d
 
 
 
342e4c4
 
 
 
 
 
495d32d
342e4c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
495d32d
 
342e4c4
 
 
 
 
a0357aa
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
import sys, os
import tempfile
import streamlit as st
import copy

from config import MODEL_CONFIGS, CUSTOM_MODEL_KEY
from utils.save_secrets import *
from prompt_engineer.sec1_call_llm import DataLoadingAgent
from prompt_engineer.sec2_call_llm import DataPreprocessAgent
from prompt_engineer.sec3_call_llm import VisualizationAgent
from prompt_engineer.sec4_call_llm import ModelingCodingAgent
from prompt_engineer.sec5_call_llm import ReportAgent
from prompt_engineer.planner import PlannerAgent

import warnings
warnings.filterwarnings("ignore")
warnings.filterwarnings("ignore", message="missing ScriptRunContext")

import numpy as np
np.set_printoptions(edgeitems=250, threshold=501)

sys.path.append(os.path.dirname(__file__))


st.set_page_config(
    page_title="Autostat",
    page_icon="🤖",
    layout="wide"
)


def init_session_state():

    if 'selected_model' not in st.session_state:
        st.session_state.selected_model = "DeepSeek"
    
    # if 'model_configs_runtime' not in st.session_state:
    #     # 运行时模型配置,包含预设和自定义模型
    #     st.session_state.model_configs_runtime = MODEL_CONFIGS.copy()
    #     # 加载用户配置(包括 API 密钥和自定义模型)
    #     user_configs = load_local_model_configs()
    #     for model_name, config in user_configs.items():
    #         if model_name in MODEL_CONFIGS:
    #             # 预设模型:只更新 API 密钥
    #             st.session_state.model_configs_runtime[model_name]["api_key"] = config.get("api_key", "")
    #         else:
    #             # 自定义模型:添加完整配置
    #             st.session_state.model_configs_runtime[model_name] = {
    #                 "api_base": config.get("api_base", ""),
    #                 "model_name": config.get("model_name", ""),
    #                 "api_key": config.get("api_key", ""),
    #                 "api_type": "openai",
    #                 "is_preset": False,
    #             }

    if "model_configs_runtime" not in st.session_state:
        # 使用深拷贝避免修改全局 MODEL_CONFIGS
        st.session_state.model_configs_runtime = copy.deepcopy(MODEL_CONFIGS)
    
    # 从 model_configs_runtime 提取 api_keys(用于传递给 Agent)
    if 'api_keys' not in st.session_state:
        st.session_state.api_keys = {
            name: config.get("api_key", "")
            for name, config in st.session_state.model_configs_runtime.items()
        }
    
    if 'auto_mode' not in st.session_state:
        st.session_state.auto_mode = False

    if 'preference_select' not in st.session_state:
        st.session_state.preference_select = None
    if 'additional_preference' not in st.session_state:
        st.session_state.additional_preference = None
    if "from_auto" not in st.session_state:
        st.session_state.from_auto = False

    if 'data_loading_agent' not in st.session_state:
        st.session_state.data_loading_agent = DataLoadingAgent(
            api_keys=st.session_state.api_keys,
            model_configs=st.session_state.model_configs_runtime,
            model=st.session_state.selected_model
        )
    if 'data_preprocess_agent' not in st.session_state:
        st.session_state.data_preprocess_agent = DataPreprocessAgent(
            api_keys=st.session_state.api_keys,
            model_configs=st.session_state.model_configs_runtime,
            model=st.session_state.selected_model
        )
    if 'visualization_agent' not in st.session_state:
        st.session_state.visualization_agent = VisualizationAgent(
            api_keys=st.session_state.api_keys,
            model_configs=st.session_state.model_configs_runtime,
            model=st.session_state.selected_model
        )
    if 'modeling_coding_agent' not in st.session_state:
        st.session_state.modeling_coding_agent = ModelingCodingAgent(
            api_keys=st.session_state.api_keys,
            model_configs=st.session_state.model_configs_runtime,
            model=st.session_state.selected_model
        )
    if 'report_agent' not in st.session_state:
        st.session_state.report_agent = ReportAgent(
            api_keys=st.session_state.api_keys,
            model_configs=st.session_state.model_configs_runtime,
            model=st.session_state.selected_model
        )
    if 'planner_agent' not in st.session_state:
        st.session_state.planner_agent = PlannerAgent(
            api_keys=st.session_state.api_keys,
            model_configs=st.session_state.model_configs_runtime,
            model=st.session_state.selected_model
        )


def on_model_selector_change():
    """
    Callback when the model selector in the sidebar changes.
    """
    st.session_state.selected_model = st.session_state.model_selector
    

def run_app():
    """
    Main entry point to render the Streamlit app.
    """
    init_session_state()
    with st.sidebar:
        st.subheader("选择大模型")
        
        # 获取所有可用的模型(预设模型 + OpenAI API 兼容模型)
        models = list(MODEL_CONFIGS.keys()) + [CUSTOM_MODEL_KEY]
        
        # 确保选择的索引有效
        try:
            current_index = models.index(st.session_state.selected_model)
        except ValueError:
            current_index = 0
            st.session_state.selected_model = models[0]
        
        st.selectbox(
            "选择要使用的大模型",
            models,
            index=current_index,
            key="model_selector",
            on_change=on_model_selector_change,
        )

        st.subheader("API 密钥设置")
        selected = st.session_state.selected_model

        # 判断是否为 OpenAI API 兼容模型
        is_custom_model = (selected == CUSTOM_MODEL_KEY)
        
        if is_custom_model:
            # 显示 OpenAI API 兼容模型的配置界面
            existing_config = st.session_state.model_configs_runtime.get(CUSTOM_MODEL_KEY, {})
            
            base_url_input = st.text_input(
                "Base URL",
                value=existing_config.get("api_base", ""),
                key="base_url_input",
                placeholder="例如: https://api.siliconflow.cn/v1"
            )
            
            model_name_input = st.text_input(
                "模型 ID",
                value=existing_config.get("model_name", ""),
                key="model_name_input",
                placeholder="例如: Qwen/Qwen3-8B"
            )
            
            api_key_input = st.text_input(
                "API 密钥",
                value=st.session_state.api_keys.get(CUSTOM_MODEL_KEY, ""),
                type="password",
                key="api_key_input",
            )
            
            if existing_config and existing_config.get("api_base"):
                st.info(f"当前配置: {existing_config.get('model_name', 'N/A')}")
            else:
                st.info("配置 OpenAI API 兼容模型")
            
            if st.button("💾 保存配置", use_container_width=True, key="save_key"):
                if not base_url_input or not model_name_input or not api_key_input:
                    st.error("请填写所有必需字段")
                else:
                    # # 保存到配置文件
                    # update_local_model_config(
                    #     display_name=CUSTOM_MODEL_KEY,
                    #     api_key=api_key_input,
                    #     base_url=base_url_input,
                    #     model_name=model_name_input
                    # )
                    
                    # 更新运行时配置
                    st.session_state.model_configs_runtime[CUSTOM_MODEL_KEY] = {
                        "api_base": base_url_input,
                        "model_name": model_name_input,
                        "api_key": api_key_input,  # 也保存 api_key
                        "api_type": "openai",
                        "is_preset": False,
                    }
                    # 同步到 api_keys
                    st.session_state.api_keys[CUSTOM_MODEL_KEY] = api_key_input
                    st.session_state.selected_model = CUSTOM_MODEL_KEY
                    
                    st.success("已保存配置")
                    st.rerun()
        else:
            # 预设模型或已保存的自定义模型
            api_key_input = st.text_input(
                f"{selected} API 密钥",
                value=st.session_state.api_keys.get(selected, ""),
                type="password",
                key="api_key_input",
            )
            
            # 如果是自定义模型,显示其配置信息
            if selected in st.session_state.model_configs_runtime:
                config = st.session_state.model_configs_runtime[selected]
                if not config.get("is_preset", False):
                    st.caption(f"Base URL: {config.get('api_base', 'N/A')}")
                    st.caption(f"Model: {config.get('model_name', 'N/A')}")

            if st.button("💾 保存密钥", use_container_width=True, key="save_key"):
                # 保存到配置文件
                config = st.session_state.model_configs_runtime.get(selected, {})
                # if config.get("is_preset", False):
                #     # 预设模型,只保存 API key
                #     update_local_model_config(display_name=selected, api_key=api_key_input)
                # else:
                #     # 自定义模型,保存完整配置
                #     update_local_model_config(
                #         display_name=selected,
                #         api_key=api_key_input,
                #         base_url=config.get("api_base"),
                #         model_name=config.get("model_name")
                #     )

                # 同步更新运行时配置和 api_keys
                st.session_state.model_configs_runtime[selected]["api_key"] = api_key_input
                st.session_state.api_keys[selected] = api_key_input
                st.success("已保存")
                st.rerun()

        if st.button("🧹 清空数据", use_container_width=True, key="clear_data"):

            st.session_state.data_loading_agent = DataLoadingAgent(
                api_keys=st.session_state.api_keys,
                model_configs=st.session_state.model_configs_runtime,
                model=st.session_state.selected_model
            )
            st.session_state.data_preprocess_agent = DataPreprocessAgent(
                api_keys=st.session_state.api_keys,
                model_configs=st.session_state.model_configs_runtime,
                model=st.session_state.selected_model
            )
            st.session_state.visualization_agent = VisualizationAgent(
                api_keys=st.session_state.api_keys,
                model_configs=st.session_state.model_configs_runtime,
                model=st.session_state.selected_model
            )
            st.session_state.modeling_coding_agent = ModelingCodingAgent(
                api_keys=st.session_state.api_keys,
                model_configs=st.session_state.model_configs_runtime,
                model=st.session_state.selected_model
            )
            st.session_state.report_agent = ReportAgent(
                api_keys=st.session_state.api_keys,
                model_configs=st.session_state.model_configs_runtime,
                model=st.session_state.selected_model
            )
            st.session_state.planner_agent = PlannerAgent(
                api_keys=st.session_state.api_keys,
                model_configs=st.session_state.model_configs_runtime,
                model=st.session_state.selected_model
            )
            st.session_state.auto_mode = False
            st.rerun()

        if st.session_state.data_loading_agent.load_df() is not None:
            planner = st.session_state.planner_agent

            if st.session_state.auto_mode is False:
                if st.button("🚗 自动模式", use_container_width=True):
                    st.session_state.auto_mode = True
                    planner.self_driving(st.session_state.data_loading_agent.load_df())
                    st.switch_page("workflow/dataloading/dataloading_render.py")
                    st.rerun()
            else:
                if st.button("❌ 结束自动模式", use_container_width=True):
                    st.session_state.auto_mode = False
                    st.session_state.planner_agent = PlannerAgent(
                    api_keys=st.session_state.api_keys,
                    model_configs=st.session_state.model_configs_runtime,
                    model=st.session_state.selected_model
                    )
                    st.rerun()

        st.image(
            "logo/logo_big.png",
            use_container_width=True
        )

    # Define pages
    preference = st.Page(
        "workflow/preference/pref_render.py",
        title="⚙️ 偏好设置",
    )
    data_loading = st.Page(
        "workflow/dataloading/dataloading_render.py",
        title="📥 数据导入",
    )
    preprocessing = st.Page(
        "workflow/preprocessing/preprocessing_render.py",
        title="🛠️ 数据预处理",
    )
    visualization = st.Page(
        "workflow/visualization/viz_render.py",
        title="📊 数据可视化",
    )
    report = st.Page(
        "workflow/report/report_render.py",
        title="📝 报告生成",
    )
    coding_modeling = st.Page(
        "workflow/modeling/modeling_render.py",
        title="🧠 建模分析",
    )
    # Navigation
    pg = st.navigation(
        {
            "功能": [data_loading, preprocessing, visualization, coding_modeling, report],
            "设置": [preference]
        }
    )
    pg.run()
    
if __name__ == "__main__":
    run_app()