import os from src.clients.llm_client import LLMClient import json import base64 from io import BytesIO from PIL import Image import re from pydantic import BaseModel import numpy as np from enum import Enum from datetime import datetime import pytz from src.utils.tracer import customtracer 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, ) """ EC用のバリアント生成API baseimg2ecinfo_rect.pyのpageInfo構造に準拠 """ class Category(str, Enum): ビジネス = "ビジネス�E�EaaS・法人支援�E�E ヘルスケア = "ヘルスケア�E�美容・健康�E�E ヒューマンリソース = "ヒューマンリソース�E�求人・紹介!E コマ�Eス = "コマ�Eス�E�趣味・食品・衣類!E ファイナンス = "ファイナンス�E���融�E保険・不動産�E�E インフラ = "インフラ�E�電気�E通信・ガス・住屁E��E ライフイベンチE= "ライフイベント(教育・結婚�E相諁E��E class CategoryMiddle(str, Enum): # ビジネス ITソフトウェア = "IT・ソフトウェア" マ�Eケ支援コンサル = "マ�Eケ支援・コンサル" オフィス機器用品E= "オフィス・機器用品E # ヘルスケア 健康食品器具 = "健康食品・器具" 美容医療クリニック = "美容・医療クリニック" 美容コスメ = "美容コスメ" フィチE��ネスジム = "フィチE��ネスジム" # ヒューマンリソース 求人惁E�� = "求人惁E��" 人材紹仁E= "人材紹仁E 人材派遣 = "人材派遣" # コマ�Eス 動画アニメゲーム = "動画・アニメ・ゲーム" リユースリサイクル = "リユース・リサイクル" 旁E���EチE��レジャー = "旁E���Eホテル・レジャー" 趣味交隁E= "趣味・交隁E 新聞雑誌メチE��ア = "新聞�E雑誌�E惁E��メチE��ア" 自動車レンタカー用品E= "自動車�Eレンタカー・用品E 飲料食品生活用品E= "飲料食品・生活用品E 家電パソコン = "家電・パソコン" ファチE��ョン = "ファチE��ョン" # ファイナンス 不動産 = "不動産" 保険 = "保険" ローン = "ローン" クレカ電子決渁E= "クレカ・電子決渁E 証券FX先物 = "証券・FX・先物" 銀衁E= "銀衁E # インフラ ネット通信サービス = "ネット�E通信サービス" 電気ガス = "電気�Eガス" 住宁E��備リフォーム = "住宁E��備�Eリフォーム" # ライフイベンチE 士業相諁E= "士業・相諁E 学習スクール = "学習�Eスクール" 結婚�E会い = "結婚�E出会い" 葬儀墓地 = "葬儀・墓地" 引越し介護 = "引越し・介護" class Meta(BaseModel): 会社吁E str 業畁E Category 中刁E��E CategoryMiddle サービス: str 啁E��: str タイトル: str 訴求テーチE list[str] class cood(BaseModel): x: int y: int class str_with_rect(BaseModel): text: str html: str rect: list[cood] class pageInfo(BaseModel): # ペ�Eジ共送E メタ: Meta ロゴ: list[str_with_rect] グローバル検索バ�E: list[str_with_rect] ハンバ�Eガーメニューアイコン: list[str_with_rect] カートアイコン: list[str_with_rect] ユーザーメニュー: list[str_with_rect] # ナビゲーション ブレチE��クラム: list[str_with_rect] ペ�Eジネ�Eション: list[str_with_rect] タブ�E替: list[str_with_rect] # トップ�Eージ メインビジュアル: list[str_with_rect] プロモーションバナー: list[str_with_rect] カチE��リカーチE list[str_with_rect] # 啁E��一覧ペ�Eジ 啁E��一覧: list[str_with_rect] フィルタ: list[str_with_rect] ソーチE list[str_with_rect] ペ�Eジャー: list[str_with_rect] クイチE��ビューアイコン: list[str_with_rect] # 啁E��詳細ペ�Eジ 啁E��吁E list[str_with_rect] 価格: list[str_with_rect] ブランチE list[str_with_rect] サムネイル: list[str_with_rect] 画像ギャラリー: list[str_with_rect] カラースウォチE��: list[str_with_rect] サイズセレクタ: list[str_with_rect] 在庫スチE�Eタス: list[str_with_rect] 配送情報: list[str_with_rect] ボタン_カート追加: list[str_with_rect] ボタン_今すぐ購入: list[str_with_rect] レビューサマリー: list[str_with_rect] レビューボタン: list[str_with_rect] QnAリンク: list[str_with_rect] バッジタグ: list[str_with_rect] 関連啁E��カルーセル: list[str_with_rect] # カート�Eージ カート商品リスチE list[str_with_rect] 数量セレクタ: list[str_with_rect] 削除アイコン: list[str_with_rect] クーポン入劁E list[str_with_rect] 注斁E��計サマリー: list[str_with_rect] チェチE��アウト�Eタン: list[str_with_rect] # 共通下部 フッターリンク: list[str_with_rect] SNSアイコン: list[str_with_rect] カスタマ�Eサポ�Eトリンク: list[str_with_rect] def get_openai_request(messages, format, openai_key): """OpenAI APIを呼び出ぁE"" 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 format2ecinfo(p, openai_key=os.environ.get('OPENAI_KEY')): """ ECサイト用のバリアント生成API baseimg2ecinfo_rect.pyのpageInfo構造に準拠 input1 (text): プロンプト�E�Eormat2fvinfoと同様�E形式!E input2 (text): default output1 (json): pageInfo形式�EJSON """ print(datetime.now(pytz.timezone('Asia/Tokyo')).strftime("%Y-%m-%d %H:%M:%S"), __name__) if openai_key == "default" or not openai_key: openai_key = os.environ.get('OPENAI_KEY', '') if openai_key: os.environ['OPENAI_API_KEY'] = openai_key messages=[ { "role": "system", "content": """提供したフォーマットデータから、ECサイト向け�Eペ�Eジ惁E��を生成してください。baseimg2ecinfo_rect.pyのpageInfo構造に準拠し、ECサイト�E特性�E�商品比輁E��カチE��リ一覧、賁E��請求など�E�を老E�Eして、E��刁E��要素を生成してください。各要素はstr_with_rect形式!Eext, html, rect�E�で記述してください、E"", }, { "role": "user", "content": [{"type": "text", "text":p}] }, ] return get_openai_request(messages, pageInfo, openai_key)