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())