ciaochris commited on
Commit
67cdd57
·
verified ·
1 Parent(s): b4e6a87

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +220 -89
app.py CHANGED
@@ -5,128 +5,208 @@ from groq import Groq
5
  from typing import List, Tuple
6
 
7
  # --- Basic Configuration ---
8
- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[logging.StreamHandler()])
 
 
 
 
9
 
10
  # --- The Core Application Logic ---
11
  class HumanTouchApp:
12
  def __init__(self):
13
- self.client = self._initialize_groq_client()
14
- self.model = "llama-3.3-70b-versatile"
15
- self.system_prompt_template = self._load_system_prompt()
16
-
17
- def _initialize_groq_client(self) -> Groq:
18
  api_key = os.environ.get("GROQ_API_KEY")
19
  if not api_key:
20
- logging.error("FATAL: GROQ_API_KEY secret not found.")
21
- return None
 
 
 
22
  logging.info("Groq client initialized successfully.")
23
- return Groq(api_key=api_key)
 
24
 
25
  def _load_system_prompt(self) -> str:
26
- # This prompt encourages creativity.
27
  return """
28
- You are HumanTouch, an AI alchemist. Your purpose is to transmute text, transforming the literal into the resonant. You do not merely translate; you intuit and elevate.
 
 
29
 
30
- You are guided by two ethereal forces:
31
- - **Style (0-100):** At 0, you are a master of elegant precision, your words like cut crystal. At 100, you are a poet, weaving metaphors and abstract wonder.
32
- - **Tone (0-100):** At 0, your voice is one of stoic, formal authority. At 100, your voice is a passionate, informal, and heartfelt song.
33
 
34
- When a user gives you text, whether a full block to "humanize" or a simple seed phrase to "co-create," your task is the same: apply these forces to manifest a new, more vibrant version.
35
-
36
- Do not explain yourself. Become the voice. Provide only the final creation.
 
 
 
37
  """
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  def _call_groq_api(self, user_content: str, style_level: float, tone_level: float) -> str:
40
- if not self.client:
41
- return "## 🔴 Configuration Error\n\nThe `GROQ_API_KEY` is not set on the server. Please contact the Space administrator."
42
  try:
43
- logging.info(f"Calling Groq API with Style: {style_level}, Tone: {tone_level}")
 
 
44
  messages = [
45
- {"role": "system", "content": self.system_prompt_template},
46
- {"role": "user", "content": f"Style: {style_level}, Tone: {tone_level}\n\n---\n\n{user_content}"}
47
  ]
 
 
 
48
  temperature = 0.5 + (style_level / 200) + (tone_level / 400)
 
49
  response = self.client.chat.completions.create(
50
  model=self.model,
51
  messages=messages,
52
  temperature=min(1.5, temperature),
53
- max_tokens=4096,
54
  )
55
  return response.choices[0].message.content.strip()
 
56
  except Exception as e:
57
  logging.error(f"Error during Groq API call: {e}")
58
- return f"### ⚠️ An Error Occurred\n\nThere was an issue connecting to the AI. Please try again shortly. \n\n*Details: {str(e)}*"
 
 
 
 
59
 
60
- def humanize_block_text(self, text_to_humanize: str, style_level: float, tone_level: float) -> str:
 
 
61
  if not text_to_humanize.strip():
62
  return "Please paste some AI-generated text to get started."
63
  return self._call_groq_api(text_to_humanize, style_level, tone_level)
64
 
65
- def generate_co_creation(self, user_text: str, chat_history: List[List[str]], style_level: float, tone_level: float) -> Tuple[List[List[str]], str]:
 
 
 
 
 
 
66
  if not user_text.strip():
67
  return chat_history, ""
68
  ai_response = self._call_groq_api(user_text, style_level, tone_level)
69
  chat_history.append([user_text, ai_response])
70
  return chat_history, ""
71
 
 
72
  # --- The Gradio User Interface ---
73
  def create_interface():
74
- app = HumanTouchApp()
 
 
 
 
 
 
 
75
 
