| import gradio as gr |
| from google import genai |
| import time |
| import os |
|
|
| |
| 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 |
|
|
| |
| |
|
|
| log_output = "🚀 投資インサイト解析を開始します...\n" |
| yield log_output |
|
|
| try: |
| |
| 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 |
|
|
| |
| 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 |
|
|
| |
| 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)}" |
|
|
| |
| 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()) |