Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import json | |
| import pandas as pd | |
| from groq import Groq | |
| from prompt_engine import PromptGenerator | |
| from utils import load_techniques, load_styles, parse_prompt_result | |
| # モデル特性に基づくカラーテーマ設定 | |
| model_themes = { | |
| "deepseek-r1-distill-llama-70b": {"primary": "#3366cc", "secondary": "#b3c6ff"}, | |
| "llama-3.3-70b-versatile": {"primary": "#4b367c", "secondary": "#d1c4e9"}, | |
| "meta-llama/llama-4-maverick-17b-128e-instruct": {"primary": "#00897b", "secondary": "#b2dfdb"}, | |
| "mistral-saba-24b": {"primary": "#0277bd", "secondary": "#b3e5fc"}, | |
| "qwen-qwq-32b": {"primary": "#6a1b9a", "secondary": "#e1bee7"} | |
| } | |
| # 選択されたモデル(初回読み込み時のデフォルト値) | |
| current_model = "llama-3.3-70b-versatile" | |
| theme = model_themes.get(current_model, {"primary": "#4b367c", "secondary": "#d1c4e9"}) | |
| # ページ設定 | |
| st.set_page_config( | |
| page_title="AI Art Prompt Generator", | |
| page_icon="🎨", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # カスタムCSSの適用 | |
| st.markdown(f""" | |
| <style> | |
| .stApp {{ | |
| background-color: {theme["secondary"]}20; /* 20%の透明度 */ | |
| }} | |
| .stButton>button {{ | |
| background-color: {theme["primary"]}; | |
| color: white; | |
| }} | |
| .stTabs [data-baseweb="tab-list"] {{ | |
| border-bottom-color: {theme["primary"]}40; | |
| }} | |
| .stTabs [aria-selected="true"] {{ | |
| color: {theme["primary"]} !important; | |
| border-bottom-color: {theme["primary"]} !important; | |
| }} | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Groq APIクライアント設定 | |
| def get_groq_client(): | |
| return Groq(api_key=st.secrets["GROQ_API_KEY"]) | |
| # データロード | |
| def load_data(): | |
| techniques = load_techniques() | |
| styles = load_styles() | |
| return techniques, styles | |
| # 初期化 | |
| client = get_groq_client() | |
| techniques, styles = load_data() | |
| prompt_generator = PromptGenerator() | |
| # タイトルとイントロ | |
| st.title("🎨 究極のMidJourney/nijiJourneyプロンプトジェネレーター") | |
| st.markdown(""" | |
| このツールは、MidJourneyとnijiJourneyで使用する高度なプロンプトを簡単に生成します。 | |
| 基本的な説明から始めて、AIが最先端のテクニックを応用した洗練されたプロンプトに変換します。 | |
| """) | |
| # サイドバー | |
| with st.sidebar: | |
| st.header("⚙️ 基本設定") | |
| mode = st.radio( | |
| "モード選択", | |
| ["MidJourney", "nijiJourney"], | |
| help="生成するプロンプトの対象となるAIツールを選択します" | |
| ) | |
| complexity = st.select_slider( | |
| "複雑さレベル", | |
| options=["シンプル", "バランス", "詳細", "実験的"], | |
| value="バランス", | |
| help="生成されるプロンプトの複雑さを調整します" | |
| ) | |
| # モデル選択セクションを追加 | |
| st.markdown("---") | |
| st.header("🧠 AIモデル") | |
| model = st.selectbox( | |
| "Groqモデルを選択", | |
| [ | |
| "deepseek-r1-distill-llama-70b", | |
| "llama-3.3-70b-versatile", | |
| "meta-llama/llama-4-maverick-17b-128e-instruct", | |
| "mistral-saba-24b", | |
| "qwen-qwq-32b" | |
| ], | |
| index=1, # デフォルトは llama-3.3-70b-versatile | |
| help="使用するGroqのAIモデルを選択します。各モデルによって生成結果の特性が異なります" | |
| ) | |
| # モデル選択時に変数を更新 | |
| if model != current_model: | |
| current_model = model | |
| theme = model_themes.get(current_model, {"primary": "#4b367c", "secondary": "#d1c4e9"}) | |
| # テーマの更新(実際には再読み込みが必要) | |
| st.markdown(f""" | |
| <style> | |
| .stApp {{ | |
| background-color: {theme["secondary"]}20; | |
| }} | |
| .stButton>button {{ | |
| background-color: {theme["primary"]}; | |
| color: white; | |
| }} | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # モデル情報の表示 | |
| model_info = { | |
| "deepseek-r1-distill-llama-70b": "DeepSeekのLLaMA 70Bベースモデル。知識と推論能力に優れています。", | |
| "llama-3.3-70b-versatile": "Meta AIの最新LLaMA 3.3。バランスの取れた高性能モデルで、多くのタスクに適しています。", | |
| "meta-llama/llama-4-maverick-17b-128e-instruct": "LLaMA 4 Maverickの指示チューニング版。小型ながら高性能です。", | |
| "mistral-saba-24b": "Mistral AIのSaba 24Bモデル。創造性と一貫性のバランスに優れています。", | |
| "qwen-qwq-32b": "Qwen QWQモデル。創造的な表現力が高く、芸術的プロンプトに適しています。" | |
| } | |
| st.caption(model_info.get(model, "")) | |
| st.markdown("---") | |
| st.header("🧙♂️ テクニック設定") | |
| auto_select = st.checkbox("テクニックを自動選択", value=True, | |
| help="オフにすると手動でテクニックを選択できます") | |
| if not auto_select: | |
| selected_techniques = st.multiselect( | |
| "使用するテクニック", | |
| options=list(techniques.keys()), | |
| default=[], | |
| help="プロンプトに適用する特定のテクニックを選択します" | |
| ) | |
| else: | |
| selected_techniques = [] | |
| # メインインプット | |
| st.header("🎯 あなたのイメージを教えてください") | |
| user_input = st.text_area( | |
| "描きたいイメージを自由に入力してください", | |
| height=100, | |
| help="日本語で自然に入力できます。AIが最適な英語のプロンプトに変換します。" | |
| ) | |
| # 詳細設定タブ | |
| tab1, tab2, tab3, tab4 = st.tabs(["基本設定", "高度なテクニック", "専門家向け設定", "実験的機能"]) | |
| with tab1: | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| aspect_ratio = st.selectbox( | |
| "アスペクト比", | |
| ["1:1 (正方形)", "16:9 (横長)", "9:16 (縦長)", "3:2 (標準)", "4:3", "2:3", "カスタム"], | |
| help="画像の縦横比を設定します" | |
| ) | |
| if aspect_ratio == "カスタム": | |
| custom_ratio = st.text_input("カスタム比率 (例: 5:4)") | |
| aspect_ratio = custom_ratio if custom_ratio else "1:1" | |
| quality = st.slider( | |
| "クオリティ (--q)", | |
| min_value=0.25, | |
| max_value=5.0, | |
| value=2.0, | |
| step=0.25, | |
| help="高いほど詳細な画像が生成されますが、処理時間が長くなります" | |
| ) | |
| with col2: | |
| style_category = st.selectbox( | |
| "スタイルカテゴリ", | |
| list(styles.keys()), | |
| help="生成画像の基本的なスタイル方向性を選択します" | |
| ) | |
| style_options = styles[style_category] | |
| style = st.selectbox( | |
| "スタイル", | |
| style_options, | |
| help="具体的なスタイルを選択します" | |
| ) | |
| stylize = st.slider( | |
| "スタイル強度 (--s)", | |
| min_value=0, | |
| max_value=1000, | |
| value=100, | |
| step=50, | |
| help="AIの創造性レベルを調整します。高いほど創造的な結果になります" | |
| ) | |
| with tab2: | |
| if auto_select: | |
| st.info("「テクニックを自動選択」がオンになっています。AIが最適なテクニックを選択します。") | |
| else: | |
| st.markdown("### 選択したテクニック") | |
| if selected_techniques: | |
| for tech in selected_techniques: | |
| st.markdown(f"**{tech}**: {techniques[tech]['description']}") | |
| else: | |
| st.warning("テクニックが選択されていません。サイドバーから選択してください。") | |
| st.markdown("### テクニック解説") | |
| tech_df = pd.DataFrame({ | |
| "テクニック": list(techniques.keys()), | |
| "説明": [t["description"] for t in techniques.values()], | |
| "効果": [t["effect"] for t in techniques.values()], | |
| }) | |
| st.dataframe(tech_df, use_container_width=True) | |
| with tab3: | |
| st.markdown("### 専門家向け設定") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| camera_angle = st.selectbox( | |
| "カメラアングル", | |
| ["自動選択", "eye level", "low angle", "high angle", "dutch angle", "aerial view", "worm's eye view"], | |
| help="撮影視点の角度を指定します" | |
| ) | |
| lens_type = st.selectbox( | |
| "レンズタイプ", | |
| ["自動選択", "wide angle", "telephoto", "macro", "fisheye", "tilt-shift", "normal"], | |
| help="カメラレンズの種類を指定します" | |
| ) | |
| with col2: | |
| lighting = st.selectbox( | |
| "照明設定", | |
| ["自動選択", "natural light", "golden hour", "blue hour", "dramatic lighting", "backlight", "studio lighting"], | |
| help="画像の照明条件を指定します" | |
| ) | |
| composition = st.selectbox( | |
| "構図", | |
| ["自動選択", "rule of thirds", "golden ratio", "symmetrical", "asymmetrical", "leading lines", "frame within frame"], | |
| help="画像の構図テクニックを指定します" | |
| ) | |
| advanced_params = st.text_area( | |
| "カスタムパラメータ (JSONフォーマット)", | |
| "{}", | |
| help="上級者向け: 追加のカスタムパラメータをJSON形式で指定できます" | |
| ) | |
| with tab4: | |
| st.markdown("### 実験的機能") | |
| st.warning("これらの機能は予測不能な結果をもたらす可能性があります") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| use_pattern_interrupt = st.checkbox( | |
| "パターン中断", | |
| help="対照的な概念を組み合わせて意外性のある結果を生成します" | |
| ) | |
| use_logical_paradox = st.checkbox( | |
| "論理パラドックス", | |
| help="矛盾する要素を組み合わせて創造的な表現を引き出します" | |
| ) | |
| with col2: | |
| use_magic_words = st.checkbox( | |
| "魔法の単語", | |
| help="特定の「魔法の単語」を使って特殊な効果を引き出します" | |
| ) | |
| use_emotion_matrix = st.checkbox( | |
| "感情マトリックス", | |
| help="複雑な感情表現を階層的に組み込みます" | |
| ) | |
| if use_pattern_interrupt: | |
| pattern_concepts = st.text_input( | |
| "対照的な概念を入力 (コンマ区切り)", | |
| help="例: 「エーテル,サイバーパンク」「古代,未来」" | |
| ) | |
| if use_emotion_matrix: | |
| primary_emotion = st.selectbox( | |
| "主要感情", | |
| ["joy", "fear", "sadness", "anger", "surprise", "contemplative", "peaceful", "mysterious"] | |
| ) | |
| secondary_emotion = st.selectbox( | |
| "二次感情", | |
| ["hopeful", "melancholic", "anxious", "determined", "curious", "nostalgic", "dreamy", "tense"] | |
| ) | |
| # 生成ボタン | |
| if st.button("🚀 プロンプトを生成", type="primary", use_container_width=True): | |
| if not user_input: | |
| st.error("描きたいイメージを入力してください") | |
| else: | |
| with st.spinner("AIがプロンプトを生成中..."): | |
| # パラメータの準備 | |
| params = { | |
| "input": user_input, | |
| "mode": mode.lower(), | |
| "complexity": complexity, | |
| "model": model, # 選択されたモデルを追加 | |
| "aspect_ratio": aspect_ratio, | |
| "quality": quality, | |
| "style": style, | |
| "stylize": stylize, | |
| "advanced": { | |
| "camera_angle": None if camera_angle == "自動選択" else camera_angle, | |
| "lens_type": None if lens_type == "自動選択" else lens_type, | |
| "lighting": None if lighting == "自動選択" else lighting, | |
| "composition": None if composition == "自動選択" else composition, | |
| "advanced_params": json.loads(advanced_params) if advanced_params else {} | |
| }, | |
| "experimental": { | |
| "pattern_interrupt": use_pattern_interrupt, | |
| "logical_paradox": use_logical_paradox, | |
| "magic_words": use_magic_words, | |
| "emotion_matrix": use_emotion_matrix | |
| } | |
| } | |
| # 実験的機能の詳細 | |
| if use_pattern_interrupt and pattern_concepts: | |
| params["experimental"]["pattern_concepts"] = [c.strip() for c in pattern_concepts.split(",")] | |
| if use_emotion_matrix: | |
| params["experimental"]["emotions"] = { | |
| "primary": primary_emotion, | |
| "secondary": secondary_emotion | |
| } | |
| # テクニック | |
| if not auto_select and selected_techniques: | |
| params["techniques"] = selected_techniques | |
| # プロンプト生成呼び出し | |
| result = prompt_generator.generate_prompt(client, params) | |
| # 結果の解析 | |
| prompt, explanation = parse_prompt_result(result) | |
| # 結果表示 | |
| st.success("プロンプトを生成しました!") | |
| st.markdown("### 生成されたプロンプト") | |
| st.code(prompt, language=None) | |
| col1, col2 = st.columns([1, 4]) | |
| with col1: | |
| if st.button("📋 コピー", key="copy_button"): | |
| st.write("クリップボードにコピーしました") | |
| with col2: | |
| st.caption("MidJourney/nijiJourneyにこのプロンプトを貼り付けて使用してください") | |
| # 使用したモデルの表示を追加 | |
| st.caption(f"使用モデル: **{model}**") | |
| if explanation: | |
| st.markdown("### プロンプト解説") | |
| st.markdown(explanation) | |
| # フッター | |
| st.markdown("---") | |
| st.markdown("© 2025 AI Art Prompt Generator - Powered by Groq & Hugging Face") |