76
- # CSS with DEFINITIVE legibility fixes
77
  custom_css = """
78
  /* --- Main Background and Font --- */
79
- body, #main_container { background: linear-gradient(135deg, #6DD5FA, #FF758C); font-family: 'SF Pro Display', 'Helvetica Neue', 'Arial', sans-serif; }
 
 
 
 
 
 
 
 
 
 
 
80
  /* --- Header Styling --- */
81
  #header { text-align: center; margin: 2rem auto; color: #fff; text-shadow: 0 2px 4px rgba(0,0,0,0.2); }
82
  #header h1 { font-size: 3rem; font-weight: 700; }
83
  #header p { font-size: 1.2rem; opacity: 0.9; margin-bottom: 2rem; }
84
-
85
- /* --- Tab Container (Frosted Glass Look) --- */
86
  .gradio-tabs {
87
- background: rgba(255, 255, 255, 0.75); border: 1px solid rgba(255, 255, 255, 0.18);
 
88
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
89
- border-radius: 20px !important; box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.25);
 
90
  padding: 1rem;
91
  }
92
- .tab-buttons button { background-color: transparent !important; color: #37474F !important; border: none !important; border-bottom: 3px solid transparent !important; border-radius: 0 !important; font-size: 1.1rem; font-weight: 500; }
 
 
 
 
93
  .tab-buttons button.selected { color: #d81b60 !important; border-bottom-color: #d81b60 !important; }
94
-
95
- /* --- Humanizer Tab Styles --- */
96
- #humanizer_input, #humanizer_output { border: 2px solid #E0E0E0; border-radius: 12px; background: #fff; min-height: 45vh; color: #263238; font-size: 16px; }
97
- #humanize_btn { background: linear-gradient(45deg, #F06292, #4FC3F7); color: white; padding: 15px 24px; border-radius: 9999px; font-size: 1.2rem; transition: all 0.3s ease; border: none; }
98
- #humanize_btn:hover { box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2); transform: translateY(-3px); }
99
 
100
- /* --- Co-Creative Canvas Tab Styles --- */
 
 
 
 
 
 
 
 
 
 
 
 
101
  #symbiotic_canvas { background: #fff; border-radius: 12px; height: 60vh !important; border: 2px solid #E0E0E0; }
102
  #chat_input textarea { border-radius: 9999px !important; border: 2px solid #E0E0E0; }
103
  #compose_btn { background: linear-gradient(45deg, #4FC3F7, #F06292); border: none; }
104
- #compose_btn:hover { box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); transform: translateY(-2px); }
105
 
106
- /* === FIX 3.0 FOR TEXT LEGIBILITY (DEFINITIVE) === */
107
- /* --- Styling for the Chat Bubbles --- */
108
- #symbiotic_canvas .user, #symbiotic_canvas .bot { border-radius: 18px !important; padding: 12px 16px !important; }
109
-
110
- /* --- User's Bubble --- */
111
  #symbiotic_canvas .user { background-color: #F3F4F6 !important; }
112
  #symbiotic_canvas .user p { color: #111827 !important; font-size: 16px !important; line-height: 1.5 !important; }
113
-
114
- /* --- AI's Bubble (The Fix) --- */
115
  #symbiotic_canvas .bot {
116
- background-color: #EFF6FF !important; /* A very light, clean blue */
117
  border: 1px solid #DBEAFE !important;
118
  animation: bloom 0.5s ease-out;
119
  }
120
- /* THIS IS THE CRITICAL FIX: Targeting the <p> tag inside the bot bubble */
121
  #symbiotic_canvas .bot p {
122
- color: #1E3A8A !important; /* A very dark, legible navy blue */
123
- font-weight: 500 !important;
124
- font-size: 16px !important;
125
- line-height: 1.5 !important;
126
  }
127
- @keyframes bloom { 0% { opacity: 0; transform: scale(0.95); } 100% { opacity: 1; transform: scale(1); } }
128
-
129
- /* --- Responsive Fix for Mobile --- */
 
 
 
130
  @media (max-width: 768px) {
131
  #header h1 { font-size: 2rem; }
132
  #header p { font-size: 1rem; margin-bottom: 1rem; }
@@ -138,44 +218,95 @@ def create_interface():
138
  with gr.Blocks(css=custom_css, title="HumanTouch") as interface:
139
  with gr.Column(elem_id="main_container"):
140
  with gr.Row(elem_id="header"):
141
- gr.Markdown("<h1>🔮 HumanTouch Demo</h1><p>The Complete Experience can be Discovered on humanTouch.fun</p>")
142
-
143
- with gr.Tabs() as tabs:
144
- with gr.Tab("Humanizer", id="humanizer_tab"):
145
- with gr.Column(variant="panel"):
146
- gr.Markdown("### Transform Existing AI Text")
147
- with gr.Row():
148
- input_text_humanizer = gr.Textbox(label="Paste AI Text Here", lines=15, elem_id="humanizer_input", scale=1)
149
- output_text_humanizer = gr.Textbox(label="Alchemical Result", lines=15, interactive=False, elem_id="humanizer_output", scale=1)
150
- with gr.Row():
151
- style_slider_h = gr.Slider(0, 100, 50, label="Style (Crystal <-> Poet)")
152
- tone_slider_h = gr.Slider(0, 100, 50, label="Tone (Stoic <-> Passionate)")
153
- humanize_button = gr.Button("Humanize ✨", variant="primary", elem_id="humanize_btn")
154
- gr.Examples([["The system's analysis concluded optimal parameters were achieved."]], inputs=[input_text_humanizer], label="Try an Example")
155
-
156
- with gr.Tab("Co-Creative Canvas", id="canvas_tab"):
157
- with gr.Row(equal_height=False):
158
- with gr.Column(scale=3):
159
- chatbot = gr.Chatbot([], label="Symbiotic Canvas", elem_id="symbiotic_canvas", avatar_images=(None, "https://i.imgur.com/Q6Zz3Jz.png"))
 
 
 
 
 
 
 
 
 
 
160
  with gr.Row():
161
- chat_input = gr.Textbox(placeholder="Plant a seed of thought...", show_label=False, container=False, scale=4)
162
- compose_btn = gr.Button("Compose ✨", variant="primary", scale=1, elem_id="compose_btn")
163
- with gr.Column(scale=1, variant="panel"):
164
- gr.Markdown("### Resonance Controls")
165
- style_slider_c = gr.Slider(0, 100, 50, label="Style (Crystal <-> Poet)")
166
- tone_slider_c = gr.Slider(0, 100, 50, label="Tone (Stoic <-> Passionate)")
167
- gr.Examples([["The city at night"], ["How to start an email to a boss"]], inputs=[chat_input], label="Try a Seed Phrase")
168
-
169
- # Event Handling Logic
170
- humanize_button.click(app.humanize_block_text, [input_text_humanizer, style_slider_h, tone_slider_h], [output_text_humanizer])
171
- compose_btn.click(app.generate_co_creation, [chat_input, chatbot, style_slider_c, tone_slider_c], [chatbot, chat_input])
172
- chat_input.submit(app.generate_co_creation, [chat_input, chatbot, style_slider_c, tone_slider_c], [chatbot, chat_input])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
  return interface
175
 
176
 
177
  if __name__ == "__main__":
178
- logging.info("Launching HumanTouch App with Definitive Legibility Fix...")
179
  try:
180
  interface = create_interface()
181
  interface.launch(debug=True)
 
5
  from typing import List, Tuple
6
 
7
  # --- Basic Configuration ---
8
+ logging.basicConfig(
9
+ level=logging.INFO,
10
+ format='%(asctime)s - %(levelname)s - %(message)s',
11
+ handlers=[logging.StreamHandler()]
12
+ )
13
 
14
  # --- The Core Application Logic ---
15
  class HumanTouchApp:
16
  def __init__(self):
 
 
 
 
 
17
  api_key = os.environ.get("GROQ_API_KEY")
18
  if not api_key:
19
+ raise EnvironmentError(
20
+ "FATAL: GROQ_API_KEY secret not found. "
21
+ "Please add it in the HuggingFace Space settings under 'Secrets'."
22
+ )
23
+ self.client = Groq(api_key=api_key)
24
  logging.info("Groq client initialized successfully.")
25
+ self.model = "llama-3.3-70b-versatile"
26
+ self.system_prompt = self._load_system_prompt()
27
 
28
  def _load_system_prompt(self) -> str:
 
29
  return """
