Spaces:
Sleeping
Sleeping
朱东升
commited on
Commit
·
32a0a99
1
Parent(s):
074639d
update6
Browse files
app.py
CHANGED
@@ -27,11 +27,13 @@ active_tasks = {}
|
|
27 |
completed_tasks = []
|
28 |
task_id_counter = 0
|
29 |
task_lock = threading.Lock()
|
30 |
-
|
31 |
|
32 |
def trigger_ui_update():
|
33 |
"""触发UI更新事件"""
|
34 |
-
|
|
|
|
|
35 |
|
36 |
def get_next_task_id():
|
37 |
global task_id_counter
|
@@ -87,18 +89,27 @@ def estimate_completion_time(input_data):
|
|
87 |
Returns:
|
88 |
timedelta: 估计的完成时间
|
89 |
"""
|
90 |
-
#
|
91 |
-
#
|
92 |
-
avg_time_per_item =
|
93 |
total_items = len(input_data)
|
94 |
|
95 |
-
#
|
96 |
-
|
97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
|
99 |
if parallel_factor > 0:
|
100 |
estimated_seconds = (total_items * avg_time_per_item) / parallel_factor
|
101 |
-
|
|
|
|
|
102 |
else:
|
103 |
return timedelta(seconds=0)
|
104 |
|
@@ -152,27 +163,67 @@ def evaluate(input_data):
|
|
152 |
Returns:
|
153 |
list: 包含评估结果的列表
|
154 |
"""
|
|
|
|
|
|
|
|
|
155 |
try:
|
156 |
if not isinstance(input_data, list):
|
157 |
return {"status": "Exception", "error": "Input must be a list"}
|
158 |
|
159 |
results = []
|
160 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
|
162 |
-
future_to_item = {
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
return results
|
173 |
|
174 |
except Exception as e:
|
175 |
-
return {"status": "Exception", "error": str(e)}
|
176 |
|
177 |
def evaluate_single_case(input_data):
|
178 |
"""评估单个代码用例
|
@@ -389,6 +440,7 @@ def render_queue_status():
|
|
389 |
|
390 |
def refresh_ui():
|
391 |
"""定期刷新UI函数"""
|
|
|
392 |
return render_queue_status()
|
393 |
|
394 |
def submit_json_data(json_data):
|
@@ -429,32 +481,70 @@ with gr.Blocks(title="代码评估服务", theme=gr.themes.Soft()) as demo:
|
|
429 |
# JavaScript-based auto-refresh solution
|
430 |
gr.HTML("""
|
431 |
<script>
|
432 |
-
//
|
433 |
function setupAutoRefresh() {
|
434 |
-
|
|
|
|
|
|
|
435 |
|
436 |
// 查找刷新按钮并模拟点击
|
437 |
function autoRefresh() {
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
button.
|
444 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
445 |
}
|
|
|
|
|
446 |
}
|
447 |
}
|
448 |
|
449 |
-
//
|
450 |
-
setInterval(autoRefresh, refreshInterval);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
451 |
|
452 |
// 设置首次加载时立即刷新一次
|
453 |
setTimeout(autoRefresh, 100);
|
454 |
}
|
455 |
|
456 |
-
//
|
457 |
-
|
|
|
|
|
|
|
|
|
458 |
</script>
|
459 |
""")
|
460 |
|
@@ -534,12 +624,20 @@ with gr.Blocks(title="代码评估服务", theme=gr.themes.Soft()) as demo:
|
|
534 |
api_input.change(fn=evaluate, inputs=api_input, outputs=api_output)
|
535 |
|
536 |
if __name__ == "__main__":
|
537 |
-
# 打印Gradio版本,用于调试
|
538 |
-
import gradio
|
539 |
-
print(f"Gradio version: {gradio.__version__}")
|
540 |
-
|
541 |
# 设置队列,并添加API支持
|
542 |
-
demo.queue(api_open=True)
|
|
|
|
|
|
|
|
|
|
|
543 |
|
544 |
# 启动应用
|
545 |
-
demo.launch(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
completed_tasks = []
|
28 |
task_id_counter = 0
|
29 |
task_lock = threading.Lock()
|
30 |
+
last_update_time = datetime.now() # 替换update_event为时间戳跟踪
|
31 |
|
32 |
def trigger_ui_update():
|
33 |
"""触发UI更新事件"""
|
34 |
+
global last_update_time
|
35 |
+
with task_lock:
|
36 |
+
last_update_time = datetime.now() # 更新时间戳而不是使用Event
|
37 |
|
38 |
def get_next_task_id():
|
39 |
global task_id_counter
|
|
|
89 |
Returns:
|
90 |
timedelta: 估计的完成时间
|
91 |
"""
|
92 |
+
# 在Hugging Face Spaces环境中,资源通常受限,调整处理时间预估
|
93 |
+
# 假设每个任务项平均需要5秒处理(HF环境中可能更慢)
|
94 |
+
avg_time_per_item = 5
|
95 |
total_items = len(input_data)
|
96 |
|
97 |
+
# Hugging Face Spaces通常有限制的CPU资源
|
98 |
+
# 保守估计并行处理能力
|
99 |
+
try:
|
100 |
+
cpu_count = multiprocessing.cpu_count()
|
101 |
+
except:
|
102 |
+
# 如果获取失败,假设只有2个CPU
|
103 |
+
cpu_count = 2
|
104 |
+
|
105 |
+
# 在HF环境中,即使有多核也可能性能受限,降低并行因子
|
106 |
+
parallel_factor = min(2, total_items) # 限制最多2个并行任务
|
107 |
|
108 |
if parallel_factor > 0:
|
109 |
estimated_seconds = (total_items * avg_time_per_item) / parallel_factor
|
110 |
+
# 为了避免过于乐观的估计,增加30%的缓冲时间
|
111 |
+
estimated_seconds = estimated_seconds * 1.3
|
112 |
+
return timedelta(seconds=round(estimated_seconds))
|
113 |
else:
|
114 |
return timedelta(seconds=0)
|
115 |
|
|
|
163 |
Returns:
|
164 |
list: 包含评估结果的列表
|
165 |
"""
|
166 |
+
# 打印Gradio版本,用于调试
|
167 |
+
import gradio
|
168 |
+
print(f"Gradio version: {gradio.__version__}")
|
169 |
+
|
170 |
try:
|
171 |
if not isinstance(input_data, list):
|
172 |
return {"status": "Exception", "error": "Input must be a list"}
|
173 |
|
174 |
results = []
|
175 |
+
|
176 |
+
# 在HF Spaces环境中可能受限,降低并行数量
|
177 |
+
try:
|
178 |
+
max_workers = min(multiprocessing.cpu_count(), 2) # 最多2个并行任务
|
179 |
+
except:
|
180 |
+
max_workers = 2 # 如果无法获取,默认为2
|
181 |
+
|
182 |
+
# 增加超时处理
|
183 |
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
|
184 |
+
future_to_item = {}
|
185 |
+
# 分批处理,每批最多5个任务,避免资源耗尽
|
186 |
+
batch_size = 5
|
187 |
+
for i in range(0, len(input_data), batch_size):
|
188 |
+
batch = input_data[i:i+batch_size]
|
189 |
+
# 为每个任务提交并记录
|
190 |
+
for item in batch:
|
191 |
+
future = executor.submit(evaluate_single_case, item)
|
192 |
+
future_to_item[future] = item
|
193 |
+
|
194 |
+
# 等待当前批次完成
|
195 |
+
for future in concurrent.futures.as_completed(future_to_item):
|
196 |
+
item = future_to_item[future]
|
197 |
+
try:
|
198 |
+
# 设置较短的超时时间,避免任务卡死
|
199 |
+
result = future.result(timeout=60) # 60秒超时
|
200 |
+
item.update(result)
|
201 |
+
results.append(item)
|
202 |
+
except concurrent.futures.TimeoutError:
|
203 |
+
# 处理超时情况
|
204 |
+
item.update({
|
205 |
+
"status": "Timeout",
|
206 |
+
"error": "Task processing timed out in Hugging Face environment"
|
207 |
+
})
|
208 |
+
results.append(item)
|
209 |
+
except Exception as e:
|
210 |
+
# 处理其他异常
|
211 |
+
item.update({
|
212 |
+
"status": "Exception",
|
213 |
+
"error": f"Error in Hugging Face environment: {str(e)}"
|
214 |
+
})
|
215 |
+
results.append(item)
|
216 |
+
|
217 |
+
# 清空当前批次
|
218 |
+
future_to_item = {}
|
219 |
+
|
220 |
+
# 短暂休息,让系统喘息
|
221 |
+
time.sleep(0.5)
|
222 |
+
|
223 |
return results
|
224 |
|
225 |
except Exception as e:
|
226 |
+
return {"status": "Exception", "error": f"Evaluation error in Hugging Face environment: {str(e)}"}
|
227 |
|
228 |
def evaluate_single_case(input_data):
|
229 |
"""评估单个代码用例
|
|
|
440 |
|
441 |
def refresh_ui():
|
442 |
"""定期刷新UI函数"""
|
443 |
+
# 不再需要等待事件,直接返回最新状态
|
444 |
return render_queue_status()
|
445 |
|
446 |
def submit_json_data(json_data):
|
|
|
481 |
# JavaScript-based auto-refresh solution
|
482 |
gr.HTML("""
|
483 |
<script>
|
484 |
+
// 为Hugging Face Spaces环境优化的自动刷新机制
|
485 |
function setupAutoRefresh() {
|
486 |
+
// 在HF Spaces中更保守的刷新间隔,避免过多请求
|
487 |
+
const refreshInterval = 3000; // 3秒刷新一次
|
488 |
+
let lastTaskCount = 0;
|
489 |
+
let consecutiveNoChange = 0;
|
490 |
|
491 |
// 查找刷新按钮并模拟点击
|
492 |
function autoRefresh() {
|
493 |
+
try {
|
494 |
+
// 获取所有按钮元素
|
495 |
+
const buttons = document.querySelectorAll('button');
|
496 |
+
// 查找刷新状态按钮
|
497 |
+
for (const button of buttons) {
|
498 |
+
if (button.textContent === '刷新状态') {
|
499 |
+
button.click();
|
500 |
+
|
501 |
+
// 检查任务数量是否变化 (动态优化刷新频率的预留代码)
|
502 |
+
setTimeout(() => {
|
503 |
+
const activeTasks = document.querySelectorAll('table tbody tr');
|
504 |
+
const currentTaskCount = activeTasks.length;
|
505 |
+
|
506 |
+
if (currentTaskCount === lastTaskCount) {
|
507 |
+
consecutiveNoChange++;
|
508 |
+
} else {
|
509 |
+
consecutiveNoChange = 0;
|
510 |
+
}
|
511 |
+
|
512 |
+
lastTaskCount = currentTaskCount;
|
513 |
+
}, 500);
|
514 |
+
|
515 |
+
break;
|
516 |
+
}
|
517 |
}
|
518 |
+
} catch (e) {
|
519 |
+
console.error("Auto-refresh error:", e);
|
520 |
}
|
521 |
}
|
522 |
|
523 |
+
// 周期性检查刷新,确保即使在HF Spaces资源受限情况下也能工作
|
524 |
+
let refreshTimer = setInterval(autoRefresh, refreshInterval);
|
525 |
+
|
526 |
+
// 确保页面可见性变化时刷新机制正常工作
|
527 |
+
document.addEventListener('visibilitychange', function() {
|
528 |
+
if (document.visibilityState === 'visible') {
|
529 |
+
// 页面变为可见时立即刷新一次
|
530 |
+
autoRefresh();
|
531 |
+
// 如果计时器被清除,重新创建
|
532 |
+
if (!refreshTimer) {
|
533 |
+
refreshTimer = setInterval(autoRefresh, refreshInterval);
|
534 |
+
}
|
535 |
+
}
|
536 |
+
});
|
537 |
|
538 |
// 设置首次加载时立即刷新一次
|
539 |
setTimeout(autoRefresh, 100);
|
540 |
}
|
541 |
|
542 |
+
// 确保在DOM完全加载后运行
|
543 |
+
if (document.readyState === 'loading') {
|
544 |
+
document.addEventListener('DOMContentLoaded', setupAutoRefresh);
|
545 |
+
} else {
|
546 |
+
setupAutoRefresh();
|
547 |
+
}
|
548 |
</script>
|
549 |
""")
|
550 |
|
|
|
624 |
api_input.change(fn=evaluate, inputs=api_input, outputs=api_output)
|
625 |
|
626 |
if __name__ == "__main__":
|
|
|
|
|
|
|
|
|
627 |
# 设置队列,并添加API支持
|
628 |
+
demo.queue(api_open=True, concurrency_count=2, max_size=30)
|
629 |
+
|
630 |
+
# 针对Hugging Face Spaces环境的优化配置
|
631 |
+
is_hf_space = os.environ.get("SPACE_ID") is not None
|
632 |
+
server_port = int(os.environ.get("PORT", 7860))
|
633 |
+
server_name = "0.0.0.0" if is_hf_space else "127.0.0.1"
|
634 |
|
635 |
# 启动应用
|
636 |
+
demo.launch(
|
637 |
+
server_name=server_name,
|
638 |
+
server_port=server_port,
|
639 |
+
share=False, # 在HF Spaces环境中无需share
|
640 |
+
debug=False, # 在HF Spaces环境中关闭调试,提高稳定性
|
641 |
+
show_api=True,
|
642 |
+
max_threads=2 # 限制最大线程数,避免资源耗尽
|
643 |
+
)
|