AII / app.py
lune-lune's picture
Upload 4 files
9ea7f70 verified
import gradio as gr
from google import genai
import time
import os
# 外部ファイルの読み込み(news_collector.py と ai_analyst.py が同じ場所にある前提)
from news_collector import fetch_rss_news
from ai_analyst import select_and_analyze_batch
from datetime import datetime
import pytz
def run_insight_process(api_key):
"""
ニュース取得から解析までを順次実行し、ログをリアルタイムで画面に返す関数
"""
if not api_key or len(api_key) < 10:
yield "❌ エラー: 有効なGemini APIキーをサイドバーに入力してください。"
return
# 新しいSDKではClientを渡す形が望ましい
# 新しいSDKではClientを渡す形が望ましいが、既存の構成を尊重して環境変数経由にする
log_output = "🚀 投資インサイト解析を開始します...\n"
yield log_output
try:
# 1. ニュース収集
log_output += "📡 ニュースサイトから最新記事を収集中...\n"
yield log_output
articles = fetch_rss_news()
if not articles:
yield log_output + "❌ ニュースの取得に失敗したか、記事が見つかりませんでした。"
return
log_output += f"✅ {len(articles)}件のニュースを取得しました。AIが「最も意外性の高い」5件を厳選し、一括で解析します...\n"
yield log_output
# 2. AIによる選別・一括解析
analyzed_articles = select_and_analyze_batch(articles, api_key, limit=5)
if not analyzed_articles:
yield log_output + "❌ 解析結果の取得に失敗しました。"
return
log_output += f"✨ AIが厳選した{len(analyzed_articles)}件のレポートを生成します。\n\n"
yield log_output
# 3. レポート表示
for article in analyzed_articles:
res = article.get("analysis", {})
try:
score = int(res.get('market_impact_score', 0))
except:
score = 0
# スコアに応じたアイコン
if score > 0:
icon = "📈"
score_display = f"+{score}"
elif score < 0:
icon = "📉"
score_display = f"{score}"
else:
icon = "➖"
score_display = "0"
now = datetime.now(pytz.timezone('Asia/Tokyo')).strftime('%Y-%m-%d %H:%M:%S')
report = f"===== 【分析結果】 {icon} スコア: {score_display} / 10 =====\n"
report += f"■ タイトル: {article['title']}\n"
report += f"■ 情報元: {article['source']} (取得: {now})\n"
report += f"■ 歴史的類似性:\n{res.get('historical_precedent', '情報なし')}\n\n"
report += f"■ 警戒すべきリスク/弱気視点:\n"
bearish = res.get('bearish_view', [])
if isinstance(bearish, list):
for r in bearish:
report += f" ・{str(r)}\n"
else:
report += f" ・{str(bearish)}\n"
report += f"\n■ 影響セクター:\n"
sectors = res.get('sector_impact', [])
if isinstance(sectors, list):
report += f"{', '.join([str(s) for s in sectors])}\n"
else:
report += f"{str(sectors)}\n"
report += "==========================================\n\n"
log_output += report
yield log_output
log_output += "🎉 すべての解析作業が完了しました(一括実行)"
yield log_output
except Exception as e:
yield log_output + f"\n❌ システムエラーが発生しました: {str(e)}"
# --- Gradio UIのデザイン ---
with gr.Blocks() as demo:
gr.Markdown("""
# 📈 AI投資インサイト・アナライザー
最新の経済ニュースを取得し、Gemini 2.5 Flashが投資判断を21段階でスコアリングします。
""")
with gr.Sidebar():
gr.Markdown("### 設定")
api_input = gr.Textbox(
label="1. Gemini API Key",
type="password",
placeholder="AI Studioのキーを貼り付け"
)
start_btn = gr.Button("解析実行", variant="primary")
gr.Markdown("---")
gr.Markdown("[APIキーの取得はこちら(無料)](https://aistudio.google.com/app/apikey)")
# 実行ログ兼レポート表示エリア
status_log = gr.Textbox(
label="実行ログおよび詳細レポート",
lines=30,
interactive=False
)
# ボタンクリック時の動作
start_btn.click(
fn=run_insight_process,
inputs=[api_input],
outputs=status_log
)
# アプリの起動
if __name__ == "__main__":
demo.launch(theme=gr.themes.Soft())