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)