File size: 6,065 Bytes
cf7f643
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import os
from src.clients.llm_client import LLMClient
import json 
import pandas as pd
from pydantic import BaseModel, Field
from enum import Enum
import base64
from io import BytesIO
from PIL import Image
from typing import List, Optional
from functools import cache
from datetime import datetime
import pytz
from src.utils.tracer import customtracer
from src.models.common import model

def _ask_raw_hf(messages, model, response_format=None):
    """Compatibility wrapper: routes OpenAI-style messages through HF LLMClient."""
    from src.clients.llm_client import LLMClient
    import json as _json

    client = LLMClient()
    system_prompt = None
    user_text = ""
    images = []
    for msg in messages:
        role = msg.get("role", "")
        c = msg.get("content", "")
        if role == "system":
            if isinstance(c, str):
                system_prompt = c
        elif role == "user":
            if isinstance(c, str):
                user_text = c
            elif isinstance(c, list):
                for part in c:
                    if isinstance(part, dict):
                        if part.get("type") == "text":
                            user_text += part.get("text", "")
                        elif part.get("type") == "image_url":
                            url = part.get("image_url", {}).get("url", "")
                            if url.startswith("data:"):
                                images.append(url.split(",", 1)[1] if "," in url else url)
                            else:
                                images.append(url)

    if response_format is not None and hasattr(response_format, "model_json_schema"):
        result = client.call(
            prompt=user_text,
            schema=response_format,
            model=model,
            system_prompt=system_prompt,
            images=images if images else None,
            temperature=0,
        )
        return _json.dumps(result.model_dump(), ensure_ascii=False)
    else:
        return client.call_raw(
            prompt=user_text,
            model=model,
            system_prompt=system_prompt,
            images=images if images else None,
        )


"""
class FVinfo(BaseModel):
    メインコピ�E: list[str]
    サブコピ�E: list[str]
    ビジュアル: list[str]
    権威付け: list[str]
    CTA: list[str]
"""

class Meta(BaseModel):
    会社吁E str
    業畁E str
    ブランチE str
    サービス: str
    啁E��: str
    タイトル: str
    訴求テーチE list[str]

class Font(str, Enum):
    font1 = "ゴシチE��"
    font2 = "明朝"
    font3 = "手書ぁE

class EvsF(str, Enum):
    EMOTIONAL = "惁E��E
    FUNCTIONAL = "機�E"

class PvsS(str, Enum):
    PROBLEM = "問題提起"
    SOLUTION = "課題解決"

class Copy(BaseModel):
    text: str
    font: Font
    color: str
    visual: str
    appeal_mode : EvsF
    forcus_stage : PvsS

class CatchCopy(BaseModel):
    main_copy: list[Copy]
    sub_copy: list[Copy]

class FVinfo(BaseModel):
    非LP: bool
    メタ: Meta
    キャチE��コピ�E: CatchCopy
    権威付け: list[str]
    ビジュアル: list[str]
    CTAボタン: list[str]

def get_openai_request(messages, format):
    client = LLMClient()
    response = _ask_raw_hf([{"role":"user","content":p}], model,
        model="meta-llama/Llama-3.3-70B-Instruct",
        messages=messages,
        top_p=1,
        frequency_penalty=0,
        presence_penalty=0,
        response_format=format,
        temperature=0
    )
    return response

@customtracer
def format2fvinfo(p, openai_key=os.environ.get('OPENAI_KEY')):
    """
    input1 (text): ■自社: 親子でのスマ�E料��節紁E親子でのお得感 チE�Eタの余剰利用 通話とネット�Eコストパフォーマンス スマ�EチE��ュー支援 家族向け�E安�E機�E 豊富な端末ラインアチE�E ■競合他社: 22歳までのお得なプラン	大好評�Eサービス	親子でお得にスマ�Eを利用	22歳以下限定�Eお得なキャンペ�Eン	学生向け�Eお得さ 青春年齢向けのお得なプラン	低価格で高品質な通信サービス	格安SIMとスマ�Eの利便性	22歳以下限定�E割引キャンペ�Eン	スマ�EチE��ュー応援 家族割引との絁E��合わせでの最安値	料��プランの多様性	親子でのお得な割引サービス	スマ�EチE��ューのお得さ	特別割弁EチE�Eタ3GB提侁E割引サービスによるコスト削渁E新規契紁E��プラン変更による特典	機種代と基本料�Eダブル割弁E大容量データ エントリー制の特典シスチE��	24時間ぁE��でもオンラインで手続き可能	家族�E員が割引を受けられるサービス	家族間の無料通話サービス	プライムビデオ特典 22歳までの長期利用可能	製品ラインナップ�E允E��E期間限定�Eキャンペ�Eン	人気スマ�Eの割引販売	安�E教育サービス 話題�Eスマ�Eが安く手に入めE詳細なサポ�EトとFAQ	シンプルな料��プラン	家族�E員の料��割弁E子育てサポ�Eトサービス   業界トレンド:「◯◯◯◯◯」「◯◯◯◯◯」「◯◯◯◯◯」が吁E��共通する訴求コンチE��チE��ある、E60字程度)
    input2 (text): default
    output1 (json): 頁E��
    """
    print(datetime.now(pytz.timezone('Asia/Tokyo')).strftime("%Y-%m-%d %H:%M:%S"), __name__)
    if openai_key == "default":
        os.environ['OPENAI_API_KEY'] = os.environ.get('OPENAI_KEY')
    else:
        os.environ['OPENAI_API_KEY'] = openai_key
    
    messages=[
        {
        "role": "system",
        "content": """提供したフォーマットデータから、忁E��なファーストビューの要素を生成してください、E"",
        },
        {
        "role": "user",
        "content":  [{"type": "text", "text":p}]
        },
    ]
    
    return get_openai_request(messages, FVinfo)