File size: 5,381 Bytes
ff7d898
 
b32e168
dbd0a1f
b32e168
dbd0a1f
5621a82
dbd0a1f
 
5621a82
dbd0a1f
 
5621a82
 
 
 
 
 
 
 
 
 
b32e168
 
 
ff7d898
b32e168
 
 
ff7d898
b32e168
ff7d898
b32e168
 
ff7d898
b32e168
ff7d898
b32e168
 
ff7d898
 
b32e168
 
 
 
ff7d898
 
 
 
 
 
 
 
 
 
 
b32e168
 
ff7d898
b32e168
 
 
 
 
 
 
 
 
ff7d898
b32e168
 
 
 
ff7d898
 
b32e168
 
 
 
 
 
 
 
 
 
 
ff7d898
b32e168
 
ff7d898
b32e168
 
ff7d898
b32e168
ff7d898
 
b32e168
ff7d898
 
 
b32e168
ff7d898
 
 
 
 
b32e168
 
ff7d898
b32e168
 
ff7d898
 
 
b32e168
 
 
 
ff7d898
 
 
 
b32e168
 
ff7d898
b32e168
ff7d898
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import os
import io
import time
import sys
import gradio as gr

# --- Ensure we can import modules whether it's a package or a plain folder ---
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
MODULES_DIR = os.path.join(BASE_DIR, "modules")
if os.path.isdir(MODULES_DIR) and MODULES_DIR not in sys.path:
    sys.path.insert(0, MODULES_DIR)

try:
    # Prefer package-style if modules/__init__.py exists
    from modules.text_processing import process_text
    from modules.pptx_builder import build_presentation
    from modules.utils import safe_hex_to_rgb, ensure_tmpdir
except ModuleNotFoundError:
    # Fallback: flat imports from ./modules added to sys.path
    from text_processing import process_text
    from pptx_builder import build_presentation
    from utils import safe_hex_to_rgb, ensure_tmpdir

APP_NAME = "Auto-PPT Generator"


def generate_pptx(long_text: str,
                  title: str,
                  theme_hex: str,
                  logo_file,
                  add_summary: bool,
                  add_tables: bool,
                  add_charts: bool,
                  use_inference_api: bool,
                  summarizer_model: str,
                  generator_model: str,
                  max_summary_words: int):
    if not long_text or not long_text.strip():
        raise gr.Error("入力テキストが空です。長文を貼り付けてください。")

    theme_rgb = safe_hex_to_rgb(theme_hex or "#3B82F6")

    # Read logo (optional)
    logo_bytes = None
    if logo_file is not None:
        try:
            if hasattr(logo_file, "read"):
                logo_bytes = logo_file.read()
            elif hasattr(logo_file, "name") and logo_file.name:
                with open(logo_file.name, "rb") as f:
                    logo_bytes = f.read()
        except Exception:
            logo_bytes = None

    # Step 1–3: NLP pipeline (summary, sections, bullets, tables, chart data)
    result = process_text(
        text=long_text,
        use_inference_api=use_inference_api,
        summarizer_model=summarizer_model,
        generator_model=generator_model,
        want_summary=add_summary,
        want_tables=add_tables,
        want_charts=add_charts,
        max_summary_words=max_summary_words,
    )

    # Step 4: Build PPTX
    ensure_tmpdir()
    timestamp = time.strftime('%Y%m%d-%H%M%S')
    out_path = f"/tmp/auto_ppt_{timestamp}.pptx"

    build_presentation(
        output_path=out_path,
        title=(title or "Auto-PPT"),
        theme_rgb=theme_rgb,
        logo_bytes=logo_bytes,
        executive_summary=result.get("summary"),
        sections=result.get("sections", []),
        bullets_by_section=result.get("bullets", {}),
        tables=result.get("tables", []),
        charts=result.get("charts", []),
    )

    # Return file path for download
    return out_path


def ui():
    with gr.Blocks(title=APP_NAME) as demo:
        gr.Markdown(f"# {APP_NAME}\n長文→要約→セクション分割→箇条書き/表/図→**PPTX出力** まで自動化")
        with gr.Row():
            with gr.Column(scale=2):
                long_text = gr.Textbox(label="長文テキスト (貼り付け)", lines=20, placeholder="ここに文章を貼り付け…")
                title = gr.Textbox(label="タイトル", value="自動生成スライド")
                theme_hex = gr.Textbox(label="ブランドカラー HEX", value="#3465A4")
                logo = gr.File(label="ロゴ (任意, PNG/JPG)")
                with gr.Row():
                    add_summary = gr.Checkbox(value=True, label="要約スライドを追加")
                    add_tables = gr.Checkbox(value=True, label="表を抽出して追加")
                    add_charts = gr.Checkbox(value=True, label="チャートを生成して追加")
            with gr.Column(scale=1):
                gr.Markdown("### モデル設定")
                use_inference_api = gr.Checkbox(value=False, label="Hugging Face Inference API を使用")
                summarizer_model = gr.Textbox(label="要約モデル (local or API)", value="sshleifer/distilbart-cnn-12-6")
                generator_model = gr.Textbox(label="生成モデル (API推奨, 任意)", value="")
                max_summary_words = gr.Slider(50, 600, value=200, step=10, label="要約の最大語数(目安)")
                generate = gr.Button("PPTXを生成", variant="primary")
                output_file = gr.File(label="ダウンロード")

        generate.click(
            fn=generate_pptx,
            inputs=[long_text, title, theme_hex, logo, add_summary, add_tables, add_charts,
                    use_inference_api, summarizer_model, generator_model, max_summary_words],
            outputs=[output_file],
        )

        gr.Markdown("""
        **Tips**
        - 日本語要約には `sonoisa/t5-base-japanese` を推奨(`text2text-generation`)。
        - Inference API を使う場合は、Space の Secrets に `HF_TOKEN` を設定してください。
        - チャートは `Label: 123` 形式の行を自動検出して棒グラフを作成します。
        """)
    return demo


if __name__ == "__main__":
    demo = ui()
    # Spaces は自動でバインドされますが、ローカル互換のため指定可能
    demo.queue().launch(server_name="0.0.0.0", server_port=int(os.getenv("PORT", "7860")))