ginipick commited on
Commit
0dd78ce
Β·
verified Β·
1 Parent(s): 298104b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -78
app.py CHANGED
@@ -1,6 +1,6 @@
1
  # -*- coding: utf-8 -*-
2
  """
3
- AI λ‰΄μŠ€ & ν—ˆκΉ…νŽ˜μ΄μŠ€ νŠΈλ Œλ”© LLM 뢄석 μ›Ήμ•± (μ™„μ „νŒ v3.3)
4
  파일λͺ…: app_advanced.py
5
 
6
  μ£Όμš” κΈ°λŠ₯:
@@ -8,7 +8,7 @@ AI λ‰΄μŠ€ & ν—ˆκΉ…νŽ˜μ΄μŠ€ νŠΈλ Œλ”© LLM 뢄석 μ›Ήμ•± (μ™„μ „νŒ v3.3)
8
  2. AI Times μ‹€μ‹œκ°„ λ‰΄μŠ€ 크둀링 (2개 μ„Ήμ…˜)
9
  3. μ‹€μ œ Hugging Face Trending API 연동 (λͺ¨λΈ/슀페이슀 30μœ„)
10
  4. Fireworks AI (Qwen3-235B) μ‹€μ‹œκ°„ LLM 뢄석
11
- - λ‰΄μŠ€ 쀑고ꡐ생 μˆ˜μ€€ 뢄석 (3-5쀄 상세 μš”μ•½)
12
  - λͺ¨λΈ μΉ΄λ“œ μžλ™ 뢄석 (README.md)
13
  - 슀페이슀 μ½”λ“œ μžλ™ 뢄석 (app.py)
14
  5. νƒ­ UI (λ‰΄μŠ€/λͺ¨λΈ/슀페이슀)
@@ -545,7 +545,7 @@ HTML_TEMPLATE = """
545
  <body>
546
  <div class="container">
547
  <h1>πŸ€– AI λ‰΄μŠ€ & ν—ˆκΉ…νŽ˜μ΄μŠ€ LLM 뢄석</h1>
548
- <p class="subtitle">쀑고ꡐ생을 μœ„ν•œ AI νŠΈλ Œλ“œ 뢄석 μ‹œμŠ€ν…œ πŸŽ“</p>
549
 
550
  <!-- 톡계 μΉ΄λ“œ -->
551
  <div class="stats">
@@ -676,7 +676,7 @@ HTML_TEMPLATE = """
676
  </div>
677
 
678
  <div class="space-analysis">
679
- <strong>πŸŽ“ 상세 μ„€λͺ…:</strong><br>
680
  {{ space.simple_explanation }}
681
  </div>
682
 
@@ -722,12 +722,12 @@ HTML_TEMPLATE = """
722
 
723
  <!-- ν‘Έν„° -->
724
  <div class="footer">
725
- <p>πŸ€– AI λ‰΄μŠ€ LLM 뢄석 μ‹œμŠ€ν…œ v3.3</p>
726
  <p style="margin-top: 10px; font-size: 0.9em;">
727
  πŸ’Ύ SQLite DB 영ꡬ μ €μž₯ | 🌐 AI Times μ‹€μ‹œκ°„ 크둀링 | πŸ€— Hugging Face Trending API | 🧠 Powered by Fireworks AI (Qwen3-235B)
728
  </p>
729
  <p style="margin-top: 10px; font-size: 0.85em; color: #999;">
730
- 데이터 좜처: AI Times (μ‹€μ‹œκ°„ 크둀링), Hugging Face | μ‹€μ‹œκ°„ 뢄석: Fireworks AI | 쀑고ꡐ생 μˆ˜μ€€ 뢄석
731
  </p>
732
  </div>
733
  </div>
@@ -1096,32 +1096,32 @@ class LLMAnalyzer:
1096
  return None
1097
 
1098
  def analyze_news_simple(self, title: str, content: str = "") -> Dict:
1099
- """λ‰΄μŠ€ 기사λ₯Ό 쀑고ꡐ생 μˆ˜μ€€μœΌλ‘œ 뢄석"""
1100
 
