ciaochris commited on
Commit
da2ccac
·
verified ·
1 Parent(s): 123bfc8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +64 -122
app.py CHANGED
@@ -7,7 +7,6 @@ import json
7
  from typing import List, Dict, Tuple
8
 
9
  # --- Basic Configuration ---
10
- # Configure logging for better debugging in Hugging Face logs
11
  logging.basicConfig(
12
  level=logging.INFO,
13
  format='%(asctime)s - %(levelname)s - %(message)s',
@@ -17,28 +16,20 @@ logging.basicConfig(
17
  # --- The Core Application Logic ---
18
  class HumanTouchApp:
19
  def __init__(self):
20
- # Securely initialize Groq client using Hugging Face Secrets
21
  self.client = self._initialize_groq_client()
22
- self.model = "llama-3.1-70b-versatile" # Using the latest powerful model
23
  self.system_prompt_template = self._load_system_prompt()
24
 
25
  def _initialize_groq_client(self) -> Groq:
26
- """Initialize Groq client, pulling the API key from HF Secrets."""
27
  api_key = os.environ.get("GROQ_API_KEY")
28
  if not api_key:
29
  logging.error("FATAL: GROQ_API_KEY secret not found in Hugging Face Space settings.")
30
- # In a real app, this should raise an error or display a persistent message.
31
- # For this demo, we'll allow it to fail gracefully in the API call.
32
  return None
33
  logging.info("Groq client initialized successfully.")
34
  return Groq(api_key=api_key)
35
 
36
  def _load_system_prompt(self) -> str:
37
- """
38
- Loads the foundational system prompt template.
39
- This prompt is now dynamic and will be formatted with user controls.
40
- """
41
- # ⬇️ PASTE YOUR ORIGINAL SYSTEM PROMPT INSIDE THE TRIPLE QUOTES ⬇️
42
  return """
43
  You are HumanTouch, an AI specializing in transforming text into emotionally resonant communication.
44
  Your persona is determined by the chosen 'Ink Resonance'.
@@ -49,33 +40,33 @@ class HumanTouchApp:
49
  You will receive a user's text and a set of parameters. Your task is to rewrite the text according to these parameters, embodying the specified persona. Do not explain your process; only provide the transformed text.
50
 
51
  Here are the Ink Resonance personalities:
52
- - **Cosmic (Default):** Wise, expansive, slightly mysterious.
53
- - **Ember (Premium):** Passionate, fiery, bold, and direct.
54
- - **Crystal (Premium):** Sharp, analytical, precise, and elegant.
55
- - **Verdant (Premium):** Natural, organic, growing, and holistic.
56
  """
57
 
58
  def generate_response(self, user_text: str, chat_history: List[List[str]], style_level: float, tone_level: float, ink_resonance: str) -> Tuple[List[List[str]], str]:
59
- """
60
- Main function to generate the AI's co-creative response.
61
- This is the new "heart" of the application.
62
- """
63
  if not self.client:
64
- # Display error in chat if the API key is missing
65
- chat_history.append([user_text, "Error: The GROQ_API_KEY is not configured on the server. Please contact the administrator."])
66
  return chat_history, ""
67
 
68
  if not user_text.strip():
69
- # Don't respond to empty input
70
  return chat_history, ""
71
 
72
- # Check for premium features
73
  if ink_resonance in ["Ember", "Crystal", "Verdant"]:
74
- # In a real app, you'd have user authentication. Here, we simulate the paywall.
75
- chat_history.append([user_text, f"The '{ink_resonance}' Ink Resonance is a premium feature. To unlock new AI personalities and support our work, please upgrade! For now, I'll use the default Cosmic ink."])
 
 
 
 
 
 
 
76
  ink_resonance = "Cosmic"
77
 
78
- # Format the dynamic system prompt
79
  dynamic_system_prompt = self.system_prompt_template.format(
80
  ink_personality=ink_resonance,
81
  style_score=style_level,
@@ -86,16 +77,12 @@ class HumanTouchApp:
86
  logging.info(f"Generating response for '{user_text[:30]}...' with Style: {style_level}, Tone: {tone_level}, Ink: {ink_resonance}")
87
 
88
  messages = [{"role": "system", "content": dynamic_system_prompt}]
89
- # Optional: include some history for context, but for this tool, it's often better to be stateless.
90
- # for human, ai in chat_history[-2:]: # last 2 turns
91
- # messages.append({"role": "user", "content": human})
92
- # messages.append({"role": "assistant", "content": ai})
93
  messages.append({"role": "user", "content": user_text})
94
 
95
  response = self.client.chat.completions.create(
96
  model=self.model,
97
  messages=messages,
98
- temperature=0.5 + (style_level / 200) + (tone_level / 200), # Map 0-100 sliders to a sensible temp range
99
  max_tokens=4096,
100
  )
101
  ai_response = response.choices[0].message.content.strip()
@@ -105,141 +92,96 @@ class HumanTouchApp:
105
 
106
  except Exception as e:
107
  logging.error(f"Error during Groq API call: {e}")
108
- ai_response = f"An error occurred while connecting to the AI. Details: {str(e)}"
109
  chat_history.append([user_text, ai_response])
110
 
111
- # Return updated history and clear the input box
112
  return chat_history, ""
113
 
114
-
115
  # --- The Gradio User Interface ---
116
  def create_interface():
117
  app = HumanTouchApp()
118
 
119
- # The new CSS for our "Symbiotic Canvas" vision
120
  custom_css = """
121
- /* --- Main Layout & Background --- */
122
  #main_container { background: #111827; }
123
  #header { text-align: center; margin: 20px auto; color: #E5E7EB; }
124
  #header h1 { font-size: 2.5rem; font-weight: 600; }
125
  #header p { font-size: 1.1rem; color: #9CA3AF; }
126
-
127
- /* --- The Unified Canvas (achieved with gr.Chatbot) --- */
128
  #symbiotic_canvas {
129
- background: #1F2937;
130
- border-radius: 20px;
131
  box-shadow: inset 0 2px 4px 0 rgba(0,0,0,0.5);
132
- height: 60vh !important;
133
- border: 1px solid #374151;
134
  }
135
- /* Style the user's message (Seed Text) */
136
- #symbiotic_canvas .user { background-color: transparent !important; color: #F9FAFB; }
137
- /* Style the AI's message (Bloomed Text) and add the animation */
138
  #symbiotic_canvas .bot { background-color: transparent !important; color: #A7F3D0; animation: bloom 0.7s ease-in-out; }
139
- @keyframes bloom {
140
- 0% { opacity: 0; transform: translateY(10px) scale(0.98); }
141
- 100% { opacity: 1; transform: translateY(0) scale(1); }
142
- }
143
-
144
- /* --- The Control Deck --- */
145
- #control_deck {
146
- background: #1F2937;
147
- padding: 20px;
148
- border-radius: 20px;
149
- border: 1px solid #374151;
150
- }
151
- #control_deck .gradio-slider label span { color: #D1D5DB; } /* Slider labels */
152
-
153
- /* --- Ink Resonances (Radio Buttons styled as icons) --- */
154
  #ink_selector { gap: 1rem; }
155
  #ink_selector .gradio-radio label {
156
- background: #374151 !important; color: #E5E7EB !important;
157
- padding: 10px 15px !important; border-radius: 12px !important;
158
- border: 2px solid transparent !important; transition: all 0.2s ease-in-out;
159
  }
 
160
  #ink_selector .gradio-radio input:checked + label {
161
  border-color: #34D399 !important; background: #10B981 !important;
162
  box-shadow: 0 0 15px rgba(16, 185, 129, 0.5);
163
  }
164
- /* Style for premium/locked inks */
165
- #ink_selector .gradio-radio:nth-child(n+2) label:after {
166
- content: '🔒'; /* lock emoji */
167
- margin-left: 8px; font-size: 0.8em;
168
- }
169
- #ink_selector .gradio-radio:nth-child(1) label:after {
170
- content: '✨'; /* default emoji */
171
- margin-left: 8px; font-size: 0.8em;
172
- }
173
-
174
- /* --- The Input Bar --- */
175
- #chat_input textarea {
176
- background-color: #374151; color: #F9FAFB;
177
- border: 1px solid #4B5563; border-radius: 15px !important;
178
- }
179
  """
180
 
181
  with gr.Blocks(css=custom_css, theme=gr.themes.Base(), title="HumanTouch") as interface:
182
  with gr.Column(elem_id="main_container"):
183
- # Header
184
  with gr.Row(elem_id="header"):
185
- gr.Markdown("""
186
- # ✨ HumanTouch
187
- <p>A Symbiotic Canvas for Co-Creative Writing</p>
188
- """)
189
 
190
- # The main UI: Canvas on the left, Controls on the right
191
  with gr.Row(equal_height=False):
192
  with gr.Column(scale=3):
193
- chatbot = gr.Chatbot(
194
- [],
195
- label="Symbiotic Canvas",
196
- elem_id="symbiotic_canvas",
197
- bubble_full_width=True,
198
- avatar_images=(None, "https://i.imgur.com/Q6Zz3Jz.png") # User has none, Bot has a simple avatar
199
- )
200
- chat_input = gr.Textbox(
201
- placeholder="Start your thought here... (Press Enter to submit)",
202
- elem_id="chat_input",
203
- show_label=False,
204
- container=False
205
- )
206
 
207
  with gr.Column(scale=1, elem_id="control_deck"):
208
- gr.Markdown("### Resonance Controls")
209
- style_slider = gr.Slider(
210
- 0, 100, 50, step=1,
211
- label="Style",
212
- info="Logical (0) <-> Poetic (100)"
213
- )
214
- tone_slider = gr.Slider(
215
- 0, 100, 50, step=1,
216
- label="Tone",
217
- info="Formal (0) <-> Passionate (100)"
218
- )
219
 
220
  gr.Markdown("### Ink Resonance")
221
- ink_choice = gr.Radio(
222
- ["Cosmic", "Ember", "Crystal", "Verdant"],
223
- value="Cosmic",
224
- label="Select AI Personality",
225
- show_label=False,
226
- elem_id="ink_selector"
227
- )
 
 
 
 
228
 
229
  # Event Handling Logic
230
- chat_input.submit(
231
- app.generate_response,
232
- [chat_input, chatbot, style_slider, tone_slider, ink_choice],
233
- [chatbot, chat_input] # Update chatbot and clear input
234
- )
 
 
235
 
236
  return interface
237
 
238
 
239
  if __name__ == "__main__":
240
- logging.info("Launching HumanTouch App with new Symbiotic UI...")
241
  try:
242
  interface = create_interface()
243
- interface.launch(debug=True) # Share=True is not recommended for local dev with secrets
244
  except Exception as e:
245
  logging.critical(f"Application launch failed: {e}", exc_info=True)
 
7
  from typing import List, Dict, Tuple
8
 
9
  # --- Basic Configuration ---
 
10
  logging.basicConfig(
11
  level=logging.INFO,
12
  format='%(asctime)s - %(levelname)s - %(message)s',
 
16
  # --- The Core Application Logic ---
17
  class HumanTouchApp:
18
  def __init__(self):
 
19
  self.client = self._initialize_groq_client()
20
+ self.model = "llama-3.1-70b-versatile"
21
  self.system_prompt_template = self._load_system_prompt()
22
 
23
  def _initialize_groq_client(self) -> Groq:
 
24
  api_key = os.environ.get("GROQ_API_KEY")
25
  if not api_key:
26
  logging.error("FATAL: GROQ_API_KEY secret not found in Hugging Face Space settings.")
 
 
27
  return None
28
  logging.info("Groq client initialized successfully.")
29
  return Groq(api_key=api_key)
30
 
31
  def _load_system_prompt(self) -> str:
32
+ # ⬇️ PASTE YOUR UNIQUE SYSTEM PROMPT LOGIC HERE ⬇️
 
 
 
 
33
  return """
34
  You are HumanTouch, an AI specializing in transforming text into emotionally resonant communication.
35
  Your persona is determined by the chosen 'Ink Resonance'.
 
40
  You will receive a user's text and a set of parameters. Your task is to rewrite the text according to these parameters, embodying the specified persona. Do not explain your process; only provide the transformed text.
41
 
42
  Here are the Ink Resonance personalities:
43
+ - **Cosmic (Default):** Wise, expansive, slightly mysterious, and thought-provoking.
44
+ - **Ember (Premium):** Passionate, fiery, bold, and direct. Uses strong verbs and evocative imagery.
45
+ - **Crystal (Premium):** Sharp, analytical, precise, and elegant. Values clarity and structure above all.
46
+ - **Verdant (Premium):** Natural, organic, growing, and holistic. Uses metaphors from nature and life cycles.
47
  """
48
 
49
  def generate_response(self, user_text: str, chat_history: List[List[str]], style_level: float, tone_level: float, ink_resonance: str) -> Tuple[List[List[str]], str]:
 
 
 
 
50
  if not self.client:
51
+ chat_history.append([user_text, "## 🔴 Configuration Error\n\nThe `GROQ_API_KEY` is not set on the server. Please contact the Space administrator."])
 
52
  return chat_history, ""
53
 
54
  if not user_text.strip():
 
55
  return chat_history, ""
56
 
57
+ # Premium Feature Simulation
58
  if ink_resonance in ["Ember", "Crystal", "Verdant"]:
59
+ upsell_message = f"""
60
+ ### Unlock the '{ink_resonance}' Resonance
61
+ The fiery, passionate voice of the **Ember** ink is a premium feature.
62
+
63
+ Upgrading gives you access to all unique AI personalities, allowing you to perfectly match your tone for any occasion.
64
+
65
+ *(For now, I'll respond with the default Cosmic ink.)*
66
+ """
67
+ chat_history.append([user_text, upsell_message])
68
  ink_resonance = "Cosmic"
69
 
 
70
  dynamic_system_prompt = self.system_prompt_template.format(
71
  ink_personality=ink_resonance,
72
  style_score=style_level,
 
77
  logging.info(f"Generating response for '{user_text[:30]}...' with Style: {style_level}, Tone: {tone_level}, Ink: {ink_resonance}")
78
 
79
  messages = [{"role": "system", "content": dynamic_system_prompt}]
 
 
 
 
80
  messages.append({"role": "user", "content": user_text})
81
 
82
  response = self.client.chat.completions.create(
83
  model=self.model,
84
  messages=messages,
85
+ temperature=0.6 + (style_level / 250) + (tone_level / 250),
86
  max_tokens=4096,
87
  )
88
  ai_response = response.choices[0].message.content.strip()
 
92
 
93
  except Exception as e:
94
  logging.error(f"Error during Groq API call: {e}")
95
+ ai_response = f"### ⚠️ An Error Occurred\n\nThere was an issue connecting to the AI. Please try again shortly. \n\n*Details: {str(e)}*"
96
  chat_history.append([user_text, ai_response])
97
 
 
98
  return chat_history, ""
99
 
 
100
  # --- The Gradio User Interface ---
101
  def create_interface():
102
  app = HumanTouchApp()
103
 
 
104
  custom_css = """
 
105
  #main_container { background: #111827; }
106
  #header { text-align: center; margin: 20px auto; color: #E5E7EB; }
107
  #header h1 { font-size: 2.5rem; font-weight: 600; }
108
  #header p { font-size: 1.1rem; color: #9CA3AF; }
 
 
109
  #symbiotic_canvas {
110
+ background: #1F2937; border-radius: 20px;
 
111
  box-shadow: inset 0 2px 4px 0 rgba(0,0,0,0.5);
112
+ height: 65vh !important; border: 1px solid #374151;
 
113
  }
114
+ #symbiotic_canvas .user { background-color: transparent !important; color: #F9FAFB; border: 1px solid #4B5563; }
 
 
115
  #symbiotic_canvas .bot { background-color: transparent !important; color: #A7F3D0; animation: bloom 0.7s ease-in-out; }
116
+ @keyframes bloom { 0% { opacity: 0; transform: translateY(10px) scale(0.98); } 100% { opacity: 1; transform: translateY(0) scale(1); } }
117
+ #control_deck { background: #1F2937; padding: 20px; border-radius: 20px; border: 1px solid #374151; }
118
+ #control_deck .gradio-slider label span { color: #D1D5DB; }
 
 
 
 
 
 
 
 
 
 
 
 
119
  #ink_selector { gap: 1rem; }
120
  #ink_selector .gradio-radio label {
121
+ background: #374151 !important; color: #E5E7EB !important; padding: 10px 15px !important;
122
+ border-radius: 12px !important; border: 2px solid transparent !important; transition: all 0.2s ease-in-out;
 
123
  }
124
+ #ink_selector .gradio-radio label:hover { border-color: #4B5563 !important; }
125
  #ink_selector .gradio-radio input:checked + label {
126
  border-color: #34D399 !important; background: #10B981 !important;
127
  box-shadow: 0 0 15px rgba(16, 185, 129, 0.5);
128
  }
129
+ #ink_selector .gradio-radio:nth-child(n+2) label:after { content: '🔒'; margin-left: 8px; font-size: 0.8em; }
130
+ #ink_selector .gradio-radio:nth-child(1) label:after { content: '✨'; margin-left: 8px; font-size: 0.8em; }
131
+ #chat_input_row { padding: 10px 0; }
132
+ #chat_input textarea { background-color: #374151; color: #F9FAFB; border: 1px solid #4B5563; border-radius: 15px !important; }
133
+ #submit_button { background: #10B981; color: white; font-weight: bold; }
134
+ #clear_button { background: #4B5563; }
 
 
 
 
 
 
 
 
 
135
  """
136
 
137
  with gr.Blocks(css=custom_css, theme=gr.themes.Base(), title="HumanTouch") as interface:
138
  with gr.Column(elem_id="main_container"):
 
139
  with gr.Row(elem_id="header"):
140
+ gr.Markdown("<h1>✨ HumanTouch</h1><p>A Symbiotic Canvas for Co-Creative Writing</p>")
 
 
 
141
 
 
142
  with gr.Row(equal_height=False):
143
  with gr.Column(scale=3):
144
+ chatbot = gr.Chatbot([], label="Symbiotic Canvas", elem_id="symbiotic_canvas", bubble_full_width=True, avatar_images=(None, "https://i.imgur.com/Q6Zz3Jz.png"))
145
+
146
+ with gr.Row(elem_id="chat_input_row"):
147
+ chat_input = gr.Textbox(placeholder="Start your thought here...", show_label=False, container=False, scale=5)
148
+ clear_btn = gr.Button("New Canvas", elem_id="clear_button", scale=1)
149
+ submit_btn = gr.Button("Compose ✨", variant="primary", elem_id="submit_button", scale=1)
 
 
 
 
 
 
 
150
 
151
  with gr.Column(scale=1, elem_id="control_deck"):
152
+ gr.Markdown("### Resonance Controls <p style='font-size:0.9rem; color:#9CA3AF;'>Adjust these to influence the AI's next response.</p>")
153
+ style_slider = gr.Slider(0, 100, 50, step=1, label="Style", info="Logical (0) <-> Poetic (100)")
154
+ tone_slider = gr.Slider(0, 100, 50, step=1, label="Tone", info="Formal (0) <-> Passionate (100)")
 
 
 
 
 
 
 
 
155
 
156
  gr.Markdown("### Ink Resonance")
157
+ ink_choice = gr.Radio(["Cosmic", "Ember", "Crystal", "Verdant"], value="Cosmic", label="Select AI Personality", show_label=False, elem_id="ink_selector")
158
+
159
+ gr.Examples(
160
+ examples=[
161
+ "Let's finalize the Q3 report.",
162
+ "The city at night is a complex tapestry of light and sound.",
163
+ "I'm not sure how to start this email.",
164
+ ],
165
+ inputs=[chat_input],
166
+ label="Try an Example"
167
+ )
168
 
169
  # Event Handling Logic
170
+ def clear_chat():
171
+ return [], ""
172
+
173
+ # Wire up all events
174
+ submit_btn.click(app.generate_response, [chat_input, chatbot, style_slider, tone_slider, ink_choice], [chatbot, chat_input])
175
+ chat_input.submit(app.generate_response, [chat_input, chatbot, style_slider, tone_slider, ink_choice], [chatbot, chat_input])
176
+ clear_btn.click(clear_chat, [], [chatbot, chat_input])
177
 
178
  return interface
179
 
180
 
181
  if __name__ == "__main__":
182
+ logging.info("Launching HumanTouch App with complete UI...")
183
  try:
184
  interface = create_interface()
185
+ interface.launch(debug=True)
186
  except Exception as e:
187
  logging.critical(f"Application launch failed: {e}", exc_info=True)