Spaces:
Running
Running
kz209 commited on
Commit ·
5faa1d3
1
Parent(s): d4f8072
cklean up interfaces
Browse files
app.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
| 1 |
import os
|
| 2 |
-
|
| 3 |
import gradio as gr
|
| 4 |
import pandas as pd
|
| 5 |
import plotly.express as px
|
|
@@ -15,13 +14,15 @@ def run_shell_script(secret_key):
|
|
| 15 |
# 记得在 Space 的 Settings -> Variables and secrets 里设置一个环境变量叫 "RUN_KEY"
|
| 16 |
expected_key = os.environ.get("RUN_KEY")
|
| 17 |
|
|
|
|
|
|
|
|
|
|
| 18 |
if secret_key != expected_key:
|
| 19 |
return "❌ 鉴权失败:暗号错误!"
|
| 20 |
|
| 21 |
print("收到指令,开始运行脚本...")
|
| 22 |
|
| 23 |
# 2. 核心:运行 .sh 文件
|
| 24 |
-
# capture_output=True 可以让我们看到脚本输出的日志
|
| 25 |
try:
|
| 26 |
result = subprocess.run(
|
| 27 |
["./gpu_info_collector.sh"],
|
|
@@ -30,25 +31,16 @@ def run_shell_script(secret_key):
|
|
| 30 |
text=True
|
| 31 |
)
|
| 32 |
log_output = f"Standard Output:\n{result.stdout}\n\nError Output:\n{result.stderr}"
|
| 33 |
-
print(log_output)
|
| 34 |
return f"✅ 脚本运行完毕!\n{log_output}"
|
| 35 |
except Exception as e:
|
| 36 |
return f"⚠️ 运行出错: {str(e)}"
|
| 37 |
|
| 38 |
-
|
| 39 |
-
|
| 40 |
# ==========================================
|
| 41 |
# 1. Data Reading Engine
|
| 42 |
# ==========================================
|
| 43 |
|
| 44 |
-
|
| 45 |
def clean_and_read_file(file_path):
|
| 46 |
-
"""
|
| 47 |
-
Robust file reader:
|
| 48 |
-
1. Handles .xlsx masquerading as .csv
|
| 49 |
-
2. Cleans garbage tags like
|
| 50 |
-
3. Fixes broken lines
|
| 51 |
-
"""
|
| 52 |
if not file_path or not os.path.exists(file_path):
|
| 53 |
return pd.DataFrame()
|
| 54 |
|
|
@@ -122,7 +114,6 @@ def clean_and_read_file(file_path):
|
|
| 122 |
# 2. Data Processing
|
| 123 |
# ==========================================
|
| 124 |
|
| 125 |
-
|
| 126 |
def process_gpu_data(df):
|
| 127 |
if df.empty:
|
| 128 |
return df
|
|
@@ -168,7 +159,6 @@ def process_llm_data(df):
|
|
| 168 |
# 3. Plotting Logic
|
| 169 |
# ==========================================
|
| 170 |
|
| 171 |
-
|
| 172 |
def plot_gpu_trends(df):
|
| 173 |
if df is None or df.empty or 'Rent_Price_Num' not in df.columns:
|
| 174 |
return None
|
|
@@ -177,7 +167,8 @@ def plot_gpu_trends(df):
|
|
| 177 |
if plot_df.empty:
|
| 178 |
return None
|
| 179 |
|
| 180 |
-
|
|
|
|
| 181 |
|
| 182 |
fig = px.line(plot_df,
|
| 183 |
x='Date',
|
|
@@ -192,18 +183,15 @@ def plot_gpu_trends(df):
|
|
| 192 |
return fig
|
| 193 |
|
| 194 |
def plot_llm_trends(df):
|
| 195 |
-
"""Plot trends for all columns, no selection needed anymore"""
|
| 196 |
if df is None or df.empty:
|
| 197 |
return None
|
| 198 |
|
| 199 |
-
# Automatically select all columns except Date
|
| 200 |
value_vars = [c for c in df.columns if c != 'Date']
|
| 201 |
if not value_vars:
|
| 202 |
return None
|
| 203 |
|
| 204 |
plot_df = df[['Date'] + value_vars].copy().dropna(subset=['Date'])
|
| 205 |
|
| 206 |
-
# Melt
|
| 207 |
df_long = plot_df.melt(id_vars=['Date'], var_name='Model', value_name='Price')
|
| 208 |
|
| 209 |
fig = px.line(
|
|
@@ -248,10 +236,9 @@ with gr.Blocks(title="AI Price Tracker") as demo:
|
|
| 248 |
with gr.Accordion("Data Preview", open=False):
|
| 249 |
gpu_table = gr.DataFrame()
|
| 250 |
|
| 251 |
-
# LLM Tab
|
| 252 |
with gr.TabItem("LLM Prices"):
|
| 253 |
with gr.Row():
|
| 254 |
-
# Display chart directly, no column division
|
| 255 |
with gr.Column(scale=1):
|
| 256 |
llm_plot = gr.Plot(label="Price Trend")
|
| 257 |
|
|
@@ -261,39 +248,32 @@ with gr.Blocks(title="AI Price Tracker") as demo:
|
|
| 261 |
|
| 262 |
# --- Initialization Logic ---
|
| 263 |
def init_on_load():
|
| 264 |
-
# Load GPU
|
| 265 |
g_df, g_fig = load_gpu_pipeline()
|
| 266 |
-
|
| 267 |
-
# Load LLM (No checkbox needed anymore)
|
| 268 |
l_df, l_fig = load_llm_pipeline()
|
|
|
|
| 269 |
|
| 270 |
-
return (
|
| 271 |
-
g_fig, # gpu_plot
|
| 272 |
-
g_df, # gpu_table
|
| 273 |
-
l_fig, # llm_plot
|
| 274 |
-
l_df # llm_table
|
| 275 |
-
)
|
| 276 |
-
|
| 277 |
-
# Bind load event
|
| 278 |
demo.load(
|
| 279 |
init_on_load,
|
| 280 |
inputs=None,
|
| 281 |
-
outputs=[
|
| 282 |
-
gpu_plot,
|
| 283 |
-
gpu_table,
|
| 284 |
-
llm_plot,
|
| 285 |
-
llm_table
|
| 286 |
-
]
|
| 287 |
)
|
| 288 |
|
| 289 |
-
#
|
| 290 |
-
#
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 297 |
|
| 298 |
if __name__ == "__main__":
|
| 299 |
-
demo.launch(share=True)
|
|
|
|
| 1 |
import os
|
|
|
|
| 2 |
import gradio as gr
|
| 3 |
import pandas as pd
|
| 4 |
import plotly.express as px
|
|
|
|
| 14 |
# 记得在 Space 的 Settings -> Variables and secrets 里设置一个环境变量叫 "RUN_KEY"
|
| 15 |
expected_key = os.environ.get("RUN_KEY")
|
| 16 |
|
| 17 |
+
if not expected_key:
|
| 18 |
+
return "❌ 鉴权失败:服务端未配置 RUN_KEY 环境变量!"
|
| 19 |
+
|
| 20 |
if secret_key != expected_key:
|
| 21 |
return "❌ 鉴权失败:暗号错误!"
|
| 22 |
|
| 23 |
print("收到指令,开始运行脚本...")
|
| 24 |
|
| 25 |
# 2. 核心:运行 .sh 文件
|
|
|
|
| 26 |
try:
|
| 27 |
result = subprocess.run(
|
| 28 |
["./gpu_info_collector.sh"],
|
|
|
|
| 31 |
text=True
|
| 32 |
)
|
| 33 |
log_output = f"Standard Output:\n{result.stdout}\n\nError Output:\n{result.stderr}"
|
| 34 |
+
print(log_output)
|
| 35 |
return f"✅ 脚本运行完毕!\n{log_output}"
|
| 36 |
except Exception as e:
|
| 37 |
return f"⚠️ 运行出错: {str(e)}"
|
| 38 |
|
|
|
|
|
|
|
| 39 |
# ==========================================
|
| 40 |
# 1. Data Reading Engine
|
| 41 |
# ==========================================
|
| 42 |
|
|
|
|
| 43 |
def clean_and_read_file(file_path):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
if not file_path or not os.path.exists(file_path):
|
| 45 |
return pd.DataFrame()
|
| 46 |
|
|
|
|
| 114 |
# 2. Data Processing
|
| 115 |
# ==========================================
|
| 116 |
|
|
|
|
| 117 |
def process_gpu_data(df):
|
| 118 |
if df.empty:
|
| 119 |
return df
|
|
|
|
| 159 |
# 3. Plotting Logic
|
| 160 |
# ==========================================
|
| 161 |
|
|
|
|
| 162 |
def plot_gpu_trends(df):
|
| 163 |
if df is None or df.empty or 'Rent_Price_Num' not in df.columns:
|
| 164 |
return None
|
|
|
|
| 167 |
if plot_df.empty:
|
| 168 |
return None
|
| 169 |
|
| 170 |
+
# 防御性修复:防止 df 列数不够导致 Index 出界
|
| 171 |
+
chip_col = 'Chip' if 'Chip' in df.columns else (df.columns[1] if len(df.columns) > 1 else None)
|
| 172 |
|
| 173 |
fig = px.line(plot_df,
|
| 174 |
x='Date',
|
|
|
|
| 183 |
return fig
|
| 184 |
|
| 185 |
def plot_llm_trends(df):
|
|
|
|
| 186 |
if df is None or df.empty:
|
| 187 |
return None
|
| 188 |
|
|
|
|
| 189 |
value_vars = [c for c in df.columns if c != 'Date']
|
| 190 |
if not value_vars:
|
| 191 |
return None
|
| 192 |
|
| 193 |
plot_df = df[['Date'] + value_vars].copy().dropna(subset=['Date'])
|
| 194 |
|
|
|
|
| 195 |
df_long = plot_df.melt(id_vars=['Date'], var_name='Model', value_name='Price')
|
| 196 |
|
| 197 |
fig = px.line(
|
|
|
|
| 236 |
with gr.Accordion("Data Preview", open=False):
|
| 237 |
gpu_table = gr.DataFrame()
|
| 238 |
|
| 239 |
+
# LLM Tab
|
| 240 |
with gr.TabItem("LLM Prices"):
|
| 241 |
with gr.Row():
|
|
|
|
| 242 |
with gr.Column(scale=1):
|
| 243 |
llm_plot = gr.Plot(label="Price Trend")
|
| 244 |
|
|
|
|
| 248 |
|
| 249 |
# --- Initialization Logic ---
|
| 250 |
def init_on_load():
|
|
|
|
| 251 |
g_df, g_fig = load_gpu_pipeline()
|
|
|
|
|
|
|
| 252 |
l_df, l_fig = load_llm_pipeline()
|
| 253 |
+
return g_fig, g_df, l_fig, l_df
|
| 254 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 255 |
demo.load(
|
| 256 |
init_on_load,
|
| 257 |
inputs=None,
|
| 258 |
+
outputs=[gpu_plot, gpu_table, llm_plot, llm_table]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
)
|
| 260 |
|
| 261 |
+
# ---------------- 修复区 ----------------
|
| 262 |
+
# 替换原本违规的 gr.Interface 为一个隐形的组件组 (visible=False)
|
| 263 |
+
# 这样可以在不破坏 UI 布局的前提下,成功暴露名为 "run_collector" 的 API
|
| 264 |
+
with gr.Group(visible=False):
|
| 265 |
+
api_input = gr.Textbox(label="Secret Key")
|
| 266 |
+
api_output = gr.Textbox(label="Script Output")
|
| 267 |
+
api_btn = gr.Button("Run")
|
| 268 |
+
|
| 269 |
+
# 绑定点击事件并赋予 API Name
|
| 270 |
+
api_btn.click(
|
| 271 |
+
fn=run_shell_script,
|
| 272 |
+
inputs=api_input,
|
| 273 |
+
outputs=api_output,
|
| 274 |
+
api_name="run_collector"
|
| 275 |
+
)
|
| 276 |
+
# ----------------------------------------
|
| 277 |
|
| 278 |
if __name__ == "__main__":
|
| 279 |
+
demo.launch(share=True)
|