import gradio as gr import pandas as pd import numpy as np from sklearn.ensemble import RandomForestClassifier import cohere from dotenv import load_dotenv import os load_dotenv(verbose=True) # CohereのAPIキーを取得 cohere_api_key = os.environ.get("COHERE_API_KEY") client = cohere.ClientV2(api_key=cohere_api_key) template = """ Executive Report - Liquid Glass Edition
Quarterly Report 2024

マーケティング戦略
進捗報告書

社外秘

💡 Key Insight

過去3ヶ月の施策により、リード獲得コストは25%削減されました。 次四半期は、現在のLiquid Glassデザインを導入したLPのABテストを強化し、CVRの更なる向上を目指します。

総リード数 1,240 +12%
CPA(獲得単価) ¥4,200 -8%
成約率 4.8% +1.2%

今後の重点施策

市場のトレンドは「視覚的な透明感」と「信頼性」の両立に移行しています。 本報告書で採用しているデザインコンセプトは、ユーザーに清潔感とモダンな印象を与え、滞在時間の延長に寄与します。

""" meta_prompt = ''' 思考のガイドライン 文脈の理解: ユーザーの意図、背景、制約条件を正確に把握してください。 推論の先行: 結論を出す前に、必ず「なぜその結論に至るのか」という思考のプロセスを記述してください。 多角的視点: 表面的な回答だけでなく、潜在的な課題や代替案、リスクについても考慮してください。 論理的整合性: ステップ間のつながりを明確にし、矛盾がないかセルフチェックを行ってください。 実行ステップ 1. タスクの分解と分析 実行すべきタスクを最小単位の要素に分解してください。 必要な情報、使用すべきトーン、守るべきルールを明確にします。 2. 推論と戦略立案(Reasoning) 結論に至るまでの論理的な道筋を立ててください。 複数のアプローチがある場合は、最も適切なものを選択した理由を明記してください。 計算や複雑な論理が必要な場合は、ここでステップバイステップで展開してください。 3. 検証と洗練 生成した解決策が、すべての制約条件を満たしているか確認してください。 より簡潔に、あるいはより強力にできる部分を修正してください。 出力形式 以下の構造で回答してください。 推論プロセス(Reasoning) [タスクの分析、論理的な思考、解決までのステップを詳細に記述してください。] 最終回答(Conclusion/Result) [推論に基づいた最終的な成果物を出力してください。形式はタスクに応じて最適化してください(JSON、マークダウン、文章など)。] ''' # ========================================== # 1. 専門家分析・ガイドライン データベース (6,000文字級) # ========================================== ADVISORY_DB = { "STRATEGIC_HEADER": "# 🏛️ 戦略的組織防衛・人事アドバイザリー・フルレポート\n**本レポートは、AI予測に基づき、経営心理学と労務リスク管理の観点から生成されました。**\n---\n", "GUIDELINE": """ ## 📘 専門家による対応ガイドライン 離職予兆を検知した際、人事が取るべき行動指針は以下の通りです。 1. **「評価」ではなく「共感」の対話:** 離職を検討している層は、組織への不信感を抱いています。詰問ではなく「あなたの状況を心配している」というメッセージを優先してください。 2. **制度の弾力的運用:** 介護や育児、心身の不調など、個別の事情に合わせた「特別措置(特例のリモート、短時間勤務等)」を即断で提示することが、最強のリテンションになります。 3. **心理的安全性の担保:** 相談内容が査定に影響しないことを明確に約束し、本音を引き出してください。 """, "FINANCIAL_IMPACT": """ ## 💰 離職に伴う経済的インパクト予測(推定損失額) 対象者が離職した場合、組織には以下の経済的損失が発生します。 1. **直接的損失(採用・教育費):** 年収の約35%〜50%(エージェント手数料、媒体費、面接工数)。 2. **生産性の空白期間:** 後任が前任者と同等のパフォーマンスを発揮するまでの4〜6ヶ月間の給与相当額。 3. **ナレッジ・ロス:** 担当顧客との関係、業務ノウハウ、およびチームの士気低下による「連鎖離職」の潜在的リスク。 **【結論】推定損失合計:年収の1.5倍〜2.2倍。** 本レポートの提言を実行することは、経営上、極めて合理的な投資です。 """ } # ========================================== # 2. モデルの学習(すべての入力を整数として定義) # ========================================== def train_mega_model(): np.random.seed(42) # 項目名とそれぞれの整数の範囲 feature_config = { '仕事の満足度(0-10)': (0, 10), '上司への満足度(0-10)': (0, 10), '月間総労働時間(h)': (140, 350), '先月の残業時間(h)': (0, 150), '勤続年数': (0, 40), '昇進からの経過年数': (0, 20), '年間研修受講時間(h)': (0, 200), '通勤時間(片道分)': (0, 180), 'リモートワーク比率(0-100%)': (0, 100), '週の面談回数': (0, 10), '給与ランク(1-10)': (1, 10), '賞与評価(0-10)': (0, 10), 'チームの一体感(0-10)': (0, 10), '年齢': (20, 70), '扶養家族数': (0, 5) } feature_names = list(feature_config.keys()) n_samples = 5000 # 整数データの生成 data = {f: np.random.randint(low, high + 1, n_samples) for f, (low, high) in feature_config.items()} df = pd.DataFrame(data) # 離職ロジック(整数値に基づいた重み付け) def churn_logic(row): score = 0 if row['仕事の満足度(0-10)'] <= 3: score += 0.5 if row['先月の残業時間(h)'] >= 60: score += 0.4 if row['上司への満足度(0-10)'] <= 3: score += 0.4 if row['昇進からの経過年数'] >= 5: score += 0.2 return 1 if score > 0.7 else 0 df['target'] = df.apply(churn_logic, axis=1) X = df[feature_names] y = df['target'] model = RandomForestClassifier(n_estimators=100, random_state=42).fit(X, y) return model, feature_names model, feature_names = train_mega_model() # ========================================== # 3. レポート生成エンジン(個別所見 & 専門家分析) # ========================================== def generate_individual_findings(d): findings = "## 📋 入力データに基づく個別所見(精密分析)\n" if d['仕事の満足度(0-10)'] <= 3: findings += f"⚠️ **モチベーション低下:** 満足度スコアが極めて低いです({d['仕事の満足度(0-10)']}/10)。現職務への適性再確認が必要です。\n" if d['先月の残業時間(h)'] >= 45: findings += f"⚠️ **過重労働リスク:** 残業時間({d['先月の残業時間(h)']}h)が危険域です。メンタル不調による突発的離職を防ぐため、即時の業務調整を。\n" if d['上司への満足度(0-10)'] <= 3: findings += f"⚠️ **人間関係の不全:** 上司との関係({d['上司への満足度(0-10)']}/10)が最大の離職リスクです。指示系統の変更を検討してください。\n" if d['昇進からの経過年数'] >= 5: findings += f"⚠️ **キャリア停滞感:** 5年以上昇進がないことで、組織内での未来に限界を感じています。\n" if d['通勤時間(片道分)'] >= 60 and d['リモートワーク比率(0-100%)'] <= 20: findings += f"⚠️ **環境負荷:** 長距離通勤と低いリモート率が私生活を圧迫しています。\n" if not any("⚠️" in s for s in findings.split('\n')): findings += "✅ **良好な傾向:** 現在の入力値において、深刻な離職リスクを押し上げる単一要因は見当たりません。\n" return findings def generate_expert_analysis(prob): analysis = "## 🔍 専門家による多角的分析\n" if prob > 0.7: analysis += "**【判定:緊急離脱状態】** 対象者は既に「心理的契約」を解除しています。引き止めよりも、まずは本音を吐き出させる「デトックス面談」を優先してください。\n" elif prob > 0.4: analysis += "**【判定:揺らぎ状態】** 他社からの誘いや、現状への疑問が芽生えています。今、具体的な改善策を提示すれば定着に繋がります。\n" else: analysis += "**【判定:安定維持】** 組織へのコミットメントは高いですが、定期的な1on1を怠らず、小さな変化を見逃さないでください。\n" return analysis # ========================================== # 4. メイン関数(UserWarning解消 & レポート構築) # ========================================== def generate_advisory_report(*args): # すべての入力を整数として扱う args_int = [int(a) for a in args] input_df = pd.DataFrame([args_int], columns=feature_names) prob = model.predict_proba(input_df)[0][1] d = dict(zip(feature_names, args_int)) report = ADVISORY_DB["STRATEGIC_HEADER"] report += f"## 🏆 総合評価:離職予測確率 {prob*100:.1f}%\n\n" report += generate_individual_findings(d) report += generate_expert_analysis(prob) report += ADVISORY_DB["GUIDELINE"] report += ADVISORY_DB["FINANCIAL_IMPACT"] full_prompt = f"{meta_prompt}に基づいて{report}を分析して、最終評価を{template}に基づいてHTML形式で出力してください。回答が見つからない場合は、ウェブで検索して{meta_prompt}に基づいて必ず、{template}に基づいてHTML形式で回答してください。" # Cohere APIの呼び出し response = client.chat( model="command-a-03-2025", messages=[ {"role": "user", "content": full_prompt} ] ) myresp = response.message.content[0].text if '```html' in myresp: part1 = myresp.find('```html') part2 = myresp.rfind('```') reasoning_part = myresp[:part1].strip() html_part = myresp[part1+7:part2].strip() else: # Markdownタグがない場合のフォールバック reasoning_part = "HTMLタグが見つかりませんでした。全文を表示します。" html_part = myresp prevbody = report + '\n\n' + reasoning_part return prevbody, html_part, "Powered by RYH International." # ========================================== # 5. Gradio UI (すべて整数入力) # ========================================== with gr.Blocks(theme=gr.themes.Soft(), title="HR Advisory Platform", css="footer {visibility: hidden;}") as demo: gr.Markdown("# 🏢 組織・人事評価 統合アドバイザリー (AI版)") with gr.Row(): with gr.Column(scale=1): gr.Markdown("### 📊 従業員データ入力") inputs = [] for f in feature_names: if '0-10' in f or '1-10' in f: inputs.append(gr.Slider(0, 10, 5, step=1, label=f)) elif '0-100%' in f: inputs.append(gr.Slider(0, 100, 20, step=1, label=f)) elif 'h' in f or '年' in f or '分' in f or '歳' in f or '数' in f or '回' in f: inputs.append(gr.Number(value=0, precision=0, label=f)) else: inputs.append(gr.Number(value=0, precision=0, label=f)) btn = gr.Button("🔍 統合レポートを生成", variant="primary") with gr.Column(scale=2): output = gr.Markdown(show_copy_button=True) html_output = gr.HTML() ip_right = gr.Textbox(label="IP Information", interactive=False) btn.click(generate_advisory_report, inputs=inputs, outputs=[output, html_output, ip_right]) demo.launch(favicon_path="favicon.ico")