cnhkmcp 1.8.10__py3-none-any.whl → 2.0__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.
- cnhkmcp/untracked/APP/MODULAR_STRUCTURE.md +38 -49
- cnhkmcp/untracked/APP/Tranformer/Transformer.py +131 -1
- cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates.json +951 -2055
- cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_error.json +261 -1
- cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_success.json +168 -1362
- cnhkmcp/untracked/APP/Tranformer/template_summary.txt +57 -1
- cnhkmcp/untracked/APP/ace.log +26 -0
- cnhkmcp/untracked/APP/give_me_idea/BRAIN_Alpha_Template_Expert_SystemPrompt.md +400 -0
- cnhkmcp/untracked/APP/give_me_idea/ace_lib.py +1489 -0
- cnhkmcp/untracked/APP/give_me_idea/alpha_data_specific_template_master.py +247 -0
- cnhkmcp/untracked/APP/give_me_idea/helpful_functions.py +180 -0
- cnhkmcp/untracked/APP/give_me_idea/what_is_Alpha_template.md +11 -0
- cnhkmcp/untracked/APP/static/brain.js +13 -3
- cnhkmcp/untracked/APP/static/inspiration.js +434 -0
- cnhkmcp/untracked/APP/templates/index.html +126 -0
- cnhkmcp/untracked/APP/usage.md +29 -3
- 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 +233 -1
- {cnhkmcp-1.8.10.dist-info → cnhkmcp-2.0.dist-info}/METADATA +1 -1
- {cnhkmcp-1.8.10.dist-info → cnhkmcp-2.0.dist-info}/RECORD +23 -17
- {cnhkmcp-1.8.10.dist-info → cnhkmcp-2.0.dist-info}/WHEEL +0 -0
- {cnhkmcp-1.8.10.dist-info → cnhkmcp-2.0.dist-info}/entry_points.txt +0 -0
- {cnhkmcp-1.8.10.dist-info → cnhkmcp-2.0.dist-info}/licenses/LICENSE +0 -0
- {cnhkmcp-1.8.10.dist-info → cnhkmcp-2.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inspiration Master - Frontend Logic
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Global state for inspiration feature
|
|
6
|
+
let inspirationState = {
|
|
7
|
+
isLoggedIn: false,
|
|
8
|
+
llmConfig: {
|
|
9
|
+
baseUrl: "https://api.moonshot.cn/v1",
|
|
10
|
+
model: "kimi-k2-turbo-preview",
|
|
11
|
+
apiKey: ""
|
|
12
|
+
},
|
|
13
|
+
options: null,
|
|
14
|
+
selectedDataset: null
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
18
|
+
const inspirationBtn = document.getElementById('inspirationBtn');
|
|
19
|
+
if (inspirationBtn) {
|
|
20
|
+
inspirationBtn.addEventListener('click', openInspirationModal);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Initialize event listeners for the modal
|
|
24
|
+
document.getElementById('inspire-region').addEventListener('change', updateUniversesAndDelays);
|
|
25
|
+
document.getElementById('inspire-search-dataset').addEventListener('click', searchDatasets);
|
|
26
|
+
document.getElementById('inspire-generate').addEventListener('click', generateAlphaTemplates);
|
|
27
|
+
document.getElementById('inspire-download').addEventListener('click', downloadInspirationResult);
|
|
28
|
+
document.getElementById('inspire-new-task').addEventListener('click', resetInspirationTask);
|
|
29
|
+
document.getElementById('inspire-close').addEventListener('click', closeInspirationModal);
|
|
30
|
+
|
|
31
|
+
const testBtn = document.getElementById('inspire-test-llm');
|
|
32
|
+
if (testBtn) {
|
|
33
|
+
testBtn.addEventListener('click', testLLMConnection);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Initially disable generate button until tested
|
|
37
|
+
const genBtn = document.getElementById('inspire-generate');
|
|
38
|
+
if (genBtn) {
|
|
39
|
+
genBtn.disabled = true;
|
|
40
|
+
genBtn.title = "Please test LLM connection first";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Check login status periodically or on load to update button state
|
|
44
|
+
checkLoginAndUpdateButton();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
function getHeaders() {
|
|
48
|
+
const headers = {'Content-Type': 'application/json'};
|
|
49
|
+
const sessionId = localStorage.getItem('brain_session_id');
|
|
50
|
+
if (sessionId) {
|
|
51
|
+
headers['Session-ID'] = sessionId;
|
|
52
|
+
}
|
|
53
|
+
return headers;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function checkLoginAndUpdateButton() {
|
|
57
|
+
fetch('/api/check_login', { headers: getHeaders() })
|
|
58
|
+
.then(response => response.json())
|
|
59
|
+
.then(data => {
|
|
60
|
+
const btn = document.getElementById('inspirationBtn');
|
|
61
|
+
if (data.logged_in) {
|
|
62
|
+
inspirationState.isLoggedIn = true;
|
|
63
|
+
if (btn) {
|
|
64
|
+
btn.style.opacity = '1';
|
|
65
|
+
btn.style.cursor = 'pointer';
|
|
66
|
+
// Add a visual indicator of logged-in state if desired, e.g., change icon color
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
inspirationState.isLoggedIn = false;
|
|
70
|
+
if (btn) {
|
|
71
|
+
// Keep it clickable but maybe visually distinct
|
|
72
|
+
btn.style.opacity = '1';
|
|
73
|
+
btn.style.cursor = 'pointer';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Always ensure it's enabled
|
|
77
|
+
if (btn) btn.disabled = false;
|
|
78
|
+
})
|
|
79
|
+
.catch(err => console.error("Error checking login status:", err));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Expose this function globally so other scripts (like brain.js) can call it after login
|
|
83
|
+
window.updateInspirationButtonState = checkLoginAndUpdateButton;
|
|
84
|
+
|
|
85
|
+
function openInspirationModal() {
|
|
86
|
+
if (!inspirationState.isLoggedIn) {
|
|
87
|
+
// Double check
|
|
88
|
+
fetch('/api/check_login', { headers: getHeaders() })
|
|
89
|
+
.then(response => response.json())
|
|
90
|
+
.then(data => {
|
|
91
|
+
if (data.logged_in) {
|
|
92
|
+
inspirationState.isLoggedIn = true;
|
|
93
|
+
document.getElementById('inspirationModal').style.display = 'block';
|
|
94
|
+
loadInspirationOptions();
|
|
95
|
+
} else {
|
|
96
|
+
// Trigger Brain Login Modal
|
|
97
|
+
if (typeof openBrainLoginModal === 'function') {
|
|
98
|
+
openBrainLoginModal();
|
|
99
|
+
} else {
|
|
100
|
+
alert("请先登录 BRAIN。");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
document.getElementById('inspirationModal').style.display = 'block';
|
|
107
|
+
loadInspirationOptions();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function closeInspirationModal() {
|
|
111
|
+
document.getElementById('inspirationModal').style.display = 'none';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function loadInspirationOptions() {
|
|
115
|
+
if (inspirationState.options) return; // Already loaded
|
|
116
|
+
|
|
117
|
+
fetch('/api/inspiration/options', { headers: getHeaders() })
|
|
118
|
+
.then(res => res.json())
|
|
119
|
+
.then(data => {
|
|
120
|
+
inspirationState.options = data;
|
|
121
|
+
populateRegionDropdown(data);
|
|
122
|
+
})
|
|
123
|
+
.catch(err => console.error("Failed to load options:", err));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function populateRegionDropdown(data) {
|
|
127
|
+
const regionSelect = document.getElementById('inspire-region');
|
|
128
|
+
regionSelect.innerHTML = '<option value="">Select Region</option>';
|
|
129
|
+
|
|
130
|
+
// Assuming data structure matches what we get from ace_lib
|
|
131
|
+
// Structure: { "EQUITY": { "USA": { ... }, "CHN": { ... } } }
|
|
132
|
+
// We'll focus on EQUITY for now or iterate all
|
|
133
|
+
|
|
134
|
+
let regions = new Set();
|
|
135
|
+
if (data.EQUITY) {
|
|
136
|
+
Object.keys(data.EQUITY).forEach(r => regions.add(r));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
regions.forEach(r => {
|
|
140
|
+
const option = document.createElement('option');
|
|
141
|
+
option.value = r;
|
|
142
|
+
option.textContent = r;
|
|
143
|
+
regionSelect.appendChild(option);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function updateUniversesAndDelays() {
|
|
148
|
+
const region = document.getElementById('inspire-region').value;
|
|
149
|
+
const universeSelect = document.getElementById('inspire-universe');
|
|
150
|
+
const delaySelect = document.getElementById('inspire-delay');
|
|
151
|
+
|
|
152
|
+
universeSelect.innerHTML = '<option value="">Select Universe</option>';
|
|
153
|
+
delaySelect.innerHTML = '<option value="">Select Delay</option>';
|
|
154
|
+
|
|
155
|
+
if (!region || !inspirationState.options || !inspirationState.options.EQUITY || !inspirationState.options.EQUITY[region]) return;
|
|
156
|
+
|
|
157
|
+
const data = inspirationState.options.EQUITY[region];
|
|
158
|
+
|
|
159
|
+
data.universes.forEach(u => {
|
|
160
|
+
const option = document.createElement('option');
|
|
161
|
+
option.value = u;
|
|
162
|
+
option.textContent = u;
|
|
163
|
+
universeSelect.appendChild(option);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
data.delays.forEach(d => {
|
|
167
|
+
const option = document.createElement('option');
|
|
168
|
+
option.value = d;
|
|
169
|
+
option.textContent = d;
|
|
170
|
+
delaySelect.appendChild(option);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function searchDatasets() {
|
|
175
|
+
const region = document.getElementById('inspire-region').value;
|
|
176
|
+
const delay = document.getElementById('inspire-delay').value;
|
|
177
|
+
const universe = document.getElementById('inspire-universe').value;
|
|
178
|
+
const search = document.getElementById('inspire-dataset-search').value;
|
|
179
|
+
|
|
180
|
+
if (!region || !delay || !universe) {
|
|
181
|
+
alert("请先选择区域、延迟和股票池。");
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const resultsDiv = document.getElementById('inspire-dataset-results');
|
|
186
|
+
resultsDiv.innerHTML = '正在加载数据集...';
|
|
187
|
+
|
|
188
|
+
fetch('/api/inspiration/datasets', {
|
|
189
|
+
method: 'POST',
|
|
190
|
+
headers: getHeaders(),
|
|
191
|
+
body: JSON.stringify({ region, delay, universe, search })
|
|
192
|
+
})
|
|
193
|
+
.then(res => res.json())
|
|
194
|
+
.then(data => {
|
|
195
|
+
displayDatasetResults(data);
|
|
196
|
+
})
|
|
197
|
+
.catch(err => {
|
|
198
|
+
resultsDiv.innerHTML = '加载数据集出错: ' + err;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function displayDatasetResults(datasets) {
|
|
203
|
+
const resultsDiv = document.getElementById('inspire-dataset-results');
|
|
204
|
+
resultsDiv.innerHTML = '';
|
|
205
|
+
|
|
206
|
+
if (datasets.length === 0) {
|
|
207
|
+
resultsDiv.innerHTML = '未找到数据集。';
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const table = document.createElement('table');
|
|
212
|
+
table.className = 'dataset-table';
|
|
213
|
+
table.style.width = '100%'; // Ensure full width
|
|
214
|
+
table.style.borderCollapse = 'collapse';
|
|
215
|
+
|
|
216
|
+
table.innerHTML = `
|
|
217
|
+
<thead>
|
|
218
|
+
<tr style="text-align: left; background: #f1f1f1;">
|
|
219
|
+
<th style="padding: 8px; border-bottom: 1px solid #ddd;">ID</th>
|
|
220
|
+
<th style="padding: 8px; border-bottom: 1px solid #ddd;">Name</th>
|
|
221
|
+
<th style="padding: 8px; border-bottom: 1px solid #ddd;">Category</th>
|
|
222
|
+
</tr>
|
|
223
|
+
</thead>
|
|
224
|
+
<tbody></tbody>
|
|
225
|
+
`;
|
|
226
|
+
|
|
227
|
+
const tbody = table.querySelector('tbody');
|
|
228
|
+
|
|
229
|
+
datasets.forEach(ds => {
|
|
230
|
+
const tr = document.createElement('tr');
|
|
231
|
+
tr.dataset.id = ds.id;
|
|
232
|
+
tr.style.cursor = 'pointer';
|
|
233
|
+
tr.style.transition = 'background-color 0.2s';
|
|
234
|
+
|
|
235
|
+
// Fix [object Object] issue for category
|
|
236
|
+
let category = ds.category;
|
|
237
|
+
if (typeof category === 'object' && category !== null) {
|
|
238
|
+
// Try to find a meaningful string representation
|
|
239
|
+
category = category.name || category.id || JSON.stringify(category);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
tr.innerHTML = `
|
|
243
|
+
<td style="padding: 8px; border-bottom: 1px solid #eee; color: #007bff; font-weight: bold;">${ds.id}</td>
|
|
244
|
+
<td style="padding: 8px; border-bottom: 1px solid #eee;">${ds.name}</td>
|
|
245
|
+
<td style="padding: 8px; border-bottom: 1px solid #eee;">${category}</td>
|
|
246
|
+
`;
|
|
247
|
+
|
|
248
|
+
tr.addEventListener('click', function() {
|
|
249
|
+
selectDataset(ds.id);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
tr.addEventListener('mouseenter', function() {
|
|
253
|
+
if (inspirationState.selectedDataset !== ds.id) {
|
|
254
|
+
this.style.backgroundColor = '#f8f9fa';
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
tr.addEventListener('mouseleave', function() {
|
|
259
|
+
if (inspirationState.selectedDataset !== ds.id) {
|
|
260
|
+
this.style.backgroundColor = '';
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
tbody.appendChild(tr);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
resultsDiv.appendChild(table);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function selectDataset(id) {
|
|
271
|
+
inspirationState.selectedDataset = id;
|
|
272
|
+
const display = document.getElementById('inspire-selected-dataset');
|
|
273
|
+
if (display) {
|
|
274
|
+
display.textContent = "已选数据集: " + id;
|
|
275
|
+
display.style.display = 'block';
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Highlight the selected row
|
|
279
|
+
document.querySelectorAll('.dataset-table tr').forEach(tr => tr.style.backgroundColor = '');
|
|
280
|
+
const row = document.querySelector(`.dataset-table tr[data-id="${id}"]`);
|
|
281
|
+
if (row) {
|
|
282
|
+
row.style.backgroundColor = '#e7f1ff';
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Removed toggleAccordion as we are moving to a horizontal layout
|
|
287
|
+
|
|
288
|
+
function generateAlphaTemplates() {
|
|
289
|
+
if (!inspirationState.selectedDataset) {
|
|
290
|
+
alert("请先选择一个数据集。");
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const apiKey = document.getElementById('inspire-llm-key').value;
|
|
295
|
+
const baseUrl = document.getElementById('inspire-llm-url').value;
|
|
296
|
+
const model = document.getElementById('inspire-llm-model').value;
|
|
297
|
+
|
|
298
|
+
if (!apiKey) {
|
|
299
|
+
alert("请输入 LLM API Key。");
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const region = document.getElementById('inspire-region').value;
|
|
304
|
+
const delay = document.getElementById('inspire-delay').value;
|
|
305
|
+
const universe = document.getElementById('inspire-universe').value;
|
|
306
|
+
|
|
307
|
+
const outputDiv = document.getElementById('inspire-output');
|
|
308
|
+
outputDiv.innerHTML = '正在生成模板... 这可能需要几分钟...';
|
|
309
|
+
|
|
310
|
+
fetch('/api/inspiration/generate', {
|
|
311
|
+
method: 'POST',
|
|
312
|
+
headers: getHeaders(),
|
|
313
|
+
body: JSON.stringify({
|
|
314
|
+
apiKey, baseUrl, model,
|
|
315
|
+
region, delay, universe,
|
|
316
|
+
datasetId: inspirationState.selectedDataset
|
|
317
|
+
})
|
|
318
|
+
})
|
|
319
|
+
.then(res => res.json())
|
|
320
|
+
.then(data => {
|
|
321
|
+
if (data.error) {
|
|
322
|
+
outputDiv.innerHTML = '错误: ' + data.error;
|
|
323
|
+
} else {
|
|
324
|
+
// Render Markdown
|
|
325
|
+
// Assuming marked.js or similar is available, or just text for now
|
|
326
|
+
// If you have a markdown renderer, use it.
|
|
327
|
+
// For now, simple text or basic HTML replacement
|
|
328
|
+
outputDiv.innerHTML = formatMarkdown(data.result);
|
|
329
|
+
inspirationState.lastResult = data.result;
|
|
330
|
+
const dlBtn = document.getElementById('inspire-download');
|
|
331
|
+
if (dlBtn) dlBtn.style.display = 'inline-block';
|
|
332
|
+
}
|
|
333
|
+
})
|
|
334
|
+
.catch(err => {
|
|
335
|
+
outputDiv.innerHTML = '生成模板出错: ' + err;
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function formatMarkdown(text) {
|
|
340
|
+
// Escape HTML tags to prevent browser from hiding them or interpreting them
|
|
341
|
+
// specifically for Brain expressions like <field_name>
|
|
342
|
+
// We only escape < and > if they look like tags, but for simplicity and safety with this specific content,
|
|
343
|
+
// escaping all is usually safer before markdown parsing, as markdown doesn't use < > for syntax
|
|
344
|
+
// (except for raw HTML, which we don't need here).
|
|
345
|
+
const escapedText = text.replace(/</g, '<').replace(/>/g, '>');
|
|
346
|
+
|
|
347
|
+
if (typeof marked !== 'undefined') {
|
|
348
|
+
return marked.parse(escapedText);
|
|
349
|
+
}
|
|
350
|
+
// Fallback simple formatter
|
|
351
|
+
let html = escapedText
|
|
352
|
+
.replace(/```([\s\S]*?)```/g, '<pre><code>$1</code></pre>')
|
|
353
|
+
.replace(/\n/g, '<br>');
|
|
354
|
+
return html;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function testLLMConnection() {
|
|
358
|
+
const apiKey = document.getElementById('inspire-llm-key').value;
|
|
359
|
+
const baseUrl = document.getElementById('inspire-llm-url').value;
|
|
360
|
+
const model = document.getElementById('inspire-llm-model').value;
|
|
361
|
+
const testBtn = document.getElementById('inspire-test-llm');
|
|
362
|
+
const generateBtn = document.getElementById('inspire-generate');
|
|
363
|
+
|
|
364
|
+
if (!apiKey) {
|
|
365
|
+
alert("请先输入 API Key。");
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
testBtn.textContent = "测试中...";
|
|
370
|
+
testBtn.disabled = true;
|
|
371
|
+
|
|
372
|
+
fetch('/api/inspiration/test_llm', {
|
|
373
|
+
method: 'POST',
|
|
374
|
+
headers: getHeaders(),
|
|
375
|
+
body: JSON.stringify({ apiKey, baseUrl, model })
|
|
376
|
+
})
|
|
377
|
+
.then(res => res.json())
|
|
378
|
+
.then(data => {
|
|
379
|
+
testBtn.disabled = false;
|
|
380
|
+
if (data.success) {
|
|
381
|
+
testBtn.textContent = "成功";
|
|
382
|
+
testBtn.className = "btn btn-success";
|
|
383
|
+
generateBtn.disabled = false;
|
|
384
|
+
setTimeout(() => { testBtn.textContent = "测试连接"; testBtn.className = "btn btn-secondary"; }, 3000);
|
|
385
|
+
} else {
|
|
386
|
+
testBtn.textContent = "失败";
|
|
387
|
+
testBtn.className = "btn btn-danger";
|
|
388
|
+
alert("连接失败: " + data.error);
|
|
389
|
+
generateBtn.disabled = true;
|
|
390
|
+
setTimeout(() => { testBtn.textContent = "测试连接"; testBtn.className = "btn btn-secondary"; }, 3000);
|
|
391
|
+
}
|
|
392
|
+
})
|
|
393
|
+
.catch(err => {
|
|
394
|
+
testBtn.disabled = false;
|
|
395
|
+
testBtn.textContent = "错误";
|
|
396
|
+
alert("错误: " + err);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function downloadInspirationResult() {
|
|
401
|
+
if (!inspirationState.lastResult) return;
|
|
402
|
+
|
|
403
|
+
const blob = new Blob([inspirationState.lastResult], { type: 'text/markdown' });
|
|
404
|
+
const url = URL.createObjectURL(blob);
|
|
405
|
+
const a = document.createElement('a');
|
|
406
|
+
a.href = url;
|
|
407
|
+
a.download = `alpha_inspiration_${inspirationState.selectedDataset}.md`;
|
|
408
|
+
document.body.appendChild(a);
|
|
409
|
+
a.click();
|
|
410
|
+
document.body.removeChild(a);
|
|
411
|
+
URL.revokeObjectURL(url);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function resetInspirationTask() {
|
|
415
|
+
inspirationState.selectedDataset = null;
|
|
416
|
+
const display = document.getElementById('inspire-selected-dataset');
|
|
417
|
+
if (display) {
|
|
418
|
+
display.textContent = "";
|
|
419
|
+
display.style.display = 'none';
|
|
420
|
+
}
|
|
421
|
+
document.getElementById('inspire-output').innerHTML = "";
|
|
422
|
+
document.getElementById('inspire-dataset-results').innerHTML = "";
|
|
423
|
+
|
|
424
|
+
const dlBtn = document.getElementById('inspire-download');
|
|
425
|
+
if (dlBtn) dlBtn.style.display = 'none';
|
|
426
|
+
// Keep LLM config and Region/Universe selections
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function toggleInspireColumn(colId) {
|
|
430
|
+
const col = document.getElementById(colId);
|
|
431
|
+
if (col) {
|
|
432
|
+
col.classList.toggle('collapsed');
|
|
433
|
+
}
|
|
434
|
+
}
|
|
@@ -121,6 +121,9 @@
|
|
|
121
121
|
<button class="btn btn-outline" onclick="overwriteExistingTemplate()">
|
|
122
122
|
<span style="margin-right: 5px;">🔄</span>Overwrite Existing
|
|
123
123
|
</button>
|
|
124
|
+
<button id="inspirationBtn" class="btn btn-primary" style="background-color: #6f42c1; border-color: #6f42c1; opacity: 0.5; cursor: not-allowed;" disabled>
|
|
125
|
+
<span style="margin-right: 5px;">💡</span>找灵感
|
|
126
|
+
</button>
|
|
124
127
|
</div>
|
|
125
128
|
</div>
|
|
126
129
|
|
|
@@ -777,8 +780,131 @@
|
|
|
777
780
|
</div>
|
|
778
781
|
</div>
|
|
779
782
|
|
|
783
|
+
<!-- Inspiration Modal -->
|
|
784
|
+
<div id="inspirationModal" class="modal" style="display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; overflow: hidden; background-color: rgba(0,0,0,0.4);">
|
|
785
|
+
<div class="modal-content" style="background-color: #fefefe; margin: 1% auto; padding: 0; border: 1px solid #888; width: 98%; max-width: 1800px; height: 95vh; border-radius: 8px; display: flex; flex-direction: column;">
|
|
786
|
+
<div class="modal-header" style="display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #eee; padding: 15px 20px;">
|
|
787
|
+
<h3 style="margin: 0;">Alpha Inspiration Master (找灵感)</h3>
|
|
788
|
+
<span id="inspire-close" style="color: #aaa; float: right; font-size: 28px; font-weight: bold; cursor: pointer;">×</span>
|
|
789
|
+
</div>
|
|
790
|
+
|
|
791
|
+
<div class="modal-body" style="padding: 20px; display: flex; gap: 20px; flex: 1; overflow: hidden;">
|
|
792
|
+
<style>
|
|
793
|
+
.inspire-col { transition: all 0.3s ease; position: relative; }
|
|
794
|
+
.inspire-col.collapsed { flex: 0 0 50px !important; min-width: 50px; overflow: hidden; background: #f8f9fa; border-radius: 4px; cursor: pointer; border: 1px solid #eee; }
|
|
795
|
+
.inspire-col.collapsed .inspire-col-content { display: none; }
|
|
796
|
+
.inspire-col.collapsed .col-header { flex-direction: column; align-items: center; height: 100%; justify-content: flex-start; padding-top: 10px; border-bottom: none !important; }
|
|
797
|
+
.inspire-col.collapsed .col-header h4 { display: none; }
|
|
798
|
+
.inspire-col.collapsed .toggle-btn { transform: rotate(180deg); margin-bottom: 20px; }
|
|
799
|
+
.vertical-label { display: none; writing-mode: vertical-rl; text-orientation: mixed; font-weight: bold; font-size: 1.2em; white-space: nowrap; letter-spacing: 2px; padding-top: 10px; }
|
|
800
|
+
.inspire-col.collapsed .vertical-label { display: block; }
|
|
801
|
+
.toggle-btn { background: none; border: none; cursor: pointer; font-size: 1.2em; color: #666; padding: 0 5px; transition: transform 0.3s; }
|
|
802
|
+
.toggle-btn:hover { color: #000; }
|
|
803
|
+
</style>
|
|
804
|
+
|
|
805
|
+
<!-- Column 1: Configuration -->
|
|
806
|
+
<div id="inspire-col-1" class="inspire-col" style="flex: 0 0 320px; display: flex; flex-direction: column; border-right: 1px solid #eee; padding-right: 15px; overflow-y: auto;">
|
|
807
|
+
<div class="col-header" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; border-bottom: 2px solid #007bff; padding-bottom: 5px;">
|
|
808
|
+
<h4 style="margin: 0; color: #007bff;">1. Configuration</h4>
|
|
809
|
+
<button class="toggle-btn" onclick="toggleInspireColumn('inspire-col-1')" title="Toggle Column">◀</button>
|
|
810
|
+
<span class="vertical-label" style="color: #007bff;">Configuration</span>
|
|
811
|
+
</div>
|
|
812
|
+
|
|
813
|
+
<div class="inspire-col-content" style="display: flex; flex-direction: column; gap: 20px;">
|
|
814
|
+
<div style="background: #f8f9fa; padding: 15px; border-radius: 5px;">
|
|
815
|
+
<h5 style="margin-top: 0; margin-bottom: 10px;">LLM Settings</h5>
|
|
816
|
+
<div style="margin-bottom: 10px;">
|
|
817
|
+
<label style="display: block; margin-bottom: 5px; font-size: 0.9em; color: #666;">Base URL</label>
|
|
818
|
+
<input type="text" id="inspire-llm-url" value="https://api.moonshot.cn/v1" class="form-input" style="width: 100%;">
|
|
819
|
+
</div>
|
|
820
|
+
<div style="margin-bottom: 10px;">
|
|
821
|
+
<label style="display: block; margin-bottom: 5px; font-size: 0.9em; color: #666;">Model Name</label>
|
|
822
|
+
<input type="text" id="inspire-llm-model" value="kimi-k2-turbo-preview" class="form-input" style="width: 100%;">
|
|
823
|
+
</div>
|
|
824
|
+
<div style="margin-bottom: 10px;">
|
|
825
|
+
<label style="display: block; margin-bottom: 5px; font-size: 0.9em; color: #666;">API Key</label>
|
|
826
|
+
<div style="display: flex; gap: 5px;">
|
|
827
|
+
<input type="password" id="inspire-llm-key" placeholder="Enter API Key" class="form-input" style="width: 100%;">
|
|
828
|
+
<button id="inspire-test-llm" class="btn btn-secondary" style="white-space: nowrap;">测试连接</button>
|
|
829
|
+
</div>
|
|
830
|
+
</div>
|
|
831
|
+
</div>
|
|
832
|
+
|
|
833
|
+
<div style="background: #f8f9fa; padding: 15px; border-radius: 5px;">
|
|
834
|
+
<h5 style="margin-top: 0; margin-bottom: 10px;">Simulation Settings</h5>
|
|
835
|
+
<div style="margin-bottom: 10px;">
|
|
836
|
+
<label style="display: block; margin-bottom: 5px; font-size: 0.9em; color: #666;">Region</label>
|
|
837
|
+
<select id="inspire-region" class="form-input" style="width: 100%;"><option>Loading...</option></select>
|
|
838
|
+
</div>
|
|
839
|
+
<div style="margin-bottom: 10px;">
|
|
840
|
+
<label style="display: block; margin-bottom: 5px; font-size: 0.9em; color: #666;">Universe</label>
|
|
841
|
+
<select id="inspire-universe" class="form-input" style="width: 100%;"><option>Select Region First</option></select>
|
|
842
|
+
</div>
|
|
843
|
+
<div style="margin-bottom: 10px;">
|
|
844
|
+
<label style="display: block; margin-bottom: 5px; font-size: 0.9em; color: #666;">Delay</label>
|
|
845
|
+
<select id="inspire-delay" class="form-input" style="width: 100%;"><option>Select Region First</option></select>
|
|
846
|
+
</div>
|
|
847
|
+
</div>
|
|
848
|
+
</div>
|
|
849
|
+
</div>
|
|
850
|
+
|
|
851
|
+
<!-- Column 2: Dataset Selection -->
|
|
852
|
+
<div id="inspire-col-2" class="inspire-col" style="flex: 0 0 500px; display: flex; flex-direction: column; border-right: 1px solid #eee; padding-right: 15px; overflow-y: auto;">
|
|
853
|
+
<div class="col-header" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; border-bottom: 2px solid #28a745; padding-bottom: 5px;">
|
|
854
|
+
<h4 style="margin: 0; color: #28a745;">2. Select Dataset</h4>
|
|
855
|
+
<button class="toggle-btn" onclick="toggleInspireColumn('inspire-col-2')" title="Toggle Column">◀</button>
|
|
856
|
+
<span class="vertical-label" style="color: #28a745;">Select Dataset</span>
|
|
857
|
+
</div>
|
|
858
|
+
|
|
859
|
+
<div class="inspire-col-content" style="display: flex; flex-direction: column; flex: 1;">
|
|
860
|
+
<div style="display: flex; gap: 10px; margin-bottom: 10px;">
|
|
861
|
+
<input type="text" id="inspire-dataset-search" placeholder="Search dataset..." class="form-input" style="flex-grow: 1;">
|
|
862
|
+
<button id="inspire-search-dataset" class="btn btn-secondary">搜索</button>
|
|
863
|
+
</div>
|
|
864
|
+
|
|
865
|
+
<div id="inspire-selected-dataset" style="margin-bottom: 10px; padding: 10px; background-color: #e8f5e9; border: 1px solid #c3e6cb; border-radius: 4px; display: none;"></div>
|
|
866
|
+
|
|
867
|
+
<div id="inspire-dataset-results" style="flex-grow: 1; overflow-y: auto; border: 1px solid #eee; border-radius: 4px;">
|
|
868
|
+
<!-- Results will appear here -->
|
|
869
|
+
<div style="padding: 20px; text-align: center; color: #666;">
|
|
870
|
+
搜索数据集以开始。
|
|
871
|
+
</div>
|
|
872
|
+
</div>
|
|
873
|
+
</div>
|
|
874
|
+
</div>
|
|
875
|
+
|
|
876
|
+
<!-- Column 3: Results -->
|
|
877
|
+
<div id="inspire-col-3" class="inspire-col" style="flex: 1; display: flex; flex-direction: column; overflow-y: auto;">
|
|
878
|
+
<div class="col-header" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; border-bottom: 2px solid #ffc107; padding-bottom: 5px;">
|
|
879
|
+
<h4 style="margin: 0; color: #d39e00;">3. Results</h4>
|
|
880
|
+
<div style="display: flex; gap: 10px; align-items: center;">
|
|
881
|
+
<button id="inspire-generate" class="btn btn-primary">生成 Alpha 模板</button>
|
|
882
|
+
<button id="inspire-download" class="btn btn-success" style="display: none;">下载模板到本地 📥</button>
|
|
883
|
+
</div>
|
|
884
|
+
<span class="vertical-label" style="color: #d39e00;">Results</span>
|
|
885
|
+
</div>
|
|
886
|
+
|
|
887
|
+
<div class="inspire-col-content" style="display: flex; flex-direction: column; flex: 1;">
|
|
888
|
+
<div id="inspire-output" style="flex-grow: 1; background: #fff; border: 1px solid #ddd; padding: 15px; overflow-y: auto; border-radius: 4px;">
|
|
889
|
+
<div style="text-align: center; color: #666; margin-top: 50px;">
|
|
890
|
+
生成的灵感将显示在这里。
|
|
891
|
+
</div>
|
|
892
|
+
</div>
|
|
893
|
+
|
|
894
|
+
<div style="margin-top: 15px;">
|
|
895
|
+
<button id="inspire-new-task" class="btn btn-secondary" style="width: 100%;">开始新任务</button>
|
|
896
|
+
</div>
|
|
897
|
+
</div>
|
|
898
|
+
</div>
|
|
899
|
+
|
|
900
|
+
</div>
|
|
901
|
+
</div>
|
|
902
|
+
</div>
|
|
903
|
+
|
|
904
|
+
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
780
905
|
<script src="{{ url_for('static', filename='brain.js') }}"></script>
|
|
781
906
|
<script src="{{ url_for('static', filename='script.js') }}"></script>
|
|
907
|
+
<script src="{{ url_for('static', filename='inspiration.js') }}"></script>
|
|
782
908
|
<script src="{{ url_for('static', filename='decoder.js') }}"></script>
|
|
783
909
|
<script src="{{ url_for('static', filename='usage_widget.js') }}"></script>
|
|
784
910
|
</body>
|
cnhkmcp/untracked/APP/usage.md
CHANGED
|
@@ -98,7 +98,33 @@
|
|
|
98
98
|
- 72 变模板:通过“加载72变生成的模板”导入。
|
|
99
99
|
|
|
100
100
|
可用按钮:
|
|
101
|
+
- `Save Current Template`:保存当前编辑器内容到本地存储。
|
|
102
|
+
- `Overwrite Existing`:覆盖已存在的同名模板。
|
|
103
|
+
|
|
104
|
+
### 4.3 找灵感 (Alpha Inspiration Master)
|
|
105
|
+
|
|
106
|
+
位于编辑器工具栏的 `💡 找灵感` 按钮,提供基于 LLM (如 Kimi/Moonshot) 的 Alpha 灵感生成功能。
|
|
107
|
+
|
|
108
|
+
**功能流程:**
|
|
109
|
+
1. **前置条件**:需先登录 BRAIN(点击 `Connect to BRAIN`)。
|
|
110
|
+
2. **打开工具**:点击编辑器上方的 `💡 找灵感` 按钮,打开配置弹窗。
|
|
111
|
+
3. **配置 LLM**:
|
|
112
|
+
- 填入 Base URL (默认 Moonshot API)
|
|
113
|
+
- 填入 API Key
|
|
114
|
+
- 选择模型 (如 `kimi-k2-turbo-preview`)
|
|
115
|
+
4. **选择数据**:
|
|
116
|
+
- 选择 Region / Universe / Delay
|
|
117
|
+
- 搜索并选择一个 Dataset (如 `analyst10`)
|
|
118
|
+
- 系统会自动拉取该 Dataset 的字段信息和 BRAIN 的 Operators。
|
|
119
|
+
5. **生成灵感**:
|
|
120
|
+
- 点击 `Generate Alpha Templates`。
|
|
121
|
+
- LLM 会根据字段含义和算子文档,推荐一批 Alpha 模板。
|
|
122
|
+
6. **使用结果**:
|
|
123
|
+
- 生成的模板可以直接复制到编辑器中使用,或下载保存。
|
|
101
124
|
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 5. 进阶功能页
|
|
102
128
|
- `只展示用户自建模板`:切换模板按钮区的显示范围。
|
|
103
129
|
- `📤 导出用户自建模板`:导出自建模板为 JSON 文件。
|
|
104
130
|
- `📥 导入用户自建模板`:导入之前导出的 JSON。
|
|
@@ -107,7 +133,7 @@
|
|
|
107
133
|
- 常见来源:72 变 Web 下载的 `Alpha_generated_expressions_success.json`
|
|
108
134
|
- 页面也支持载入“JSON 数组(每项为字符串表达式)”的文件
|
|
109
135
|
|
|
110
|
-
### 4.
|
|
136
|
+
### 4.4 Expression Editor(编辑器页)
|
|
111
137
|
|
|
112
138
|
功能:编写/粘贴带模板的表达式,并进行基础语法检查与模板检测。
|
|
113
139
|
|
|
@@ -122,14 +148,14 @@
|
|
|
122
148
|
- `Detected Templates`:自动列出识别到的 `<xxx/>` 模板。
|
|
123
149
|
- `Grammar Rules`:展示此编辑器的语法规则(如分号、注释等)。
|
|
124
150
|
|
|
125
|
-
### 4.
|
|
151
|
+
### 4.5 Decode Templates(解码页)
|
|
126
152
|
|
|
127
153
|
功能:把模板的候选值做组合,生成最终表达式列表。
|
|
128
154
|
|
|
129
155
|
- `full_iteration`:生成所有组合。
|
|
130
156
|
- `random_iteration`:抽样生成;右侧 `Count` 输入抽样数量。
|
|
131
157
|
|
|
132
|
-
### 4.
|
|
158
|
+
### 4.6 Results(结果页)
|
|
133
159
|
|
|
134
160
|
功能:查看/下载生成的表达式,并将表达式与 settings 组合成回测 JSON。
|
|
135
161
|
|