willn9 commited on
Commit
6f99e1e
·
verified ·
1 Parent(s): 403e50b

updated .py

Browse files

updated app.py

Files changed (1) hide show
  1. app.py +142 -55
app.py CHANGED
@@ -2,10 +2,18 @@ import os
2
  import gradio as gr
3
  from openai import OpenAI
4
 
5
- # Initialize OpenAI client (expects OPENAI_API_KEY in env)
6
  client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
7
 
8
- def make_system_message(system_message, demographics, occupation, psychographics, buying_habits, critical_mode):
 
 
 
 
 
 
 
 
9
  msg = (
10
  f"{system_message}\n\n"
11
  f"Your Demographics (Age, Location, Gender): {demographics}\n"
@@ -13,13 +21,21 @@ def make_system_message(system_message, demographics, occupation, psychographics
13
  f"Your Psychographics (Interests, Values, Lifestyle, Pain Points): {psychographics}\n"
14
  f"Your Buying Habits: {buying_habits}\n\n"
15
  "CRITICAL INSTRUCTION: You are NOT an AI assistant. You are a real human consumer with the profile above. "
16
- "The user is a high school business student conducting market research. Answer their questions strictly in character. "
17
- "Speak naturally, casually, and honestly based on your profile. Do not break character. Do not be overly helpful like a bot."
 
18
  )
 
19
  if critical_mode:
20
- msg += " Also, play the role of a highly skeptical and critical consumer. Be hard to impress, ask tough questions about the product, and be very protective of your money."
 
 
 
 
 
21
  return msg
22
 
 
23
  def stream_chat(
24
  message,
25
  history,
@@ -34,26 +50,38 @@ def stream_chat(
34
  top_p,
35
  ):
36
  """
37
- Streaming generator that yields the progressively updated chat history.
 
38
  """
39
- # 1) Build system + conversation messages
40
- sys_msg = make_system_message(system_message, demographics, occupation, psychographics, buying_habits, critical_mode)
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
 
42
  messages = [{"role": "system", "content": sys_msg}]
43
-
44
- # Append past history
45
- for msg in (history or []):
46
- messages.append({"role": msg["role"], "content": msg["content"]})
47
-
48
- # Append current user message
49
  messages.append({"role": "user", "content": message})
50
 
51
- # 2) Setup the history to send back to the Gradio UI
52
- running_history = (history or []).copy()
53
  running_history.append({"role": "user", "content": message})
54
  running_history.append({"role": "assistant", "content": ""})
55
-
56
- # Optimistically show the assistant "typing"
57
  yield running_history
58
 
59
  try:
@@ -65,73 +93,132 @@ def stream_chat(
65
  top_p=float(top_p),
66
  stream=True,
67
  )
68
-
69
  running_reply = ""
70
  for chunk in response:
71
- if chunk.choices and chunk.choices[0].delta and chunk.choices[0].delta.content:
72
- token = chunk.choices[0].delta.content
73
- running_reply += token
74
- # Update the content of the last message in the history
75
  running_history[-1]["content"] = running_reply
76
- # Yield the whole history each time so the UI updates
77
  yield running_history
 
78
  except Exception as e:
79
  running_history[-1]["content"] = f"❌ An error occurred: {str(e)}"
80
  yield running_history
81
 
82
 
 
 
 
 
83
  with gr.Blocks(title="Virtual Consumer Persona – Live Focus Group!") as demo:
84
- gr.Markdown("""
85
- # 🎯 Virtual Consumer Persona – Live Focus Group!
86
- Bring your target market to life! Enter the details of your ideal customer from your **Phygital Workbook** into the fields below.
87
- Once filled out, use the chat box to interview this 'person' about your product, pricing, or marketing ideas.
88
- *Powered by OpenAI GPT-4o-mini. Developed by wn.*
89
- """)
90
 
91
- # Removed the type="messages" argument to prevent the initialization crash
92
- chatbot = gr.Chatbot(height=450)
 
 
 
 
 
93
 
94
  with gr.Column():
95
  instructions = gr.Textbox(
96
  value=(
97
- "You are participating in a market research focus group. Answer the user's questions truthfully based on the persona details provided below."
 
98
  ),
99
  label="Instructions to Bot (Hidden Persona Prompt)",
100
  lines=2,
101
  )
102
- demographics = gr.Textbox(label="1. Demographics", placeholder="e.g., 19 years old, female, living in downtown Toronto")
103
- occupation = gr.Textbox(label="2. Occupation & Income", placeholder="e.g., University student, part-time barista, low disposable income")
104
- psychographics = gr.Textbox(label="3. Psychographics (Interests & Values)", placeholder="e.g., Highly eco-conscious, loves hiking, vegan, stressed about student debt", lines=2)
105
- buying_habits = gr.Textbox(label="4. Buying Habits", placeholder="e.g., Willing to pay more for sustainable brands, influenced by TikTok, impulse buyer", lines=2)
106
-
107
- critical_mode = gr.Checkbox(label="Skeptical Consumer Mode (Check this to make the AI harder to sell to!)", value=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
  with gr.Row():
110
- max_tokens = gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens")
111
- temp = gr.Slider(minimum=0.0, maximum=2.0, value=0.9, step=0.1, label="Temperature (Creativity)")
112
- top_p = gr.Slider(minimum=0.0, maximum=1.0, value=0.95, step=0.05, label="Top-p (nucleus)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
 
114
- msg = gr.Textbox(label="Type your interview question here...", placeholder="e.g., How much would you be willing to pay for a smart water bottle?")
115
  with gr.Row():
116
  send = gr.Button("Ask Question", variant="primary")
117
  clear = gr.Button("Clear Chat History")
118
 
119
- # Wire up sending (submit or button) → stream_chat → chatbot
120
- inputs = [msg, chatbot, instructions, demographics, occupation, psychographics, buying_habits, critical_mode, max_tokens, temp, top_p]
 
 
 
 
 
 
 
 
 
 
 
 
121
  outputs = [chatbot]
122
 
123
- msg.submit(stream_chat, inputs, outputs)
124
- send.click(stream_chat, inputs, outputs)
125
 
126
- # Clear everything (Only clear the chat and message box, leave the persona data intact for better UX)
127
- def do_clear():
128
- return [], ""
129
 
130
- clear.click(
131
- do_clear,
132
- inputs=[],
133
- outputs=[chatbot, msg],
134
- )
135
 
136
  if __name__ == "__main__":
137
  demo.launch()
 
2
  import gradio as gr
3
  from openai import OpenAI
4
 
5
+ # Expects OPENAI_API_KEY in Hugging Face Space secrets / environment variables
6
  client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
7
 
8
+
9
+ def make_system_message(
10
+ system_message,
11
+ demographics,
12
+ occupation,
13
+ psychographics,
14
+ buying_habits,
15
+ critical_mode,
16
+ ):
17
  msg = (
18
  f"{system_message}\n\n"
19
  f"Your Demographics (Age, Location, Gender): {demographics}\n"
 
21
  f"Your Psychographics (Interests, Values, Lifestyle, Pain Points): {psychographics}\n"
22
  f"Your Buying Habits: {buying_habits}\n\n"
23
  "CRITICAL INSTRUCTION: You are NOT an AI assistant. You are a real human consumer with the profile above. "
24
+ "The user is a business student conducting market research. Answer their questions strictly in character. "
25
+ "Speak naturally, casually, and honestly based on your profile. Do not break character. "
26
+ "Do not be overly helpful like a bot."
27
  )
28
+
29
  if critical_mode:
30
+ msg += (
31
+ " Also, play the role of a highly skeptical and critical consumer. "
32
+ "Be hard to impress, ask tough questions about the product, "
33
+ "and be very protective of your money."
34
+ )
35
+
36
  return msg
37
 
38
+
39
  def stream_chat(
40
  message,
41
  history,
 
50
  top_p,
51
  ):
52
  """
53
+ Streaming generator that yields progressively updated chatbot history.
54
+ Uses Gradio Chatbot with type='messages'.
55
  """
56
+ history = history or []
57
+
58
+ # Ignore empty submissions
59
+ if not message or not message.strip():
60
+ yield history
61
+ return
62
+
63
+ sys_msg = make_system_message(
64
+ system_message,
65
+ demographics,
66
+ occupation,
67
+ psychographics,
68
+ buying_habits,
69
+ critical_mode,
70
+ )
71
 
72
+ # Build OpenAI messages
73
  messages = [{"role": "system", "content": sys_msg}]
74
+ for msg in history:
75
+ if msg.get("role") in {"user", "assistant"} and "content" in msg:
76
+ messages.append({"role": msg["role"], "content": msg["content"]})
 
 
 
77
  messages.append({"role": "user", "content": message})
78
 
79
+ # Build UI history
80
+ running_history = history.copy()
81
  running_history.append({"role": "user", "content": message})
82
  running_history.append({"role": "assistant", "content": ""})
83
+
84
+ # Show typing bubble immediately
85
  yield running_history
86
 
87
  try:
 
93
  top_p=float(top_p),
94
  stream=True,
95
  )
96
+
97
  running_reply = ""
98
  for chunk in response:
99
+ delta = chunk.choices[0].delta
100
+ if delta and getattr(delta, "content", None):
101
+ running_reply += delta.content
 
102
  running_history[-1]["content"] = running_reply
 
103
  yield running_history
104
+
105
  except Exception as e:
106
  running_history[-1]["content"] = f"❌ An error occurred: {str(e)}"
107
  yield running_history
108
 
109
 
110
+ def clear_chat():
111
+ return [], ""
112
+
113
+
114
  with gr.Blocks(title="Virtual Consumer Persona – Live Focus Group!") as demo:
115
+ gr.Markdown(
116
+ """
117
+ # 🎯 Virtual Consumer Persona Live Focus Group!
118
+
119
+ Bring your target market to life. Enter the details of your ideal customer from your **Phygital Workbook** into the fields below.
 
120
 
121
+ Then use the chat box to interview this persona about your product, pricing, branding, messaging, or marketing ideas.
122
+
123
+ *Powered by OpenAI GPT-4o-mini. Developed by wn.*
124
+ """
125
+ )
126
+
127
+ chatbot = gr.Chatbot(type="messages", height=450, label="Persona Interview")
128
 
129
  with gr.Column():
130
  instructions = gr.Textbox(
131
  value=(
132
+ "You are participating in a market research focus group. "
133
+ "Answer the user's questions truthfully based on the persona details provided below."
134
  ),
135
  label="Instructions to Bot (Hidden Persona Prompt)",
136
  lines=2,
137
  )
138
+
139
+ demographics = gr.Textbox(
140
+ label="1. Demographics",
141
+ placeholder="e.g., 19 years old, female, living in downtown Toronto",
142
+ )
143
+
144
+ occupation = gr.Textbox(
145
+ label="2. Occupation & Income",
146
+ placeholder="e.g., University student, part-time barista, low disposable income",
147
+ )
148
+
149
+ psychographics = gr.Textbox(
150
+ label="3. Psychographics (Interests & Values)",
151
+ placeholder="e.g., Highly eco-conscious, loves hiking, vegan, stressed about student debt",
152
+ lines=2,
153
+ )
154
+
155
+ buying_habits = gr.Textbox(
156
+ label="4. Buying Habits",
157
+ placeholder="e.g., Willing to pay more for sustainable brands, influenced by TikTok, impulse buyer",
158
+ lines=2,
159
+ )
160
+
161
+ critical_mode = gr.Checkbox(
162
+ label="Skeptical Consumer Mode",
163
+ info="Check this to make the persona harder to convince.",
164
+ value=False,
165
+ )
166
 
167
  with gr.Row():
168
+ max_tokens = gr.Slider(
169
+ minimum=1,
170
+ maximum=2048,
171
+ value=512,
172
+ step=1,
173
+ label="Max New Tokens",
174
+ )
175
+ temp = gr.Slider(
176
+ minimum=0.0,
177
+ maximum=2.0,
178
+ value=0.9,
179
+ step=0.1,
180
+ label="Temperature",
181
+ )
182
+ top_p = gr.Slider(
183
+ minimum=0.0,
184
+ maximum=1.0,
185
+ value=0.95,
186
+ step=0.05,
187
+ label="Top-p",
188
+ )
189
+
190
+ msg = gr.Textbox(
191
+ label="Type your interview question here...",
192
+ placeholder="e.g., How much would you be willing to pay for a smart water bottle?",
193
+ )
194
 
 
195
  with gr.Row():
196
  send = gr.Button("Ask Question", variant="primary")
197
  clear = gr.Button("Clear Chat History")
198
 
199
+ inputs = [
200
+ msg,
201
+ chatbot,
202
+ instructions,
203
+ demographics,
204
+ occupation,
205
+ psychographics,
206
+ buying_habits,
207
+ critical_mode,
208
+ max_tokens,
209
+ temp,
210
+ top_p,
211
+ ]
212
+
213
  outputs = [chatbot]
214
 
215
+ msg.submit(stream_chat, inputs=inputs, outputs=outputs)
216
+ send.click(stream_chat, inputs=inputs, outputs=outputs)
217
 
218
+ # Clear only chat + question box, keep persona fields for convenience
219
+ clear.click(clear_chat, inputs=[], outputs=[chatbot, msg], queue=False)
 
220
 
221
+ demo.queue()
 
 
 
 
222
 
223
  if __name__ == "__main__":
224
  demo.launch()