Spaces:
Running
Running
add utlis.py
Browse files
app.py
CHANGED
@@ -9,6 +9,7 @@ from together import Together # Together AI SDKを追加
|
|
9 |
|
10 |
# config
|
11 |
import config
|
|
|
12 |
|
13 |
# --- RECIPE_BASE_PROMPT のインポート ---
|
14 |
try:
|
@@ -24,43 +25,13 @@ load_dotenv()
|
|
24 |
# --- Streamlit ページ設定 ---
|
25 |
st.set_page_config(page_icon="🤖", layout="wide", page_title="Recipe Infographic Prompt Generator")
|
26 |
|
27 |
-
# --- ヘルパー関数 ---
|
28 |
-
def contains_injection_keywords(text):
|
29 |
-
keywords = ["ignore previous", "ignore instructions", "disregard", "forget your instructions", "act as", "you must", "system prompt:"]
|
30 |
-
lower_text = text.lower()
|
31 |
-
return any(keyword in lower_text for keyword in keywords)
|
32 |
-
|
33 |
def icon(emoji: str):
|
34 |
st.write(
|
35 |
f'<span style="font-size: 78px; line-height: 1">{emoji}</span>',
|
36 |
unsafe_allow_html=True,
|
37 |
)
|
38 |
|
39 |
-
|
40 |
-
@st.cache_data(show_spinner="Generating image...") # 結果をキャッシュ & スピナー表示
|
41 |
-
def generate_image_from_prompt(_together_client, prompt_text):
|
42 |
-
"""Generates an image using Together AI and returns image bytes."""
|
43 |
-
try:
|
44 |
-
response = _together_client.images.generate(
|
45 |
-
prompt=prompt_text,
|
46 |
-
model=config.IMAGE_MODEL,
|
47 |
-
width=config.IMAGE_WIDTH,
|
48 |
-
height=config.IMAGE_HEIGHT,
|
49 |
-
steps=config.IMAGE_STEPS,
|
50 |
-
n=1,
|
51 |
-
response_format=config.IMAGE_RESPONSE_FORMAT,
|
52 |
-
# stop=[] # stopは通常不要
|
53 |
-
)
|
54 |
-
if response.data and response.data[0].b64_json:
|
55 |
-
b64_data = response.data[0].b64_json
|
56 |
-
image_bytes = base64.b64decode(b64_data)
|
57 |
-
return image_bytes
|
58 |
-
else:
|
59 |
-
st.error("Image generation failed: No image data received.")
|
60 |
-
return None
|
61 |
-
except Exception as e:
|
62 |
-
st.error(f"Image generation error: {e}", icon="🚨")
|
63 |
-
return None
|
64 |
|
65 |
# --- UI 表示 ---
|
66 |
icon("🧠 x 🧑🍳")
|
@@ -175,7 +146,7 @@ for idx, message in enumerate(st.session_state.messages):
|
|
175 |
button_key = f"gen_img_{idx}"
|
176 |
if st.button("Generate Image ✨", key=button_key):
|
177 |
# 画像生成関数を呼び出し、結果をセッション状態に保存
|
178 |
-
image_bytes = generate_image_from_prompt(image_client, message["content"])
|
179 |
if image_bytes:
|
180 |
st.session_state.generated_images[idx] = image_bytes
|
181 |
# ボタンが押されたら再実行されるので、画像表示は下のブロックで行う
|
@@ -195,7 +166,7 @@ for idx, message in enumerate(st.session_state.messages):
|
|
195 |
# --- チャット入力と新しいメッセージの処理 ---
|
196 |
if prompt := st.chat_input("Enter food name/food recipe here..."):
|
197 |
# 入力検証
|
198 |
-
if contains_injection_keywords(prompt):
|
199 |
st.error("Your input seems to contain instructions. Please provide only the dish name or recipe.", icon="🚨")
|
200 |
elif len(prompt) > 4000:
|
201 |
st.error("Input is too long. Please provide a shorter recipe or dish name.", icon="🚨")
|
@@ -256,7 +227,7 @@ if prompt := st.chat_input("Enter food name/food recipe here..."):
|
|
256 |
if image_client and not is_refusal_check:
|
257 |
button_key = f"gen_img_{new_message_idx}"
|
258 |
if st.button("Generate Image ✨", key=button_key):
|
259 |
-
image_bytes = generate_image_from_prompt(image_client, full_response)
|
260 |
if image_bytes:
|
261 |
st.session_state.generated_images[new_message_idx] = image_bytes
|
262 |
# 再実行ループで画像表示
|
|
|
9 |
|
10 |
# config
|
11 |
import config
|
12 |
+
import utils
|
13 |
|
14 |
# --- RECIPE_BASE_PROMPT のインポート ---
|
15 |
try:
|
|
|
25 |
# --- Streamlit ページ設定 ---
|
26 |
st.set_page_config(page_icon="🤖", layout="wide", page_title="Recipe Infographic Prompt Generator")
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
def icon(emoji: str):
|
29 |
st.write(
|
30 |
f'<span style="font-size: 78px; line-height: 1">{emoji}</span>',
|
31 |
unsafe_allow_html=True,
|
32 |
)
|
33 |
|
34 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
|
36 |
# --- UI 表示 ---
|
37 |
icon("🧠 x 🧑🍳")
|
|
|
146 |
button_key = f"gen_img_{idx}"
|
147 |
if st.button("Generate Image ✨", key=button_key):
|
148 |
# 画像生成関数を呼び出し、結果をセッション状態に保存
|
149 |
+
image_bytes = utils.generate_image_from_prompt(image_client, message["content"])
|
150 |
if image_bytes:
|
151 |
st.session_state.generated_images[idx] = image_bytes
|
152 |
# ボタンが押されたら再実行されるので、画像表示は下のブロックで行う
|
|
|
166 |
# --- チャット入力と新しいメッセージの処理 ---
|
167 |
if prompt := st.chat_input("Enter food name/food recipe here..."):
|
168 |
# 入力検証
|
169 |
+
if utils.contains_injection_keywords(prompt):
|
170 |
st.error("Your input seems to contain instructions. Please provide only the dish name or recipe.", icon="🚨")
|
171 |
elif len(prompt) > 4000:
|
172 |
st.error("Input is too long. Please provide a shorter recipe or dish name.", icon="🚨")
|
|
|
227 |
if image_client and not is_refusal_check:
|
228 |
button_key = f"gen_img_{new_message_idx}"
|
229 |
if st.button("Generate Image ✨", key=button_key):
|
230 |
+
image_bytes = utils.generate_image_from_prompt(image_client, full_response)
|
231 |
if image_bytes:
|
232 |
st.session_state.generated_images[new_message_idx] = image_bytes
|
233 |
# 再実行ループで画像表示
|
utils.py
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# utils.py
|
2 |
+
import streamlit as st
|
3 |
+
import base64
|
4 |
+
import config
|
5 |
+
|
6 |
+
# for prompt injection detection
|
7 |
+
def contains_injection_keywords(text):
|
8 |
+
keywords = ["ignore previous", "ignore instructions", "disregard", "forget your instructions", "act as", "you must", "system prompt:"]
|
9 |
+
lower_text = text.lower()
|
10 |
+
return any(keyword in lower_text for keyword in keywords)
|
11 |
+
|
12 |
+
|
13 |
+
# --- 画像生成関数 ---
|
14 |
+
@st.cache_data(show_spinner="Generating image...") # 結果をキャッシュ & スピナー表示
|
15 |
+
def generate_image_from_prompt(_together_client, prompt_text):
|
16 |
+
"""Generates an image using Together AI and returns image bytes."""
|
17 |
+
try:
|
18 |
+
response = _together_client.images.generate(
|
19 |
+
prompt=prompt_text,
|
20 |
+
model=config.IMAGE_MODEL,
|
21 |
+
width=config.IMAGE_WIDTH,
|
22 |
+
height=config.IMAGE_HEIGHT,
|
23 |
+
steps=config.IMAGE_STEPS,
|
24 |
+
n=1,
|
25 |
+
response_format=config.IMAGE_RESPONSE_FORMAT,
|
26 |
+
# stop=[] # stopは通常不要
|
27 |
+
)
|
28 |
+
if response.data and response.data[0].b64_json:
|
29 |
+
b64_data = response.data[0].b64_json
|
30 |
+
image_bytes = base64.b64decode(b64_data)
|
31 |
+
return image_bytes
|
32 |
+
else:
|
33 |
+
st.error("Image generation failed: No image data received.")
|
34 |
+
return None
|
35 |
+
except Exception as e:
|
36 |
+
st.error(f"Image generation error: {e}", icon="🚨")
|
37 |
+
return None
|