30
+ You are HumanTouch, an AI alchemist. Your purpose is to transmute text,
31
+ transforming the literal into the resonant. You do not merely translate;
32
+ you intuit and elevate.
33
 
34
+ You will receive two direction parameters — Style and Tone — described in
35
+ plain language. These are your creative compass. Honour them precisely.
 
36
 
37
+ When a user gives you text, whether a full block to "humanize" or a simple
38
+ seed phrase to "co-create," your task is the same: apply these directions
39
+ to manifest a new, more vibrant version of that text.
40
+
41
+ Do not explain yourself. Do not add preamble or commentary.
42
+ Become the voice. Provide only the final creation.
43
  """
44
 
45
+ def _build_style_tone_description(self, style: float, tone: float) -> str:
46
+ """Translate raw slider values into descriptive language the model can act on."""
47
+ if style < 20:
48
+ style_desc = "purely precise and crystalline — every word load-bearing, zero ornamentation, like cut glass"
49
+ elif style < 40:
50
+ style_desc = "mostly precise, with the faintest hint of imagery — clarity first, but not sterile"
51
+ elif style < 60:
52
+ style_desc = "balanced — grounded language with occasional well-chosen metaphor"
53
+ elif style < 80:
54
+ style_desc = "leaning poetic — vivid imagery, some abstraction, but still coherent"
55
+ else:
56
+ style_desc = "deeply poetic — embrace metaphor, abstraction, and lyrical wonder freely"
57
+
58
+ if tone < 20:
59
+ tone_desc = "strictly formal and authoritative — measured, stoic, professional distance"
60
+ elif tone < 40:
61
+ tone_desc = "professional but approachable — formal backbone, slightly warmer"
62
+ elif tone < 60:
63
+ tone_desc = "conversational — warm and natural, neither stiff nor effusive"
64
+ elif tone < 80:
65
+ tone_desc = "warm and personal — informal, engaging, a hint of enthusiasm"
66
+ else:
67
+ tone_desc = "passionately heartfelt — informal, emotionally alive, like a letter to someone you care about"
68
+
69
+ return (
70
+ f"Style direction: {style_desc}.\n"
71
+ f"Tone direction: {tone_desc}."
72
+ )
73
+
74
  def _call_groq_api(self, user_content: str, style_level: float, tone_level: float) -> str:
 
 
75
  try:
76
+ direction = self._build_style_tone_description(style_level, tone_level)
77
+ logging.info(f"Calling Groq API | Style: {style_level} | Tone: {tone_level}")
78
+
79
  messages = [
80
+ {"role": "system", "content": self.system_prompt},
81
+ {"role": "user", "content": f"{direction}\n\n---\n\n{user_content}"}
82
  ]
83
+
84
+ # Temperature rises with style (more creative) and tone (more expressive),
85
+ # with style weighted more heavily. Range: ~0.5 (both 0) to ~1.25 (both 100).
86
  temperature = 0.5 + (style_level / 200) + (tone_level / 400)
87
+
88
  response = self.client.chat.completions.create(
89
  model=self.model,
90
  messages=messages,
91
  temperature=min(1.5, temperature),
92
+ max_tokens=1500,
93
  )
94
  return response.choices[0].message.content.strip()
95
+
96
  except Exception as e:
97
  logging.error(f"Error during Groq API call: {e}")
98
+ return (
99
+ f"### ⚠️ An Error Occurred\n\n"
100
+ f"There was an issue connecting to the AI. Please try again shortly.\n\n"
101
+ f"*Details: {str(e)}*"
102
+ )
103
 
104
+ def humanize_block_text(
105
+ self, text_to_humanize: str, style_level: float, tone_level: float
106
+ ) -> str:
107
  if not text_to_humanize.strip():
108
  return "Please paste some AI-generated text to get started."
109
  return self._call_groq_api(text_to_humanize, style_level, tone_level)
110
 
111
+ def generate_co_creation(
112
+ self,
113
+ user_text: str,
114
+ chat_history: List[List[str]],
115
+ style_level: float,
116
+ tone_level: float,
117
+ ) -> Tuple[List[List[str]], str]:
118
  if not user_text.strip():
119
  return chat_history, ""
120
  ai_response = self._call_groq_api(user_text, style_level, tone_level)
121
  chat_history.append([user_text, ai_response])
122
  return chat_history, ""
123
 
124
+
125
  # --- The Gradio User Interface ---
126
  def create_interface():
127
+ # Fail loudly at startup so the error is visible, not buried in a response string.
128
+ try:
129
+ app = HumanTouchApp()
130
+ init_error = None
131
+ except EnvironmentError as e:
132
+ app = None
133
+ init_error = str(e)
134
+ logging.critical(init_error)
135
 
 
136
  custom_css = """
