File size: 3,545 Bytes
1323e14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
from typing import Literal
from openai import OpenAI

_OPENAI_CLIENT = None

def _client() -> OpenAI:
    global _OPENAI_CLIENT
    if _OPENAI_CLIENT is None:
        api_key = os.getenv("OPENAI_API_KEY", "")
        if not api_key:
            raise RuntimeError("OPENAI_API_KEY is not set in Secrets.")
        _OPENAI_CLIENT = OpenAI(api_key=api_key)
    return _OPENAI_CLIENT

TONE_MAP = {
    "neutral": "ニュートラルで事実中心",
    "formal": "フォーマルで簡潔",
    "friendly": "親しみやすく平易",
    "investor": "投資家向け、KPI/財務メトリクスを強調",
    "pr_bold": "PR向け、ヘッドラインを強調し勢いある表現",
}

TYPE_GUIDE = {
    "press_release": "ニュースリリース: タイトル/リード/本文/会社概要/問い合わせ先",
    "ir_letter": "IRレター: タイトル/ご挨拶/ハイライト/今後の見通し/お問い合わせ",
    "investor_summary": "投資家向けサマリー: 3-7箇条書き、KPI・成長要因・リスク要因",
}

SYSTEM_TMPL = """
あなたは日本語のPR/IRライターです。事実の正確性、簡潔さ、再利用しやすいMarkdown構成を重視します。
- 出力は必ずMarkdown。
- センセーショナルすぎる表現や根拠のない主張は避ける。
- プレス/IRのルールに配慮し、誤解を招かない文に整える。
"""

PROMPT_TMPL = """
【目的】{ctype}のドラフトを{tone_ja}で作成。
【入力テキスト要約】以下の素材から、要点を抽出し、{ctype_guide}に沿ってMarkdownドラフトを生成。
---
{source_text}
---
出力要件:
- 1行目に短いタイトル(H1)
- 適切な小見出し(H2/H3)
- 箇条書きは短文で
- ファクトと数値はそのまま
- 最後に「メタデータ」セクションを追加(推奨タグ・要約140字・推奨URLスラッグ)
"""

def generate_draft(source_text: str,
                   content_type: Literal["press_release","ir_letter","investor_summary"],
                   tone: str):
    client = _client()
    tone_ja = TONE_MAP.get(tone, TONE_MAP["neutral"])
    guide = TYPE_GUIDE[content_type]

    messages = [
        {"role": "system", "content": SYSTEM_TMPL},
        {"role": "user", "content": PROMPT_TMPL.format(
            ctype=content_type, tone_ja=tone_ja, ctype_guide=guide,
            source_text=source_text[:12000]
        )}
    ]
    resp = client.chat.completions.create(
        model=os.getenv("OPENAI_MODEL","gpt-4o-mini"),
        temperature=float(os.getenv("OPENAI_TEMPERATURE","0.2")),
        messages=messages,
    )
    text = resp.choices[0].message.content

    subj_resp = client.chat.completions.create(
        model=os.getenv("OPENAI_MODEL","gpt-4o-mini"),
        temperature=0.3,
        messages=[
            {"role":"system","content":"日本語のPRメール件名ライター。50文字以内、事実に忠実。"},
            {"role":"user","content": f"次のMarkdownドラフトから、差分のある件名案を2つ出して。\n---\n{text[:6000]}"},
        ]
    )
    subs = [s.strip("- ・* ") for s in subj_resp.choices[0].message.content.splitlines() if s.strip()]
    subj_a = subs[0] if subs else "お知らせ"
    subj_b = subs[1] if len(subs) > 1 else subj_a + "【続報】"

    title = None
    for line in text.splitlines():
        if line.strip().startswith("# "):
            title = line.strip().lstrip("# ").strip()
            break
    return title or "ドラフト", text, subj_a, subj_b