@yorha2b-lab/autodev 5.4.0 → 5.5.1
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.
- package/.github/scripts/analyze/deep_intelligence.py +159 -0
- package/.github/scripts/deploy/publish.py +1 -3
- package/.github/scripts/render/dashboard.py +59 -15
- package/.github/workflows/bunker-intelligence.yml +2 -3
- package/bin/autodev.js +3 -1
- package/package.json +1 -1
- package/src/bootstrap/index.js +2 -2
- package/src/bootstrap/yorha.js +6 -6
- package/src/framework/react/handlebars/partials/handleBlock.hbs +1 -1
- package/src/handlers/page.js +5 -2
- package/src/handlers/part.js +1 -1
- package/src/services/llm.js +15 -15
- package/src/utils/foundation.js +3 -2
- package/.github/scripts/analyze/bot_detect.py +0 -43
- package/.github/scripts/analyze/cluster.py +0 -40
- package/src/bootstrap/registry.js +0 -14
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
import seaborn as sns
|
|
6
|
+
from sklearn.cluster import DBSCAN
|
|
7
|
+
from sklearn.preprocessing import StandardScaler
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def sigmoid(x):
|
|
11
|
+
"""
|
|
12
|
+
概率平滑函数:
|
|
13
|
+
避免指标达到某个值后直接封顶,
|
|
14
|
+
让异常程度呈渐进变化。
|
|
15
|
+
"""
|
|
16
|
+
return 1 / (1 + np.exp(-x))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def map_rank(cluster_id):
|
|
20
|
+
"""
|
|
21
|
+
DBSCAN 的 cluster 数量不是固定的,
|
|
22
|
+
不能写死 0/1/2,否则新增聚类会出现 NaN。
|
|
23
|
+
"""
|
|
24
|
+
if cluster_id == -1:
|
|
25
|
+
return 'Legendary'
|
|
26
|
+
if cluster_id == 0:
|
|
27
|
+
return 'Veteran'
|
|
28
|
+
return f'Tactical Unit {cluster_id}'
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def execute_deep_intelligence():
|
|
32
|
+
|
|
33
|
+
print("🤖 Pod 042: 启动‘全量情报融合协议’...")
|
|
34
|
+
|
|
35
|
+
clone_path = 'ghrs-data/clones_ledger.csv'
|
|
36
|
+
view_path = 'ghrs-data/views_ledger.csv'
|
|
37
|
+
|
|
38
|
+
if not os.path.exists(clone_path) or not os.path.exists(view_path):
|
|
39
|
+
print("⚠️ 数据账本缺失,取消分析。")
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
# 1. 物理对账
|
|
43
|
+
df_c = pd.read_csv(clone_path)
|
|
44
|
+
df_v = pd.read_csv(view_path)
|
|
45
|
+
|
|
46
|
+
df = pd.merge(df_c, df_v, on='date', how='inner').fillna(0)
|
|
47
|
+
|
|
48
|
+
# ==================================================
|
|
49
|
+
# 2. 特征工程
|
|
50
|
+
# ==================================================
|
|
51
|
+
|
|
52
|
+
# 访问转化强度
|
|
53
|
+
df['ratio'] = (df['clones'] / df['views'].replace(0, 1))
|
|
54
|
+
|
|
55
|
+
# Github 行为天然长尾,因此进入 Log 空间
|
|
56
|
+
df['log_volume'] = np.log1p(df['clones'])
|
|
57
|
+
df['log_intensity'] = np.log1p(df['ratio'])
|
|
58
|
+
|
|
59
|
+
# ==================================================
|
|
60
|
+
# 3. 自动化概率审计
|
|
61
|
+
# ==================================================
|
|
62
|
+
|
|
63
|
+
# 原始 ratio 越高,越像自动化行为
|
|
64
|
+
ratio_score = sigmoid(df['ratio'] - 3)
|
|
65
|
+
|
|
66
|
+
# 单日爆发越高,异常概率越高
|
|
67
|
+
burst_score = sigmoid((df['clones'] - 100) / 100)
|
|
68
|
+
|
|
69
|
+
# 综合异常系数
|
|
70
|
+
df['bot_prob'] = (ratio_score * 0.6 + burst_score * 0.4)
|
|
71
|
+
|
|
72
|
+
# ==================================================
|
|
73
|
+
# 4. DBSCAN 行为聚类
|
|
74
|
+
# ==================================================
|
|
75
|
+
X = StandardScaler().fit_transform(df[['log_volume', 'log_intensity']])
|
|
76
|
+
db = DBSCAN(eps=0.4, min_samples=3).fit(X)
|
|
77
|
+
df['cluster'] = db.labels_
|
|
78
|
+
|
|
79
|
+
# ==================================================
|
|
80
|
+
# 5. 战力结算
|
|
81
|
+
# ==================================================
|
|
82
|
+
bot_clones = (df['clones'] * df['bot_prob']).sum()
|
|
83
|
+
total_clones = df['clones'].sum()
|
|
84
|
+
human_clones = max(0, total_clones - bot_clones)
|
|
85
|
+
df['rank'] = df['cluster'].apply(map_rank)
|
|
86
|
+
rank_counts = (df['rank'].value_counts())
|
|
87
|
+
|
|
88
|
+
# ==================================================
|
|
89
|
+
# 6. 全频道视觉矩阵
|
|
90
|
+
# ==================================================
|
|
91
|
+
|
|
92
|
+
plt.style.use('dark_background')
|
|
93
|
+
fig = plt.figure(figsize=(24, 8))
|
|
94
|
+
|
|
95
|
+
gs = fig.add_gridspec(1, 3, width_ratios=[1, 1.2, 1.8])
|
|
96
|
+
|
|
97
|
+
# ----------------------------
|
|
98
|
+
# A. 自动化组成
|
|
99
|
+
# ----------------------------
|
|
100
|
+
|
|
101
|
+
ax1 = fig.add_subplot(gs[0])
|
|
102
|
+
|
|
103
|
+
ax1.pie(
|
|
104
|
+
[human_clones, bot_clones],
|
|
105
|
+
labels=['Human', 'Machine'],
|
|
106
|
+
autopct='%1.1f%%',
|
|
107
|
+
startangle=90,
|
|
108
|
+
pctdistance=0.85,
|
|
109
|
+
explode=(0.05, 0)
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
ax1.add_artist(plt.Circle((0, 0), 0.70, fc='#0d1117'))
|
|
113
|
+
ax1.set_title("Operational Composition", color='#33cc33', pad=20)
|
|
114
|
+
|
|
115
|
+
# ----------------------------
|
|
116
|
+
# B. 行为层级
|
|
117
|
+
# ----------------------------
|
|
118
|
+
|
|
119
|
+
ax2 = fig.add_subplot(gs[1])
|
|
120
|
+
sns.barplot(x=rank_counts.index, y=rank_counts.values,
|
|
121
|
+
palette='viridis', ax=ax2)
|
|
122
|
+
|
|
123
|
+
ax2.set_title("Commander Hierarchy", color='#0066ff', pad=20)
|
|
124
|
+
|
|
125
|
+
ax2.set_ylabel("Days Count")
|
|
126
|
+
|
|
127
|
+
ax2.grid(axis='y', alpha=0.1)
|
|
128
|
+
|
|
129
|
+
# ----------------------------
|
|
130
|
+
# C. 行为拓扑
|
|
131
|
+
# ----------------------------
|
|
132
|
+
|
|
133
|
+
ax3 = fig.add_subplot(gs[2])
|
|
134
|
+
|
|
135
|
+
# sqrt 缩放避免极端 clone 撑爆气泡
|
|
136
|
+
bubble_size = (np.sqrt(df['clones'] + 1) * 20)
|
|
137
|
+
ax3.scatter(
|
|
138
|
+
df['log_volume'],
|
|
139
|
+
df['log_intensity'],
|
|
140
|
+
c=df['cluster'],
|
|
141
|
+
cmap='coolwarm',
|
|
142
|
+
s=bubble_size,
|
|
143
|
+
alpha=0.6,
|
|
144
|
+
edgecolors='w'
|
|
145
|
+
)
|
|
146
|
+
ax3.set_title("Sovereign Logistic Matrix (Log Space)",
|
|
147
|
+
color='#ff00ff', pad=20)
|
|
148
|
+
ax3.set_xlabel("Log(Total Clones)")
|
|
149
|
+
ax3.set_ylabel("Log(Intensity)")
|
|
150
|
+
ax3.grid(alpha=0.1)
|
|
151
|
+
plt.tight_layout()
|
|
152
|
+
os.makedirs('plots', exist_ok=True)
|
|
153
|
+
plt.savefig('plots/bunker_intelligence_fusion.png', dpi=120)
|
|
154
|
+
|
|
155
|
+
print("✅ 全量情报视觉矩阵封存成功!")
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
if __name__ == "__main__":
|
|
159
|
+
execute_deep_intelligence()
|
|
@@ -33,9 +33,7 @@ def assemble_readme():
|
|
|
33
33
|

|
|
34
34
|
|
|
35
35
|
### 🧠 4. 深度情报审计 (Intelligence Intelligence)
|
|
36
|
-
|
|
37
|
-
| :---: | :---: |
|
|
38
|
-
|  |  |
|
|
36
|
+

|
|
39
37
|
|
|
40
38
|
#### 🛰️ 流量来源实时追踪
|
|
41
39
|
{ref_table}
|
|
@@ -181,43 +181,87 @@ def intelligence_grid():
|
|
|
181
181
|
plt.savefig('plots/bunker_intelligence_grid.png', dpi=100)
|
|
182
182
|
|
|
183
183
|
|
|
184
|
-
def load_clean(path,
|
|
184
|
+
def load_clean(path, col_name):
|
|
185
185
|
df = pd.read_csv(path)
|
|
186
186
|
df['date'] = pd.to_datetime(df['date'], errors='coerce')
|
|
187
187
|
df = df.dropna(subset=['date']).copy()
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
188
|
+
|
|
189
|
+
# 物理强转数字
|
|
190
|
+
df[col_name] = pd.to_numeric(
|
|
191
|
+
df[col_name.lower()], errors='coerce').fillna(0)
|
|
192
|
+
|
|
193
|
+
# 💡 核心修正:直接在这里把 uniques 重命名为 [类别]_Uniques
|
|
194
|
+
# 这样合并后,列名就是固定的 'Clones_Uniques' 和 'Views_Uniques'
|
|
195
|
+
new_unique_name = f"{col_name}_Uniques"
|
|
196
|
+
df[new_unique_name] = pd.to_numeric(
|
|
197
|
+
df['uniques'], errors='coerce').fillna(0)
|
|
198
|
+
|
|
199
|
+
return df[['date', col_name, new_unique_name]]
|
|
191
200
|
|
|
192
201
|
|
|
193
202
|
def main_dashboard(df_c, df_v):
|
|
203
|
+
# 💡 1. 数据融合与脱水
|
|
194
204
|
df = pd.merge(df_c, df_v, on='date', how='outer').fillna(
|
|
195
205
|
0).sort_values('date')
|
|
196
206
|
df['cumulative'] = df['Clones'].cumsum()
|
|
197
|
-
df['ratio'] = df['Clones'] /
|
|
198
|
-
|
|
207
|
+
df['ratio'] = df['Clones'] / \
|
|
208
|
+
df['Views_Uniques'].replace(0, 1)
|
|
209
|
+
|
|
210
|
+
# 💡 2. 核心算法注入:计算“信号纯度” (Purity)
|
|
211
|
+
df['cumulative'] = df['Clones'].cumsum()
|
|
212
|
+
|
|
213
|
+
# 计算“信号纯度”:克隆数 / 访客数
|
|
214
|
+
df['ratio'] = df['Clones'] / df['Views_Uniques'].replace(0, 1)
|
|
215
|
+
|
|
216
|
+
# 算法:(比例/10 * 0.6) + (总量/500 * 0.4)
|
|
217
|
+
df['bot_prob'] = (df['ratio'] / 10).clip(upper=1) * 0.6 + \
|
|
218
|
+
(df['Clones'] / 500).clip(upper=1) * 0.4
|
|
219
|
+
df['purity'] = (1.0 - df['bot_prob']) * 100
|
|
199
220
|
|
|
200
|
-
|
|
201
|
-
|
|
221
|
+
# 💡 3. 画布物理扩容:由 3 行 1 列 升级为 4 行 1 列
|
|
222
|
+
fig1 = plt.figure(figsize=(12, 14)) # 增加高度以容纳四个雷达
|
|
223
|
+
gs1 = fig1.add_gridspec(4, 1)
|
|
224
|
+
|
|
225
|
+
# --- 子图 1: 实时侦察 (Views vs Clones) ---
|
|
202
226
|
ax1 = fig1.add_subplot(gs1[0])
|
|
203
227
|
ax1.plot(df['date'].tail(30), df['Views'].tail(
|
|
204
228
|
30), alpha=0.5, ls='--', label='Views (Web)')
|
|
205
229
|
ax1.plot(df['date'].tail(30), df['Clones'].tail(30),
|
|
206
230
|
color='#33cc33', lw=2, label='Clones (Terminal)')
|
|
207
231
|
ax1.set_title(
|
|
208
|
-
'Strategic Recon:
|
|
232
|
+
'Strategic Recon: Web Visitors vs Terminal Commandos (30D)', color='#33cc33')
|
|
209
233
|
ax1.legend(loc='upper left', frameon=True, fontsize='small')
|
|
234
|
+
|
|
235
|
+
# --- 子图 2: 累计荣光 (Growth) ---
|
|
210
236
|
ax2 = fig1.add_subplot(gs1[1])
|
|
211
|
-
ax2.fill_between(df['date'], df['cumulative'],
|
|
212
|
-
color='#0066ff', alpha=0.2)
|
|
237
|
+
ax2.fill_between(df['date'], df['cumulative'], color='#0066ff', alpha=0.2)
|
|
213
238
|
ax2.plot(df['date'], df['cumulative'], color='#0066ff', lw=3)
|
|
214
239
|
ax2.set_title('Bunker Glory: Total Cumulative Growth', color='#0066ff')
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
240
|
+
|
|
241
|
+
# --- 💡 子图 3 [核心新增]: 信号纯度审计 (Signal Purity) ---
|
|
242
|
+
ax_p = fig1.add_subplot(gs1[2])
|
|
243
|
+
# 使用渐变紫色,代表地堡的“骇入感知”
|
|
244
|
+
ax_p.fill_between(df['date'].tail(45), df['purity'].tail(
|
|
245
|
+
45), color='#ff00ff', alpha=0.1)
|
|
246
|
+
ax_p.plot(df['date'].tail(45), df['purity'].tail(45),
|
|
247
|
+
color='#ff00ff', lw=1.5, label='Signal Purity %')
|
|
248
|
+
ax_p.set_ylim(0, 105) # 留点空白放标题
|
|
249
|
+
ax_p.axhline(y=50, color='#444', linestyle=':', alpha=0.5) # 50% 警戒线
|
|
250
|
+
ax_p.set_title(
|
|
251
|
+
'Neural Cloud Integrity: Human Signal Purity Audit (%)', color='#ff00ff')
|
|
252
|
+
ax_p.legend(loc='lower left', fontsize='x-small')
|
|
253
|
+
|
|
254
|
+
# --- 子图 4: 作战热力图 (Heatmap) ---
|
|
255
|
+
ax3 = fig1.add_subplot(gs1[3])
|
|
256
|
+
pivot = df.assign(week=df['date'].dt.isocalendar().week, day=df['date'].dt.day_name()).pivot_table(
|
|
257
|
+
index='day', columns='week', values='Clones', aggfunc='sum'
|
|
258
|
+
).fillna(0).reindex(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'])
|
|
259
|
+
|
|
218
260
|
sns.heatmap(pivot, cmap='Greens', ax=ax3,
|
|
219
261
|
cbar=False, lw=2, linecolor='#1a1a1a')
|
|
220
|
-
ax3.set_title(
|
|
262
|
+
ax3.set_title(
|
|
263
|
+
'Global Deployment Heatmap: Strategic Activity Matrix', color='#33cc33')
|
|
264
|
+
|
|
221
265
|
plt.tight_layout()
|
|
222
266
|
plt.savefig('plots/bunker_main_v7.png', dpi=120)
|
|
223
267
|
|
|
@@ -35,7 +35,7 @@ jobs:
|
|
|
35
35
|
python-version: '3.10'
|
|
36
36
|
|
|
37
37
|
- name: Install Dependencies
|
|
38
|
-
run: pip install matplotlib pandas seaborn scipy numpy requests
|
|
38
|
+
run: pip install matplotlib pandas seaborn scipy numpy requests scikit-learn
|
|
39
39
|
|
|
40
40
|
# 💡 步骤 3:运行脚本,注意现在的相对路径!
|
|
41
41
|
# 我们在当前根目录运行,调用 scripts_repo 里的脚本,去处理 data_repo 里的数据
|
|
@@ -48,8 +48,7 @@ jobs:
|
|
|
48
48
|
run: |
|
|
49
49
|
cd data_repo
|
|
50
50
|
# 执行“肉机比”扫描与“军衔”聚类分析
|
|
51
|
-
python ../scripts_repo/.github/scripts/analyze/
|
|
52
|
-
python ../scripts_repo/.github/scripts/analyze/cluster.py
|
|
51
|
+
python ../scripts_repo/.github/scripts/analyze/deep_intelligence.py
|
|
53
52
|
|
|
54
53
|
- name: '📈 Step 3: Visualization Rendering'
|
|
55
54
|
run: |
|
package/bin/autodev.js
CHANGED
|
@@ -4,9 +4,11 @@ const path = require('path')
|
|
|
4
4
|
const chalk = require('chalk')
|
|
5
5
|
const pkg = require('../package.json')
|
|
6
6
|
const { program } = require('commander')
|
|
7
|
+
|
|
8
|
+
const { discover } = require('../src/utils/foundation')
|
|
7
9
|
const { local, matrixEffect, bootSequence } = require('../src/utils/ux')
|
|
8
10
|
|
|
9
|
-
const dialogs =
|
|
11
|
+
const dialogs = discover(path.join(__dirname, '../src/dialogs'))
|
|
10
12
|
const dialog = dialogs[local] ?? dialogs['EN-US']
|
|
11
13
|
|
|
12
14
|
program
|
package/package.json
CHANGED
package/src/bootstrap/index.js
CHANGED
|
@@ -27,9 +27,9 @@ module.exports = {
|
|
|
27
27
|
openAI: require('./openai')(),
|
|
28
28
|
core: require('../utils/core'),
|
|
29
29
|
menus: foundation.getExistingMenus(),
|
|
30
|
+
handlers: foundation.discover(path.join(__dirname, '../handlers')),
|
|
30
31
|
handlebars: require('./handlebar')({ config, template, ...foundation }),
|
|
31
|
-
|
|
32
|
-
prompts: require('./registry')({ dir: path.join(__dirname, `../framework/${template}/prompts`) }),
|
|
32
|
+
prompts: foundation.discover(path.join(__dirname, `../framework/${template}/prompts`)),
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
require('./foundation')(accessPoint)
|
package/src/bootstrap/yorha.js
CHANGED
|
@@ -5,23 +5,23 @@ module.exports = () => {
|
|
|
5
5
|
|
|
6
6
|
const createMember = ({ name }) => ({
|
|
7
7
|
start(text) {
|
|
8
|
-
const spinner = ora({ text: chalk.cyan(
|
|
8
|
+
const spinner = ora({ text: chalk.cyan(`${name} ${text}\n`) }).start()
|
|
9
9
|
return spinner
|
|
10
10
|
},
|
|
11
11
|
fail(spinner, text) {
|
|
12
|
-
spinner.fail(chalk.red(
|
|
12
|
+
spinner.fail(chalk.red(`${name} ${text}\n`))
|
|
13
13
|
},
|
|
14
14
|
report(text, color = 'yellow') {
|
|
15
|
-
console.log(chalk[color](
|
|
15
|
+
console.log(chalk[color](`${name} ${text}\n`))
|
|
16
16
|
},
|
|
17
17
|
update(spinner, text) {
|
|
18
|
-
spinner.text = chalk.cyan(
|
|
18
|
+
spinner.text = chalk.cyan(`${name} ${text}\n`)
|
|
19
19
|
},
|
|
20
20
|
warning(spinner, text) {
|
|
21
|
-
spinner.warn(chalk.yellow(
|
|
21
|
+
spinner.warn(chalk.yellow(`${name} ${text}\n`))
|
|
22
22
|
},
|
|
23
23
|
success(spinner, text) {
|
|
24
|
-
spinner.succeed(chalk.green(
|
|
24
|
+
spinner.succeed(chalk.green(`${name} ${text}\n`))
|
|
25
25
|
},
|
|
26
26
|
})
|
|
27
27
|
|
|
@@ -38,7 +38,7 @@ const onTabChange = key => {
|
|
|
38
38
|
{{#if hasExpandable}}
|
|
39
39
|
const onExpand = async (expanded, record) => {
|
|
40
40
|
if (expanded) {
|
|
41
|
-
setExpandedRowKeys(prev=>[...prev, record[rowKey])
|
|
41
|
+
setExpandedRowKeys(prev=>[...prev, record[rowKey]])
|
|
42
42
|
} else {
|
|
43
43
|
setExpandedRowKeys(prev=>prev.filter(item => item !== record[rowKey]))
|
|
44
44
|
}
|
package/src/handlers/page.js
CHANGED
|
@@ -5,7 +5,7 @@ module.exports = {
|
|
|
5
5
|
watch: 'screenShot',
|
|
6
6
|
async handle(filePath) {
|
|
7
7
|
|
|
8
|
-
const { llm, menus, yorha, dialog, config, prompts, generator, foundation } = require('../bootstrap').get()
|
|
8
|
+
const { llm, menus, yorha, dialog, config, prompts, template, generator, foundation } = require('../bootstrap').get()
|
|
9
9
|
|
|
10
10
|
const { page } = prompts
|
|
11
11
|
const { nineS, pod042 } = yorha
|
|
@@ -37,7 +37,7 @@ module.exports = {
|
|
|
37
37
|
pageConfig = require('../../example/example.json')
|
|
38
38
|
} else {
|
|
39
39
|
pod042.update(spinner, dialog.pod042.uploadVisualMetadata)
|
|
40
|
-
pageConfig = await recognizePage({ prompt: page(fileName), filePath })
|
|
40
|
+
pageConfig = await recognizePage({ prompt: page(fileName), filePath, schema: require(`../framework/${template}/schema/page.json`) })
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
fs.writeFileSync(path.join(targetDir, 'resource.js'), resource({ pageConfig }))
|
|
@@ -62,6 +62,9 @@ module.exports = {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
} catch (error) {
|
|
65
|
+
if (fs.existsSync(targetDir)) {
|
|
66
|
+
fs.rmSync(targetDir, { recursive: true, force: true })
|
|
67
|
+
}
|
|
65
68
|
pod042.fail(spinner, dialog.pod042.constructionAborted(error))
|
|
66
69
|
}
|
|
67
70
|
}
|
package/src/handlers/part.js
CHANGED
|
@@ -20,7 +20,7 @@ module.exports = {
|
|
|
20
20
|
try {
|
|
21
21
|
pod042.update(spinner, dialog.pod042.extractingUiMetadata)
|
|
22
22
|
|
|
23
|
-
const pageConfig = await recognizePage({ prompt, filePath
|
|
23
|
+
const pageConfig = await recognizePage({ prompt, filePath })
|
|
24
24
|
|
|
25
25
|
const { formItems, dictBlocks, processedColumns } = formatFormItemAndColumns({ pageConfig })
|
|
26
26
|
|
package/src/services/llm.js
CHANGED
|
@@ -32,7 +32,7 @@ const askAI = async ({ model, yorha, dialog, openAI, messages, response_format =
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
module.exports = ({ config, yorha, openAI, dialog, prompts
|
|
35
|
+
module.exports = ({ config, yorha, openAI, dialog, prompts }) => {
|
|
36
36
|
|
|
37
37
|
const sharp = require('sharp')
|
|
38
38
|
|
|
@@ -65,19 +65,7 @@ module.exports = ({ config, yorha, openAI, dialog, prompts, template }) => {
|
|
|
65
65
|
]
|
|
66
66
|
})
|
|
67
67
|
},
|
|
68
|
-
|
|
69
|
-
return askAI({
|
|
70
|
-
yorha,
|
|
71
|
-
openAI,
|
|
72
|
-
dialog,
|
|
73
|
-
model: textModel,
|
|
74
|
-
messages: [
|
|
75
|
-
{ role: 'system', content: API_DESIGNER },
|
|
76
|
-
{ role: 'user', content: api({ responseStr, resourceStr }) }
|
|
77
|
-
]
|
|
78
|
-
})
|
|
79
|
-
},
|
|
80
|
-
recognizePage: async ({ prompt, filePath, taskType = 'page' }) => {
|
|
68
|
+
recognizePage: async ({ prompt, filePath, schema }) => {
|
|
81
69
|
const compressedBuffer = await sharp(filePath)
|
|
82
70
|
.resize(1280, null, { withoutEnlargement: true })
|
|
83
71
|
.jpeg({ quality: 80 })
|
|
@@ -99,7 +87,19 @@ module.exports = ({ config, yorha, openAI, dialog, prompts, template }) => {
|
|
|
99
87
|
]
|
|
100
88
|
}
|
|
101
89
|
],
|
|
102
|
-
response_format:
|
|
90
|
+
response_format: schema ? { strict: true, type: 'json_schema', json_schema: schema } : { type: 'json_object' }
|
|
91
|
+
})
|
|
92
|
+
},
|
|
93
|
+
alignResponseFields: async ({ responseStr, resourceStr }) => {
|
|
94
|
+
return askAI({
|
|
95
|
+
yorha,
|
|
96
|
+
openAI,
|
|
97
|
+
dialog,
|
|
98
|
+
model: textModel,
|
|
99
|
+
messages: [
|
|
100
|
+
{ role: 'system', content: API_DESIGNER },
|
|
101
|
+
{ role: 'user', content: api({ responseStr, resourceStr }) }
|
|
102
|
+
]
|
|
103
103
|
})
|
|
104
104
|
},
|
|
105
105
|
}
|
package/src/utils/foundation.js
CHANGED
|
@@ -11,7 +11,6 @@ const fs = require('fs')
|
|
|
11
11
|
const path = require('path')
|
|
12
12
|
const stringify = require('json-stringify-pretty-compact')
|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
/**
|
|
16
15
|
* 获取项目配置信息
|
|
17
16
|
* 优先读取项目根目录的 config.js,如果不存在则使用默认配置
|
|
@@ -63,4 +62,6 @@ const copyTemplateDir = (template, templateSubDir, targetSubDir) => {
|
|
|
63
62
|
|
|
64
63
|
const contextStringify = ({ context, indent = 4, maxLength = 200 }) => stringify.default(context, { indent, maxLength })
|
|
65
64
|
|
|
66
|
-
|
|
65
|
+
const discover = dir => Object.fromEntries(fs.readdirSync(dir).filter(file => file.endsWith('.js')).map(file => [path.basename(file, '.js'), require(path.join(dir, file))]))
|
|
66
|
+
|
|
67
|
+
module.exports = { discover, getConfig, getExistingMenus, copyTemplateDir, contextStringify }
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import pandas as pd
|
|
3
|
-
import matplotlib.pyplot as plt
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def plot_bot_composition():
|
|
7
|
-
print('🤖 Pod 042: 正在绘制‘肉机成分分析图’...')
|
|
8
|
-
df_c = pd.read_csv('ghrs-data/clones_ledger.csv')
|
|
9
|
-
df_v = pd.read_csv('ghrs-data/views_ledger.csv')
|
|
10
|
-
df = pd.merge(df_c, df_v, on='date', how='inner')
|
|
11
|
-
|
|
12
|
-
# 算法:Shadow Ratio > 5 判定为机器
|
|
13
|
-
df['is_bot'] = (df['clones'] / df['views'].replace(0, 1)) > 5
|
|
14
|
-
bot_clones = df[df['is_bot']]['clones'].sum()
|
|
15
|
-
total_clones = df['clones'].sum()
|
|
16
|
-
human_clones = total_clones - bot_clones
|
|
17
|
-
|
|
18
|
-
# 💡 绘图:地堡级甜甜圈图
|
|
19
|
-
plt.style.use('dark_background')
|
|
20
|
-
fig, ax = plt.subplots(figsize=(8, 8))
|
|
21
|
-
|
|
22
|
-
data = [human_clones, bot_clones]
|
|
23
|
-
labels = ['Human Commanders', 'Machine Lifeforms']
|
|
24
|
-
colors = ['#33cc33', '#444444'] # 地堡绿 vs 灰
|
|
25
|
-
|
|
26
|
-
wedges, texts, autotexts = ax.pie(data, labels=labels, autopct='%1.1f%%',
|
|
27
|
-
startangle=90, colors=colors, pctdistance=0.85,
|
|
28
|
-
explode=(0.05, 0), textprops={'color': 'w'})
|
|
29
|
-
|
|
30
|
-
# 画个中间的黑洞,变成甜甜圈
|
|
31
|
-
centre_circle = plt.Circle((0, 0), 0.70, fc='#0d1117')
|
|
32
|
-
fig.gca().add_artist(centre_circle)
|
|
33
|
-
|
|
34
|
-
ax.set_title('Operational Composition: Meat vs Machine',
|
|
35
|
-
color='#33cc33', fontsize=14)
|
|
36
|
-
plt.tight_layout()
|
|
37
|
-
os.makedirs('plots', exist_ok=True)
|
|
38
|
-
plt.savefig('plots/bot_composition.png', dpi=100)
|
|
39
|
-
print('✅ 甜甜圈图封存成功。')
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if __name__ == '__main__':
|
|
43
|
-
plot_bot_composition()
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import pandas as pd
|
|
2
|
-
import seaborn as sns
|
|
3
|
-
import matplotlib.pyplot as plt
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def plot_commander_profiles():
|
|
7
|
-
print('🤖 Pod 042: 正在绘制‘指挥官军衔分布图’...')
|
|
8
|
-
df_c = pd.read_csv('ghrs-data/clones_ledger.csv')
|
|
9
|
-
df_c['intensity'] = df_c['clones'] / df_c['uniques'].replace(0, 1)
|
|
10
|
-
|
|
11
|
-
# 定义军衔逻辑
|
|
12
|
-
def get_rank(row):
|
|
13
|
-
if row['intensity'] > 5:
|
|
14
|
-
return 'Industrial (CI/CD)'
|
|
15
|
-
if row['intensity'] > 1.5:
|
|
16
|
-
return 'Veteran (Hardcore)'
|
|
17
|
-
return 'Recruit (Fresh)'
|
|
18
|
-
|
|
19
|
-
df_c['rank'] = df_c.apply(get_rank, axis=1)
|
|
20
|
-
rank_counts = df_c['rank'].value_counts()
|
|
21
|
-
|
|
22
|
-
# 💡 绘图:战力梯度图
|
|
23
|
-
plt.style.use('dark_background')
|
|
24
|
-
plt.figure(figsize=(10, 6))
|
|
25
|
-
|
|
26
|
-
# 用 seaborn 画出更有质感的柱状图
|
|
27
|
-
ax = sns.barplot(x=rank_counts.index,
|
|
28
|
-
y=rank_counts.values, palette='viridis')
|
|
29
|
-
|
|
30
|
-
plt.title('Commander Hierarchy Distribution', color='#0066ff', fontsize=14)
|
|
31
|
-
plt.ylabel('Node Count', color='#888')
|
|
32
|
-
plt.grid(axis='y', color='#333', linestyle='--', alpha=0.5)
|
|
33
|
-
|
|
34
|
-
plt.tight_layout()
|
|
35
|
-
plt.savefig('plots/commander_profiles.png', dpi=100)
|
|
36
|
-
print('✅ 军衔分布图封存成功。')
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if __name__ == '__main__':
|
|
40
|
-
plot_commander_profiles()
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
module.exports = ({ dir }) => {
|
|
2
|
-
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
const path = require('path')
|
|
5
|
-
|
|
6
|
-
return Object.fromEntries(
|
|
7
|
-
fs.readdirSync(dir)
|
|
8
|
-
.filter(file => file.endsWith('.js'))
|
|
9
|
-
.map(file => [
|
|
10
|
-
path.basename(file, '.js'),
|
|
11
|
-
require(path.join(dir, file))
|
|
12
|
-
])
|
|
13
|
-
)
|
|
14
|
-
}
|