1101
  analysis_templates = {
1102
  "μ±—GPT": {
1103
- "summary": "λ§ˆμ΄ν¬λ‘œμ†Œν”„νŠΈ(MS)λŠ” μ±—GPT의 폭발적인 μ‚¬μš©λŸ‰ μ¦κ°€λ‘œ 인해 데이터센터 μš©λŸ‰μ΄ λΆ€μ‘±ν•œ 상황에 μ§λ©΄ν–ˆμŠ΅λ‹ˆλ‹€. ν˜„μž¬ λ―Έκ΅­ λ‚΄ μ—¬λŸ¬ μ§€μ—­μ—μ„œ 물리적 곡간과 μ„œλ²„κ°€ λͺ¨λ‘ λΆ€μ‘±ν•œ μƒνƒœμ΄λ©°, 이둜 인해 λ²„μ§€λ‹ˆμ•„μ™€ ν…μ‚¬μŠ€ λ“± 핡심 μ§€μ—­μ—μ„œλŠ” 2026λ…„ μƒλ°˜κΈ°κΉŒμ§€ μ‹ κ·œ Azure ν΄λΌμš°λ“œ ꡬ독이 μ œν•œλ  κ²ƒμœΌλ‘œ μ˜ˆμƒλ©λ‹ˆλ‹€. μ΄λŠ” μƒμ„±ν˜• AI μ„œλΉ„μŠ€μ˜ κΈ‰κ²©ν•œ μ„±μž₯이 κ°€μ Έμ˜¨ 인프라 곡급 문제λ₯Ό μ—¬μ‹€νžˆ λ³΄μ—¬μ£ΌλŠ” μ‚¬λ‘€μž…λ‹ˆλ‹€.",
1104
- "significance": "이 λ‰΄μŠ€λŠ” AI 기술의 λŒ€μ€‘ν™” 속도가 κΈ°μ—…λ“€μ˜ μ˜ˆμƒμ„ 훨씬 λ›°μ–΄λ„˜κ³  μžˆμŒμ„ λ³΄μ—¬μ€λ‹ˆλ‹€. MS 같은 κΈ€λ‘œλ²Œ IT 기업도 AI μˆ˜μš”λ₯Ό λ”°λΌμž‘κΈ° μœ„ν•΄ κ³ κ΅°λΆ„νˆ¬ν•˜κ³  있으며, μ΄λŠ” AIκ°€ λ‹¨μˆœν•œ μœ ν–‰μ΄ μ•„λ‹Œ μ‚°μ—… μ „λ°˜μ„ λ³€ν™”μ‹œν‚€λŠ” 핡심 κΈ°μˆ μž„μ„ 증λͺ…ν•©λ‹ˆλ‹€.",
1105
  "impact_level": "high",
1106
  "impact_text": "λ†’μŒ",
1107
- "impact_description": "ν΄λΌμš°λ“œ 인프라 뢀쑱은 AI μ„œλΉ„μŠ€ ν™•μž₯에 직접적인 영ν–₯을 미치며, ν–₯ν›„ AI 기술 μ ‘κ·Όμ„±κ³Ό λΉ„μš© ꡬ쑰λ₯Ό λ³€ν™”μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.",
1108
- "action": "μ±—GPTλ‚˜ Claude 같은 AI 도ꡬλ₯Ό ν™œμš©ν•œ ν•™μŠ΅ 방법을 μ΅νžˆμ„Έμš”. λ³΄κ³ μ„œ μž‘μ„±, μ½”λ”© ν•™μŠ΅, μ™Έκ΅­μ–΄ 곡뢀 λ“± λ‹€μ–‘ν•œ λΆ„μ•Όμ—μ„œ AIλ₯Ό ν•™μŠ΅ 보쑰 λ„κ΅¬λ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€."
1109
  },
1110
  "GPU": {
1111
- "summary": "λ―Έκ΅­ μ •λΆ€κ°€ μ•„λžμ—λ―Έλ¦¬νŠΈ(UAE)에 μ΅œμ²¨λ‹¨ AI μΉ©(GPU) μˆ˜μΆœμ„ μŠΉμΈν–ˆμŠ΅λ‹ˆλ‹€. 이번 μŠΉμΈμ€ UAE λ‚΄ λ―Έκ΅­ 기업이 μš΄μ˜ν•˜λŠ” 데이터센터에 ν•œμ •λ˜λ©°, μ˜€ν”ˆAI μ „μš© 5GW 규λͺ¨ 데이터센터 ꡬ좕에 μ‚¬μš©λ  μ˜ˆμ •μž…λ‹ˆλ‹€. GPUλŠ” AI λͺ¨λΈ ν•™μŠ΅μ— ν•„μˆ˜μ μΈ ν•˜λ“œμ›¨μ–΄λ‘œ, μ—”λΉ„λ””μ•„κ°€ μ‹œμž₯을 μ£Όλ„ν•˜κ³  있으며 이번 κ²°μ •μœΌλ‘œ μ—”λΉ„λ””μ•„μ˜ μ‹œκ°€μ΄μ•‘μ΄ 5μ‘° λ‹¬λŸ¬μ— κ·Όμ ‘ν•  κ²ƒμœΌλ‘œ μ „λ§λ©λ‹ˆλ‹€.",
1112
- "significance": "μ΄λŠ” 미ꡭ의 AI 기술 수좜 μ •μ±… λ³€ν™”λ₯Ό λ³΄μ—¬μ£ΌλŠ” μ€‘μš”ν•œ μ‹ ν˜Έμž…λ‹ˆλ‹€. 기술 패ꢌ 경쟁 μ†μ—μ„œλ„ μ „λž΅μ  λ™λ§Ήκ΅­κ³Όμ˜ ν˜‘λ ₯을 톡해 AI μƒνƒœκ³„λ₯Ό ν™•μž₯ν•˜λ €λŠ” 미ꡭ의 μ˜λ„λ₯Ό μ—Ώλ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.",
1113
  "impact_level": "medium",
1114
  "impact_text": "쀑간",
1115
- "impact_description": "AI ν•˜λ“œμ›¨μ–΄ κ³΅κΈ‰λ§μ˜ 지정학적 λ³€ν™”λŠ” κΈ€λ‘œλ²Œ AI μ‚°μ—… μ§€ν˜•λ„μ— 영ν–₯을 λ―ΈμΉ  수 있으며, 특히 λ°˜λ„μ²΄ μ‚°μ—…κ³Ό ꡭ제 관계에 μ€‘μš”ν•œ 의미λ₯Ό κ°€μ§‘λ‹ˆλ‹€.",
1116
- "action": "컴퓨터 ν•˜λ“œμ›¨μ–΄, 특히 GPU의 μž‘λ™ 원리와 AI ν•™μŠ΅μ—μ„œμ˜ 역할을 κ³΅λΆ€ν•΄λ³΄μ„Έμš”. 병렬 처리, ν–‰λ ¬ μ—°μ‚° λ“±μ˜ κ°œλ…μ„ μ΄ν•΄ν•˜λ©΄ AI 기술의 근간을 νŒŒμ•…ν•  수 μžˆμŠ΅λ‹ˆλ‹€."
1117
  },
1118
  "μ†ŒλΌ": {
1119
- "summary": "μ˜€ν”ˆAI의 AI λ™μ˜μƒ 생성 μ•± 'μ†ŒλΌ(Sora)'κ°€ μΆœμ‹œ 5일 λ§Œμ— 100만 λ‹€μš΄λ‘œλ“œλ₯Ό λŒνŒŒν–ˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” μ±—GPT보닀 λΉ λ₯Έ μ„±μž₯ 속도이며, μ΄ˆλŒ€ μ „μš©(invite-only) μ•±μž„μ„ κ³ λ €ν•˜λ©΄ λ”μš± λ†€λΌμš΄ κΈ°λ‘μž…λ‹ˆλ‹€. μ†ŒλΌλŠ” ν…μŠ€νŠΈ ν”„λ‘¬ν”„νŠΈλ§ŒμœΌλ‘œ κ³ ν’ˆμ§ˆ λ™μ˜μƒμ„ 생성할 수 μžˆλŠ” μƒμ„±ν˜• AI λ„κ΅¬λ‘œ, λ―Έκ΅­κ³Ό μΊλ‚˜λ‹€μ—μ„œ iOS μ „μš©μœΌλ‘œ μΆœμ‹œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.",
1120
- "significance": "ν…μŠ€νŠΈλ₯Ό μ΄λ―Έμ§€λ‘œ λ³€ν™˜ν•˜λŠ” κΈ°μˆ μ—μ„œ 더 λ‚˜μ•„κ°€ λ™μ˜μƒ μƒμ„±κΉŒμ§€ κ°€λŠ₯ν•΄μ§„ 것은 AI 기술의 μ§„ν™”λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€. μ½˜ν…μΈ  μ œμž‘μ˜ λ―Όμ£Όν™”κ°€ κ°€μ†ν™”λ˜κ³  있으며, λˆ„κ΅¬λ‚˜ μ‰½κ²Œ κ³ ν’ˆμ§ˆ μ˜μƒμ„ λ§Œλ“€ 수 μžˆλŠ” μ‹œλŒ€κ°€ 열리고 μžˆμŠ΅λ‹ˆλ‹€.",
1121
  "impact_level": "high",
1122
  "impact_text": "λ†’μŒ",
1123
- "impact_description": "μ˜μƒ μ œμž‘ μ‚°μ—…μ˜ νŒ¨λŸ¬λ‹€μž„μ΄ λ³€ν™”ν•˜κ³  있으며, ꡐ윑, λ§ˆμΌ€νŒ…, μ—”ν„°ν…ŒμΈλ¨ΌνŠΈ λ“± λ‹€μ–‘ν•œ λΆ„μ•Όμ—μ„œ AI λ™μ˜μƒ 생성 기술의 ν™œμš©μ΄ 증가할 κ²ƒμœΌλ‘œ μ˜ˆμƒλ©λ‹ˆλ‹€.",
1124
- "action": "AI λ™μ˜μƒ 생성 λ„κ΅¬μ˜ κ°€λŠ₯μ„±κ³Ό ν•œκ³„λ₯Ό νƒκ΅¬ν•΄λ³΄μ„Έμš”. 창의적인 아이디어λ₯Ό μ‹œκ°ν™”ν•˜λŠ” 방법을 배우고, λ™μ‹œμ— λ”₯페이크 같은 μ•…μš© 사둀에 λŒ€ν•œ λΉ„νŒμ  사고도 ν•¨μ–‘ν•˜μ„Έμš”."
1125
  }
1126
  }
1127
 
@@ -1130,18 +1130,18 @@ class LLMAnalyzer:
1130
  if keyword.lower() in title.lower():
1131
  return template
1132
 
