Implement interactive feedback flow with Gradio and Prefect integration
Browse files
app.py
CHANGED
|
@@ -1,7 +1,112 @@
|
|
|
|
|
| 1 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
-
def greet(name):
|
| 4 |
-
return "Hello " + name + "!!"
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
import gradio as gr
|
| 3 |
+
from prefect import flow, get_run_logger, pause_flow_run, settings
|
| 4 |
+
from prefect.context import get_run_context
|
| 5 |
+
from prefect.input import RunInput
|
| 6 |
|
|
|
|
|
|
|
| 7 |
|
| 8 |
+
class UserFeedback(RunInput):
|
| 9 |
+
"""Input model for capturing user feedback in the Prefect UI."""
|
| 10 |
+
|
| 11 |
+
rating: int
|
| 12 |
+
comment: str = ""
|
| 13 |
+
improve_feature: bool = False
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
@flow(name="interactive-feedback-flow")
|
| 17 |
+
async def collect_feedback(username: str):
|
| 18 |
+
"""A flow that pauses to collect user feedback via the Prefect UI."""
|
| 19 |
+
logger = get_run_logger()
|
| 20 |
+
|
| 21 |
+
logger.info(f"Started feedback collection for user: {username}")
|
| 22 |
+
|
| 23 |
+
# Construct a message that would typically be sent as a notification
|
| 24 |
+
message = f"Collecting feedback from user: {username}"
|
| 25 |
+
|
| 26 |
+
# Get flow run context for UI URL
|
| 27 |
+
flow_run = get_run_context().flow_run
|
| 28 |
+
flow_run_url = ""
|
| 29 |
+
|
| 30 |
+
if flow_run and settings.PREFECT_UI_URL:
|
| 31 |
+
flow_run_url = (
|
| 32 |
+
f"{settings.PREFECT_UI_URL.value()}/flow-runs/flow-run/{flow_run.id}"
|
| 33 |
+
)
|
| 34 |
+
logger.info(f"Flow run UI available at: {flow_run_url}")
|
| 35 |
+
|
| 36 |
+
# Pause the flow and wait for input
|
| 37 |
+
logger.info("Pausing flow to collect feedback...")
|
| 38 |
+
user_feedback = await pause_flow_run(
|
| 39 |
+
wait_for_input=UserFeedback.with_initial_data(
|
| 40 |
+
description="Please provide your feedback about our service.",
|
| 41 |
+
rating=5,
|
| 42 |
+
comment="",
|
| 43 |
+
improve_feature=False,
|
| 44 |
+
),
|
| 45 |
+
timeout=300, # 5 minutes timeout
|
| 46 |
+
)
|
| 47 |
+
|
| 48 |
+
# Process the input received after the flow is resumed
|
| 49 |
+
logger.info(f"Feedback received from {username}:")
|
| 50 |
+
logger.info(f"Rating: {user_feedback.rating}/5")
|
| 51 |
+
logger.info(f"Comment: {user_feedback.comment}")
|
| 52 |
+
logger.info(f"Wants feature improvement: {user_feedback.improve_feature}")
|
| 53 |
+
|
| 54 |
+
# Return results to be displayed in Gradio
|
| 55 |
+
result = {
|
| 56 |
+
"username": username,
|
| 57 |
+
"rating": user_feedback.rating,
|
| 58 |
+
"comment": user_feedback.comment,
|
| 59 |
+
"improve_feature": user_feedback.improve_feature,
|
| 60 |
+
"flow_run_url": flow_run_url,
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
return result
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def run_feedback_flow(username):
|
| 67 |
+
"""Run the Prefect flow and handle the UI interaction."""
|
| 68 |
+
try:
|
| 69 |
+
# Run the flow and get the result
|
| 70 |
+
result = asyncio.run(collect_feedback(username))
|
| 71 |
+
|
| 72 |
+
# Format the result as a string for display
|
| 73 |
+
message = f"""
|
| 74 |
+
Thank you, {result['username']}!
|
| 75 |
+
|
| 76 |
+
Your feedback has been recorded:
|
| 77 |
+
- Rating: {result['rating']}/5
|
| 78 |
+
- Comment: {result['comment']}
|
| 79 |
+
- Feature improvement requested: {result['improve_feature']}
|
| 80 |
+
"""
|
| 81 |
+
|
| 82 |
+
return message
|
| 83 |
+
except Exception as e:
|
| 84 |
+
return f"An error occurred: {str(e)}"
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
# Gradio interface
|
| 88 |
+
with gr.Blocks() as demo:
|
| 89 |
+
gr.Markdown("# Interactive Human-in-the-Loop Workflow with Prefect")
|
| 90 |
+
|
| 91 |
+
with gr.Row():
|
| 92 |
+
with gr.Column():
|
| 93 |
+
username_input = gr.Textbox(label="Your Name")
|
| 94 |
+
submit_btn = gr.Button("Start Feedback Process")
|
| 95 |
+
|
| 96 |
+
with gr.Column():
|
| 97 |
+
output_text = gr.Textbox(label="Result", lines=10)
|
| 98 |
+
flow_instructions = gr.Markdown(
|
| 99 |
+
"""
|
| 100 |
+
## Instructions:
|
| 101 |
+
1. Enter your name and click "Start Feedback Process"
|
| 102 |
+
2. The flow will pause waiting for your input
|
| 103 |
+
3. Go to the Prefect UI (URL will be printed in terminal)
|
| 104 |
+
4. Click "Resume" and provide your feedback
|
| 105 |
+
5. Results will appear here after completion
|
| 106 |
+
"""
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
submit_btn.click(fn=run_feedback_flow, inputs=username_input, outputs=output_text)
|
| 110 |
+
|
| 111 |
+
if __name__ == "__main__":
|
| 112 |
+
demo.launch()
|