Merkle_AI_agent / app.py
Adritbgh's picture
Update app.py
bcc4183 verified
Raw
History Blame Contribute Delete
10.1 kB
import os
import requests
from openai import OpenAI
from quiz_data import PROFILES, QUESTIONS
# OpenAI lit OPENAI_API_KEY dans les variables d'environnement du Space
client = OpenAI()
print("OPENAI_API_KEY set:", bool(os.environ.get("OPENAI_API_KEY")))
# ⚠️ À remplacer par ton vrai Form Handler Pardot
PARDOT_FORM_HANDLER_URL = " http://go.demo.pardot.com/l/718473/2025-11-20/3jhj"
def start_state():
return {
"current_question_index": 0,
"answers": [], # list of {id, question, answer, profile}
"profile_counts": {
"time_saver": 0,
"voice_amplifier": 0,
"insight_alchemist": 0,
"revenue_uplifter": 0,
},
"final_profile_key": None,
"finished": False,
}
def welcome():
return [
(
"agent",
"Hi there, I’m your Agentic AI Personality Guide 🤖\n\n"
"I’ll ask you 5 quick questions to understand how agentic AI should work for you: "
"saving time, amplifying your brand voice, uncovering insights, or driving revenue.",
),
("agent", "Ready? Let’s start with question 1."),
]
def compute_winning_profile(profile_counts):
priority_order = [
"time_saver",
"voice_amplifier",
"insight_alchemist",
"revenue_uplifter",
]
best_key = None
best_score = -1
for key, score in profile_counts.items():
if score > best_score:
best_score = score
best_key = key
elif score == best_score and best_score > -1:
if priority_order.index(key) < priority_order.index(best_key):
best_key = key
return best_key
def format_messages_for_ui(messages):
chat = []
for role, text in messages:
if role == "user":
chat.append([text, ""])
else:
chat.append(["", text])
return chat
def next_question_text(state):
idx = state["current_question_index"]
if idx >= len(QUESTIONS):
return None
return QUESTIONS[idx]["text"]
def get_current_options(state):
idx = state["current_question_index"]
if idx >= len(QUESTIONS):
return []
q = QUESTIONS[idx]
return [opt[0] for opt in q["options"]]
def generate_gpt_summary(profile, answers):
answers_text = "\n".join(
[f"- {a['question']}: {a['answer']}" for a in answers]
)
prompt = f"""
You are a friendly Merkle assistant at an event.
The user's Agentic AI personality result is: {profile['result_title']}.
Here is the detailed description of this profile:
{profile['result_body']}
Here are the answers they selected:
{answers_text}
Write a SHORT conversational summary (4–6 lines max), in English, as if you were speaking directly to the user.
Be warm but professional. Start by naming the profile, then highlight 2–3 key ideas and 1 very concrete next step.
Do not repeat the full text above, just synthesize it.
"""
try:
completion = client.chat.completions.create(
model="gpt-4.1-mini",
messages=[
{
"role": "system",
"content": "You are a concise, friendly event assistant from Merkle.",
},
{"role": "user", "content": prompt},
],
temperature=0.6,
)
return completion.choices[0].message.content.strip()
except Exception:
return (
f"{profile['result_title']}\n\n"
f"{profile['result_body']}\n\n"
"(We couldn’t generate a dynamic summary, so here is the static description.)"
)
def chat_step(selected_option, state, history):
if state is None:
state = start_state()
messages = welcome()
else:
messages = []
for u, b in history:
if u:
messages.append(("user", u))
if b:
messages.append(("agent", b))
if state["finished"]:
messages.append(
(
"agent",
"You already have your Agentic AI profile. If you’d like to restart, refresh the page.",
)
)
chat = format_messages_for_ui(messages)
return chat, state, gr.update(choices=[], interactive=False), "", ""
if state["current_question_index"] == 0 and not state["answers"] and not selected_option:
q_text = next_question_text(state)
messages.append(("agent", q_text))
chat = format_messages_for_ui(messages)
options = get_current_options(state)
return chat, state, gr.update(choices=options, value=None, interactive=True), "", ""
if selected_option:
idx = state["current_question_index"]
q = QUESTIONS[idx]
profile = None
for opt_text, prof in q["options"]:
if opt_text == selected_option:
profile = prof
break
state["answers"].append(
{
"id": q["id"],
"question": q["text"],
"answer": selected_option,
"profile": profile,
}
)
state["profile_counts"][profile] += 1
messages.append(("user", selected_option))
messages.append(("agent", "Got it, thanks. Let’s move on."))
state["current_question_index"] += 1
if state["current_question_index"] < len(QUESTIONS):
q_text = next_question_text(state)
messages.append(("agent", q_text))
chat = format_messages_for_ui(messages)
options = get_current_options(state)
return chat, state, gr.update(choices=options, value=None, interactive=True), "", ""
winning_key = compute_winning_profile(state["profile_counts"])
state["final_profile_key"] = winning_key
state["finished"] = True
profile_data = PROFILES[winning_key]
summary = generate_gpt_summary(profile_data, state["answers"])
messages.append(("agent", f"Your Agentic AI personality: {profile_data['label']}"))
messages.append(("agent", summary))
chat = format_messages_for_ui(messages)
email_subject = profile_data["email_subject"]
email_body = profile_data["email_template"]
return (
chat,
state,
gr.update(choices=[], value=None, interactive=False),
email_subject,
email_body,
)
chat = format_messages_for_ui(messages)
options = get_current_options(state)
return chat, state, gr.update(choices=options, value=None, interactive=True), "", ""
def send_to_pardot(state, first_name, email, history):
messages = []
for u, b in history:
if u:
messages.append(("user", u))
if b:
messages.append(("agent", b))
if not state["finished"] or not state["final_profile_key"]:
messages.append(
("agent", "Let’s first finish the 5 questions so I can determine your profile. 🙂")
)
chat = format_messages_for_ui(messages)
return chat, state
if not email:
messages.append(
("agent", "Could you please add your work email so we can log your result?")
)
chat = format_messages_for_ui(messages)
return chat, state
if not PARDOT_FORM_HANDLER_URL:
messages.append(
("agent",
"Pardot integration is not configured yet (no Form Handler URL). "
"Your result is still available above.")
)
chat = format_messages_for_ui(messages)
return chat, state
profile_key = state["final_profile_key"]
profile = PROFILES[profile_key]
data = {
"firstname": first_name or "",
"email": email,
"profile_key": profile["key"],
"profile_label": profile["label"],
}
for idx, answer in enumerate(state["answers"], start=1):
data[f"q{idx}_id"] = answer["id"]
data[f"q{idx}_text"] = answer["answer"]
data[f"q{idx}_profile"] = answer["profile"]
try:
requests.post(PARDOT_FORM_HANDLER_URL, data=data, timeout=5)
messages.append(
("agent",
"Got it ✅ I’ve sent your profile and answers to the Merkle team. "
"They can now follow up with ideas tailored to your result.")
)
except Exception:
messages.append(
("agent",
"I’m sorry — I couldn’t send your data to our system. "
"You can still copy the email template and send it manually.")
)
chat = format_messages_for_ui(messages)
return chat, state
with gr.Blocks(css="#chatbot {height: 480px;}") as demo:
gr.Markdown(
"### Agentic AI Personality Chat\n"
"Answer 5 quick questions to discover your Agentic AI personality."
)
state = gr.State(start_state())
chatbot = gr.Chatbot(
value=[["", m[1]] for m in welcome()],
elem_id="chatbot"
)
with gr.Row():
options = gr.Radio(
choices=get_current_options(start_state()),
label="Choose your answer",
interactive=True,
)
gr.Markdown("#### Share your result with the Merkle team")
with gr.Row():
first_name_tb = gr.Textbox(label="First name")
email_tb = gr.Textbox(label="Work email")
send_btn = gr.Button("Send my result to Merkle")
gr.Markdown("#### Optional email template")
email_subject = gr.Textbox(label="Email subject", interactive=False)
email_body = gr.Textbox(
label="Email body (copy-paste and update with your name + email)",
lines=8,
interactive=False,
)
options.change(
fn=chat_step,
inputs=[options, state, chatbot],
outputs=[chatbot, state, options, email_subject, email_body],
)
send_btn.click(
fn=send_to_pardot,
inputs=[state, first_name_tb, email_tb, chatbot],
outputs=[chatbot, state],
)
demo.launch()