1133
- # κΈ°λ³Έ 뢄석 (쀑고ꡐ생 μˆ˜μ€€)
1134
  return {
1135
- "summary": f"'{title}'와 κ΄€λ ¨λœ μ΅œμ‹  AI 기술 동ν–₯μž…λ‹ˆλ‹€. 인곡지λŠ₯ λΆ„μ•ΌλŠ” λΉ λ₯΄κ²Œ λ°œμ „ν•˜κ³  있으며, μ΄λŸ¬ν•œ 기술 λ³€ν™”λŠ” 우리의 μΌμƒμƒν™œκ³Ό 미래 직업 세계에 큰 영ν–₯을 λ―ΈμΉ  κ²ƒμœΌλ‘œ μ˜ˆμƒλ©λ‹ˆλ‹€. κ΄€λ ¨ 기술의 원리와 μ‚¬νšŒμ  νŒŒκΈ‰νš¨κ³Όλ₯Ό ν•¨κ»˜ μ΄ν•΄ν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€.",
1136
- "significance": "AI 기술의 λ°œμ „μ€ λ‹¨μˆœν•œ 기술 ν˜μ‹ μ„ λ„˜μ–΄ μ‚¬νšŒ, 경제, 윀리적 μΈ‘λ©΄μ—μ„œ λ‹€μ–‘ν•œ λ…Όμ˜λ₯Ό λΆˆλŸ¬μΌμœΌν‚€κ³  μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ λ³€ν™”λ₯Ό μ΄ν•΄ν•˜κ³  λŒ€λΉ„ν•˜λŠ” 것이 미래 μ„ΈλŒ€μ—κ²Œ μ€‘μš”ν•œ μ—­λŸ‰μž…λ‹ˆλ‹€.",
1137
  "impact_level": "medium",
1138
  "impact_text": "쀑간",
1139
- "impact_description": "AI 기술의 λ°œμ „μ€ ꡐ윑, μ·¨μ—…, μ‚°μ—… μ „λ°˜μ— 걸쳐 ꡬ쑰적 λ³€ν™”λ₯Ό κ°€μ Έμ˜¬ 것이며, 이에 λŒ€ν•œ 이해와 μ€€λΉ„κ°€ οΏ½οΏ½οΏ½μš”ν•©λ‹ˆλ‹€.",
1140
- "action": "AI 기술의 κΈ°λ³Έ 원리λ₯Ό ν•™μŠ΅ν•˜κ³ , κ΄€λ ¨ ν”„λ‘œκ·Έλž˜λ°(Python λ“±)μ΄λ‚˜ 데이터 κ³Όν•™ 기초λ₯Ό κ³΅λΆ€ν•΄λ³΄μ„Έμš”. λ˜ν•œ AI μœ€λ¦¬μ™€ μ‚¬νšŒμ  영ν–₯에 λŒ€ν•΄μ„œλ„ λΉ„νŒμ μœΌλ‘œ μ‚¬κ³ ν•˜λŠ” μŠ΅κ΄€μ„ κΈ°λ₯΄μ„Έμš”."
1141
  }
1142
 
1143
  def analyze_model(self, model_name: str, task: str, downloads: int) -> str:
1144
- """ν—ˆκΉ…νŽ˜μ΄μŠ€ λͺ¨λΈ 뢄석 - λͺ¨λΈ μΉ΄λ“œλ₯Ό LLM으둜 쀑고ꡐ생 μˆ˜μ€€ 뢄석"""
1145
 
1146
  # 1. λͺ¨λΈ μΉ΄λ“œ κ°€μ Έμ˜€κΈ°
1147
  model_card = self.fetch_model_card(model_name)
