gradio-pr-bot's picture
Upload folder using huggingface_hub
3a8233a verified
"""Demo showcasing runtime gr.cache(fn)(...) for an intermediate helper call."""
import re
import time
import gradio as gr
POLICIES = {
"Billing": [
{
"title": "Refund windows",
"text": "Customers can request a refund within 30 days of purchase. "
"Annual subscriptions can be prorated if the request arrives after the "
"first 30 days but before day 90.",
},
{
"title": "Invoice corrections",
"text": "Billing agents can correct invoice email addresses, company "
"names, and tax identifiers, but cannot alter the purchase date.",
},
{
"title": "Duplicate charges",
"text": "If two charges appear within 24 hours for the same plan and "
"customer account, billing should confirm card fingerprint and issue a "
"same-day reversal.",
},
],
"IT": [
{
"title": "Password resets",
"text": "IT can revoke all active sessions and force a password reset "
"after verifying the employee through the HR directory.",
},
{
"title": "VPN access",
"text": "New VPN access is approved only for employees with manager "
"approval and a registered MFA device.",
},
{
"title": "Laptop replacement",
"text": "Broken laptops should be tagged with the device asset number "
"and shipped to the repair center before a replacement is issued.",
},
],
"HR": [
{
"title": "Parental leave",
"text": "Full-time employees are eligible for 16 weeks of paid parental "
"leave after six months of employment.",
},
{
"title": "Address changes",
"text": "Employees should update their home address in the HR portal "
"before payroll closes on the 20th of each month.",
},
{
"title": "Interview scheduling",
"text": "Recruiters should provide interview panels at least 48 hours "
"to review candidate materials before the session starts.",
},
],
}
TONE_PREFIX = {
"Concise": "Give a short answer.",
"Friendly": "Give a warm, helpful answer.",
"Formal": "Give a professional and policy-focused answer.",
}
def _tokens(text: str) -> set[str]:
return set(re.findall(r"[a-z0-9]+", text.lower()))
def retrieve_passages(question: str, team: str) -> list[dict[str, str | int]]:
"""Pretend retrieval is the expensive deterministic step."""
time.sleep(2)
query_tokens = _tokens(question)
ranked = []
for doc in POLICIES[team]:
combined_text = f"{doc['title']} {doc['text']}"
score = len(query_tokens & _tokens(combined_text))
ranked.append(
{
"title": doc["title"],
"text": doc["text"],
"score": score,
}
)
ranked.sort(key=lambda item: item["score"], reverse=True)
return ranked[:2]
def draft_answer(question: str, team: str, tone: str) -> tuple[str, str, str]:
start = time.time()
passages = gr.cache(retrieve_passages)(question, team)
top_match = passages[0]
bullets = "\n".join(
f"- {match['title']}: {match['text']}" for match in passages
)
answer = (
f"{TONE_PREFIX[tone]}\n\n"
f"For a {team.lower()} request about '{question}', the strongest match is "
f"**{top_match['title']}**.\n\n"
f"Suggested reply: Based on the current {team.lower()} policy, {top_match['text']}"
)
debug = (
f"Retrieved {len(passages)} passages in {time.time() - start:.2f}s.\n"
"Try the same question twice, or change only the tone. "
"The retrieval helper should be reused from cache."
)
return answer, bullets, debug
with gr.Blocks(title="Intermediate gr.cache() Demo") as demo:
gr.Markdown(
"# Intermediate `gr.cache()` Demo\n"
"This simulates a support assistant where the **retrieval** step is expensive "
"but deterministic, while the final answer still recomputes. "
"Submit the same question twice, or change only the tone, and watch Gradio "
"show the `used cache` badge when the cached helper is reused."
)
with gr.Row():
with gr.Column():
team = gr.Dropdown(
choices=list(POLICIES.keys()),
value="Billing",
label="Team",
)
tone = gr.Dropdown(
choices=["Concise", "Friendly", "Formal"],
value="Friendly",
label="Answer style",
)
question = gr.Textbox(
label="Customer question",
lines=3,
value="Can this customer get a refund after being charged twice?",
)
draft = gr.Markdown()
retrieved = gr.Markdown()
debug = gr.Textbox(label="Debug", lines=3)
gr.Button("Draft reply").click(
draft_answer,
[question, team, tone],
outputs=[draft, retrieved, debug],
)
if __name__ == "__main__":
demo.launch()