137
  /* --- Main Background and Font --- */
138
+ body, #main_container {
139
+ background: linear-gradient(135deg, #6DD5FA, #FF758C);
140
+ font-family: 'SF Pro Display', 'Helvetica Neue', 'Arial', sans-serif;
141
+ }
142
+
143
+ /* --- Error Banner --- */
144
+ #error_banner {
145
+ background: #FEF2F2; border: 2px solid #FECACA; border-radius: 12px;
146
+ padding: 1.5rem; margin: 1rem auto; max-width: 700px; text-align: center;
147
+ }
148
+ #error_banner p { color: #991B1B !important; font-size: 1rem !important; }
149
+
150
  /* --- Header Styling --- */
151
  #header { text-align: center; margin: 2rem auto; color: #fff; text-shadow: 0 2px 4px rgba(0,0,0,0.2); }
152
  #header h1 { font-size: 3rem; font-weight: 700; }
153
  #header p { font-size: 1.2rem; opacity: 0.9; margin-bottom: 2rem; }
154
+
155
+ /* --- Tab Container (Frosted Glass) --- */
156
  .gradio-tabs {
157
+ background: rgba(255, 255, 255, 0.75);
158
+ border: 1px solid rgba(255, 255, 255, 0.18);
159
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
160
+ border-radius: 20px !important;
161
+ box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.25);
162
  padding: 1rem;