@@ -1152,7 +1152,7 @@ class LLMAnalyzer:
1152
  messages = [
1153
  {
1154
  "role": "system",
1155
- "content": "당신은 쀑고ꡐ생이 이해할 수 있게 AI λͺ¨λΈμ„ μ „λ¬Έμ μ΄λ©΄μ„œλ„ λͺ…ν™•ν•˜κ²Œ μ„€λͺ…ν•˜λŠ” μ „λ¬Έκ°€μž…λ‹ˆλ‹€. ν•œκ΅­μ–΄λ‘œ λ‹΅λ³€ν•˜μ„Έμš”."
1156
  },
1157
  {
1158
  "role": "user",
@@ -1160,12 +1160,12 @@ class LLMAnalyzer:
1160
 
1161
  {model_card}
1162
 
1163
- 이 λͺ¨λΈμ„ 쀑고ꡐ생이 이해할 수 μžˆλ„λ‘ 3-5λ¬Έμž₯으둜 μ„€λͺ…ν•΄μ£Όμ„Έμš”. λ‹€μŒ λ‚΄μš©μ„ ν¬ν•¨ν•˜μ„Έμš”:
1164
- 1. 이 λͺ¨λΈμ΄ 무엇을 ν•˜λŠ”μ§€ (ꡬ체적인 κΈ°λŠ₯)
1165
- 2. μ–΄λ–€ 기술적 νŠΉμ§•μ΄λ‚˜ 강점이 μžˆλŠ”μ§€
1166
- 3. μ‹€μ œλ‘œ μ–΄λ–€ λΆ„μ•Όμ—μ„œ ν™œμš©λ  수 μžˆλŠ”μ§€
1167
 
1168
- μ „λ¬Έ μš©μ–΄λŠ” κ°„λ‹¨νžˆ μ„€λͺ…ν•˜λ©΄μ„œ μ‚¬μš©ν•˜κ³ , 3-5λ¬Έμž₯의 ν•œκ΅­μ–΄λ‘œ μž‘μ„±ν•˜μ„Έμš”."""
1169
  }
1170
  ]
1171
 
@@ -1177,31 +1177,31 @@ class LLMAnalyzer:
1177
  except Exception as e:
1178
  print(f" ⚠️ λͺ¨λΈ 뢄석 LLM 였λ₯˜: {e}")
1179
 
1180
- # 3. Fallback: ν…œν”Œλ¦Ώ 기반 μ„€λͺ… (쀑고ꡐ생 μˆ˜μ€€)
1181
  task_explanations = {
1182
- "text-generation": "μžμ—°μ–΄λ₯Ό μƒμ„±ν•˜λŠ” μ–Έμ–΄ λͺ¨λΈλ‘œ, μ£Όμ–΄μ§„ λ§₯락을 μ΄ν•΄ν•˜κ³  μ΄μ–΄μ§€λŠ” ν…μŠ€νŠΈλ₯Ό 생성",
1183
- "image-to-text": "이미지λ₯Ό λΆ„μ„ν•˜μ—¬ μ‹œκ°μ  λ‚΄μš©μ„ μžμ—°μ–΄λ‘œ μ„€λͺ…ν•˜λŠ” λΉ„μ „-μ–Έμ–΄ λͺ¨λΈ",
1184
- "text-to-image": "ν…μŠ€νŠΈ ν”„λ‘¬ν”„νŠΈλ₯Ό ν•΄μ„ν•˜μ—¬ 이미지λ₯Ό μƒμ„±ν•˜λŠ” ν™•μ‚° λͺ¨λΈ",
1185
- "translation": "λ‹€κ΅­μ–΄ λ²ˆμ—­μ„ μˆ˜ν–‰ν•˜λŠ” μ‹œν€€μŠ€-투-μ‹œν€€μŠ€ λͺ¨λΈ",
1186
- "question-answering": "질문의 λ§₯락을 μ΄ν•΄ν•˜κ³  μ •ν™•ν•œ 닡변을 μΆ”μΆœν•˜λŠ” λͺ¨λΈ",
1187
- "summarization": "κΈ΄ ν…μŠ€νŠΈμ˜ 핡심 λ‚΄μš©μ„ μΆ”μΆœν•˜μ—¬ μš”μ•½ν•˜λŠ” λͺ¨λΈ",
1188
- "text-classification": "ν…μŠ€νŠΈμ˜ 감정, 주제, μΉ΄ν…Œκ³ λ¦¬ 등을 λΆ„λ₯˜ν•˜λŠ” λͺ¨λΈ",
1189
- "token-classification": "개체λͺ… 인식(NER) λ“± 토큰 λ‹¨μœ„ λΆ„λ₯˜λ₯Ό μˆ˜ν–‰ν•˜λŠ” λͺ¨λΈ",
1190
- "fill-mask": "λ¬Έλ§₯을 λΆ„μ„ν•˜μ—¬ λ§ˆμŠ€ν‚Ήλœ 단어λ₯Ό μ˜ˆμΈ‘ν•˜λŠ” μ–Έμ–΄ λͺ¨λΈ"
1191
  }
1192
 
1193
- task_desc = task_explanations.get(task, "νŠΉμ • AI μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” μ „λ¬Έν™”λœ λͺ¨λΈ")
1194
 
1195
  if downloads > 10000000:
1196
- popularity = "맀우 높은 λ‹€μš΄λ‘œλ“œ 수λ₯Ό κΈ°λ‘ν•˜λ©° μ—…κ³„μ—μ„œ κ΄‘λ²”μœ„ν•˜κ²Œ ν™œμš©λ˜κ³  μžˆλŠ”"
1197
  elif downloads > 1000000:
1198
- popularity = "μƒλ‹Ήν•œ λ‹€μš΄λ‘œλ“œ 수λ₯Ό κΈ°λ‘ν•˜λ©° ν™œλ°œνžˆ μ‚¬μš©λ˜κ³  μžˆλŠ”"
1199
  elif downloads > 100000:
1200
- popularity = "λ‹€μˆ˜μ˜ κ°œλ°œμžμ™€ μ—°κ΅¬μžλ“€μ΄ ν™œμš©ν•˜κ³  μžˆλŠ”"
1201
  else:
1202
- popularity = "μƒˆλ‘­κ²Œ μ£Όλͺ©λ°›κ³  μžˆλŠ”"
1203
 
1204
- return f"이 λͺ¨λΈμ€ {task_desc}οΏ½οΏ½λ‹ˆλ‹€. {popularity} λͺ¨λΈλ‘œ, ν—ˆκΉ…νŽ˜μ΄μŠ€ μƒνƒœκ³„μ—μ„œ '{model_name.split('/')[-1]}'λΌλŠ” μ΄λ¦„μœΌλ‘œ μ•Œλ €μ Έ μžˆμŠ΅λ‹ˆλ‹€. κ΄€λ ¨ λΆ„μ•Όμ˜ ν”„λ‘œμ νŠΈλ‚˜ 연ꡬ에 ν™œμš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€."
1205
 
1206
  def analyze_space(self, space_name: str, space_id: str, description: str) -> Dict:
1207
  """ν—ˆκΉ…νŽ˜μ΄μŠ€ 슀페이슀 뢄석 - app.pyλ₯Ό LLM으둜 뢄석"""
@@ -1215,7 +1215,7 @@ class LLMAnalyzer:
1215
  messages = [
1216
  {
1217
  "role": "system",
1218
- "content": "당신은 쀑고ꡐ생이 이해할 수 있게 AI μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ „λ¬Έμ μ΄λ©΄μ„œλ„ λͺ…ν™•ν•˜κ²Œ μ„€λͺ…ν•˜λŠ” μ „λ¬Έκ°€μž…λ‹ˆλ‹€. ν•œκ΅­μ–΄λ‘œ λ‹΅λ³€ν•˜μ„Έμš”."
1219
  },
1220
  {
1221
  "role": "user",
@@ -1223,12 +1223,12 @@ class LLMAnalyzer:
1223
 
1224
  {app_code}
1225
 
1226
- 이 앱을 쀑고ꡐ생이 이해할 수 μžˆλ„λ‘ 3-5λ¬Έμž₯으둜 μ„€λͺ…ν•΄μ£Όμ„Έμš”. λ‹€μŒ λ‚΄μš©μ„ ν¬ν•¨ν•˜μ„Έμš”:
1227
- 1. 이 앱이 ꡬ체적으둜 μ–΄λ–€ κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ”μ§€
1228
- 2. μ–΄λ–€ AI κΈ°μˆ μ΄λ‚˜ 라이브러리λ₯Ό μ‚¬μš©ν•˜λŠ”μ§€
1229
- 3. μ–΄λ–€ λΆ„μ•Όμ—μ„œ ν™œμš© κ°€λŠ₯ν•œμ§€ λ˜λŠ” μ–΄λ–€ 문제λ₯Ό ν•΄κ²°ν•˜λŠ”μ§€
1230
 
1231
- μ „λ¬Έ μš©μ–΄λŠ” κ°„λ‹¨νžˆ μ„€λͺ…ν•˜λ©΄μ„œ μ‚¬μš©ν•˜κ³ , 3-5λ¬Έμž₯의 ν•œκ΅­μ–΄λ‘œ μž‘μ„±ν•˜μ„Έμš”."""
1232
  }
1233
  ]
1234
 
@@ -1261,9 +1261,9 @@ class LLMAnalyzer:
1261
  except Exception as e:
1262
  print(f" ⚠️ 슀페이슀 뢄석 LLM 였λ₯˜: {e}")
1263
 
1264
- # 3. Fallback: ν…œν”Œλ¦Ώ 기반 μ„€λͺ… (쀑고ꡐ생 μˆ˜μ€€)
1265
  return {
1266
- "simple_explanation": f"{space_name}λŠ” μ›Ή 기반 AI 데λͺ¨ ν”Œλž«νΌμœΌλ‘œ, λΈŒλΌμš°μ €μ—μ„œ 직접 μ‹€ν–‰ κ°€λŠ₯ν•œ μΈν„°λž™ν‹°λΈŒ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μž…λ‹ˆλ‹€. λ³„λ„μ˜ μ„€μΉ˜λ‚˜ ν™˜κ²½ μ„€μ • 없이도 μ΅œμ‹  AI λͺ¨λΈμ˜ κΈ°λŠ₯을 ν…ŒμŠ€νŠΈν•˜κ³  μ²΄ν—˜ν•  수 있으며, μ‹€μ‹œκ°„μœΌλ‘œ κ²°κ³Όλ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.",
1267
  "tech_stack": ["Python", "Gradio", "Transformers", "PyTorch"]
1268
  }
1269
 
@@ -1287,13 +1287,14 @@ class AdvancedAIAnalyzer:
1287
  """AI Timesμ—μ„œ 였늘 λ‚ μ§œ λ‰΄μŠ€ 크둀링"""
1288
  print("πŸ“° AI Times λ‰΄μŠ€ μˆ˜μ§‘ 쀑...")
1289
 
 
1290
  urls = [
1291
  'https://www.aitimes.com/news/articleList.html?sc_multi_code=S2&view_type=sm',
1292
  'https://www.aitimes.com/news/articleList.html?sc_section_code=S1N24&view_type=sm'
1293
  ]
1294
 
1295
  all_news = []
1296
- today = datetime.now().strftime('%m-%d')
1297
 
1298
  for url_idx, url in enumerate(urls, 1):
