Update app.py
Browse files
app.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 3 |
from flask import Flask, render_template_string, jsonify, request
|
| 4 |
import requests
|
| 5 |
import json
|
| 6 |
-
from datetime import datetime
|
| 7 |
from typing import List, Dict, Optional
|
| 8 |
import os
|
| 9 |
import sys
|
|
@@ -698,12 +698,12 @@ HTML_TEMPLATE = """
|
|
| 698 |
|
| 699 |
<!-- 푸터 -->
|
| 700 |
<div class="footer">
|
| 701 |
-
<p>🤖 AI 뉴스 LLM 분석 시스템 v3.
|
| 702 |
<p style="margin-top: 10px; font-size: 0.9em;">
|
| 703 |
-
💾 SQLite DB 영구 저장 | 🌐 AI Times 실시간
|
| 704 |
</p>
|
| 705 |
<p style="margin-top: 10px; font-size: 0.85em; color: #999;">
|
| 706 |
-
데이터 출처: AI Times
|
| 707 |
</p>
|
| 708 |
</div>
|
| 709 |
</div>
|
|
@@ -1081,27 +1081,27 @@ class LLMAnalyzer:
|
|
| 1081 |
{
|
| 1082 |
"role": "system",
|
| 1083 |
"content": """당신은 중고등학생도 이해할 수 있게 AI 뉴스를 쉽게 설명하는 전문가입니다.
|
| 1084 |
-
|
| 1085 |
|
| 1086 |
-
|
| 1087 |
-
|
| 1088 |
-
|
| 1089 |
-
|
| 1090 |
-
|
| 1091 |
-
|
| 1092 |
-
|
| 1093 |
-
|
| 1094 |
|
| 1095 |
-
|
| 1096 |
},
|
| 1097 |
{
|
| 1098 |
"role": "user",
|
| 1099 |
"content": f"""다음 AI 뉴스를 중고등학생이 이해할 수 있도록 분석해주세요:
|
| 1100 |
|
| 1101 |
-
|
| 1102 |
|
| 1103 |
-
|
| 1104 |
-
|
| 1105 |
}
|
| 1106 |
]
|
| 1107 |
|
|
@@ -1134,13 +1134,13 @@ class LLMAnalyzer:
|
|
| 1134 |
analysis_templates = {
|
| 1135 |
"챗GPT": {
|
| 1136 |
"summary": """마이크로소프트(MS)는 챗GPT의 폭발적인 사용량 증가로 인해 데이터센터 용량이 부족한 심각한 상황에 직면했습니다.
|
| 1137 |
-
|
| 1138 |
-
|
| 1139 |
-
|
| 1140 |
-
|
| 1141 |
-
|
| 1142 |
-
|
| 1143 |
-
|
| 1144 |
"significance": "이 뉴스는 AI 기술의 대중화 속도가 기업들의 예상을 훨씬 뛰어넘고 있음을 보여줍니다. MS 같은 글로벌 IT 기업도 AI 수요를 따라잡기 위해 고군분투하고 있으며, 이는 AI가 단순한 유행이 아닌 산업 전반을 변화시키는 핵심 기술임을 증명합니다.",
|
| 1145 |
"impact_level": "high",
|
| 1146 |
"impact_text": "높음",
|
|
@@ -1149,12 +1149,12 @@ class LLMAnalyzer:
|
|
| 1149 |
},
|
| 1150 |
"GPU": {
|
| 1151 |
"summary": """미국 정부가 아랍에미리트(UAE)에 최첨단 AI 칩(GPU) 수출을 공식적으로 승인했습니다.
|
| 1152 |
-
|
| 1153 |
-
|
| 1154 |
-
|
| 1155 |
-
|
| 1156 |
-
|
| 1157 |
-
|
| 1158 |
"significance": "이는 미국의 AI 기술 수출 정책 변화를 보여주는 중요한 신호입니다. 기술 패권 경쟁 속에서도 전략적 동맹국과의 협력을 통해 AI 생태계를 확장하려는 미국의 의도를 엿볼 수 있습니다.",
|
| 1159 |
"impact_level": "medium",
|
| 1160 |
"impact_text": "중간",
|
|
@@ -1163,12 +1163,12 @@ class LLMAnalyzer:
|
|
| 1163 |
},
|
| 1164 |
"소라": {
|
| 1165 |
"summary": """오픈AI의 혁신적인 AI 동영상 생성 앱 '소라(Sora)'가 출시 단 5일 만에 100만 다운로드를 돌파하는 경이적인 기록을 세웠습니다.
|
| 1166 |
-
|
| 1167 |
-
|
| 1168 |
-
|
| 1169 |
-
|
| 1170 |
-
|
| 1171 |
-
|
| 1172 |
"significance": "텍스트를 이미지로 변환하는 기술에서 더 나아가 동영상 생성까지 가능해진 것은 AI 기술의 진화를 보여줍니다. 콘텐츠 제작의 민주화가 가속화되고 있으며, 누구나 쉽게 고품질 영상을 만들 수 있는 시대가 열리고 있습니다.",
|
| 1173 |
"impact_level": "high",
|
| 1174 |
"impact_text": "높음",
|
|
@@ -1185,12 +1185,12 @@ class LLMAnalyzer:
|
|
| 1185 |
# 기본 분석 (중고등학생 수준)
|
| 1186 |
return {
|
| 1187 |
"summary": f"""'{title}'는 최신 AI 기술 동향을 다루는 중요한 뉴스입니다.
|
| 1188 |
-
|
| 1189 |
-
|
| 1190 |
-
|
| 1191 |
-
|
| 1192 |
-
|
| 1193 |
-
|
| 1194 |
"significance": "AI 기술의 발전은 단순한 기술 혁신을 넘어 사회, 경제, 윤리적 측면에서 다양한 논의를 불러일으키고 있습니다. 이러한 변화를 이해하고 대비하는 것이 미래 세대에게 중요한 역량입니다.",
|
| 1195 |
"impact_level": "medium",
|
| 1196 |
"impact_text": "중간",
|
|
@@ -1352,7 +1352,8 @@ class AdvancedAIAnalyzer:
|
|
| 1352 |
]
|
| 1353 |
|
| 1354 |
all_news = []
|
| 1355 |
-
today = datetime.now().strftime('%m-%d') # 예: '10-
|
|
|
|
| 1356 |
|
| 1357 |
for url_idx, url in enumerate(urls, 1):
|
| 1358 |
try:
|
|
@@ -1412,8 +1413,8 @@ class AdvancedAIAnalyzer:
|
|
| 1412 |
if not date_text:
|
| 1413 |
date_text = today
|
| 1414 |
|
| 1415 |
-
# 오늘 날짜만 필터링
|
| 1416 |
-
if today not in date_text:
|
| 1417 |
continue
|
| 1418 |
|
| 1419 |
news_item = {
|
|
@@ -1432,7 +1433,7 @@ class AdvancedAIAnalyzer:
|
|
| 1432 |
except Exception as e:
|
| 1433 |
continue
|
| 1434 |
|
| 1435 |
-
print(f" → {articles_found}개
|
| 1436 |
time.sleep(1) # 서버 부하 방지
|
| 1437 |
|
| 1438 |
except Exception as e:
|
|
@@ -1447,7 +1448,7 @@ class AdvancedAIAnalyzer:
|
|
| 1447 |
unique_news.append(news)
|
| 1448 |
seen_urls.add(news['url'])
|
| 1449 |
|
| 1450 |
-
print(f"✅ 총 {len(unique_news)}개 중복 제거된
|
| 1451 |
|
| 1452 |
# 최소 3개는 보장 (없으면 샘플 추가)
|
| 1453 |
if len(unique_news) < 3:
|
|
@@ -1481,6 +1482,104 @@ class AdvancedAIAnalyzer:
|
|
| 1481 |
|
| 1482 |
return unique_news[:20] # 최대 20개
|
| 1483 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1484 |
def fetch_huggingface_models(self, limit: int = 30) -> List[Dict]:
|
| 1485 |
"""허깅페이스 트렌딩 모델 30개 수집 (실제 API)"""
|
| 1486 |
print(f"🤗 허깅페이스 트렌딩 모델 {limit}개 수집 중...")
|
|
@@ -1532,7 +1631,7 @@ class AdvancedAIAnalyzer:
|
|
| 1532 |
print(f" ⚠️ 모델 {idx} 처리 오류: {e}")
|
| 1533 |
continue
|
| 1534 |
|
| 1535 |
-
print(f"✅ {len(models_list)}개 트렌딩 모델 수집 완료")
|
| 1536 |
|
| 1537 |
# DB에 저장
|
| 1538 |
if models_list:
|
|
@@ -1542,7 +1641,7 @@ class AdvancedAIAnalyzer:
|
|
| 1542 |
|
| 1543 |
except Exception as e:
|
| 1544 |
print(f"❌ 모델 수집 오류: {e}")
|
| 1545 |
-
print("💾 DB에서 이전 데이터 로드 시도...")
|
| 1546 |
return load_models_from_db()
|
| 1547 |
|
| 1548 |
def fetch_huggingface_spaces(self, limit: int = 30) -> List[Dict]:
|
|
@@ -1602,7 +1701,7 @@ class AdvancedAIAnalyzer:
|
|
| 1602 |
print(f" ⚠️ 스페이스 {idx} 처리 오류: {e}")
|
| 1603 |
continue
|
| 1604 |
|
| 1605 |
-
print(f"✅ {len(spaces_list)}개 트렌딩 스페이스 수집 완료")
|
| 1606 |
|
| 1607 |
# DB에 저장
|
| 1608 |
if spaces_list:
|
|
@@ -1612,15 +1711,15 @@ class AdvancedAIAnalyzer:
|
|
| 1612 |
|
| 1613 |
except Exception as e:
|
| 1614 |
print(f"❌ 스페이스 수집 오류: {e}")
|
| 1615 |
-
print("💾 DB에서 이전 데이터 로드 시도...")
|
| 1616 |
return load_spaces_from_db()
|
| 1617 |
|
| 1618 |
def analyze_all_news(self) -> List[Dict]:
|
| 1619 |
"""모든 뉴스에 LLM 분석 추가"""
|
| 1620 |
-
print("📰 뉴스 LLM 분석 시작...")
|
| 1621 |
|
| 1622 |
-
#
|
| 1623 |
-
news = self.
|
| 1624 |
|
| 1625 |
if not news:
|
| 1626 |
print("⚠️ 수집된 뉴스가 없습니다.")
|
|
@@ -1638,8 +1737,11 @@ class AdvancedAIAnalyzer:
|
|
| 1638 |
|
| 1639 |
article['analysis'] = analysis
|
| 1640 |
analyzed_news.append(article)
|
|
|
|
|
|
|
|
|
|
| 1641 |
|
| 1642 |
-
print(f"✅ {len(analyzed_news)}개 뉴스 분석 완료")
|
| 1643 |
|
| 1644 |
# DB에 저장
|
| 1645 |
if analyzed_news:
|
|
@@ -1658,12 +1760,12 @@ class AdvancedAIAnalyzer:
|
|
| 1658 |
print("="*60 + "\n")
|
| 1659 |
|
| 1660 |
if force_refresh:
|
| 1661 |
-
print("🔄 강제 새로고침 모드: 모든 데이터 새로 수집")
|
| 1662 |
analyzed_news = self.analyze_all_news()
|
| 1663 |
analyzed_models = self.fetch_huggingface_models(30)
|
| 1664 |
analyzed_spaces = self.fetch_huggingface_spaces(30)
|
| 1665 |
else:
|
| 1666 |
-
print("💾 DB 우선 로드 모드")
|
| 1667 |
|
| 1668 |
# DB에서 먼저 로드
|
| 1669 |
analyzed_news = load_news_from_db()
|
|
@@ -1671,21 +1773,21 @@ class AdvancedAIAnalyzer:
|
|
| 1671 |
print("📰 DB에 뉴스 없음 → 새로 수집")
|
| 1672 |
analyzed_news = self.analyze_all_news()
|
| 1673 |
else:
|
| 1674 |
-
print(f"✅ DB에서 {len(analyzed_news)}개 뉴스 로드")
|
| 1675 |
|
| 1676 |
analyzed_models = load_models_from_db()
|
| 1677 |
if not analyzed_models:
|
| 1678 |
print("🤗 DB에 모델 없음 → 새로 수집")
|
| 1679 |
analyzed_models = self.fetch_huggingface_models(30)
|
| 1680 |
else:
|
| 1681 |
-
print(f"✅ DB에서 {len(analyzed_models)}개 모델 로드")
|
| 1682 |
|
| 1683 |
analyzed_spaces = load_spaces_from_db()
|
| 1684 |
if not analyzed_spaces:
|
| 1685 |
print("🚀 DB에 스페이스 없음 → 새로 수집")
|
| 1686 |
analyzed_spaces = self.fetch_huggingface_spaces(30)
|
| 1687 |
else:
|
| 1688 |
-
print(f"✅ DB에서 {len(analyzed_spaces)}개 스페이스 로드")
|
| 1689 |
|
| 1690 |
# 통계
|
| 1691 |
stats = {
|
|
@@ -1698,7 +1800,7 @@ class AdvancedAIAnalyzer:
|
|
| 1698 |
print(f"\n✅ 전체 분석 완료: {stats['llm_analyses']}개 항목")
|
| 1699 |
print(f" 📰 뉴스: {stats['total_news']}개")
|
| 1700 |
print(f" 🤗 모델: {stats['hf_models']}개")
|
| 1701 |
-
print(f" 🚀 스페이스: {stats['hf_spaces']}개")
|
| 1702 |
|
| 1703 |
return {
|
| 1704 |
'analyzed_news': analyzed_news,
|
|
@@ -1799,7 +1901,7 @@ def health():
|
|
| 1799 |
return jsonify({
|
| 1800 |
"status": "healthy",
|
| 1801 |
"service": "AI News LLM Analyzer",
|
| 1802 |
-
"version": "3.
|
| 1803 |
"database": {
|
| 1804 |
"connected": True,
|
| 1805 |
"news_count": news_count,
|
|
@@ -1828,14 +1930,15 @@ if __name__ == '__main__':
|
|
| 1828 |
print(f"""
|
| 1829 |
╔═══════════════════════════════════════��════════════════════╗
|
| 1830 |
║ ║
|
| 1831 |
-
║ 🤖 AI 뉴스 & 허깅페이스 LLM 분석 웹앱 v3.
|
| 1832 |
║ ║
|
| 1833 |
╚════════════════════════════════════════════════════════════╝
|
| 1834 |
|
| 1835 |
✨ 주요 기능:
|
| 1836 |
• 💾 SQLite DB 영구 스토리지
|
| 1837 |
-
• 🌐 AI Times 실시간 뉴스 크롤링 (
|
| 1838 |
-
•
|
|
|
|
| 1839 |
• 🤗 허깅페이스 트렌딩 모델 TOP 30 (모델 카드 분석)
|
| 1840 |
• 🚀 허깅페이스 트렌딩 스페이스 TOP 30 (app.py 분석)
|
| 1841 |
• 🧠 Fireworks AI (Qwen3-235B) 실시간 LLM 분석
|
|
|
|
| 3 |
from flask import Flask, render_template_string, jsonify, request
|
| 4 |
import requests
|
| 5 |
import json
|
| 6 |
+
from datetime import datetime, timedelta
|
| 7 |
from typing import List, Dict, Optional
|
| 8 |
import os
|
| 9 |
import sys
|
|
|
|
| 698 |
|
| 699 |
<!-- 푸터 -->
|
| 700 |
<div class="footer">
|
| 701 |
+
<p>🤖 AI 뉴스 LLM 분석 시스템 v3.3</p>
|
| 702 |
<p style="margin-top: 10px; font-size: 0.9em;">
|
| 703 |
+
💾 SQLite DB 영구 저장 | 🌐 AI Times + Hacker News 실시간 수집 | 🤗 Hugging Face Trending API | 🧠 Powered by Fireworks AI (Qwen3-235B)
|
| 704 |
</p>
|
| 705 |
<p style="margin-top: 10px; font-size: 0.85em; color: #999;">
|
| 706 |
+
데이터 출처: AI Times, Hacker News, Hugging Face | 실시간 분석: Fireworks AI
|
| 707 |
</p>
|
| 708 |
</div>
|
| 709 |
</div>
|
|
|
|
| 1081 |
{
|
| 1082 |
"role": "system",
|
| 1083 |
"content": """당신은 중고등학생도 이해할 수 있게 AI 뉴스를 쉽게 설명하는 전문가입니다.
|
| 1084 |
+
한국어로 답변하며, 다음 형식의 JSON으로만 응답하세요:
|
| 1085 |
|
| 1086 |
+
{
|
| 1087 |
+
"summary": "뉴스 내용을 8-10문장으로 자세하고 구체적으로 설명 (수치, 사실, 배경 포함)",
|
| 1088 |
+
"significance": "이 뉴스가 왜 중요한지 2-3문장으로 설명",
|
| 1089 |
+
"impact_level": "high 또는 medium 또는 low",
|
| 1090 |
+
"impact_text": "높음 또는 중간 또는 낮음",
|
| 1091 |
+
"impact_description": "어떤 영향이 있을지 2-3문장으로 설명",
|
| 1092 |
+
"action": "중고등학생이 할 수 있는 것을 2-3문장으로 제안"
|
| 1093 |
+
}
|
| 1094 |
|
| 1095 |
+
반드시 위 형식의 JSON만 출력하세요."""
|
| 1096 |
},
|
| 1097 |
{
|
| 1098 |
"role": "user",
|
| 1099 |
"content": f"""다음 AI 뉴스를 중고등학생이 이해할 수 있도록 분석해주세요:
|
| 1100 |
|
| 1101 |
+
제목: {title}
|
| 1102 |
|
| 1103 |
+
각 항목을 구체적이고 자세하게 작성하되, 중고등학생 수준에 맞춰 쉽게 설명해주세요.
|
| 1104 |
+
특히 summary는 8-10문장으로 충분히 상세하게 작성하세요."""
|
| 1105 |
}
|
| 1106 |
]
|
| 1107 |
|
|
|
|
| 1134 |
analysis_templates = {
|
| 1135 |
"챗GPT": {
|
| 1136 |
"summary": """마이크로소프트(MS)는 챗GPT의 폭발적인 사용량 증가로 인해 데이터센터 용량이 부족한 심각한 상황에 직면했습니다.
|
| 1137 |
+
현재 미국 내 여러 핵심 지역에서 물리적 공간과 서버 용량이 모두 한계에 도달한 상태입니다.
|
| 1138 |
+
특히 버지니아와 텍사스 등 주요 클라우드 허브 지역에서는 2026년 상반기까지 신규 Azure 클라우드 구독이 제한될 것으로 예상됩니다.
|
| 1139 |
+
이는 생성형 AI 서비스의 급격한 성장 속도가 기업들의 인프라 준비 능력을 크게 초과하고 있음을 보여��니다.
|
| 1140 |
+
MS는 데이터센터 확장을 위해 막대한 투자를 하고 있지만, 실제 인프라 구축에는 최소 2-3년이 소요됩니다.
|
| 1141 |
+
이러한 공급 부족 현상은 AI 서비스 가격 상승과 접근성 제한으로 이어질 수 있으며,
|
| 1142 |
+
경쟁사들도 유사한 문제에 직면할 가능성이 높습니다.
|
| 1143 |
+
전문가들은 이 상황이 AI 산업의 성장 속도를 일시적으로 늦출 수 있다고 분석하고 있습니다.""",
|
| 1144 |
"significance": "이 뉴스는 AI 기술의 대중화 속도가 기업들의 예상을 훨씬 뛰어넘고 있음을 보여줍니다. MS 같은 글로벌 IT 기업도 AI 수요를 따라잡기 위해 고군분투하고 있으며, 이는 AI가 단순한 유행이 아닌 산업 전반을 변화시키는 핵심 기술임을 증명합니다.",
|
| 1145 |
"impact_level": "high",
|
| 1146 |
"impact_text": "높음",
|
|
|
|
| 1149 |
},
|
| 1150 |
"GPU": {
|
| 1151 |
"summary": """미국 정부가 아랍에미리트(UAE)에 최첨단 AI 칩(GPU) 수출을 공식적으로 승인했습니다.
|
| 1152 |
+
이번 승인은 UAE 내에서 미국 기업이 직접 운영하는 데이터센터에만 한정되며, 특히 오픈AI 전용 5기가와트(GW) 규모의 대형 데이터센터 구축에 사용될 예정입니다.
|
| 1153 |
+
GPU는 AI 모델 학습과 추론에 필수적인 하드웨어로, 수천 개의 연산을 동시에 처리할 수 있는 병렬 처리 능력이 핵심입니다.
|
| 1154 |
+
현재 GPU 시장은 엔비디아가 약 80% 이상을 장악하고 있으며, 특히 AI 전용 H100, H200 칩은 공급 부족 현상이 심각합니다.
|
| 1155 |
+
이번 결정으로 엔비디아의 시가총액이 5조 달러에 근접할 것으로 월스트리트는 전망하고 있습니다.
|
| 1156 |
+
한편, 이는 미국의 전략적 기술 수출 정책 변화를 보여주는 중요한 사례입니다.
|
| 1157 |
+
중국에 대해서는 엄격한 수출 통제를 유지하면서도, 중동의 주요 동맹국에는 선별적으로 허용하는 '기술 동맹' 전략을 구사하고 있습니다.""",
|
| 1158 |
"significance": "이는 미국의 AI 기술 수출 정책 변화를 보여주는 중요한 신호입니다. 기술 패권 경쟁 속에서도 전략적 동맹국과의 협력을 통해 AI 생태계를 확장하려는 미국의 의도를 엿볼 수 있습니다.",
|
| 1159 |
"impact_level": "medium",
|
| 1160 |
"impact_text": "중간",
|
|
|
|
| 1163 |
},
|
| 1164 |
"소라": {
|
| 1165 |
"summary": """오픈AI의 혁신적인 AI 동영상 생성 앱 '소라(Sora)'가 출시 단 5일 만에 100만 다운로드를 돌파하는 경이적인 기록을 세웠습니다.
|
| 1166 |
+
이는 전설적인 챗GPT보다도 빠른 성장 속도이며, 초대 전용(invite-only) 방식의 제한적 출시임을 고려하면 더욱 놀라운 성과입니다.
|
| 1167 |
+
소라는 사용자가 입력한 텍스트 프롬프트만으로 최대 1분 길이의 고품질 동영상을 자동으로 생성할 수 있는 생성형 AI 도구입니다.
|
| 1168 |
+
현재 미국과 캐나다에서 iOS 전���으로 먼저 출시되었으며, 안드로이드 버전과 글로벌 확장이 계획되어 있습니다.
|
| 1169 |
+
소라는 기존의 이미지 생성 AI(미드저니, 스테이블 디퓨전 등)를 뛰어넘어, 시간의 흐름과 물리 법칙을 이해하는 수준으로 발전했습니다.
|
| 1170 |
+
예를 들어, 파도가 치는 장면을 생성할 때 물의 움직임, 빛의 반사, 소리까지 자연스럽게 표현할 수 있습니다.
|
| 1171 |
+
이는 영화, 광고, 교육 콘텐츠, 게임 등 모든 영상 산업에 혁명적 변화를 예고합니다.""",
|
| 1172 |
"significance": "텍스트를 이미지로 변환하는 기술에서 더 나아가 동영상 생성까지 가능해진 것은 AI 기술의 진화를 보여줍니다. 콘텐츠 제작의 민주화가 가속화되고 있으며, 누구나 쉽게 고품질 영상을 만들 수 있는 시대가 열리고 있습니다.",
|
| 1173 |
"impact_level": "high",
|
| 1174 |
"impact_text": "높음",
|
|
|
|
| 1185 |
# 기본 분석 (중고등학생 수준)
|
| 1186 |
return {
|
| 1187 |
"summary": f"""'{title}'는 최신 AI 기술 동향을 다루는 중요한 뉴스입니다.
|
| 1188 |
+
인공지능 분야는 매일 새로운 발전을 이루고 있으며, 이러한 기술 변화는 우리의 일상생활, 교육, 그리고 미래 직업 세계에 직접적인 영향을 미칠 것으로 예상됩니다.
|
| 1189 |
+
최근 AI 기술은 단순히 데이터를 처리하는 수준을 넘어, 창의적인 콘텐츠를 생성하고 복잡한 문제를 해결하는 단계로 진화하고 있습니다.
|
| 1190 |
+
특히 대규모 언어 모델(LLM)과 생성형 AI의 발전은 산업 전반에 걸쳐 혁신을 가져오고 있습니다.
|
| 1191 |
+
이러한 기술 변화는 새로운 일자리를 창출하는 동시에, 기존 직업의 성격을 변화시키고 있어 우리 모두가 주목해야 할 트렌드입니다.
|
| 1192 |
+
전문가들은 향후 5-10년 내에 AI가 거의 모든 산업 분야에 통합될 것으로 전망하고 있습니다.
|
| 1193 |
+
따라서 관련 기술의 원리를 이해하고, 사회적 파급효과를 함께 고민하는 것이 미래 세대에게 매우 중요한 역량이 될 것입니다.""",
|
| 1194 |
"significance": "AI 기술의 발전은 단순한 기술 혁신을 넘어 사회, 경제, 윤리적 측면에서 다양한 논의를 불러일으키고 있습니다. 이러한 변화를 이해하고 대비하는 것이 미래 세대에게 중요한 역량입니다.",
|
| 1195 |
"impact_level": "medium",
|
| 1196 |
"impact_text": "중간",
|
|
|
|
| 1352 |
]
|
| 1353 |
|
| 1354 |
all_news = []
|
| 1355 |
+
today = datetime.now().strftime('%m-%d') # 예: '10-11'
|
| 1356 |
+
yesterday = (datetime.now() - timedelta(days=1)).strftime('%m-%d') # 예: '10-10'
|
| 1357 |
|
| 1358 |
for url_idx, url in enumerate(urls, 1):
|
| 1359 |
try:
|
|
|
|
| 1413 |
if not date_text:
|
| 1414 |
date_text = today
|
| 1415 |
|
| 1416 |
+
# 오늘 또는 어제 날짜만 필터링 (시간대 차이 고려)
|
| 1417 |
+
if today not in date_text and yesterday not in date_text:
|
| 1418 |
continue
|
| 1419 |
|
| 1420 |
news_item = {
|
|
|
|
| 1433 |
except Exception as e:
|
| 1434 |
continue
|
| 1435 |
|
| 1436 |
+
print(f" → {articles_found}개 최근 기사 수집\n")
|
| 1437 |
time.sleep(1) # 서버 부하 방지
|
| 1438 |
|
| 1439 |
except Exception as e:
|
|
|
|
| 1448 |
unique_news.append(news)
|
| 1449 |
seen_urls.add(news['url'])
|
| 1450 |
|
| 1451 |
+
print(f"✅ 총 {len(unique_news)}개 중복 제거된 최근 뉴스\n")
|
| 1452 |
|
| 1453 |
# 최소 3개는 보장 (없으면 샘플 추가)
|
| 1454 |
if len(unique_news) < 3:
|
|
|
|
| 1482 |
|
| 1483 |
return unique_news[:20] # 최대 20개
|
| 1484 |
|
| 1485 |
+
def fetch_hackernews(self, limit: int = 15) -> List[Dict]:
|
| 1486 |
+
"""Hacker News Top Stories 수집 (미국 시간 기준 24시간 이내)"""
|
| 1487 |
+
print(f"🔥 Hacker News Top {limit}개 스토리 수집 중...")
|
| 1488 |
+
|
| 1489 |
+
news_list = []
|
| 1490 |
+
|
| 1491 |
+
try:
|
| 1492 |
+
# 1. Top Stories ID 목록 가져오기
|
| 1493 |
+
topstories_url = "https://hacker-news.firebaseio.com/v0/topstories.json"
|
| 1494 |
+
response = requests.get(topstories_url, timeout=10)
|
| 1495 |
+
response.raise_for_status()
|
| 1496 |
+
|
| 1497 |
+
story_ids = response.json()[:limit * 3] # 여유있게 가져오기
|
| 1498 |
+
print(f" 📊 {len(story_ids)}개 스토리 ID 받음")
|
| 1499 |
+
|
| 1500 |
+
# 현재 시간 (UTC 기준)
|
| 1501 |
+
current_time = datetime.utcnow()
|
| 1502 |
+
cutoff_time = current_time - timedelta(hours=36) # 36시간 전까지 (미국 시간 고려)
|
| 1503 |
+
|
| 1504 |
+
# 2. 각 스토리 상세 정보 가져오기
|
| 1505 |
+
for idx, story_id in enumerate(story_ids, 1):
|
| 1506 |
+
try:
|
| 1507 |
+
if len(news_list) >= limit:
|
| 1508 |
+
break
|
| 1509 |
+
|
| 1510 |
+
item_url = f"https://hacker-news.firebaseio.com/v0/item/{story_id}.json"
|
| 1511 |
+
item_response = requests.get(item_url, timeout=5)
|
| 1512 |
+
item_response.raise_for_status()
|
| 1513 |
+
|
| 1514 |
+
story = item_response.json()
|
| 1515 |
+
|
| 1516 |
+
# story 타입만 (job, poll 등 제외)
|
| 1517 |
+
if story.get('type') != 'story':
|
| 1518 |
+
continue
|
| 1519 |
+
|
| 1520 |
+
# URL이 없는 경우 스킵 (Ask HN 등)
|
| 1521 |
+
if not story.get('url'):
|
| 1522 |
+
continue
|
| 1523 |
+
|
| 1524 |
+
# 시간 확인 (36시간 이내만)
|
| 1525 |
+
timestamp = story.get('time', 0)
|
| 1526 |
+
story_time = datetime.utcfromtimestamp(timestamp)
|
| 1527 |
+
|
| 1528 |
+
if story_time < cutoff_time:
|
| 1529 |
+
continue
|
| 1530 |
+
|
| 1531 |
+
# 시간 변환 (Unix timestamp -> 날짜)
|
| 1532 |
+
date_str = story_time.strftime('%m-%d %H:%M')
|
| 1533 |
+
|
| 1534 |
+
news_item = {
|
| 1535 |
+
'title': story.get('title', 'No Title'),
|
| 1536 |
+
'url': story.get('url', ''),
|
| 1537 |
+
'date': date_str,
|
| 1538 |
+
'source': 'Hacker News',
|
| 1539 |
+
'category': 'Tech',
|
| 1540 |
+
'score': story.get('score', 0),
|
| 1541 |
+
'author': story.get('by', 'Unknown'),
|
| 1542 |
+
'comments': story.get('descendants', 0)
|
| 1543 |
+
}
|
| 1544 |
+
|
| 1545 |
+
news_list.append(news_item)
|
| 1546 |
+
|
| 1547 |
+
print(f" ✓ [{len(news_list)}/{limit}] {news_item['title'][:60]}... (점수: {news_item['score']})")
|
| 1548 |
+
|
| 1549 |
+
# API rate limit 방지
|
| 1550 |
+
time.sleep(0.2)
|
| 1551 |
+
|
| 1552 |
+
except Exception as e:
|
| 1553 |
+
print(f" ⚠️ 스토리 {story_id} 처리 오류: {e}")
|
| 1554 |
+
continue
|
| 1555 |
+
|
| 1556 |
+
print(f"✅ {len(news_list)}개 Hacker News 스토리 수집 완료\n")
|
| 1557 |
+
return news_list
|
| 1558 |
+
|
| 1559 |
+
except Exception as e:
|
| 1560 |
+
print(f"❌ Hacker News 수집 오류: {e}\n")
|
| 1561 |
+
return []
|
| 1562 |
+
|
| 1563 |
+
def fetch_all_news_sources(self) -> List[Dict]:
|
| 1564 |
+
"""모든 뉴스 소스에서 수집"""
|
| 1565 |
+
print("🌐 여러 소스에서 뉴스 수집 중...\n")
|
| 1566 |
+
|
| 1567 |
+
all_news = []
|
| 1568 |
+
|
| 1569 |
+
# 1. AI Times 뉴스
|
| 1570 |
+
aitimes_news = self.fetch_aitimes_news()
|
| 1571 |
+
all_news.extend(aitimes_news)
|
| 1572 |
+
|
| 1573 |
+
# 2. Hacker News
|
| 1574 |
+
hackernews = self.fetch_hackernews(limit=15)
|
| 1575 |
+
all_news.extend(hackernews)
|
| 1576 |
+
|
| 1577 |
+
print(f"\n📰 총 {len(all_news)}개 뉴스 수집 완료")
|
| 1578 |
+
print(f" - AI Times: {len(aitimes_news)}개")
|
| 1579 |
+
print(f" - Hacker News: {len(hackernews)}개\n")
|
| 1580 |
+
|
| 1581 |
+
return all_news
|
| 1582 |
+
|
| 1583 |
def fetch_huggingface_models(self, limit: int = 30) -> List[Dict]:
|
| 1584 |
"""허깅페이스 트렌딩 모델 30개 수집 (실제 API)"""
|
| 1585 |
print(f"🤗 허깅페이스 트렌딩 모델 {limit}개 수집 중...")
|
|
|
|
| 1631 |
print(f" ⚠️ 모델 {idx} 처리 오류: {e}")
|
| 1632 |
continue
|
| 1633 |
|
| 1634 |
+
print(f"✅ {len(models_list)}개 트렌딩 모델 수집 완료\n")
|
| 1635 |
|
| 1636 |
# DB에 저장
|
| 1637 |
if models_list:
|
|
|
|
| 1641 |
|
| 1642 |
except Exception as e:
|
| 1643 |
print(f"❌ 모델 수집 오류: {e}")
|
| 1644 |
+
print("💾 DB에서 이전 데이터 로드 시도...\n")
|
| 1645 |
return load_models_from_db()
|
| 1646 |
|
| 1647 |
def fetch_huggingface_spaces(self, limit: int = 30) -> List[Dict]:
|
|
|
|
| 1701 |
print(f" ⚠️ 스페이스 {idx} 처리 오류: {e}")
|
| 1702 |
continue
|
| 1703 |
|
| 1704 |
+
print(f"✅ {len(spaces_list)}개 트렌딩 스페이스 수집 완료\n")
|
| 1705 |
|
| 1706 |
# DB에 저장
|
| 1707 |
if spaces_list:
|
|
|
|
| 1711 |
|
| 1712 |
except Exception as e:
|
| 1713 |
print(f"❌ 스페이스 수집 오류: {e}")
|
| 1714 |
+
print("💾 DB에서 이전 데이터 로드 시도...\n")
|
| 1715 |
return load_spaces_from_db()
|
| 1716 |
|
| 1717 |
def analyze_all_news(self) -> List[Dict]:
|
| 1718 |
"""모든 뉴스에 LLM 분석 추가"""
|
| 1719 |
+
print("📰 뉴스 LLM 분석 시작...\n")
|
| 1720 |
|
| 1721 |
+
# 여러 소스에서 뉴스 수집
|
| 1722 |
+
news = self.fetch_all_news_sources()
|
| 1723 |
|
| 1724 |
if not news:
|
| 1725 |
print("⚠️ 수집된 뉴스가 없습니다.")
|
|
|
|
| 1737 |
|
| 1738 |
article['analysis'] = analysis
|
| 1739 |
analyzed_news.append(article)
|
| 1740 |
+
|
| 1741 |
+
# API rate limit 방지
|
| 1742 |
+
time.sleep(0.3)
|
| 1743 |
|
| 1744 |
+
print(f"\n✅ {len(analyzed_news)}개 뉴스 분석 완료\n")
|
| 1745 |
|
| 1746 |
# DB에 저장
|
| 1747 |
if analyzed_news:
|
|
|
|
| 1760 |
print("="*60 + "\n")
|
| 1761 |
|
| 1762 |
if force_refresh:
|
| 1763 |
+
print("🔄 강제 새로고침 모드: 모든 데이터 새로 수집\n")
|
| 1764 |
analyzed_news = self.analyze_all_news()
|
| 1765 |
analyzed_models = self.fetch_huggingface_models(30)
|
| 1766 |
analyzed_spaces = self.fetch_huggingface_spaces(30)
|
| 1767 |
else:
|
| 1768 |
+
print("💾 DB 우선 로드 모드\n")
|
| 1769 |
|
| 1770 |
# DB에서 먼저 로드
|
| 1771 |
analyzed_news = load_news_from_db()
|
|
|
|
| 1773 |
print("📰 DB에 뉴스 없음 → 새로 수집")
|
| 1774 |
analyzed_news = self.analyze_all_news()
|
| 1775 |
else:
|
| 1776 |
+
print(f"✅ DB에서 {len(analyzed_news)}개 뉴스 로드\n")
|
| 1777 |
|
| 1778 |
analyzed_models = load_models_from_db()
|
| 1779 |
if not analyzed_models:
|
| 1780 |
print("🤗 DB에 모델 없음 → 새로 수집")
|
| 1781 |
analyzed_models = self.fetch_huggingface_models(30)
|
| 1782 |
else:
|
| 1783 |
+
print(f"✅ DB에서 {len(analyzed_models)}개 모델 로드\n")
|
| 1784 |
|
| 1785 |
analyzed_spaces = load_spaces_from_db()
|
| 1786 |
if not analyzed_spaces:
|
| 1787 |
print("🚀 DB에 스페이스 없음 → 새로 수집")
|
| 1788 |
analyzed_spaces = self.fetch_huggingface_spaces(30)
|
| 1789 |
else:
|
| 1790 |
+
print(f"✅ DB에서 {len(analyzed_spaces)}개 스페이스 로드\n")
|
| 1791 |
|
| 1792 |
# 통계
|
| 1793 |
stats = {
|
|
|
|
| 1800 |
print(f"\n✅ 전체 분석 완료: {stats['llm_analyses']}개 항목")
|
| 1801 |
print(f" 📰 뉴스: {stats['total_news']}개")
|
| 1802 |
print(f" 🤗 모델: {stats['hf_models']}개")
|
| 1803 |
+
print(f" 🚀 스페이스: {stats['hf_spaces']}개\n")
|
| 1804 |
|
| 1805 |
return {
|
| 1806 |
'analyzed_news': analyzed_news,
|
|
|
|
| 1901 |
return jsonify({
|
| 1902 |
"status": "healthy",
|
| 1903 |
"service": "AI News LLM Analyzer",
|
| 1904 |
+
"version": "3.3.0",
|
| 1905 |
"database": {
|
| 1906 |
"connected": True,
|
| 1907 |
"news_count": news_count,
|
|
|
|
| 1930 |
print(f"""
|
| 1931 |
╔═══════════════════════════════════════��════════════════════╗
|
| 1932 |
║ ║
|
| 1933 |
+
║ 🤖 AI 뉴스 & 허깅페이스 LLM 분석 웹앱 v3.3 ║
|
| 1934 |
║ ║
|
| 1935 |
╚════════════════════════════════════════════════════════════╝
|
| 1936 |
|
| 1937 |
✨ 주요 기능:
|
| 1938 |
• 💾 SQLite DB 영구 스토리지
|
| 1939 |
+
• 🌐 AI Times 실시간 뉴스 크롤링 (오늘+어제)
|
| 1940 |
+
• 🔥 Hacker News Top Stories (36시간 이내)
|
| 1941 |
+
• 📰 뉴스 중고등학생 수준 LLM 분석
|
| 1942 |
• 🤗 허깅페이스 트렌딩 모델 TOP 30 (모델 카드 분석)
|
| 1943 |
• 🚀 허깅페이스 트렌딩 스페이스 TOP 30 (app.py 분석)
|
| 1944 |
• 🧠 Fireworks AI (Qwen3-235B) 실시간 LLM 분석
|