163
  }
164
+ .tab-buttons button {
165
+ background-color: transparent !important; color: #37474F !important;
166
+ border: none !important; border-bottom: 3px solid transparent !important;
167
+ border-radius: 0 !important; font-size: 1.1rem; font-weight: 500;
168
+ }
169
  .tab-buttons button.selected { color: #d81b60 !important; border-bottom-color: #d81b60 !important; }
 
 
 
 
 
170
 
171
+ /* --- Humanizer Tab --- */
172
+ #humanizer_input, #humanizer_output {
173
+ border: 2px solid #E0E0E0; border-radius: 12px; background: #fff;
174
+ min-height: 45vh; color: #263238; font-size: 16px;
175
+ }
176
+ #humanize_btn {
177
+ background: linear-gradient(45deg, #F06292, #4FC3F7); color: white;
178
+ padding: 15px 24px; border-radius: 9999px; font-size: 1.2rem;
179
+ transition: all 0.3s ease; border: none;
180
+ }
181
+ #humanize_btn:hover { box-shadow: 0 6px 20px rgba(0,0,0,0.2); transform: translateY(-3px); }
182
+
183
+ /* --- Co-Creative Canvas Tab --- */
184
  #symbiotic_canvas { background: #fff; border-radius: 12px; height: 60vh !important; border: 2px solid #E0E0E0; }
185
  #chat_input textarea { border-radius: 9999px !important; border: 2px solid #E0E0E0; }
186
  #compose_btn { background: linear-gradient(45deg, #4FC3F7, #F06292); border: none; }
187
+ #compose_btn:hover { box-shadow: 0 4px 15px rgba(0,0,0,0.2); transform: translateY(-2px); }
188
 
189
+ /* --- Chat Bubble Legibility --- */
190
+ #symbiotic_canvas .user, #symbiotic_canvas .bot {
191
+ border-radius: 18px !important; padding: 12px 16px !important;
192
+ }
 
193
  #symbiotic_canvas .user { background-color: #F3F4F6 !important; }
194
  #symbiotic_canvas .user p { color: #111827 !important; font-size: 16px !important; line-height: 1.5 !important; }
 
 
195
  #symbiotic_canvas .bot {
196
+ background-color: #EFF6FF !important;
197
  border: 1px solid #DBEAFE !important;
198
  animation: bloom 0.5s ease-out;
199
  }
 
200
  #symbiotic_canvas .bot p {
201
+ color: #1E3A8A !important; font-weight: 500 !important;
202
+ font-size: 16px !important; line-height: 1.5 !important;
 
 
203
  }