1299
  try:
@@ -1304,28 +1305,54 @@ class AdvancedAIAnalyzer:
1304
  response.raise_for_status()
1305
  response.encoding = 'utf-8'
1306
 
1307
- text = response.text
1308
 
1309
- # μ •κ·œν‘œν˜„μ‹μœΌλ‘œ [제λͺ©](링크) νŒ¨ν„΄ μΆ”μΆœ
1310
- pattern = r'\[([^\]]+)\]\((https://www\.aitimes\.com/news/articleView\.html\?idxno=\d+)\)'
1311
- matches = re.finditer(pattern, text)
 
1312
 
1313
  articles_found = 0
1314
- for match in matches:
1315
  try:
1316
- title = match.group(1).strip()
1317
- link = match.group(2).strip()
 
 
 
 
 
 
 
 
1318
 
1319
- if len(title) < 10:
 
1320
  continue
1321
 
1322
- # λ‚ μ§œ μ°ΎκΈ° (링크 λ’€ 200자 이내)
1323
- pos = match.end()
1324
- nearby_text = text[pos:pos+200]
1325
- date_pattern = r'(\d{2}-\d{2}\s+\d{2}:\d{2})'
1326
- date_match = re.search(date_pattern, nearby_text)
 
 
 
 
 
1327
 
1328
- date_text = date_match.group(1) if date_match else today
 
 
 
 
 
 
 
 
 
 
 
1329
 
1330
  # 였늘 λ‚ μ§œλ§Œ 필터링
1331
  if today not in date_text:
@@ -1341,19 +1368,20 @@ class AdvancedAIAnalyzer:
1341
 
1342
  all_news.append(news_item)
1343
  articles_found += 1
 
1344
  print(f" βœ“ μΆ”κ°€: {title[:60]}... ({date_text})")
1345
 
1346
  except Exception as e:
1347
  continue
1348
 
1349
- print(f" β†’ {articles_found}개 였늘자 기사 발견\n")
1350
- time.sleep(1)
1351
 
1352
  except Exception as e:
1353
  print(f" ⚠️ URL μˆ˜μ§‘ 였λ₯˜: {e}\n")
1354
  continue
1355
 
1356
- # 쀑볡 제거
1357
  unique_news = []
1358
  seen_urls = set()
1359
  for news in all_news:
@@ -1363,7 +1391,7 @@ class AdvancedAIAnalyzer:
1363
 
1364
  print(f"βœ… 총 {len(unique_news)}개 쀑볡 제거된 였늘자 λ‰΄μŠ€\n")
1365
 
1366
- # μ΅œμ†Œ 3개 보μž₯
1367
  if len(unique_news) < 3:
1368
  print("⚠️ λ‰΄μŠ€κ°€ λΆ€μ‘±ν•˜μ—¬ 졜근 μƒ˜ν”Œ μΆ”κ°€\n")
