cnhkmcp 2.0.4__py3-none-any.whl → 2.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/README.md +38 -0
  2. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/config.json +6 -0
  3. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/ace_lib.py +1510 -0
  4. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/fetch_all_datasets.py +157 -0
  5. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/fetch_all_documentation.py +132 -0
  6. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/fetch_all_operators.py +99 -0
  7. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/get_knowledgeBase_tool/helpful_functions.py +180 -0
  8. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/icon.ico +0 -0
  9. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/icon.png +0 -0
  10. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/knowledge/test.txt +1 -0
  11. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/main.py +576 -0
  12. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/process_knowledge_base.py +280 -0
  13. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/rag_engine.py +356 -0
  14. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/requirements.txt +7 -0
  15. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/run.bat +3 -0
  16. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/vector_db/_manifest.json +326 -0
  17. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/vector_db/_meta.json +1 -0
  18. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/vector_db/be5d957c-b724-46e3-91d1-999e9f5f7d28/index_metadata.pickle +0 -0
  19. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/vector_db/chroma.sqlite3 +0 -0
  20. cnhkmcp/untracked/AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242//321/211/320/266/320/246/321/206/320/274/320/261/321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/231/320/243/321/205/342/225/235/320/220/321/206/320/230/320/241.py +265 -0
  21. cnhkmcp/untracked/APP/Tranformer/Transformer.py +2804 -11
  22. cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates.json +1524 -889
  23. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_error.json +884 -111
  24. cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_success.json +442 -168
  25. cnhkmcp/untracked/APP/Tranformer/template_summary.txt +2775 -1
  26. cnhkmcp/untracked/APP/ace.log +2 -0
  27. cnhkmcp/untracked/APP/give_me_idea/fetch_all_datasets.py +157 -0
  28. cnhkmcp/untracked/APP/give_me_idea/fetch_all_operators.py +99 -0
  29. cnhkmcp/untracked/APP/simulator/simulator_wqb.py +16 -16
  30. cnhkmcp/untracked/APP/static/brain.js +61 -0
  31. cnhkmcp/untracked/APP/static/script.js +140 -0
  32. cnhkmcp/untracked/APP/templates/index.html +25 -4
  33. cnhkmcp/untracked/APP//321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/231/320/243/321/205/342/225/235/320/220/321/206/320/230/320/241.py +67 -6
  34. {cnhkmcp-2.0.4.dist-info → cnhkmcp-2.1.1.dist-info}/METADATA +1 -1
  35. {cnhkmcp-2.0.4.dist-info → cnhkmcp-2.1.1.dist-info}/RECORD +40 -20
  36. cnhkmcp/untracked/APP/hkSimulator/autosim_20251205_145240.log +0 -0
  37. cnhkmcp/untracked/APP/hkSimulator/autosim_20251215_030103.log +0 -0
  38. /cnhkmcp/untracked/{APP/hkSimulator/ace.log → AI/321/206/320/261/320/234/321/211/320/255/320/262/321/206/320/237/320/242/321/204/342/225/227/342/225/242/ace.log"} +0 -0
  39. {cnhkmcp-2.0.4.dist-info → cnhkmcp-2.1.1.dist-info}/WHEEL +0 -0
  40. {cnhkmcp-2.0.4.dist-info → cnhkmcp-2.1.1.dist-info}/entry_points.txt +0 -0
  41. {cnhkmcp-2.0.4.dist-info → cnhkmcp-2.1.1.dist-info}/licenses/LICENSE +0 -0
  42. {cnhkmcp-2.0.4.dist-info → cnhkmcp-2.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,326 @@
1
+ {
2
+ "001_10_Steps_to_Start_on_BRAIN_documentation.json": {
3
+ "mtime": 1767187226.1783848,
4
+ "size": 2483
5
+ },
6
+ "001_Intermediate_Pack_-_Improve_your_Alpha_2_2_documentation.json": {
7
+ "mtime": 1767187225.6750722,
8
+ "size": 9295
9
+ },
10
+ "001_Intermediate_Pack_-_Understand_Results_1_2_documentation.json": {
11
+ "mtime": 1767187225.1160033,
12
+ "size": 9758
13
+ },
14
+ "001_Introduction_to_Alphas_documentation.json": {
15
+ "mtime": 1767187223.7560995,
16
+ "size": 11156
17
+ },
18
+ "001_Introduction_to_BRAIN_Expression_Language_documentation.json": {
19
+ "mtime": 1767187224.277528,
20
+ "size": 4925
21
+ },
22
+ "001_WorldQuant_Challenge_documentation.json": {
23
+ "mtime": 1767187226.6850047,
24
+ "size": 4605
25
+ },
26
+ "001__Read_this_First_-_Starter_Pack_documentation.json": {
27
+ "mtime": 1767187223.2536645,
28
+ "size": 31286
29
+ },
30
+ "002_How_to_choose_the_Simulation_Settings_documentation.json": {
31
+ "mtime": 1767187228.2257776,
32
+ "size": 13775
33
+ },
34
+ "002_Simulate_your_first_Alpha_documentation.json": {
35
+ "mtime": 1767187227.7143147,
36
+ "size": 8701
37
+ },
38
+ "002__Alpha_Examples_for_Beginners_documentation.json": {
39
+ "mtime": 1767187229.1900375,
40
+ "size": 10826
41
+ },
42
+ "002__Alpha_Examples_for_Bronze_Users_documentation.json": {
43
+ "mtime": 1767187229.664476,
44
+ "size": 4795
45
+ },
46
+ "002__Alpha_Examples_for_Silver_Users_documentation.json": {
47
+ "mtime": 1767187230.1425803,
48
+ "size": 3854
49
+ },
50
+ "002__How_BRAIN_works_documentation.json": {
51
+ "mtime": 1767187228.7194252,
52
+ "size": 16929
53
+ },
54
+ "003_Clear_these_tests_before_submitting_an_Alpha_documentation.json": {
55
+ "mtime": 1767187231.1392078,
56
+ "size": 24609
57
+ },
58
+ "003_Parameters_in_the_Simulation_results_documentation.json": {
59
+ "mtime": 1767187231.8167577,
60
+ "size": 16168
61
+ },
62
+ "004_Group_Data_Fields_documentation.json": {
63
+ "mtime": 1767187234.323853,
64
+ "size": 4663
65
+ },
66
+ "004_How_to_use_the_Data_Explorer_documentation.json": {
67
+ "mtime": 1767187233.2908292,
68
+ "size": 6196
69
+ },
70
+ "004_Model77_dataset_documentation.json": {
71
+ "mtime": 1767187234.7999012,
72
+ "size": 3274
73
+ },
74
+ "004_Sentiment1_dataset_documentation.json": {
75
+ "mtime": 1767187235.2783144,
76
+ "size": 2058
77
+ },
78
+ "004_Understanding_Data_in_BRAIN_Key_Concepts_and_Tips_documentation.json": {
79
+ "mtime": 1767187232.782544,
80
+ "size": 9173
81
+ },
82
+ "004_Vector_Data_Fields_documentation.json": {
83
+ "mtime": 1767187233.8419762,
84
+ "size": 6058
85
+ },
86
+ "005_Crowding_Risk-Neutralized_Alphas_documentation.json": {
87
+ "mtime": 1767187239.4696057,
88
+ "size": 3404
89
+ },
90
+ "005_D0_documentation.json": {
91
+ "mtime": 1767187237.8772166,
92
+ "size": 5894
93
+ },
94
+ "005_Double_Neutralization_documentation.json": {
95
+ "mtime": 1767187237.2801647,
96
+ "size": 3308
97
+ },
98
+ "005_Fast_D1_Documentation_documentation.json": {
99
+ "mtime": 1767187244.849411,
100
+ "size": 11325
101
+ },
102
+ "005_Investability_Constrained_Metrics_documentation.json": {
103
+ "mtime": 1767187244.361986,
104
+ "size": 7971
105
+ },
106
+ "005_Must-read_posts_How_to_improve_your_Alphas_documentation.json": {
107
+ "mtime": 1767187236.2457168,
108
+ "size": 2781
109
+ },
110
+ "005_Neutralization_documentation.json": {
111
+ "mtime": 1767187236.7823203,
112
+ "size": 8962
113
+ },
114
+ "005_RAM_Risk-Neutralized_Alphas_documentation.json": {
115
+ "mtime": 1767187240.0576506,
116
+ "size": 4121
117
+ },
118
+ "005_Risk_Neutralization_Default_setting_documentation.json": {
119
+ "mtime": 1767187238.9658227,
120
+ "size": 3796
121
+ },
122
+ "005_Risk_Neutralized_Alphas_documentation.json": {
123
+ "mtime": 1767187238.4253874,
124
+ "size": 11617
125
+ },
126
+ "005_Statistical_Risk-Neutralized_Alphas_documentation.json": {
127
+ "mtime": 1767187240.5924916,
128
+ "size": 5663
129
+ },
130
+ "006_EUR_TOP2500_Universe_documentation.json": {
131
+ "mtime": 1767187247.5703416,
132
+ "size": 2248
133
+ },
134
+ "006_Getting_Started_China_Research_for_Consultants_Gold_documentation.json": {
135
+ "mtime": 1767187248.0169055,
136
+ "size": 8247
137
+ },
138
+ "006_Getting_started_on_Illiquid_Universes_Gold_documentation.json": {
139
+ "mtime": 1767187247.1297894,
140
+ "size": 2224
141
+ },
142
+ "006_Getting_started_with_USA_TOPSP500_universe_Gold_documentation.json": {
143
+ "mtime": 1767187246.6729863,
144
+ "size": 2681
145
+ },
146
+ "006_GLB_TOPDIV3000_Universe_documentation.json": {
147
+ "mtime": 1767187248.4504318,
148
+ "size": 2990
149
+ },
150
+ "006_Global_Alphas_Gold_documentation.json": {
151
+ "mtime": 1767187246.0390387,
152
+ "size": 5531
153
+ },
154
+ "006_India_Alphas_documentation.json": {
155
+ "mtime": 1767187248.8769279,
156
+ "size": 1845
157
+ },
158
+ "007_Consultant_Dos_and_Don_ts_documentation.json": {
159
+ "mtime": 1767187252.9861574,
160
+ "size": 6318
161
+ },
162
+ "007_Consultant_Features_documentation.json": {
163
+ "mtime": 1767187251.6508195,
164
+ "size": 16785
165
+ },
166
+ "007_Consultant_Simulation_Features_documentation.json": {
167
+ "mtime": 1767187251.177272,
168
+ "size": 7226
169
+ },
170
+ "007_Consultant_Submission_Tests_documentation.json": {
171
+ "mtime": 1767187252.1096609,
172
+ "size": 17040
173
+ },
174
+ "007_Finding_Consultant_Alphas_documentation.json": {
175
+ "mtime": 1767187250.6579707,
176
+ "size": 24560
177
+ },
178
+ "007_Power_Pool_Alphas_documentation.json": {
179
+ "mtime": 1767187250.1653683,
180
+ "size": 6398
181
+ },
182
+ "007_Research_Advisory_Program_documentation.json": {
183
+ "mtime": 1767187253.4177225,
184
+ "size": 2637
185
+ },
186
+ "007_Starting_Guide_for_Research_Consultants_documentation.json": {
187
+ "mtime": 1767187249.7283993,
188
+ "size": 3245
189
+ },
190
+ "007_Visualization_Tool_documentation.json": {
191
+ "mtime": 1767187252.5484178,
192
+ "size": 5744
193
+ },
194
+ "007_Your_Advisor_-_Kunqi_Jiang_documentation.json": {
195
+ "mtime": 1767187253.8533716,
196
+ "size": 4746
197
+ },
198
+ "007__Brain_Genius_documentation.json": {
199
+ "mtime": 1767187257.3133671,
200
+ "size": 16460
201
+ },
202
+ "007__Single_Dataset_Alphas_documentation.json": {
203
+ "mtime": 1767187256.8453045,
204
+ "size": 4113
205
+ },
206
+ "008_Advisory_Theme_Calendar_documentation.json": {
207
+ "mtime": 1767187259.502196,
208
+ "size": 584
209
+ },
210
+ "008_Multiplier_Rules_documentation.json": {
211
+ "mtime": 1767187258.6333888,
212
+ "size": 2178
213
+ },
214
+ "008_Overview_of_Themes_documentation.json": {
215
+ "mtime": 1767187258.1852746,
216
+ "size": 1784
217
+ },
218
+ "008_Theme_Calendar_documentation.json": {
219
+ "mtime": 1767187259.0729353,
220
+ "size": 8936
221
+ },
222
+ "009_Combo_Expression_documentation.json": {
223
+ "mtime": 1767187261.4117863,
224
+ "size": 10902
225
+ },
226
+ "009_Global_SuperAlphas_documentation.json": {
227
+ "mtime": 1767187263.181562,
228
+ "size": 3717
229
+ },
230
+ "009_Helpful_Tips_documentation.json": {
231
+ "mtime": 1767187262.3033876,
232
+ "size": 3618
233
+ },
234
+ "009_Selection_Expression_documentation.json": {
235
+ "mtime": 1767187260.918844,
236
+ "size": 47119
237
+ },
238
+ "009_SuperAlpha_Operators_documentation.json": {
239
+ "mtime": 1767187262.748049,
240
+ "size": 18735
241
+ },
242
+ "009_SuperAlpha_Results_documentation.json": {
243
+ "mtime": 1767187261.8593862,
244
+ "size": 3838
245
+ },
246
+ "009_What_is_a_SuperAlpha_documentation.json": {
247
+ "mtime": 1767187260.3861206,
248
+ "size": 13234
249
+ },
250
+ "010_BRAIN_API_documentation.json": {
251
+ "mtime": 1767187264.5490012,
252
+ "size": 36407
253
+ },
254
+ "010_Documentation_for_ACE_API_Library_Gold_documentation.json": {
255
+ "mtime": 1767187264.9810457,
256
+ "size": 1660
257
+ },
258
+ "010__Understanding_simulation_limits_documentation.json": {
259
+ "mtime": 1767187264.0576608,
260
+ "size": 12013
261
+ },
262
+ "arithmetic_operators.json": {
263
+ "mtime": 1767187265.4527013,
264
+ "size": 5302
265
+ },
266
+ "asi_datasets.json": {
267
+ "mtime": 1767187329.8343418,
268
+ "size": 241709
269
+ },
270
+ "chn_datasets.json": {
271
+ "mtime": 1767187329.8464715,
272
+ "size": 112139
273
+ },
274
+ "cross_sectional_operators.json": {
275
+ "mtime": 1767187265.454866,
276
+ "size": 3393
277
+ },
278
+ "eur_datasets.json": {
279
+ "mtime": 1767187329.8725038,
280
+ "size": 268981
281
+ },
282
+ "glb_datasets.json": {
283
+ "mtime": 1767187329.8975177,
284
+ "size": 222049
285
+ },
286
+ "group_operators.json": {
287
+ "mtime": 1767187265.4558804,
288
+ "size": 4058
289
+ },
290
+ "ind_datasets.json": {
291
+ "mtime": 1767187329.930282,
292
+ "size": 259819
293
+ },
294
+ "logical_operators.json": {
295
+ "mtime": 1767187265.4568646,
296
+ "size": 3549
297
+ },
298
+ "reduce_operators.json": {
299
+ "mtime": 1767187265.4588814,
300
+ "size": 8602
301
+ },
302
+ "special_operators.json": {
303
+ "mtime": 1767188164.9683514,
304
+ "size": 893
305
+ },
306
+ "test.txt": {
307
+ "mtime": 1767174050.546388,
308
+ "size": 82
309
+ },
310
+ "time_series_operators.json": {
311
+ "mtime": 1767187265.4623148,
312
+ "size": 12968
313
+ },
314
+ "transformational_operators.json": {
315
+ "mtime": 1767187265.4623148,
316
+ "size": 2080
317
+ },
318
+ "usa_datasets.json": {
319
+ "mtime": 1767187329.9605117,
320
+ "size": 402280
321
+ },
322
+ "vector_operators.json": {
323
+ "mtime": 1767187265.4637623,
324
+ "size": 997
325
+ }
326
+ }
@@ -0,0 +1 @@
1
+ {"model": "jinaai/jina-embeddings-v2-base-zh", "embed_dim": 768, "chroma_version": "1.4.0"}
@@ -0,0 +1,265 @@
1
+ """
2
+ 首次运行初始化脚本
3
+ - 创建桌面快捷方式指向 main.py,用 Python 运行,图标为 icon.png
4
+ - 检查 knowledge 文件夹文件数量
5
+ - 如果 <= 3,提示用户建立知识库,并自动运行 process_knowledge_base.py
6
+ """
7
+
8
+ import os
9
+ import sys
10
+ import subprocess
11
+ import shutil
12
+ import json
13
+ import platform
14
+ import urllib.parse
15
+ import urllib.request
16
+ from pathlib import Path
17
+
18
+ # 获取脚本所在目录(项目根目录)
19
+ PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
20
+ MAIN_SCRIPT = os.path.join(PROJECT_DIR, "main.py")
21
+ ICON_ICO = os.path.join(PROJECT_DIR, "icon.ico")
22
+ ICON_PNG = os.path.join(PROJECT_DIR, "icon.png")
23
+ KNOWLEDGE_DIR = os.path.join(PROJECT_DIR, "knowledge")
24
+ PROCESS_SCRIPT = os.path.join(PROJECT_DIR, "process_knowledge_base.py")
25
+ CONFIG_PATH = os.path.join(PROJECT_DIR, "config.json")
26
+
27
+
28
+ def load_config():
29
+ if not os.path.exists(CONFIG_PATH):
30
+ return {}
31
+ try:
32
+ with open(CONFIG_PATH, "r", encoding="utf-8") as f:
33
+ return json.load(f) or {}
34
+ except Exception as exc:
35
+ print(f"✗ 读取 config.json 失败:{exc}")
36
+ return {}
37
+
38
+
39
+ def save_config(cfg):
40
+ try:
41
+ with open(CONFIG_PATH, "w", encoding="utf-8") as f:
42
+ json.dump(cfg, f, ensure_ascii=False, indent=4)
43
+ print(f"✓ 配置已写入:{CONFIG_PATH}")
44
+ except Exception as exc:
45
+ print(f"✗ 写入 config.json 失败:{exc}")
46
+
47
+
48
+ def check_network_reachable(url="https://www.google.com/generate_204", timeout_ms=2000):
49
+ """Check connectivity via ping + lightweight HTTPS GET. Returns True if either succeeds."""
50
+ parsed = urllib.parse.urlparse(url)
51
+ host = parsed.hostname or "google.com"
52
+ is_windows = platform.system().lower().startswith("win")
53
+ if is_windows:
54
+ cmd = ["ping", "-n", "1", "-w", str(timeout_ms), host]
55
+ else:
56
+ cmd = ["ping", "-c", "1", "-W", str(int(timeout_ms / 1000)), host]
57
+
58
+ try:
59
+ result = subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
60
+ if result.returncode == 0:
61
+ return True
62
+ except Exception as exc:
63
+ print(f"✗ 无法执行 ping:{exc}")
64
+
65
+ # Fallback: HTTPS request (respects proxy envs)
66
+ try:
67
+ with urllib.request.urlopen(url, timeout=timeout_ms / 1000.0) as resp:
68
+ return 200 <= getattr(resp, "status", 200) < 400
69
+ except Exception as exc:
70
+ print(f"✗ HTTPS 连通性检测失败:{exc}")
71
+ return False
72
+
73
+
74
+ def prompt_config_if_needed():
75
+ cfg = load_config()
76
+
77
+ defaults = {
78
+ "base_url": cfg.get("base_url") or "https://api.moonshot.cn/v1",
79
+ "model": cfg.get("model") or "kimi-latest",
80
+ }
81
+
82
+ if not cfg.get("system_prompt"):
83
+ cfg["system_prompt"] = (
84
+ "You are a WorldQuant BRAIN platform expert and Consultant. "
85
+ "Your goal is to assist users with Alpha development, BRAIN API usage, and maximizing consultant income."
86
+ )
87
+
88
+ def ask(field, label, default_value=None, allow_empty=False):
89
+ current = str(cfg.get(field, "")).strip()
90
+ prompt = f"请输入 {label}" + (f" [默认: {current or default_value}]" if (current or default_value) else "") + ": "
91
+ value = input(prompt).strip()
92
+ if not value:
93
+ value = current if current else (default_value if default_value is not None else "")
94
+ if value or allow_empty:
95
+ cfg[field] = value
96
+ return value
97
+
98
+ api_key = ask("api_key", "API Key")
99
+ base_url = ask("base_url", "Base URL", defaults["base_url"], allow_empty=True)
100
+ model = ask("model", "模型名称", defaults["model"], allow_empty=True)
101
+
102
+ if api_key:
103
+ save_config(cfg)
104
+ return True
105
+
106
+ print("✗ 配置文件中的 api_key 为空,请填写后再运行本脚本。")
107
+ return False
108
+
109
+
110
+ def is_api_key_configured():
111
+ """Check config; if api_key missing/empty, prompt user to fill and persist."""
112
+ cfg = load_config()
113
+
114
+ api_key = str(cfg.get("api_key", "")).strip()
115
+ if api_key:
116
+ return True
117
+
118
+ print("✗ 当前 config.json 中 api_key 为空。")
119
+ return prompt_config_if_needed()
120
+
121
+ def create_desktop_shortcut():
122
+ """创建桌面快捷方式"""
123
+ try:
124
+ import win32com.client
125
+
126
+ desktop = os.path.expanduser("~\\Desktop")
127
+ shortcut_path = os.path.join(desktop, "BRAIN顾问助手.lnk")
128
+
129
+ # 获取 Python 可执行文件路径
130
+ python_exe = sys.executable
131
+
132
+ # 创建 shortcut
133
+ shell = win32com.client.Dispatch("WScript.Shell")
134
+ shortcut = shell.CreateShortcut(shortcut_path)
135
+ shortcut.TargetPath = python_exe
136
+ shortcut.Arguments = f'"{MAIN_SCRIPT}"'
137
+ shortcut.WorkingDirectory = PROJECT_DIR
138
+
139
+ # 设置图标:优先使用 .ico(Windows 标准格式),再试 .png
140
+ icon_found = False
141
+ if os.path.exists(ICON_ICO):
142
+ # .ico 文件:使用 "路径,0" 格式
143
+ shortcut.IconLocation = f"{ICON_ICO},0"
144
+ icon_found = True
145
+ print(f" 使用图标:{ICON_ICO}")
146
+ elif os.path.exists(ICON_PNG):
147
+ # .png 文件:也需要 "路径,0" 格式
148
+ shortcut.IconLocation = f"{ICON_PNG},0"
149
+ icon_found = True
150
+ print(f" 使用图标:{ICON_PNG}")
151
+ else:
152
+ # 使用 Python 可执行文件的图标作为默认
153
+ shortcut.IconLocation = f"{python_exe},0"
154
+ print(f" 使用默认图标(Python 图标)")
155
+
156
+ shortcut.Description = "BRAIN 顾问助手 - AI 驱动的交互工具"
157
+ shortcut.save()
158
+
159
+ print(f"✓ 桌面快捷方式已创建:{shortcut_path}")
160
+ return True
161
+ except ImportError:
162
+ print("⚠ pywin32 未安装,尝试使用备选方案创建快捷方式...")
163
+ try:
164
+ # 备选方案:使用 Windows API
165
+ create_shortcut_via_batch(desktop, shortcut_path, python_exe)
166
+ return True
167
+ except Exception as e:
168
+ print(f"✗ 创建快捷方式失败:{e}")
169
+ print(f" 请手动创建快捷方式,目标为:{python_exe} \"{MAIN_SCRIPT}\"")
170
+ return False
171
+ except Exception as e:
172
+ print(f"✗ 创建快捷方式失败:{e}")
173
+ return False
174
+
175
+ def check_knowledge_base():
176
+ """检查 knowledge 文件夹中的文件数量"""
177
+ if not os.path.exists(KNOWLEDGE_DIR):
178
+ os.makedirs(KNOWLEDGE_DIR)
179
+ print(f"✓ 创建 knowledge 文件夹:{KNOWLEDGE_DIR}")
180
+ return 0
181
+
182
+ # 只计算文件,不计算目录
183
+ files = [f for f in os.listdir(KNOWLEDGE_DIR) if os.path.isfile(os.path.join(KNOWLEDGE_DIR, f))]
184
+ file_count = len(files)
185
+ print(f"知识库文件数量:{file_count}")
186
+
187
+ if files:
188
+ print(f" 已有文件:{', '.join(files)}")
189
+
190
+ return file_count
191
+
192
+ def run_process_knowledge_base():
193
+ """运行 process_knowledge_base.py 建立知识库"""
194
+ if not os.path.exists(PROCESS_SCRIPT):
195
+ print(f"✗ 找不到 {PROCESS_SCRIPT}")
196
+ return False
197
+
198
+ print(f"\n正在运行知识库初始化脚本...")
199
+ print(f"命令:{sys.executable} \"{PROCESS_SCRIPT}\"")
200
+
201
+ try:
202
+ subprocess.run([sys.executable, PROCESS_SCRIPT], cwd=PROJECT_DIR)
203
+ print("✓ 知识库初始化完成")
204
+ return True
205
+ except Exception as e:
206
+ print(f"✗ 运行 process_knowledge_base.py 失败:{e}")
207
+ return False
208
+
209
+ def main():
210
+ print("=" * 60)
211
+ print("BRAIN 顾问助手 - 首次运行初始化")
212
+ print("=" * 60)
213
+ print()
214
+
215
+ # 0. 检查 api_key 是否已配置,未配置则直接退出
216
+ if not is_api_key_configured():
217
+ input("按 Enter 键退出...")
218
+ return
219
+
220
+ # 0.1 检查网络(ping + HTTPS),以确认代理已开启
221
+ print("[网络检查] 正在测试到 https://www.google.com 的连通性...")
222
+ if not check_network_reachable("https://www.google.com/generate_204"):
223
+ print("✗ 无法连通 google.com,请确认代理已开启,然后重新运行本脚本。")
224
+ input("按 Enter 键退出...")
225
+ return
226
+ print("✓ 网络检查通过")
227
+
228
+ # 1. 创建桌面快捷方式
229
+ print("[1/2] 创建桌面快捷方式...")
230
+ shortcut_ok = create_desktop_shortcut()
231
+ print()
232
+
233
+ # 2. 检查知识库
234
+ print("[2/2] 检查本地知识库...")
235
+ file_count = check_knowledge_base()
236
+ print()
237
+
238
+ if file_count <= 3:
239
+ print("⚠ 知识库文件较少(<= 3 个)")
240
+ print("建议建立本地知识库以增强 AI 回答效果")
241
+ print()
242
+
243
+ response = input("是否现在运行知识库初始化脚本?(y/n) [默认: y]: ").strip().lower()
244
+ if response != 'n':
245
+ run_process_knowledge_base()
246
+ else:
247
+ print(f"✓ 知识库已初始化(包含 {file_count} 个文件)")
248
+
249
+ print()
250
+ print("=" * 60)
251
+ print("初始化完成!")
252
+ print("=" * 60)
253
+ print()
254
+
255
+ if shortcut_ok:
256
+ print("📌 你现在可以从桌面快捷方式启动应用")
257
+ print(f" 或者运行:{sys.executable} \"{MAIN_SCRIPT}\"")
258
+ else:
259
+ print(f"请运行:{sys.executable} \"{MAIN_SCRIPT}\"")
260
+ print()
261
+
262
+ input("按 Enter 键退出...")
263
+
264
+ if __name__ == "__main__":
265
+ main()