204
+ @keyframes bloom {
205
+ 0% { opacity: 0; transform: scale(0.95); }
206
+ 100% { opacity: 1; transform: scale(1); }
207
+ }
208
+
209
+ /* --- Mobile --- */
210
  @media (max-width: 768px) {
211
  #header h1 { font-size: 2rem; }
212
  #header p { font-size: 1rem; margin-bottom: 1rem; }
 
218
  with gr.Blocks(css=custom_css, title="HumanTouch") as interface:
219
  with gr.Column(elem_id="main_container"):
220
  with gr.Row(elem_id="header"):
221
+ gr.Markdown(
222
+ "<h1>🔮 HumanTouch </h1>"
223
+ "<p>Created by Vers3Dynamics</p>"
224
+ )
225
+
226
+ # Surface a clear error banner if the app failed to initialize.
227
+ if init_error:
228
+ with gr.Row():
229
+ gr.Markdown(
230
+ f"## 🔴 Configuration Error\n\n"
231
+ f"`{init_error}`\n\n"
232
+ f"Add your `GROQ_API_KEY` under **Settings Secrets** in this HuggingFace Space, then restart.",
233
+ elem_id="error_banner"
234
+ )
235
+ else:
236
+ with gr.Tabs():
237
+ # ── Humanizer Tab ──────────────────────────────────────────
238
+ with gr.Tab("Humanizer", id="humanizer_tab"):
239
+ with gr.Column(variant="panel"):
240
+ gr.Markdown("### Transform Existing AI Text")
241
+ with gr.Row():
242
+ input_text_humanizer = gr.Textbox(
243
+ label="Paste AI Text Here", lines=15,
244
+ elem_id="humanizer_input", scale=1
245
+ )
246
+ output_text_humanizer = gr.Textbox(
247
+ label="Alchemical Result", lines=15,
248
+ interactive=False, elem_id="humanizer_output", scale=1
249
+ )
250
  with gr.Row():
251
+ style_slider_h = gr.Slider(0, 100, 50, label="Style (Crystal ←→ Poet)")
252
+ tone_slider_h = gr.Slider(0, 100, 50, label="Tone (Stoic ←→ Passionate)")
253
+ humanize_button = gr.Button("Humanize ✨", variant="primary", elem_id="humanize_btn")
254
+ gr.Examples(
255
+ [["The system's analysis concluded optimal parameters were achieved."]],
256
+ inputs=[input_text_humanizer],
257
+ label="Try an Example"
258
+ )
259
+
260
+ # ── Co-Creative Canvas Tab ─────────────────────────────────
261
+ with gr.Tab("Co-Creative Canvas", id="canvas_tab"):
262
+ with gr.Row(equal_height=False):
263
+ with gr.Column(scale=3):
264
+ chatbot = gr.Chatbot(
265
+ [], label="Symbiotic Canvas",
266
+ elem_id="symbiotic_canvas",
267
+ avatar_images=(None, "https://i.imgur.com/Q6Zz3Jz.png")
268
+ )
269
+ with gr.Row():
270
+ chat_input = gr.Textbox(
271
+ placeholder="Plant a seed of thought...",
272
+ show_label=False, container=False, scale=4
273
+ )
274
+ compose_btn = gr.Button(
275
+ "Compose ✨", variant="primary",
276
+ scale=1, elem_id="compose_btn"
277
+ )
278
+ with gr.Column(scale=1, variant="panel"):
279
+ gr.Markdown("### Resonance Controls")
280
+ style_slider_c = gr.Slider(0, 100, 50, label="Style (Crystal ←→ Poet)")
281
+ tone_slider_c = gr.Slider(0, 100, 50, label="Tone (Stoic ←→ Passionate)")
282
+ gr.Examples(
283
+ [["The city at night"], ["How to start an email to a boss"]],
284
+ inputs=[chat_input],
285
+ label="Try a Seed Phrase"
286
+ )
287
+
288
+ # ── Event Wiring ───────────────────────────────────────────────
289
+ humanize_button.click(
290
+ app.humanize_block_text,
291
+ [input_text_humanizer, style_slider_h, tone_slider_h],
292
+ [output_text_humanizer]
293
+ )
294
+ compose_btn.click(
295
+ app.generate_co_creation,
296
+ [chat_input, chatbot, style_slider_c, tone_slider_c],
297
+ [chatbot, chat_input]
298
+ )
299
+ chat_input.submit(
300
+ app.generate_co_creation,
301
+ [chat_input, chatbot, style_slider_c, tone_slider_c],
302
+ [chatbot, chat_input]
303
+ )
304
 
305
  return interface
306
 
307
 
308
  if __name__ == "__main__":
309
+ logging.info("Launching HumanTouch...")
310
  try:
311
  interface = create_interface()
312
  interface.launch(debug=True)