Update app.py
Browse files
app.py
CHANGED
@@ -455,22 +455,28 @@ def process_hn_story(story, progress=None):
|
|
455 |
try:
|
456 |
url = story.get('url')
|
457 |
if not url:
|
458 |
-
return
|
459 |
|
460 |
content = get_article_content(url)
|
461 |
if not content:
|
462 |
-
return
|
463 |
|
464 |
summary_en = generate_summary(content)
|
465 |
if not summary_en:
|
466 |
-
return
|
467 |
|
468 |
summary_ko = translate_to_korean(summary_en)
|
469 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
470 |
|
471 |
except Exception as e:
|
472 |
print(f"Story processing error: {str(e)}")
|
473 |
-
return
|
474 |
|
475 |
def refresh_hn_stories():
|
476 |
"""Hacker News 스토리 새로고침 (실시간 출력 버전)"""
|
@@ -484,8 +490,8 @@ def refresh_hn_stories():
|
|
484 |
gr.update(),
|
485 |
gr.update(),
|
486 |
gr.update(visible=False), # report_button
|
487 |
-
gr.update(visible=False), #
|
488 |
-
gr.update(visible=False) #
|
489 |
])
|
490 |
|
491 |
yield outputs
|
@@ -493,42 +499,39 @@ def refresh_hn_stories():
|
|
493 |
# 최신 스토리 가져오기
|
494 |
stories = get_recent_stories()
|
495 |
processed_count = 0
|
496 |
-
|
497 |
-
# 실시간 처리 및 출력을 위한 리스트
|
498 |
-
processed_stories = []
|
499 |
|
500 |
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
|
501 |
future_to_story = {executor.submit(process_hn_story, story): story
|
502 |
for story in stories[:100]}
|
503 |
|
504 |
for future in concurrent.futures.as_completed(future_to_story):
|
505 |
-
story, summary = future.result()
|
506 |
processed_count += 1
|
|
|
507 |
|
508 |
-
if
|
509 |
-
|
510 |
-
processed_stories.insert(0, (story, summary))
|
511 |
|
512 |
# 현재까지의 결과 출력
|
513 |
-
outputs = [gr.update(value=f"처리 중... ({
|
514 |
|
515 |
# 모든 컴포넌트 업데이트
|
516 |
for idx, comp in enumerate(hn_article_components):
|
517 |
-
if idx < len(
|
518 |
-
|
519 |
outputs.extend([
|
520 |
gr.update(visible=True),
|
521 |
-
gr.update(value=f"### [{
|
522 |
gr.update(value=f"""
|
523 |
-
**작성자:** {
|
524 |
-
**시간:** {format_hn_time(
|
525 |
-
**점수:** {
|
526 |
-
**댓글:** {len(
|
527 |
-
**AI 요약:** {
|
528 |
"""),
|
529 |
gr.update(visible=True), # report_button
|
530 |
-
gr.update(visible=False), #
|
531 |
-
gr.update(visible=False) #
|
532 |
])
|
533 |
else:
|
534 |
outputs.extend([
|
@@ -543,11 +546,12 @@ def refresh_hn_stories():
|
|
543 |
yield outputs
|
544 |
|
545 |
# 최종 상태 업데이트
|
546 |
-
|
|
|
547 |
|
548 |
for idx, comp in enumerate(hn_article_components):
|
549 |
-
if idx < len(
|
550 |
-
story, summary =
|
551 |
final_outputs.extend([
|
552 |
gr.update(visible=True),
|
553 |
gr.update(value=f"### [{story.get('title', 'Untitled')}]({story.get('url', '#')})"),
|
@@ -559,8 +563,8 @@ def refresh_hn_stories():
|
|
559 |
**AI 요약:** {summary}
|
560 |
"""),
|
561 |
gr.update(visible=True), # report_button
|
562 |
-
gr.update(visible=False), #
|
563 |
-
gr.update(visible=False) #
|
564 |
])
|
565 |
else:
|
566 |
final_outputs.extend([
|
@@ -1094,21 +1098,8 @@ with gr.Blocks(theme="Nymbo/Nymbo_Theme", css=css, title="NewsAI 서비스") as
|
|
1094 |
translated_query_display_global,
|
1095 |
]
|
1096 |
|
1097 |
-
|
1098 |
-
|
1099 |
# AI 리포터 탭 이벤트 연결
|
1100 |
-
hn_outputs = [status_message_hn]
|
1101 |
for comp in hn_article_components:
|
1102 |
-
hn_outputs.extend([
|
1103 |
-
comp['group'],
|
1104 |
-
comp['title'],
|
1105 |
-
comp['info'],
|
1106 |
-
comp['report_button'],
|
1107 |
-
comp['report_content'],
|
1108 |
-
comp['show_report']
|
1109 |
-
])
|
1110 |
-
|
1111 |
-
# 각 컴포넌트의 이벤트 연결
|
1112 |
comp['report_button'].click(
|
1113 |
fn=generate_report,
|
1114 |
inputs=[
|
@@ -1119,6 +1110,7 @@ with gr.Blocks(theme="Nymbo/Nymbo_Theme", css=css, title="NewsAI 서비스") as
|
|
1119 |
comp['report_content'],
|
1120 |
comp['show_report']
|
1121 |
],
|
|
|
1122 |
show_progress=True
|
1123 |
)
|
1124 |
|
@@ -1131,9 +1123,12 @@ with gr.Blocks(theme="Nymbo/Nymbo_Theme", css=css, title="NewsAI 서비스") as
|
|
1131 |
outputs=[
|
1132 |
comp['report_content'],
|
1133 |
comp['show_report']
|
1134 |
-
]
|
|
|
1135 |
)
|
1136 |
|
|
|
|
|
1137 |
# 새로고침 버튼 이벤트 연결
|
1138 |
refresh_button.click(
|
1139 |
fn=refresh_hn_stories,
|
|
|
455 |
try:
|
456 |
url = story.get('url')
|
457 |
if not url:
|
458 |
+
return None # 스킵할 스토리
|
459 |
|
460 |
content = get_article_content(url)
|
461 |
if not content:
|
462 |
+
return None # 스크래핑 실패한 스토리 스킵
|
463 |
|
464 |
summary_en = generate_summary(content)
|
465 |
if not summary_en:
|
466 |
+
return None # 요약 실패한 스토리 스킵
|
467 |
|
468 |
summary_ko = translate_to_korean(summary_en)
|
469 |
+
if not summary_ko:
|
470 |
+
return None # 번역 실패한 스토리 스킵
|
471 |
+
|
472 |
+
return {
|
473 |
+
'story': story,
|
474 |
+
'summary': summary_ko
|
475 |
+
}
|
476 |
|
477 |
except Exception as e:
|
478 |
print(f"Story processing error: {str(e)}")
|
479 |
+
return None # 에러 발생한 스토리 스킵
|
480 |
|
481 |
def refresh_hn_stories():
|
482 |
"""Hacker News 스토리 새로고침 (실시간 출력 버전)"""
|
|
|
490 |
gr.update(),
|
491 |
gr.update(),
|
492 |
gr.update(visible=False), # report_button
|
493 |
+
gr.update(visible=False), # report_content
|
494 |
+
gr.update(visible=False) # show_report
|
495 |
])
|
496 |
|
497 |
yield outputs
|
|
|
499 |
# 최신 스토리 가져오기
|
500 |
stories = get_recent_stories()
|
501 |
processed_count = 0
|
502 |
+
valid_stories = []
|
|
|
|
|
503 |
|
504 |
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
|
505 |
future_to_story = {executor.submit(process_hn_story, story): story
|
506 |
for story in stories[:100]}
|
507 |
|
508 |
for future in concurrent.futures.as_completed(future_to_story):
|
|
|
509 |
processed_count += 1
|
510 |
+
result = future.result()
|
511 |
|
512 |
+
if result: # 성공적으로 처리된 스토리만 추가
|
513 |
+
valid_stories.append((result['story'], result['summary']))
|
|
|
514 |
|
515 |
# 현재까지의 결과 출력
|
516 |
+
outputs = [gr.update(value=f"처리 중... ({len(valid_stories)}/{processed_count} 성공)", visible=True)]
|
517 |
|
518 |
# 모든 컴포넌트 업데이트
|
519 |
for idx, comp in enumerate(hn_article_components):
|
520 |
+
if idx < len(valid_stories):
|
521 |
+
story, summary = valid_stories[idx]
|
522 |
outputs.extend([
|
523 |
gr.update(visible=True),
|
524 |
+
gr.update(value=f"### [{story.get('title', 'Untitled')}]({story.get('url', '#')})"),
|
525 |
gr.update(value=f"""
|
526 |
+
**작성자:** {story.get('by', 'unknown')} |
|
527 |
+
**시간:** {format_hn_time(story.get('time', 0))} |
|
528 |
+
**점수:** {story.get('score', 0)} |
|
529 |
+
**댓글:** {len(story.get('kids', []))}개\n
|
530 |
+
**AI 요약:** {summary}
|
531 |
"""),
|
532 |
gr.update(visible=True), # report_button
|
533 |
+
gr.update(visible=False), # report_content
|
534 |
+
gr.update(visible=False) # show_report
|
535 |
])
|
536 |
else:
|
537 |
outputs.extend([
|
|
|
546 |
yield outputs
|
547 |
|
548 |
# 최종 상태 업데이트
|
549 |
+
final_status = f"총 {len(valid_stories)}개의 포스트가 성공적으로 처리되었습니다. (전체 시도: {processed_count})"
|
550 |
+
final_outputs = [gr.update(value=final_status, visible=True)]
|
551 |
|
552 |
for idx, comp in enumerate(hn_article_components):
|
553 |
+
if idx < len(valid_stories):
|
554 |
+
story, summary = valid_stories[idx]
|
555 |
final_outputs.extend([
|
556 |
gr.update(visible=True),
|
557 |
gr.update(value=f"### [{story.get('title', 'Untitled')}]({story.get('url', '#')})"),
|
|
|
563 |
**AI 요약:** {summary}
|
564 |
"""),
|
565 |
gr.update(visible=True), # report_button
|
566 |
+
gr.update(visible=False), # report_content
|
567 |
+
gr.update(visible=False) # show_report
|
568 |
])
|
569 |
else:
|
570 |
final_outputs.extend([
|
|
|
1098 |
translated_query_display_global,
|
1099 |
]
|
1100 |
|
|
|
|
|
1101 |
# AI 리포터 탭 이벤트 연결
|
|
|
1102 |
for comp in hn_article_components:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1103 |
comp['report_button'].click(
|
1104 |
fn=generate_report,
|
1105 |
inputs=[
|
|
|
1110 |
comp['report_content'],
|
1111 |
comp['show_report']
|
1112 |
],
|
1113 |
+
api_name=f"generate_report_{comp['index']}", # 고유한 API 이름 추가
|
1114 |
show_progress=True
|
1115 |
)
|
1116 |
|
|
|
1123 |
outputs=[
|
1124 |
comp['report_content'],
|
1125 |
comp['show_report']
|
1126 |
+
],
|
1127 |
+
api_name=f"toggle_report_{comp['index']}" # 고유한 API 이름 추가
|
1128 |
)
|
1129 |
|
1130 |
+
|
1131 |
+
|
1132 |
# 새로고침 버튼 이벤트 연결
|
1133 |
refresh_button.click(
|
1134 |
fn=refresh_hn_stories,
|