1369
  sample_news = [
@@ -1393,7 +1421,7 @@ class AdvancedAIAnalyzer:
1393
  if sample['url'] not in seen_urls:
1394
  unique_news.append(sample)
1395
 
1396
- return unique_news[:20]
1397
 
1398
  def fetch_huggingface_models(self, limit: int = 30) -> List[Dict]:
1399
  """ν—ˆκΉ…νŽ˜μ΄μŠ€ νŠΈλ Œλ”© λͺ¨λΈ 30개 μˆ˜μ§‘ (μ‹€μ œ API)"""
@@ -1713,7 +1741,7 @@ def health():
1713
  return jsonify({
1714
  "status": "healthy",
1715
  "service": "AI News LLM Analyzer",
1716
- "version": "3.3.0",
1717
  "database": {
1718
  "connected": True,
1719
  "news_count": news_count,
@@ -1742,14 +1770,14 @@ if __name__ == '__main__':
1742
  print(f"""
1743
  ╔════════════════════════════════════════════════════════════╗
1744
  β•‘ β•‘
1745
- β•‘ πŸ€– AI λ‰΄μŠ€ & ν—ˆκΉ…νŽ˜μ΄μŠ€ LLM 뢄석 μ›Ήμ•± v3.3 β•‘
1746
  β•‘ β•‘
1747
  β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
1748
 
1749
  ✨ μ£Όμš” κΈ°λŠ₯:
1750
  β€’ πŸ’Ύ SQLite DB 영ꡬ μŠ€ν† λ¦¬μ§€
1751
  β€’ 🌐 AI Times μ‹€μ‹œκ°„ λ‰΄μŠ€ 크둀링 (2개 μ„Ήμ…˜)
1752
- β€’ πŸ“° λ‰΄μŠ€ 쀑고ꡐ생 μˆ˜μ€€ 뢄석 (3-5쀄 상세 μš”μ•½)
1753
  β€’ πŸ€— ν—ˆκΉ…νŽ˜μ΄μŠ€ νŠΈλ Œλ”© λͺ¨λΈ TOP 30 (λͺ¨λΈ μΉ΄λ“œ 뢄석)
1754
  β€’ πŸš€ ν—ˆκΉ…νŽ˜μ΄μŠ€ νŠΈλ Œλ”© 슀페이슀 TOP 30 (app.py 뢄석)
1755
  β€’ 🧠 Fireworks AI (Qwen3-235B) μ‹€μ‹œκ°„ LLM 뢄석
 
1
  # -*- coding: utf-8 -*-
2
  """
3
+ AI λ‰΄μŠ€ & ν—ˆκΉ…νŽ˜μ΄μŠ€ νŠΈλ Œλ”© LLM 뢄석 μ›Ήμ•± (μ™„μ „νŒ v3.2)
4
  파일λͺ…: app_advanced.py
5
 
6
  μ£Όμš” κΈ°λŠ₯:
 
8
  2. AI Times μ‹€μ‹œκ°„ λ‰΄μŠ€ 크둀링 (2개 μ„Ήμ…˜)
9
  3. μ‹€μ œ Hugging Face Trending API 연동 (λͺ¨λΈ/슀페이슀 30μœ„)
10
  4. Fireworks AI (Qwen3-235B) μ‹€μ‹œκ°„ LLM 뢄석
11
+ - λ‰΄μŠ€ μ΄ˆλ“±ν•™μƒ μˆ˜μ€€ 뢄석
12
  - λͺ¨λΈ μΉ΄λ“œ μžλ™ 뢄석 (README.md)
13
  - 슀페이슀 μ½”λ“œ μžλ™ 뢄석 (app.py)
14
  5. νƒ­ UI (λ‰΄μŠ€/λͺ¨λΈ/슀페이슀)
 
545
  <body>
546
  <div class="container">
547
  <h1>πŸ€– AI λ‰΄μŠ€ & ν—ˆκΉ…νŽ˜μ΄μŠ€ LLM 뢄석</h1>
548
+ <p class="subtitle">μ΄ˆλ“±ν•™μƒλ„ μ΄ν•΄ν•˜λŠ” AI νŠΈλ Œλ“œ 뢄석 μ‹œμŠ€ν…œ πŸŽ“</p>
549
 
550
  <!-- 톡계 μΉ΄λ“œ -->
551
  <div class="stats">
 
676
  </div>
677
 
678
  <div class="space-analysis">
679
+ <strong>πŸŽ“ μ΄ˆλ“±ν•™μƒ μ„€λͺ…:</strong><br>
680
  {{ space.simple_explanation }}
681
  </div>
682
 
 
722
 
723
  <!-- ν‘Έν„° -->
724
  <div class="footer">
725
+ <p>πŸ€– AI λ‰΄μŠ€ LLM 뢄석 μ‹œμŠ€ν…œ v3.2</p>
726
  <p style="margin-top: 10px; font-size: 0.9em;">
727
  πŸ’Ύ SQLite DB 영ꡬ μ €μž₯ | 🌐 AI Times μ‹€μ‹œκ°„ 크둀링 | πŸ€— Hugging Face Trending API | 🧠 Powered by Fireworks AI (Qwen3-235B)
728
  </p>
729
  <p style="margin-top: 10px; font-size: 0.85em; color: #999;">
730
+ 데이터 좜처: AI Times (μ‹€μ‹œκ°„ 크둀링), Hugging Face | μ‹€μ‹œκ°„ 뢄석: Fireworks AI
731
  </p>
732
  </div>
733
  </div>
 
1096
  return None
1097
 
1098
  def analyze_news_simple(self, title: str, content: str = "") -> Dict:
1099
+ """λ‰΄μŠ€ 기사λ₯Ό μ΄ˆλ“±ν•™μƒ μˆ˜μ€€μœΌλ‘œ 뢄석"""
1100
 
1101
  analysis_templates = {
1102
  "μ±—GPT": {
1103
+ "summary": "λ§ˆμ΄ν¬λ‘œμ†Œν”„νŠΈ(MS)λΌλŠ” 큰 νšŒμ‚¬κ°€ μ±—GPTλΌλŠ” AIλ₯Ό λ„ˆλ¬΄ λ§Žμ€ μ‚¬λžŒλ“€μ΄ μ‚¬μš©ν•΄μ„œ, 컴퓨터λ₯Ό λ³΄κ΄€ν•˜λŠ” 큰 건물(데이터센터)이 λΆ€μ‘±ν•˜λ‹€κ³  λ§ν–ˆμ–΄μš”.",
1104
+ "significance": "μ±—GPTκ°€ 정말 인기가 λ§Žλ‹€λŠ” λœ»μ΄μ—μš”. 마치 λ„ˆλ¬΄ λ§Žμ€ μΉœκ΅¬λ“€μ΄ ν•œ κ²Œμž„κΈ°λ₯Ό μ“°λ €κ³  ν•˜λŠ” 것과 λΉ„μŠ·ν•΄μš”.",
1105
  "impact_level": "high",
1106
  "impact_text": "λ†’μŒ",
1107
+ "impact_description": "AI 기술이 λΉ λ₯΄κ²Œ λ°œμ „ν•˜κ³  있고, λ§Žμ€ μ‚¬λžŒλ“€μ΄ μ‚¬μš©ν•˜κ³  μžˆλ‹€λŠ” μ€‘μš”ν•œ μ‹ ν˜Έμ˜ˆμš”.",
1108
+ "action": "μ±—GPT 같은 AI 도ꡬλ₯Ό λ°°μ›Œλ³΄μ„Έμš”. μˆ™μ œλ₯Ό 도와달라고 ν•˜κ±°λ‚˜, λͺ¨λ₯΄λŠ” 것을 λ¬Όμ–΄λ³Ό 수 μžˆμ–΄μš”!"
1109
  },
1110
  "GPU": {
1111
+ "summary": "미ꡭ이 μ•„λžμ—λ―Έλ¦¬νŠΈ(UAE)λΌλŠ” λ‚˜λΌμ— GPUλΌλŠ” νŠΉλ³„ν•œ 컴퓨터 λΆ€ν’ˆμ„ νŒ” 수 있게 ν—ˆλ½ν–ˆμ–΄μš”. GPUλŠ” AIλ₯Ό λ§Œλ“œλŠ” 데 κΌ­ ν•„μš”ν•œ λΆ€ν’ˆμ΄μ—μš”.",
1112
+ "significance": "GPUλŠ” AI의 λ‘λ‡Œ 같은 κ±°μ˜ˆμš”. 이걸 νŒ” 수 있게 되면 더 λ§Žμ€ λ‚˜λΌμ—μ„œ AIλ₯Ό λ§Œλ“€ 수 μžˆμ–΄μš”.",
1113
  "impact_level": "medium",
1114
  "impact_text": "쀑간",
1115
+ "impact_description": "AI 기술이 더 λ§Žμ€ λ‚˜λΌλ‘œ 퍼질 수 있게 λ˜μ—ˆμ–΄μš”.",
1116
+ "action": "컴퓨터가 μ–΄λ–»κ²Œ μž‘λ™ν•˜λŠ”μ§€ 관심을 κ°€μ Έλ³΄μ„Έμš”. GPUκ°€ 무엇인지 κ²€μƒ‰ν•΄λ³΄λŠ” 것도 μ’‹μ•„μš”!"
1117
  },
1118
  "μ†ŒλΌ": {
1119
+ "summary": "μ˜€ν”ˆAIκ°€ λ§Œλ“  'μ†ŒλΌ'λΌλŠ” AI 앱이 μ—„μ²­ λΉ λ₯΄κ²Œ 인기λ₯Ό μ–»μ—ˆμ–΄μš”. 100만 λͺ…이 λ‹€μš΄λ‘œλ“œν•˜λŠ” 데 μ±—GPT보닀 더 λΉ¨λžλŒ€μš”!",
1120
+ "significance": "μ‚¬λžŒλ“€μ΄ λΉ„λ””μ˜€λ₯Ό λ§Œλ“œλŠ” AI에 정말 관심이 λ§Žλ‹€λŠ” λœ»μ΄μ—μš”.",
1121
  "impact_level": "high",
1122
  "impact_text": "λ†’μŒ",
1123
+ "impact_description": "μ•žμœΌλ‘œ λˆ„κ΅¬λ‚˜ μ‰½κ²Œ λ©‹μ§„ λΉ„λ””μ˜€λ₯Ό λ§Œλ“€ 수 있게 될 κ±°μ˜ˆμš”.",
1124
+ "action": "μ†ŒλΌλ₯Ό 써보고, μƒμƒν•œ 것을 λΉ„λ””μ˜€λ‘œ λ§Œλ“€μ–΄λ³΄μ„Έμš”. 창의λ ₯을 λ°œνœ˜ν•  수 μžˆμ–΄μš”!"
1125
  }
1126
  }
1127
 
 
1130
  if keyword.lower() in title.lower():
1131
  return template
1132
 
1133
+ # κΈ°λ³Έ 뢄석
1134
  return {
1135
+ "summary": f"'{title}'λΌλŠ” AI κ΄€λ ¨ λ‰΄μŠ€κ°€ λ‚˜μ™”μ–΄μš”. AI 기술이 계속 λ°œμ „ν•˜κ³  μžˆλ‹€λŠ” μ†Œμ‹μ΄μ—μš”.",
1136
+ "significance": "AIλŠ” 우리 μƒν™œμ„ 더 νŽΈλ¦¬ν•˜κ²Œ λ§Œλ“€μ–΄μ£ΌλŠ” κΈ°μˆ μ΄μ—μš”.",
1137
  "impact_level": "medium",
1138
  "impact_text": "쀑간",
1139
+ "impact_description": "AI 기술의 λ°œμ „μ€ 우리 λ―Έλž˜μ— μ€‘μš”ν•œ 영ν–₯을 쀄 κ±°μ˜ˆμš”.",
1140
+ "action": "AI에 λŒ€ν•΄ 더 μ•Œμ•„λ³΄κ³ , AIλ₯Ό ν™œμš©ν•˜λŠ” 방법을 λ°°μ›Œλ³΄μ„Έμš”!"
1141
  }
1142
 
1143
  def analyze_model(self, model_name: str, task: str, downloads: int) -> str:
1144
+ """ν—ˆκΉ…νŽ˜μ΄μŠ€ λͺ¨λΈ 뢄석 - λͺ¨λΈ μΉ΄λ“œλ₯Ό LLM으둜 뢄석"""
1145
 
1146
  # 1. λͺ¨λΈ μΉ΄λ“œ κ°€μ Έμ˜€κΈ°
1147
  model_card = self.fetch_model_card(model_name)
 
1152
  messages = [
1153
  {
1154
  "role": "system",
1155
+ "content": "당신은 μ΄ˆλ“±ν•™μƒλ„ 이해할 수 있게 AI λͺ¨λΈμ„ μ‰½κ²Œ μ„€λͺ…ν•˜λŠ” μ „λ¬Έκ°€μž…λ‹ˆλ‹€. ν•œκ΅­μ–΄λ‘œ λ‹΅λ³€ν•˜μ„Έμš”."
1156
  },
1157
  {
1158
  "role": "user",
 
1160
 
1161
  {model_card}
1162
 
1163
+ 이 λͺ¨λΈμ„ μ΄ˆλ“±ν•™μƒμ΄ 이해할 수 μžˆλ„λ‘ 3-4λ¬Έμž₯으둜 μ‰½κ²Œ μ„€λͺ…ν•΄μ£Όμ„Έμš”. λ‹€μŒ λ‚΄μš©μ„ ν¬ν•¨ν•˜μ„Έμš”:
1164
+ 1. 이 λͺ¨λΈμ΄ 무엇을 ν•˜λŠ”μ§€
1165
+ 2. μ–΄λ–€ νŠΉμ§•μ΄ μžˆλŠ”μ§€
1166
+ 3. λˆ„κ°€ μ‚¬μš©ν•˜λ©΄ 쒋은지
1167
 
1168
+ 닡변은 λ°˜λ“œμ‹œ 3-4λ¬Έμž₯의 ν•œκ΅­μ–΄λ‘œλ§Œ μž‘μ„±ν•˜μ„Έμš”."""
1169
  }
1170
  ]
1171
 
 
1177
  except Exception as e:
1178
  print(f" ⚠️ λͺ¨λΈ 뢄석 LLM 였λ₯˜: {e}")
1179
 
1180
+ # 3. Fallback: ν…œν”Œλ¦Ώ 기반 μ„€λͺ…
1181
  task_explanations = {
1182
+ "text-generation": "글을 μžλ™μœΌλ‘œ λ§Œλ“€μ–΄μ£ΌλŠ”",
1183
+ "image-to-text": "사진을 보고 μ„€λͺ…을 μ¨μ£ΌλŠ”",
1184
+ "text-to-image": "글을 읽고 그림을 κ·Έλ €μ£ΌλŠ”",
1185
+ "translation": "λ‹€λ₯Έ μ–Έμ–΄λ‘œ λ²ˆμ—­ν•΄μ£ΌλŠ”",
1186
+ "question-answering": "μ§ˆλ¬Έμ— λ‹΅ν•΄μ£ΌλŠ”",
1187
+ "summarization": "κΈ΄ 글을 짧게 μš”μ•½ν•΄μ£ΌλŠ”",
1188
+ "text-classification": "글을 λΆ„λ₯˜ν•΄μ£ΌλŠ”",
1189
+ "token-classification": "단어λ₯Ό λΆ„μ„ν•΄μ£ΌλŠ”",
1190
+ "fill-mask": "λΉˆμΉΈμ„ μ±„μ›Œμ£ΌλŠ”"
1191
  }
1192
 
1193
+ task_desc = task_explanations.get(task, "νŠΉλ³„ν•œ κΈ°λŠ₯을 ν•˜λŠ”")
1194
 
1195
  if downloads > 10000000:
1196
+ popularity = "μ—„μ²­λ‚˜κ²Œ λ§Žμ€"
1197
  elif downloads > 1000000:
1198
+ popularity = "μ•„μ£Ό λ§Žμ€"
1199
  elif downloads > 100000:
1200
+ popularity = "λ§Žμ€"
1201
  else:
1202
+ popularity = "μ–΄λŠ 정도"
1203
 
1204
+ return f"이 λͺ¨λΈμ€ {task_desc} AIμ˜ˆμš”. {popularity} μ‚¬λžŒλ“€μ΄ λ‹€μš΄λ‘œλ“œν•΄μ„œ μ‚¬μš©ν•˜κ³  μžˆμ–΄μš”. {model_name.split('/')[-1]}λΌλŠ” μ΄λ¦„μœΌλ‘œ 유λͺ…ν•΄μš”!"
1205
 
1206
  def analyze_space(self, space_name: str, space_id: str, description: str) -> Dict:
1207
  """ν—ˆκΉ…νŽ˜μ΄μŠ€ 슀페이슀 뢄석 - app.pyλ₯Ό LLM으둜 뢄석"""
 
1215
  messages = [
1216
  {
1217
  "role": "system",
1218
+ "content": "당신은 μ΄ˆλ“±ν•™μƒλ„ 이해할 수 있게 AI μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‰½κ²Œ μ„€λͺ…ν•˜λŠ” μ „λ¬Έκ°€μž…λ‹ˆλ‹€. ν•œκ΅­μ–΄λ‘œ λ‹΅λ³€ν•˜μ„Έμš”."
1219
  },
1220
  {
1221
  "role": "user",
 
1223
 
1224
  {app_code}
1225
 
1226
+ 이 앱을 μ΄ˆλ“±ν•™μƒμ΄ 이해할 수 μžˆλ„λ‘ 3-4λ¬Έμž₯으둜 μ‰½κ²Œ μ„€λͺ…ν•΄μ£Όμ„Έμš”. λ‹€μŒ λ‚΄μš©μ„ ν¬ν•¨ν•˜μ„Έμš”:
1227
+ 1. 이 앱이 무엇을 ν•˜λŠ”μ§€
1228
+ 2. μ–΄λ–€ κΈ°μˆ μ„ μ‚¬μš©ν•˜λŠ”μ§€
1229
+ 3. μ–΄λ–»κ²Œ ν™œμš©ν•  수 μžˆλŠ”μ§€
1230
 
1231
+ 닡변은 λ°˜λ“œμ‹œ 3-4λ¬Έμž₯의 ν•œκ΅­μ–΄λ‘œλ§Œ μž‘μ„±ν•˜μ„Έμš”."""
1232
  }
1233
  ]
1234
 
 
1261
  except Exception as e:
1262
  print(f" ⚠️ 슀페이슀 뢄석 LLM 였λ₯˜: {e}")
1263
 
1264
+ # 3. Fallback: ν…œν”Œλ¦Ώ 기반 μ„€λͺ…
1265
  return {
1266
+ "simple_explanation": f"{space_name}λŠ” μ›ΉλΈŒλΌμš°μ €μ—μ„œ λ°”λ‘œ AIλ₯Ό μ²΄ν—˜ν•΄λ³Ό 수 μžˆλŠ” κ³³μ΄μ—μš”. μ„€μΉ˜ 없이도 μ‚¬μš©ν•  수 μžˆμ–΄μ„œ νŽΈλ¦¬ν•΄μš”! 마치 온라인 κ²Œμž„μ²˜λŸΌ λ°”λ‘œ μ ‘μ†ν•΄μ„œ AIλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹΅λ‹ˆλ‹€.",
1267
  "tech_stack": ["Python", "Gradio", "Transformers", "PyTorch"]
1268
  }
1269
 
 
1287
  """AI Timesμ—μ„œ 였늘 λ‚ μ§œ λ‰΄μŠ€ 크둀링"""
1288
  print("πŸ“° AI Times λ‰΄μŠ€ μˆ˜μ§‘ 쀑...")
1289
 
1290
+ # μˆ˜μ§‘ν•  URL λͺ©λ‘
1291
  urls = [
1292
  'https://www.aitimes.com/news/articleList.html?sc_multi_code=S2&view_type=sm',
1293
  'https://www.aitimes.com/news/articleList.html?sc_section_code=S1N24&view_type=sm'
1294
  ]
1295
 
1296
  all_news = []
1297
+ today = datetime.now().strftime('%m-%d') # 예: '10-10'
1298
 
1299
  for url_idx, url in enumerate(urls, 1):
1300
  try:
 
1305
  response.raise_for_status()
1306
  response.encoding = 'utf-8'
1307
 
1308
+ soup = BeautifulSoup(response.text, 'html.parser')
1309
 
1310
+ # λͺ¨λ“  링크 μ°ΎκΈ°
1311
+ articles = soup.find_all('a', href=re.compile(r'/news/articleView\.html\?idxno=\d+'))
1312
+
1313
+ print(f" β†’ {len(articles)}개 링크 발견")
1314
 
1315
  articles_found = 0
1316
+ for article_tag in articles:
1317
  try:
1318
+ # 제λͺ©κ³Ό 링크
1319
+ title = article_tag.get_text(strip=True)
1320
+ link = article_tag.get('href', '')
1321
+
1322
+ # 링크 μ •κ·œν™”
1323
+ if link and not link.startswith('http'):
1324
+ if link.startswith('/'):
1325
+ link = 'https://www.aitimes.com' + link
1326
+ else:
1327
+ link = 'https://www.aitimes.com/' + link
1328
 
1329
+ # 제λͺ©μ΄ λ„ˆλ¬΄ 짧으면 μŠ€ν‚΅
1330
+ if not title or len(title) < 10:
1331
  continue
1332
 
1333
+ # λΆ€λͺ¨ μš”μ†Œμ—μ„œ λ‚ μ§œ μ°ΎκΈ°
1334
+ parent = article_tag.parent
1335
+ date_text = ''
1336
+
1337
+ # λΆ€λͺ¨μ˜ λͺ¨λ“  ν…μŠ€νŠΈμ—μ„œ λ‚ μ§œ νŒ¨ν„΄ μ°ΎκΈ°
1338
+ if parent:
1339
+ parent_text = parent.get_text()
1340
+ date_match = re.search(r'(\d{2}-\d{2}\s+\d{2}:\d{2})', parent_text)
1341
+ if date_match:
1342
+ date_text = date_match.group(1)
1343
 
1344
+ # λ‚ μ§œκ°€ μ—†μœΌλ©΄ λ‹€μŒ ν˜•μ œ μš”μ†Œλ“€ 확인
1345
+ if not date_text:
1346
+ for sibling in article_tag.find_next_siblings():
1347
+ sibling_text = sibling.get_text()
1348
+ date_match = re.search(r'(\d{2}-\d{2}\s+\d{2}:\d{2})', sibling_text)
1349
+ if date_match:
1350
+ date_text = date_match.group(1)
1351
+ break
1352
+
1353
+ # λ‚ μ§œκ°€ μ—¬μ „νžˆ μ—†μœΌλ©΄ 였늘 λ‚ μ§œ μ‚¬μš©
1354
+ if not date_text:
1355
+ date_text = today
1356
 
1357
  # 였늘 λ‚ μ§œλ§Œ 필터링
1358
  if today not in date_text:
 
1368
 
1369
  all_news.append(news_item)
1370
  articles_found += 1
1371
+
1372
  print(f" βœ“ μΆ”κ°€: {title[:60]}... ({date_text})")
1373
 
1374
  except Exception as e:
1375
  continue
1376
 
1377
+ print(f" β†’ {articles_found}개 였늘자 기사 μˆ˜μ§‘\n")
1378
+ time.sleep(1) # μ„œλ²„ λΆ€ν•˜ λ°©μ§€
1379
 
1380
  except Exception as e:
1381
  print(f" ⚠️ URL μˆ˜μ§‘ 였λ₯˜: {e}\n")
1382
  continue
1383
 
1384
+ # 쀑볡 제거 (URL κΈ°μ€€)
1385
  unique_news = []
1386
  seen_urls = set()
1387
  for news in all_news:
 
1391
 
1392
  print(f"βœ… 총 {len(unique_news)}개 쀑볡 제거된 였늘자 λ‰΄μŠ€\n")
1393
 
1394
+ # μ΅œμ†Œ 3κ°œλŠ” 보μž₯ (μ—†μœΌλ©΄ μƒ˜ν”Œ μΆ”κ°€)
1395
  if len(unique_news) < 3:
1396
  print("⚠️ λ‰΄μŠ€κ°€ λΆ€μ‘±ν•˜μ—¬ 졜근 μƒ˜ν”Œ μΆ”κ°€\n")
1397
  sample_news = [
 
1421
  if sample['url'] not in seen_urls:
1422
  unique_news.append(sample)
1423
 
1424
+ return unique_news[:20] # μ΅œλŒ€ 20개
1425
 
1426
  def fetch_huggingface_models(self, limit: int = 30) -> List[Dict]:
1427
  """ν—ˆκΉ…νŽ˜μ΄μŠ€ νŠΈλ Œλ”© λͺ¨λΈ 30개 μˆ˜μ§‘ (μ‹€μ œ API)"""
 
1741
  return jsonify({
1742
  "status": "healthy",
1743
  "service": "AI News LLM Analyzer",
1744
+ "version": "3.2.0",
1745
  "database": {
1746
  "connected": True,
1747
  "news_count": news_count,
 
1770
  print(f"""
1771
  ╔════════════════════════════════════════════════════════════╗
1772
  β•‘ β•‘
1773
+ β•‘ πŸ€– AI λ‰΄μŠ€ & ν—ˆκΉ…νŽ˜μ΄μŠ€ LLM 뢄석 μ›Ήμ•± v3.2 β•‘
1774
  β•‘ β•‘
1775
  β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
1776
 
1777
  ✨ μ£Όμš” κΈ°λŠ₯:
1778
  β€’ πŸ’Ύ SQLite DB 영ꡬ μŠ€ν† λ¦¬μ§€
1779
  β€’ 🌐 AI Times μ‹€μ‹œκ°„ λ‰΄μŠ€ 크둀링 (2개 μ„Ήμ…˜)
1780
+ β€’ πŸ“° λ‰΄μŠ€ μ΄ˆλ“±ν•™μƒ μˆ˜μ€€ 뢄석
1781
  β€’ πŸ€— ν—ˆκΉ…νŽ˜μ΄μŠ€ νŠΈλ Œλ”© λͺ¨λΈ TOP 30 (λͺ¨λΈ μΉ΄λ“œ 뢄석)
1782
  β€’ πŸš€ ν—ˆκΉ…νŽ˜μ΄μŠ€ νŠΈλ Œλ”© 슀페이슀 TOP 30 (app.py 뢄석)
1783
  β€’ 🧠 Fireworks AI (Qwen3-235B) μ‹€μ‹œκ°„ LLM 뢄석