CDG / app.py
Ryomaaa's picture
Update app.py
52f8cc8 verified
raw
history blame
5.14 kB
import gradio as gr
import pandas as pd
import numpy as np
import os
from openai import OpenAI
# --- OpenAI設定 ---
api_key = os.getenv("OPENAI_API_KEY")
def analyze_cd_logic(m_file, p_file, target_brand):
if not api_key:
return "❌ OpenAI APIキーが設定されていません。Settings > Secretsを確認してください。"
if m_file is None or p_file is None or not target_brand:
return "⚠️ 原紙マスタ、製品マップの両方をアップロードし、銘柄名を入力してください。"
client = OpenAI(api_key=api_key)
try:
# データ読み込み
m_df = pd.read_csv(m_file.name)
if '1' in m_df.columns:
m_df.columns = m_df.iloc[0]
m_df = m_df[1:].reset_index(drop=True)
p_df = pd.read_csv(p_file.name)
if '基礎情報' in p_df.columns:
p_df.columns = p_df.iloc[0]
p_df = p_df[1:].reset_index(drop=True)
# 1. 銘柄特定ロジック
mask = (m_df['親品番'].astype(str) == target_brand) | \
(m_df['銘柄名'].astype(str) == target_brand) | \
(m_df.iloc[:, 2].astype(str) == target_brand)
brand_data = m_df[mask]
if brand_data.empty:
return f"❌ 銘柄「{target_brand}」は見つかりませんでした。"
spec = brand_data.iloc[0]
findings = []
# --- ロジック抽出 ---
# A. 共用銘柄化(単価差)
all_same_parent = m_df[m_df['親品番'] == spec['親品番']].copy()
all_same_parent['price'] = pd.to_numeric(all_same_parent['仕入単価(新)'], errors='coerce')
if all_same_parent['製紙会社'].nunique() > 1:
findings.append(f"【共用銘柄化】同一品番内で単価乖離あり(最大差:{all_same_parent['price'].max() - all_same_parent['price'].min()}円)。安値メーカーへの集約。")
# B. 環境対応(1Gナレッジ)
if str(spec.get('古紙使用フラグ')) == '1':
findings.append("【環境対応見直し】古紙配合品からFSC認証紙へのスペック変更。1G成功事例(▲18M)に基づくコストダウン。")
# C. 一般品化
if '1' in [str(spec.get('特抄フラグ')), str(spec.get('特寸フラグ'))]:
findings.append("【価値の再定義】特抄・特寸仕様を廃止し、汎用JIS規格品へ切り替え。競争環境の再構築。")
# D. 坪量適正化
gram = pd.to_numeric(spec['坪量 g/㎡'], errors='coerce')
if not np.isnan(gram) and gram > 70:
findings.append(f"【仕様変更】現行{gram}g/㎡。製品要件を再定義し薄物化による面積単価低減。")
if not findings:
return "💡 明確な自動判定ロジックに該当する施策が見つかりませんでした。個別交渉を検討してください。"
# OpenAIによる詳細化
prompt = f"""
あなたは調達戦略スペシャリストです。以下の分析結果を、実務的な「CD施策シート」に変換してください。
交渉メール、挨拶、反論対策は一切不要です。論理性と具体的アクションのみを出力してください。
【対象銘柄】: {target_brand} ({spec['製紙会社']} / {spec['仕入単価(新)']}円)
【抽出された事実】:
{"/".join(findings)}
【出力項目】
各項目について以下を記載:
1. 切り口
2. 具体的な方法
3. 現状の課題(データ根拠)
4. 提案内容と期待効果(具体的アクション)
"""
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "system", "content": "論理的な調達分析官として振る舞ってください。"},
{"role": "user", "content": prompt}],
temperature=0.3
)
return response.choices[0].message.content
except Exception as e:
return f"解析エラー: {str(e)}"
# --- Gradio UI ---
with gr.Blocks(title="CDG AI Strategist") as demo:
gr.Markdown("# 🛡️ CDG AI Strategist - 資材1G論理分析")
gr.Markdown("原紙マスタと製品マップから、利益貢献の切り口に基づいた具体的CD案を生成します。")
with gr.Row():
with gr.Column():
m_input = gr.File(label="1. 原紙マスタ(CSV)をアップロード")
p_input = gr.File(label="2. 製品マップ(CSV)をアップロード")
brand_input = gr.Textbox(label="3. 分析対象の銘柄名を入力", placeholder="例: Jウメ70AC")
btn = gr.Button("分析実行", variant="primary")
with gr.Column():
output = gr.Markdown(label="CD施策詳細レポート")
btn.click(fn=analyze_cd_logic, inputs=[m_input, p_input, brand_input], outputs=output)
# HuggingFace用の起動設定
if __name__ == "__main__":
demo.launch()