Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
import streamlit as st
|
2 |
import json
|
3 |
import pandas as pd
|
|
|
4 |
from groq import Groq
|
5 |
from prompt_engine import PromptGenerator
|
6 |
from utils import load_techniques, load_styles, parse_prompt_result
|
@@ -73,24 +74,24 @@ st.markdown("""
|
|
73 |
# サイドバー
|
74 |
with st.sidebar:
|
75 |
st.header("⚙️ 基本設定")
|
76 |
-
|
77 |
mode = st.radio(
|
78 |
"モード選択",
|
79 |
["MidJourney", "nijiJourney"],
|
80 |
help="生成するプロンプトの対象となるAIツールを選択します"
|
81 |
)
|
82 |
-
|
83 |
complexity = st.select_slider(
|
84 |
"複雑さレベル",
|
85 |
options=["シンプル", "バランス", "詳細", "実験的"],
|
86 |
value="バランス",
|
87 |
help="生成されるプロンプトの複雑さを調整します"
|
88 |
)
|
89 |
-
|
90 |
# モデル選択セクションを追加
|
91 |
st.markdown("---")
|
92 |
st.header("🧠 AIモデル")
|
93 |
-
|
94 |
model = st.selectbox(
|
95 |
"Groqモデルを選択",
|
96 |
[
|
@@ -103,12 +104,12 @@ with st.sidebar:
|
|
103 |
index=1, # デフォルトは llama-3.3-70b-versatile
|
104 |
help="使用するGroqのAIモデルを選択します。各モデルによって生成結果の特性が異なります"
|
105 |
)
|
106 |
-
|
107 |
# モデル選択時に変数を更新
|
108 |
if model != current_model:
|
109 |
current_model = model
|
110 |
theme = model_themes.get(current_model, {"primary": "#4b367c", "secondary": "#d1c4e9"})
|
111 |
-
|
112 |
# テーマの更新(実際には再読み込みが必要)
|
113 |
st.markdown(f"""
|
114 |
<style>
|
@@ -121,7 +122,7 @@ with st.sidebar:
|
|
121 |
}}
|
122 |
</style>
|
123 |
""", unsafe_allow_html=True)
|
124 |
-
|
125 |
# モデル情報の表示
|
126 |
model_info = {
|
127 |
"deepseek-r1-distill-llama-70b": "DeepSeekのLLaMA 70Bベースモデル。知識と推論能力に優れています。",
|
@@ -130,15 +131,15 @@ with st.sidebar:
|
|
130 |
"mistral-saba-24b": "Mistral AIのSaba 24Bモデル。創造性と一貫性のバランスに優れています。",
|
131 |
"qwen-qwq-32b": "Qwen QWQモデル。創造的な表現力が高く、芸術的プロンプトに適しています。"
|
132 |
}
|
133 |
-
|
134 |
st.caption(model_info.get(model, ""))
|
135 |
-
|
136 |
st.markdown("---")
|
137 |
-
|
138 |
st.header("🧙♂️ テクニック設定")
|
139 |
auto_select = st.checkbox("テクニックを自動選択", value=True,
|
140 |
help="オフにすると手動でテクニックを選択できます")
|
141 |
-
|
142 |
if not auto_select:
|
143 |
selected_techniques = st.multiselect(
|
144 |
"使用するテクニック",
|
@@ -162,18 +163,18 @@ tab1, tab2, tab3, tab4 = st.tabs(["基本設定", "高度なテクニック", "
|
|
162 |
|
163 |
with tab1:
|
164 |
col1, col2 = st.columns(2)
|
165 |
-
|
166 |
with col1:
|
167 |
aspect_ratio = st.selectbox(
|
168 |
"アスペクト比",
|
169 |
["1:1 (正方形)", "16:9 (横長)", "9:16 (縦長)", "3:2 (標準)", "4:3", "2:3", "カスタム"],
|
170 |
help="画像の縦横比を設定します"
|
171 |
)
|
172 |
-
|
173 |
if aspect_ratio == "カスタム":
|
174 |
custom_ratio = st.text_input("カスタム比率 (例: 5:4)")
|
175 |
aspect_ratio = custom_ratio if custom_ratio else "1:1"
|
176 |
-
|
177 |
quality = st.slider(
|
178 |
"クオリティ (--q)",
|
179 |
min_value=0.25,
|
@@ -182,21 +183,21 @@ with tab1:
|
|
182 |
step=0.25,
|
183 |
help="高いほど詳細な画像が生成されますが、処理時間が長くなります"
|
184 |
)
|
185 |
-
|
186 |
with col2:
|
187 |
style_category = st.selectbox(
|
188 |
"スタイルカテゴリ",
|
189 |
list(styles.keys()),
|
190 |
help="生成画像の基本的なスタイル方向性を選択します"
|
191 |
)
|
192 |
-
|
193 |
style_options = styles[style_category]
|
194 |
style = st.selectbox(
|
195 |
"スタイル",
|
196 |
style_options,
|
197 |
help="具体的なスタイルを選択します"
|
198 |
)
|
199 |
-
|
200 |
stylize = st.slider(
|
201 |
"スタイル強度 (--s)",
|
202 |
min_value=0,
|
@@ -211,13 +212,13 @@ with tab2:
|
|
211 |
st.info("「テクニックを自動選択」がオンになっています。AIが最適なテクニックを選択します。")
|
212 |
else:
|
213 |
st.markdown("### 選択したテクニック")
|
214 |
-
|
215 |
if selected_techniques:
|
216 |
for tech in selected_techniques:
|
217 |
st.markdown(f"**{tech}**: {techniques[tech]['description']}")
|
218 |
else:
|
219 |
st.warning("テクニックが選択されていません。サイドバーから選択してください。")
|
220 |
-
|
221 |
st.markdown("### テクニック解説")
|
222 |
tech_df = pd.DataFrame({
|
223 |
"テクニック": list(techniques.keys()),
|
@@ -228,9 +229,9 @@ with tab2:
|
|
228 |
|
229 |
with tab3:
|
230 |
st.markdown("### 専門家向け設定")
|
231 |
-
|
232 |
col1, col2 = st.columns(2)
|
233 |
-
|
234 |
with col1:
|
235 |
camera_angle = st.selectbox(
|
236 |
"カメラアングル",
|
@@ -243,7 +244,7 @@ with tab3:
|
|
243 |
- aerial view(空撮視点): 高い位置から真���を見下ろす視点。広大な風景や複雑なシーンの全体像を捉え、鳥の目線で世界を見せます。
|
244 |
- worm's eye view(ワームズアイビュー): 極端な低アングルで、まるで地面のミミズの視点から見上げるような角度。被写体の壮大さや圧倒的な存在感を強調します。"""
|
245 |
)
|
246 |
-
|
247 |
lens_type = st.selectbox(
|
248 |
"レンズタイプ",
|
249 |
["自動選択", "wide angle", "telephoto", "macro", "fisheye", "tilt-shift", "normal"],
|
@@ -255,7 +256,7 @@ with tab3:
|
|
255 |
- tilt-shift(ティルトシフトレンズ): レンズの角度や位置を調整できる特殊なレンズ。ミニチュア効果(実物を模型のように見せる)や、遠近法の調整、建築物の垂直線を修正する効果があります。
|
256 |
- normal(標準レンズ): 人間の視野に近い自然な画角を持つレンズ。歪みが少なく、最も現実に近い見え方を再現します。一般的に50mm前後の焦点距離を持ちます。"""
|
257 |
)
|
258 |
-
|
259 |
with col2:
|
260 |
lighting = st.selectbox(
|
261 |
"照明設定",
|
@@ -268,7 +269,7 @@ with tab3:
|
|
268 |
- backlight(バックライト): 被写体の後ろから当てる光。シルエットや輪郭を強調し、被写体の周りに光の縁取り(リムライト)を作ります。神秘的で幻想的な雰囲気や、逆光による独特の効果を生み出します。
|
269 |
- studio lighting(スタジオライティング): 制御された環境での複数の人工光源を使った照明技術。精密なハイライトとシャドウのコントロールが可能で、商業写真やポートレートに用いられます。"""
|
270 |
)
|
271 |
-
|
272 |
composition = st.selectbox(
|
273 |
"構図",
|
274 |
["自動選択", "rule of thirds", "golden ratio", "symmetrical", "asymmetrical", "leading lines", "frame within frame"],
|
@@ -280,23 +281,23 @@ with tab3:
|
|
280 |
- leading lines(リーディングライン): 道路、鉄道、川などの線状の要素を使って視線を画像内の特定の場所(通常は主題)へと導く構図。写真に奥行きと方向性を与え、視聴者の目の動きをコントロールします。
|
281 |
- frame within frame(フレームインフレーム): 窓、アーチ、木の枝などの要素を使って、画像内に別のフレームを作り出す構図。主題を強調し、奥行きを加え、視聴者の視線を中心に導きます。"""
|
282 |
)
|
283 |
-
|
284 |
# MidJourney特有のパラメータセクションを追加
|
285 |
st.markdown("### MidJourney/nijiJourney特有のパラメータ")
|
286 |
-
|
287 |
# タブでパラメータをカテゴリ分け
|
288 |
param_tab1, param_tab2, param_tab3 = st.tabs(["スタイル参照", "パーソナライズ", "その他"])
|
289 |
-
|
290 |
with param_tab1:
|
291 |
# スタイルリファレンス (--sref) 設定
|
292 |
use_style_reference = st.checkbox("スタイルリファレンス (--sref) を使用",
|
293 |
help="""別画像のスタイルを参照し、色調や質感を新規生成に適用します。
|
294 |
特定の画像のスタイル特性(色調、テクスチャ、画風など)を参照して新しい画像に適用するパラメータです。
|
295 |
特定の画像URL、ランダム選択、または以前に生成した画像のコードを指定できます。""")
|
296 |
-
|
297 |
if use_style_reference:
|
298 |
sref_type = st.radio("参照方法", ["ランダム", "画像URL", "コード指定"], horizontal=True)
|
299 |
-
|
300 |
if sref_type == "ランダム":
|
301 |
st.info("ランダムに選ばれたスタイルが適用されます (--sref random)")
|
302 |
sref_value = "random"
|
@@ -304,29 +305,29 @@ with tab3:
|
|
304 |
sref_value = st.text_input("画像URL", help="スタイル参照する画像のURLを入力してください")
|
305 |
else:
|
306 |
sref_value = st.text_input("スタイルコード", help="以前生成されたsrefコードを入力 (例: 1234567)")
|
307 |
-
|
308 |
# スタイルウェイト
|
309 |
style_weight = st.slider("スタイルウェイト (--sw)", 0, 1000, 100,
|
310 |
help="""参照画像の影響度を調整します。高いほど強く反映されます。
|
311 |
参照画像のスタイルがどの程度強く新しい画像に影響するかを0〜1000の値で指定します。
|
312 |
値が高いほど参照スタイルの影響が強くなります。""")
|
313 |
-
|
314 |
# スタイルバージョン
|
315 |
style_version = st.radio("スタイルバージョン (--sv)", [1, 2, 3, 4], index=3, horizontal=True,
|
316 |
help="""Style Referenceアルゴリズム���バージョンを選択します。
|
317 |
スタイル参照アルゴリズムのバージョン(1〜4)を選択します。
|
318 |
新しいバージョンほど改良されていますが、それぞれ異なる特性を持っています。""")
|
319 |
-
|
320 |
with param_tab2:
|
321 |
# パーソナライゼーション (--p) 設定
|
322 |
use_personalization = st.checkbox("パーソナライゼーション (--p) を使用",
|
323 |
help="""自身の好みに学習させたプロファイルを適用します。
|
324 |
ユーザーの好みに基づいて学習されたカスタムプロファイルを適用するパラメータです。
|
325 |
デフォルトプロファイル、特定のプロファイルID、または以前生成したコードを指定できます。""")
|
326 |
-
|
327 |
if use_personalization:
|
328 |
personalization_type = st.radio("適用方法", ["デフォルト", "プロファイルID", "コード指定"], horizontal=True)
|
329 |
-
|
330 |
if personalization_type == "デフォルト":
|
331 |
st.info("設定済みのデフォルトプロファイルが適用されます (--p)")
|
332 |
personalization_value = ""
|
@@ -334,40 +335,57 @@ with tab3:
|
|
334 |
personalization_value = st.text_input("プロファイルID", help="使用するプロファイルIDを入力")
|
335 |
else:
|
336 |
personalization_value = st.text_input("パーソナライズコード", help="以前生成されたコードを入力")
|
337 |
-
|
338 |
# パーソナライズ強度は --stylize を共用
|
339 |
st.caption("パーソナライズの適用度はスタイル強度 (--s) パラメータで調整されます")
|
340 |
-
|
341 |
with param_tab3:
|
342 |
# その他のパラメータ
|
343 |
col1, col2 = st.columns(2)
|
344 |
-
|
345 |
with col1:
|
346 |
use_character_reference = st.checkbox("キャラクター参照 (--cref)",
|
347 |
help="""複数シーンで同一キャラクターを維持します。
|
348 |
特定のキャラクターの外見を維持しながら複数の画像を生成するためのパラメータです。
|
349 |
キャラクターが写っている参照画像のURLを指定します。""")
|
350 |
-
|
351 |
if use_character_reference:
|
352 |
cref_value = st.text_input("キャラクター参照URL", help="キャラクターが写っている画像のURLを入力")
|
353 |
-
|
354 |
use_repeat = st.checkbox("繰り返し生成 (--repeat / --r)",
|
355 |
help="""同一プロンプトで複数グリッドを生成します。
|
356 |
同じプロンプトで複数セットの画像を連続して生成するパラメータです。
|
357 |
時間を節約し、より多くのバリエーションを効率的に探索できます。""")
|
358 |
-
|
359 |
if use_repeat:
|
360 |
repeat_count = st.number_input("繰り返し回数", min_value=1, max_value=10, value=2)
|
361 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
362 |
with col2:
|
363 |
use_image_weight = st.checkbox("画像プロンプトの影響度 (--iw)",
|
364 |
help="""画像プロンプト(イメージURL)の影響度を調整します。
|
365 |
画像プロンプト(URLで提供される参照画像)が��終結果にどれだけ影響するかを0.0〜2.0の値で指定します。
|
366 |
高い値ほど画像プロンプトの影響が強くなります。""")
|
367 |
-
|
368 |
if use_image_weight:
|
369 |
image_weight = st.slider("画像ウェイト", 0.0, 2.0, 1.0, 0.1)
|
370 |
-
|
371 |
generation_mode = st.radio("生成モード",
|
372 |
["デフォルト", "fast", "relax", "turbo", "draft"],
|
373 |
index=0, horizontal=True,
|
@@ -376,14 +394,51 @@ with tab3:
|
|
376 |
- relax(リラックスモード): 通常より低い優先度で処理される低コストのモード。急ぎでない場合や、サーバー負荷が高い時間帯に適しています。
|
377 |
- turbo(ターボモード): 最も高速なモードで、数秒で結果を生成します。品質は最も低くなりますが、概念実証や迅速なアイデア検証に最適です。
|
378 |
- draft(ドラフトモード): より低解像度で高速に生成するモード。迅速なイテレーションに適していますが、最終的な高品質画像には向いていません。""")
|
379 |
-
|
380 |
visibility = st.radio("共有設定",
|
381 |
["デフォルト", "public", "stealth"],
|
382 |
index=0, horizontal=True,
|
383 |
help="""MidJourneyサイトへの公開/非公開を制御:
|
384 |
- public(公開): 生成した画像をMidJourneyのコミュニティギャラリーに公開します。他のユーザーが閲覧でき、コミュニティの参考になります。
|
385 |
- stealth(非公開): 生成した画像を非公開にします。他のユーザーには表示されず、完全にプライベートに保たれます。""")
|
386 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
387 |
# カスタムパラメータセクション
|
388 |
st.markdown("### カスタムパラメータ")
|
389 |
advanced_params = st.text_area(
|
@@ -395,9 +450,9 @@ with tab3:
|
|
395 |
with tab4:
|
396 |
st.markdown("### 実験的機能")
|
397 |
st.warning("これらの機能は予測不能な結果をもたらす可能性があります")
|
398 |
-
|
399 |
col1, col2 = st.columns(2)
|
400 |
-
|
401 |
with col1:
|
402 |
use_pattern_interrupt = st.checkbox(
|
403 |
"パターン中断",
|
@@ -405,14 +460,14 @@ with tab4:
|
|
405 |
通常は組み合わせられない対照的な概念や要素を意図的に混ぜ合わせて、AIの「通常の思考パターン」を中断させる技術です。
|
406 |
例えば「古代の未来」「エーテルサイバーパンク」などの矛盾するコンセプトを組み合わせることで、予想外の創造的な結果を引き出します。"""
|
407 |
)
|
408 |
-
|
409 |
use_logical_paradox = st.checkbox(
|
410 |
"論理パラドックス",
|
411 |
help="""矛盾する要素を組み合わせて創造的な表現を引き出します。
|
412 |
矛盾する論理や概念を組み込むことで、AIに解決不能な「パズル」を提示し、より創造的な解釈を促す手法です。
|
413 |
「上昇する落下」「冷たい炎」などの矛盾する表現を用います。"""
|
414 |
)
|
415 |
-
|
416 |
with col2:
|
417 |
use_magic_words = st.checkbox(
|
418 |
"魔法の単語",
|
@@ -420,20 +475,20 @@ with tab4:
|
|
420 |
MidJourney/nijiJourneyのアルゴリズムに特に強く反応する特定の単語や語句を使用する技術です。
|
421 |
特定の芸術家名、美術用語、技法名など、特殊な効果を引き出す「キーワード」を戦略的に配置します。"""
|
422 |
)
|
423 |
-
|
424 |
use_emotion_matrix = st.checkbox(
|
425 |
"感情マトリックス",
|
426 |
help="""複雑な感情表現を階層的に組み込みます。
|
427 |
複数の感情を階層構造で組み込み、より微妙で複雑な感情表現を生成する技法です。
|
428 |
主要感情と二次感情を組み合わせることで、「懐かしさを含んだ喜び」「好奇心を伴う恐れ」など、ニュアンスのある感情を表現します。"""
|
429 |
)
|
430 |
-
|
431 |
if use_pattern_interrupt:
|
432 |
pattern_concepts = st.text_input(
|
433 |
"対照的な概念を入力 (コンマ区切り)",
|
434 |
help="例: 「エーテル,サイバーパンク」「古代,未来」"
|
435 |
)
|
436 |
-
|
437 |
if use_emotion_matrix:
|
438 |
primary_emotion = st.selectbox(
|
439 |
"主要感情",
|
@@ -474,9 +529,9 @@ if st.button("🚀 プロンプトを生成", type="primary", use_container_widt
|
|
474 |
"emotion_matrix": use_emotion_matrix
|
475 |
}
|
476 |
}
|
477 |
-
|
478 |
# MidJourney特有のパラメータを追加
|
479 |
-
|
480 |
# スタイルリファレンス
|
481 |
if 'use_style_reference' in locals() and use_style_reference:
|
482 |
params["advanced"]["style_reference"] = {
|
@@ -485,7 +540,7 @@ if st.button("🚀 プロンプトを生成", type="primary", use_container_widt
|
|
485 |
"style_weight": style_weight,
|
486 |
"style_version": style_version
|
487 |
}
|
488 |
-
|
489 |
# パーソナライゼーション
|
490 |
if 'use_personalization' in locals() and use_personalization:
|
491 |
params["advanced"]["personalization"] = {
|
@@ -493,100 +548,133 @@ if st.button("🚀 プロンプトを生成", type="primary", use_container_widt
|
|
493 |
"type": personalization_type,
|
494 |
"value": personalization_value
|
495 |
}
|
496 |
-
|
497 |
# キャラクター参照
|
498 |
if 'use_character_reference' in locals() and use_character_reference:
|
499 |
params["advanced"]["character_reference"] = {
|
500 |
"use": True,
|
501 |
"value": cref_value
|
502 |
}
|
503 |
-
|
504 |
# 繰り返し生成
|
505 |
if 'use_repeat' in locals() and use_repeat:
|
506 |
params["advanced"]["repeat"] = {
|
507 |
"use": True,
|
508 |
"count": repeat_count
|
509 |
}
|
510 |
-
|
511 |
# 画像プロンプトの影響度
|
512 |
if 'use_image_weight' in locals() and use_image_weight:
|
513 |
params["advanced"]["image_weight"] = {
|
514 |
"use": True,
|
515 |
"value": image_weight
|
516 |
}
|
517 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
518 |
# 生成モード
|
519 |
if 'generation_mode' in locals() and generation_mode != "デフォルト":
|
520 |
params["advanced"]["generation_mode"] = generation_mode
|
521 |
-
|
522 |
# 共有設定
|
523 |
if 'visibility' in locals() and visibility != "デフォルト":
|
524 |
params["advanced"]["visibility"] = visibility
|
525 |
-
|
526 |
# 実験的機能の詳細
|
527 |
if use_pattern_interrupt and 'pattern_concepts' in locals() and pattern_concepts:
|
528 |
params["experimental"]["pattern_concepts"] = [c.strip() for c in pattern_concepts.split(",")]
|
529 |
-
|
530 |
if use_emotion_matrix and 'primary_emotion' in locals() and 'secondary_emotion' in locals():
|
531 |
params["experimental"]["emotions"] = {
|
532 |
"primary": primary_emotion,
|
533 |
"secondary": secondary_emotion
|
534 |
}
|
535 |
-
|
536 |
# テクニック
|
537 |
if not auto_select and selected_techniques:
|
538 |
params["techniques"] = selected_techniques
|
539 |
-
|
540 |
# プロンプト生成呼び出し
|
541 |
result = prompt_generator.generate_prompt(client, params)
|
542 |
-
|
543 |
# 結果の解析
|
544 |
prompt, explanation = parse_prompt_result(result)
|
545 |
-
|
546 |
# 結果表示
|
547 |
st.success("プロンプトを生成しました!")
|
548 |
-
|
549 |
st.markdown("### 生成されたプロンプト")
|
550 |
-
|
551 |
# まずプロンプトを表示
|
552 |
st.code(prompt, language=None)
|
553 |
-
|
554 |
-
# JavaScript
|
555 |
-
|
556 |
-
js_code = """
|
557 |
<script>
|
558 |
-
function copyToClipboard() {
|
559 |
-
const text = `"""
|
560 |
-
navigator.clipboard.writeText(text).then(function() {
|
561 |
document.getElementById('copy-status').innerHTML = "コピーしました!";
|
562 |
-
setTimeout(function() {
|
563 |
document.getElementById('copy-status').innerHTML = "";
|
564 |
-
}, 2000);
|
565 |
-
})
|
566 |
-
.catch(function(error) {
|
567 |
document.getElementById('copy-status').innerHTML = "コピーできませんでした: " + error;
|
568 |
-
});
|
569 |
-
}
|
570 |
</script>
|
571 |
<button
|
572 |
onclick="copyToClipboard()"
|
573 |
-
style="background-color:
|
574 |
>
|
575 |
📋 クリップボードにコピー
|
576 |
</button>
|
577 |
<span id="copy-status" style="margin-left:10px; color:green;"></span>
|
578 |
"""
|
579 |
st.markdown(js_code, unsafe_allow_html=True)
|
580 |
-
|
581 |
st.caption("MidJourney/nijiJourneyにこのプロンプトを貼り付けて使用してください")
|
582 |
-
|
583 |
# 使用したモデルの表示を追加
|
584 |
st.caption(f"使用モデル: **{model}**")
|
585 |
-
|
586 |
if explanation:
|
587 |
st.markdown("### プロンプト解説")
|
588 |
st.markdown(explanation)
|
589 |
|
590 |
# フッター
|
591 |
st.markdown("---")
|
592 |
-
st.markdown("© 2025 AI Art Prompt Generator")
|
|
|
1 |
import streamlit as st
|
2 |
import json
|
3 |
import pandas as pd
|
4 |
+
import random
|
5 |
from groq import Groq
|
6 |
from prompt_engine import PromptGenerator
|
7 |
from utils import load_techniques, load_styles, parse_prompt_result
|
|
|
74 |
# サイドバー
|
75 |
with st.sidebar:
|
76 |
st.header("⚙️ 基本設定")
|
77 |
+
|
78 |
mode = st.radio(
|
79 |
"モード選択",
|
80 |
["MidJourney", "nijiJourney"],
|
81 |
help="生成するプロンプトの対象となるAIツールを選択します"
|
82 |
)
|
83 |
+
|
84 |
complexity = st.select_slider(
|
85 |
"複雑さレベル",
|
86 |
options=["シンプル", "バランス", "詳細", "実験的"],
|
87 |
value="バランス",
|
88 |
help="生成されるプロンプトの複雑さを調整します"
|
89 |
)
|
90 |
+
|
91 |
# モデル選択セクションを追加
|
92 |
st.markdown("---")
|
93 |
st.header("🧠 AIモデル")
|
94 |
+
|
95 |
model = st.selectbox(
|
96 |
"Groqモデルを選択",
|
97 |
[
|
|
|
104 |
index=1, # デフォルトは llama-3.3-70b-versatile
|
105 |
help="使用するGroqのAIモデルを選択します。各モデルによって生成結果の特性が異なります"
|
106 |
)
|
107 |
+
|
108 |
# モデル選択時に変数を更新
|
109 |
if model != current_model:
|
110 |
current_model = model
|
111 |
theme = model_themes.get(current_model, {"primary": "#4b367c", "secondary": "#d1c4e9"})
|
112 |
+
|
113 |
# テーマの更新(実際には再読み込みが必要)
|
114 |
st.markdown(f"""
|
115 |
<style>
|
|
|
122 |
}}
|
123 |
</style>
|
124 |
""", unsafe_allow_html=True)
|
125 |
+
|
126 |
# モデル情報の表示
|
127 |
model_info = {
|
128 |
"deepseek-r1-distill-llama-70b": "DeepSeekのLLaMA 70Bベースモデル。知識と推論能力に優れています。",
|
|
|
131 |
"mistral-saba-24b": "Mistral AIのSaba 24Bモデル。創造性と一貫性のバランスに優れています。",
|
132 |
"qwen-qwq-32b": "Qwen QWQモデル。創造的な表現力が高く、芸術的プロンプトに適しています。"
|
133 |
}
|
134 |
+
|
135 |
st.caption(model_info.get(model, ""))
|
136 |
+
|
137 |
st.markdown("---")
|
138 |
+
|
139 |
st.header("🧙♂️ テクニック設定")
|
140 |
auto_select = st.checkbox("テクニックを自動選択", value=True,
|
141 |
help="オフにすると手動でテクニックを選択できます")
|
142 |
+
|
143 |
if not auto_select:
|
144 |
selected_techniques = st.multiselect(
|
145 |
"使用するテクニック",
|
|
|
163 |
|
164 |
with tab1:
|
165 |
col1, col2 = st.columns(2)
|
166 |
+
|
167 |
with col1:
|
168 |
aspect_ratio = st.selectbox(
|
169 |
"アスペクト比",
|
170 |
["1:1 (正方形)", "16:9 (横長)", "9:16 (縦長)", "3:2 (標準)", "4:3", "2:3", "カスタム"],
|
171 |
help="画像の縦横比を設定します"
|
172 |
)
|
173 |
+
|
174 |
if aspect_ratio == "カスタム":
|
175 |
custom_ratio = st.text_input("カスタム比率 (例: 5:4)")
|
176 |
aspect_ratio = custom_ratio if custom_ratio else "1:1"
|
177 |
+
|
178 |
quality = st.slider(
|
179 |
"クオリティ (--q)",
|
180 |
min_value=0.25,
|
|
|
183 |
step=0.25,
|
184 |
help="高いほど詳細な画像が生成されますが、処理時間が長くなります"
|
185 |
)
|
186 |
+
|
187 |
with col2:
|
188 |
style_category = st.selectbox(
|
189 |
"スタイルカテゴリ",
|
190 |
list(styles.keys()),
|
191 |
help="生成画像の基本的なスタイル方向性を選択します"
|
192 |
)
|
193 |
+
|
194 |
style_options = styles[style_category]
|
195 |
style = st.selectbox(
|
196 |
"スタイル",
|
197 |
style_options,
|
198 |
help="具体的なスタイルを選択します"
|
199 |
)
|
200 |
+
|
201 |
stylize = st.slider(
|
202 |
"スタイル強度 (--s)",
|
203 |
min_value=0,
|
|
|
212 |
st.info("「テクニックを自動選択」がオンになっています。AIが最適なテクニックを選択します。")
|
213 |
else:
|
214 |
st.markdown("### 選択したテクニック")
|
215 |
+
|
216 |
if selected_techniques:
|
217 |
for tech in selected_techniques:
|
218 |
st.markdown(f"**{tech}**: {techniques[tech]['description']}")
|
219 |
else:
|
220 |
st.warning("テクニックが選択されていません。サイドバーから選択してください。")
|
221 |
+
|
222 |
st.markdown("### テクニック解説")
|
223 |
tech_df = pd.DataFrame({
|
224 |
"テクニック": list(techniques.keys()),
|
|
|
229 |
|
230 |
with tab3:
|
231 |
st.markdown("### 専門家向け設定")
|
232 |
+
|
233 |
col1, col2 = st.columns(2)
|
234 |
+
|
235 |
with col1:
|
236 |
camera_angle = st.selectbox(
|
237 |
"カメラアングル",
|
|
|
244 |
- aerial view(空撮視点): 高い位置から真���を見下ろす視点。広大な風景や複雑なシーンの全体像を捉え、鳥の目線で世界を見せます。
|
245 |
- worm's eye view(ワームズアイビュー): 極端な低アングルで、まるで地面のミミズの視点から見上げるような角度。被写体の壮大さや圧倒的な存在感を強調します。"""
|
246 |
)
|
247 |
+
|
248 |
lens_type = st.selectbox(
|
249 |
"レンズタイプ",
|
250 |
["自動選択", "wide angle", "telephoto", "macro", "fisheye", "tilt-shift", "normal"],
|
|
|
256 |
- tilt-shift(ティルトシフトレンズ): レンズの角度や位置を調整できる特殊なレンズ。ミニチュア効果(実物を模型のように見せる)や、遠近法の調整、建築物の垂直線を修正する効果があります。
|
257 |
- normal(標準レンズ): 人間の視野に近い自然な画角を持つレンズ。歪みが少なく、最も現実に近い見え方を再現します。一般的に50mm前後の焦点距離を持ちます。"""
|
258 |
)
|
259 |
+
|
260 |
with col2:
|
261 |
lighting = st.selectbox(
|
262 |
"照明設定",
|
|
|
269 |
- backlight(バックライト): 被写体の後ろから当てる光。シルエットや輪郭を強調し、被写体の周りに光の縁取り(リムライト)を作ります。神秘的で幻想的な雰囲気や、逆光による独特の効果を生み出します。
|
270 |
- studio lighting(スタジオライティング): 制御された環境での複数の人工光源を使った照明技術。精密なハイライトとシャドウのコントロールが可能で、商業写真やポートレートに用いられます。"""
|
271 |
)
|
272 |
+
|
273 |
composition = st.selectbox(
|
274 |
"構図",
|
275 |
["自動選択", "rule of thirds", "golden ratio", "symmetrical", "asymmetrical", "leading lines", "frame within frame"],
|
|
|
281 |
- leading lines(リーディングライン): 道路、鉄道、川などの線状の要素を使って視線を画像内の特定の場所(通常は主題)へと導く構図。写真に奥行きと方向性を与え、視聴者の目の動きをコントロールします。
|
282 |
- frame within frame(フレームインフレーム): 窓、アーチ、木の枝などの要素を使って、画像内に別のフレームを作り出す構図。主題を強調し、奥行きを加え、視聴者の視線を中心に導きます。"""
|
283 |
)
|
284 |
+
|
285 |
# MidJourney特有のパラメータセクションを追加
|
286 |
st.markdown("### MidJourney/nijiJourney特有のパラメータ")
|
287 |
+
|
288 |
# タブでパラメータをカテゴリ分け
|
289 |
param_tab1, param_tab2, param_tab3 = st.tabs(["スタイル参照", "パーソナライズ", "その他"])
|
290 |
+
|
291 |
with param_tab1:
|
292 |
# スタイルリファレンス (--sref) 設定
|
293 |
use_style_reference = st.checkbox("スタイルリファレンス (--sref) を使用",
|
294 |
help="""別画像のスタイルを参照し、色調や質感を新規生成に適用します。
|
295 |
特定の画像のスタイル特性(色調、テクスチャ、画風など)を参照して新しい画像に適用するパラメータです。
|
296 |
特定の画像URL、ランダム選択、または以前に生成した画像のコードを指定できます。""")
|
297 |
+
|
298 |
if use_style_reference:
|
299 |
sref_type = st.radio("参照方法", ["ランダム", "画像URL", "コード指定"], horizontal=True)
|
300 |
+
|
301 |
if sref_type == "ランダム":
|
302 |
st.info("ランダムに選ばれたスタイルが適用されます (--sref random)")
|
303 |
sref_value = "random"
|
|
|
305 |
sref_value = st.text_input("画像URL", help="スタイル参照する画像のURLを入力してください")
|
306 |
else:
|
307 |
sref_value = st.text_input("スタイルコード", help="以前生成されたsrefコードを入力 (例: 1234567)")
|
308 |
+
|
309 |
# スタイルウェイト
|
310 |
style_weight = st.slider("スタイルウェイト (--sw)", 0, 1000, 100,
|
311 |
help="""参照画像の影響度を調整します。高いほど強く反映されます。
|
312 |
参照画像のスタイルがどの程度強く新しい画像に影響するかを0〜1000の値で指定します。
|
313 |
値が高いほど参照スタイルの影響が強くなります。""")
|
314 |
+
|
315 |
# スタイルバージョン
|
316 |
style_version = st.radio("スタイルバージョン (--sv)", [1, 2, 3, 4], index=3, horizontal=True,
|
317 |
help="""Style Referenceアルゴリズム���バージョンを選択します。
|
318 |
スタイル参照アルゴリズムのバージョン(1〜4)を選択します。
|
319 |
新しいバージョンほど改良されていますが、それぞれ異なる特性を持っています。""")
|
320 |
+
|
321 |
with param_tab2:
|
322 |
# パーソナライゼーション (--p) 設定
|
323 |
use_personalization = st.checkbox("パーソナライゼーション (--p) を使用",
|
324 |
help="""自身の好みに学習させたプロファイルを適用します。
|
325 |
ユーザーの好みに基づいて学習されたカスタムプロファイルを適用するパラメータです。
|
326 |
デフォルトプロファイル、特定のプロファイルID、または以前生成したコードを指定できます。""")
|
327 |
+
|
328 |
if use_personalization:
|
329 |
personalization_type = st.radio("適用方法", ["デフォルト", "プロファイルID", "コード指定"], horizontal=True)
|
330 |
+
|
331 |
if personalization_type == "デフォルト":
|
332 |
st.info("設定済みのデフォルトプロファイルが適用されます (--p)")
|
333 |
personalization_value = ""
|
|
|
335 |
personalization_value = st.text_input("プロファイルID", help="使用するプロファイルIDを入力")
|
336 |
else:
|
337 |
personalization_value = st.text_input("パーソナライズコード", help="以前生成されたコードを入力")
|
338 |
+
|
339 |
# パーソナライズ強度は --stylize を共用
|
340 |
st.caption("パーソナライズの適用度はスタイル強度 (--s) パラメータで調整されます")
|
341 |
+
|
342 |
with param_tab3:
|
343 |
# その他のパラメータ
|
344 |
col1, col2 = st.columns(2)
|
345 |
+
|
346 |
with col1:
|
347 |
use_character_reference = st.checkbox("キャラクター参照 (--cref)",
|
348 |
help="""複数シーンで同一キャラクターを維持します。
|
349 |
特定のキャラクターの外見を維持しながら複数の画像を生成するためのパラメータです。
|
350 |
キャラクターが写っている参照画像のURLを指定します。""")
|
351 |
+
|
352 |
if use_character_reference:
|
353 |
cref_value = st.text_input("キャラクター参照URL", help="キャラクターが写っている画像のURLを入力")
|
354 |
+
|
355 |
use_repeat = st.checkbox("繰り返し生成 (--repeat / --r)",
|
356 |
help="""同一プロンプトで複数グリッドを生成します。
|
357 |
同じプロンプトで複数セットの画像を連続して生成するパラメータです。
|
358 |
時間を節約し、より多くのバリエーションを効率的に探索できます。""")
|
359 |
+
|
360 |
if use_repeat:
|
361 |
repeat_count = st.number_input("繰り返し回数", min_value=1, max_value=10, value=2)
|
362 |
+
|
363 |
+
# ネガティブプロンプト追加
|
364 |
+
use_negative_prompt = st.checkbox("ネガティブプロンプト (--no)",
|
365 |
+
help="""画像から除外したい要素を指定します。
|
366 |
+
生成画像に含めたくない要素を指定するパラメータです。
|
367 |
+
「bad hands」「text」「watermark」などの不要な要素を除外できます。""")
|
368 |
+
|
369 |
+
if use_negative_prompt:
|
370 |
+
negative_prompt = st.text_area("除外要素(コンマ区切り)",
|
371 |
+
placeholder="例: text, watermark, bad hands, blurry",
|
372 |
+
help="生成画像に含めたくない要素をコンマ区切りで入力")
|
373 |
+
|
374 |
+
# タイル機能追加
|
375 |
+
use_tile = st.checkbox("タイル生成 (--tile)",
|
376 |
+
help="""シームレスに繰り返し可能なタイル模様を生成します。
|
377 |
+
シームレスに繰り返し使用できるパターンやテクスチャを生成するためのパラメータです。
|
378 |
+
ウェブサイトの背景、壁紙、テキスタイル等に適しています。""")
|
379 |
+
|
380 |
with col2:
|
381 |
use_image_weight = st.checkbox("画像プロンプトの影響度 (--iw)",
|
382 |
help="""画像プロンプト(イメージURL)の影響度を調整します。
|
383 |
画像プロンプト(URLで提供される参照画像)が��終結果にどれだけ影響するかを0.0〜2.0の値で指定します。
|
384 |
高い値ほど画像プロンプトの影響が強くなります。""")
|
385 |
+
|
386 |
if use_image_weight:
|
387 |
image_weight = st.slider("画像ウェイト", 0.0, 2.0, 1.0, 0.1)
|
388 |
+
|
389 |
generation_mode = st.radio("生成モード",
|
390 |
["デフォルト", "fast", "relax", "turbo", "draft"],
|
391 |
index=0, horizontal=True,
|
|
|
394 |
- relax(リラックスモード): 通常より低い優先度で処理される低コストのモード。急ぎでない場合や、サーバー負荷が高い時間帯に適しています。
|
395 |
- turbo(ターボモード): 最も高速なモードで、数秒で結果を生成します。品質は最も低くなりますが、概念実証や迅速なアイデア検証に最適です。
|
396 |
- draft(ドラフトモード): より低解像度で高速に生成するモード。迅速なイテレーションに適していますが、最終的な高品質画像には向いていません。""")
|
397 |
+
|
398 |
visibility = st.radio("共有設定",
|
399 |
["デフォルト", "public", "stealth"],
|
400 |
index=0, horizontal=True,
|
401 |
help="""MidJourneyサイトへの公開/非公開を制御:
|
402 |
- public(公開): 生成した画像をMidJourneyのコミュニティギャラリーに公開します。他のユーザーが閲覧でき、コミュニティの参考になります。
|
403 |
- stealth(非公開): 生成した画像を非公開にします。他のユーザーには表示されず、完全にプライベートに保たれます。""")
|
404 |
+
|
405 |
+
# seed値追加
|
406 |
+
use_seed = st.checkbox("シード値を指定 (--seed)",
|
407 |
+
help="""同じ結果を再現するための値を設定します。
|
408 |
+
生成プロセスを制御する数値シードを指定するパラメータです。
|
409 |
+
同じシード値を使用すると同じ条件で同様の結果を再現できます。""")
|
410 |
+
|
411 |
+
if use_seed:
|
412 |
+
seed_value = st.number_input("シード値",
|
413 |
+
min_value=0,
|
414 |
+
max_value=4294967295,
|
415 |
+
value=random.randint(0, 4294967295),
|
416 |
+
help="特定のシード値を使用して再現性を確保します")
|
417 |
+
random_seed = st.button("ランダムなシード値を生成")
|
418 |
+
if random_seed:
|
419 |
+
seed_value = random.randint(0, 4294967295)
|
420 |
+
st.write(f"生成されたシード値: {seed_value}")
|
421 |
+
|
422 |
+
# chaosレベル追加
|
423 |
+
use_chaos = st.checkbox("ランダム性設定 (--c/--chaos)",
|
424 |
+
help="""結果の予測不能さを調整します。
|
425 |
+
生成結果の多様性やランダム性を0〜100の値で調整するパラメータです。
|
426 |
+
高い値ほど予測不能で創造的な結果が得られますが、プロンプトからの逸脱も大きくなります。""")
|
427 |
+
|
428 |
+
if use_chaos:
|
429 |
+
chaos_value = st.slider("Chaosレベル", 0, 100, 0,
|
430 |
+
help="高いほど予測不能な結果になります")
|
431 |
+
|
432 |
+
# stop値追加
|
433 |
+
use_stop = st.checkbox("途中停止 (--stop)",
|
434 |
+
help="""生成過程を途中で停止させてラフな結果を得ます。
|
435 |
+
生成プロセスを途中で意図的に停止させて中間結果を取得するパラメータです。
|
436 |
+
より未完成で実験的、アーティスティックな表現に適しています。""")
|
437 |
+
|
438 |
+
if use_stop:
|
439 |
+
stop_value = st.slider("停止ポイント", 10, 100, 100,
|
440 |
+
help="生成プロセスをどの段階で停止するか (%)")
|
441 |
+
|
442 |
# カスタムパラメータセクション
|
443 |
st.markdown("### カスタムパラメータ")
|
444 |
advanced_params = st.text_area(
|
|
|
450 |
with tab4:
|
451 |
st.markdown("### 実験的機能")
|
452 |
st.warning("これらの機能は予測不能な結果をもたらす可能性があります")
|
453 |
+
|
454 |
col1, col2 = st.columns(2)
|
455 |
+
|
456 |
with col1:
|
457 |
use_pattern_interrupt = st.checkbox(
|
458 |
"パターン中断",
|
|
|
460 |
通常は組み合わせられない対照的な概念や要素を意図的に混ぜ合わせて、AIの「通常の思考パターン」を中断させる技術です。
|
461 |
例えば「古代の未来」「エーテルサイバーパンク」などの矛盾するコンセプトを組み合わせることで、予想外の創造的な結果を引き出します。"""
|
462 |
)
|
463 |
+
|
464 |
use_logical_paradox = st.checkbox(
|
465 |
"論理パラドックス",
|
466 |
help="""矛盾する要素を組み合わせて創造的な表現を引き出します。
|
467 |
矛盾する論理や概念を組み込むことで、AIに解決不能な「パズル」を提示し、より創造的な解釈を促す手法です。
|
468 |
「上昇する落下」「冷たい炎」などの矛盾する表現を用います。"""
|
469 |
)
|
470 |
+
|
471 |
with col2:
|
472 |
use_magic_words = st.checkbox(
|
473 |
"魔法の単語",
|
|
|
475 |
MidJourney/nijiJourneyのアルゴリズムに特に強く反応する特定の単語や語句を使用する技術です。
|
476 |
特定の芸術家名、美術用語、技法名など、特殊な効果を引き出す「キーワード」を戦略的に配置します。"""
|
477 |
)
|
478 |
+
|
479 |
use_emotion_matrix = st.checkbox(
|
480 |
"感情マトリックス",
|
481 |
help="""複雑な感情表現を階層的に組み込みます。
|
482 |
複数の感情を階層構造で組み込み、より微妙で複雑な感情表現を生成する技法です。
|
483 |
主要感情と二次感情を組み合わせることで、「懐かしさを含んだ喜び」「好奇心を伴う恐れ」など、ニュアンスのある感情を表現します。"""
|
484 |
)
|
485 |
+
|
486 |
if use_pattern_interrupt:
|
487 |
pattern_concepts = st.text_input(
|
488 |
"対照的な概念を入力 (コンマ区切り)",
|
489 |
help="例: 「エーテル,サイバーパンク」「古代,未来」"
|
490 |
)
|
491 |
+
|
492 |
if use_emotion_matrix:
|
493 |
primary_emotion = st.selectbox(
|
494 |
"主要感情",
|
|
|
529 |
"emotion_matrix": use_emotion_matrix
|
530 |
}
|
531 |
}
|
532 |
+
|
533 |
# MidJourney特有のパラメータを追加
|
534 |
+
|
535 |
# スタイルリファレンス
|
536 |
if 'use_style_reference' in locals() and use_style_reference:
|
537 |
params["advanced"]["style_reference"] = {
|
|
|
540 |
"style_weight": style_weight,
|
541 |
"style_version": style_version
|
542 |
}
|
543 |
+
|
544 |
# パーソナライゼーション
|
545 |
if 'use_personalization' in locals() and use_personalization:
|
546 |
params["advanced"]["personalization"] = {
|
|
|
548 |
"type": personalization_type,
|
549 |
"value": personalization_value
|
550 |
}
|
551 |
+
|
552 |
# キャラクター参照
|
553 |
if 'use_character_reference' in locals() and use_character_reference:
|
554 |
params["advanced"]["character_reference"] = {
|
555 |
"use": True,
|
556 |
"value": cref_value
|
557 |
}
|
558 |
+
|
559 |
# 繰り返し生成
|
560 |
if 'use_repeat' in locals() and use_repeat:
|
561 |
params["advanced"]["repeat"] = {
|
562 |
"use": True,
|
563 |
"count": repeat_count
|
564 |
}
|
565 |
+
|
566 |
# 画像プロンプトの影響度
|
567 |
if 'use_image_weight' in locals() and use_image_weight:
|
568 |
params["advanced"]["image_weight"] = {
|
569 |
"use": True,
|
570 |
"value": image_weight
|
571 |
}
|
572 |
+
|
573 |
+
# seed値
|
574 |
+
if 'use_seed' in locals() and use_seed:
|
575 |
+
params["advanced"]["seed"] = {
|
576 |
+
"use": True,
|
577 |
+
"value": seed_value
|
578 |
+
}
|
579 |
+
|
580 |
+
# chaosレベル
|
581 |
+
if 'use_chaos' in locals() and use_chaos:
|
582 |
+
params["advanced"]["chaos"] = {
|
583 |
+
"use": True,
|
584 |
+
"value": chaos_value
|
585 |
+
}
|
586 |
+
|
587 |
+
# ネガティブプロンプト
|
588 |
+
if 'use_negative_prompt' in locals() and use_negative_prompt:
|
589 |
+
params["advanced"]["negative_prompt"] = {
|
590 |
+
"use": True,
|
591 |
+
"value": negative_prompt
|
592 |
+
}
|
593 |
+
|
594 |
+
# タイル機能
|
595 |
+
if 'use_tile' in locals() and use_tile:
|
596 |
+
params["advanced"]["tile"] = {
|
597 |
+
"use": True
|
598 |
+
}
|
599 |
+
|
600 |
+
# stop値
|
601 |
+
if 'use_stop' in locals() and use_stop:
|
602 |
+
params["advanced"]["stop"] = {
|
603 |
+
"use": True,
|
604 |
+
"value": stop_value
|
605 |
+
}
|
606 |
+
|
607 |
# 生成モード
|
608 |
if 'generation_mode' in locals() and generation_mode != "デフォルト":
|
609 |
params["advanced"]["generation_mode"] = generation_mode
|
610 |
+
|
611 |
# 共有設定
|
612 |
if 'visibility' in locals() and visibility != "デフォルト":
|
613 |
params["advanced"]["visibility"] = visibility
|
614 |
+
|
615 |
# 実験的機能の詳細
|
616 |
if use_pattern_interrupt and 'pattern_concepts' in locals() and pattern_concepts:
|
617 |
params["experimental"]["pattern_concepts"] = [c.strip() for c in pattern_concepts.split(",")]
|
618 |
+
|
619 |
if use_emotion_matrix and 'primary_emotion' in locals() and 'secondary_emotion' in locals():
|
620 |
params["experimental"]["emotions"] = {
|
621 |
"primary": primary_emotion,
|
622 |
"secondary": secondary_emotion
|
623 |
}
|
624 |
+
|
625 |
# テクニック
|
626 |
if not auto_select and selected_techniques:
|
627 |
params["techniques"] = selected_techniques
|
628 |
+
|
629 |
# プロンプト生成呼び出し
|
630 |
result = prompt_generator.generate_prompt(client, params)
|
631 |
+
|
632 |
# 結果の解析
|
633 |
prompt, explanation = parse_prompt_result(result)
|
634 |
+
|
635 |
# 結果表示
|
636 |
st.success("プロンプトを生成しました!")
|
637 |
+
|
638 |
st.markdown("### 生成されたプロンプト")
|
639 |
+
|
640 |
# まずプロンプトを表示
|
641 |
st.code(prompt, language=None)
|
642 |
+
|
643 |
+
# JavaScriptを使ったコピー機能の正しい実装
|
644 |
+
js_code = f"""
|
|
|
645 |
<script>
|
646 |
+
function copyToClipboard() {{
|
647 |
+
const text = `{prompt.replace("`", "\\`").replace("'", "\\'")}`;
|
648 |
+
navigator.clipboard.writeText(text).then(function() {{
|
649 |
document.getElementById('copy-status').innerHTML = "コピーしました!";
|
650 |
+
setTimeout(function() {{
|
651 |
document.getElementById('copy-status').innerHTML = "";
|
652 |
+
}}, 2000);
|
653 |
+
}})
|
654 |
+
.catch(function(error) {{
|
655 |
document.getElementById('copy-status').innerHTML = "コピーできませんでした: " + error;
|
656 |
+
}});
|
657 |
+
}}
|
658 |
</script>
|
659 |
<button
|
660 |
onclick="copyToClipboard()"
|
661 |
+
style="background-color:{theme['primary']}; color:white; border:none; padding:8px 16px; border-radius:4px; cursor:pointer;"
|
662 |
>
|
663 |
📋 クリップボードにコピー
|
664 |
</button>
|
665 |
<span id="copy-status" style="margin-left:10px; color:green;"></span>
|
666 |
"""
|
667 |
st.markdown(js_code, unsafe_allow_html=True)
|
668 |
+
|
669 |
st.caption("MidJourney/nijiJourneyにこのプロンプトを貼り付けて使用してください")
|
670 |
+
|
671 |
# 使用したモデルの表示を追加
|
672 |
st.caption(f"使用モデル: **{model}**")
|
673 |
+
|
674 |
if explanation:
|
675 |
st.markdown("### プロンプト解説")
|
676 |
st.markdown(explanation)
|
677 |
|
678 |
# フッター
|
679 |
st.markdown("---")
|
680 |
+
st.markdown("© 2025 AI Art Prompt Generator - Powered by Groq & Hugging Face")
|