Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
| 1 |
-
|
| 2 |
import gradio as gr
|
| 3 |
import pandas as pd
|
| 4 |
import numpy as np
|
|
@@ -26,9 +25,9 @@ BRAND_COLORS = {
|
|
| 26 |
|
| 27 |
default_departments = pd.DataFrame({
|
| 28 |
"Department": ["IT", "Finance", "HR", "Marketing", "Sales", "Operations"],
|
| 29 |
-
"Number of Employees": [
|
| 30 |
"Average Salary": [95000, 85000, 70000, 75000, 85000, 65000],
|
| 31 |
-
"Hours Per Week on Manual Tasks": [20,
|
| 32 |
})
|
| 33 |
|
| 34 |
default_subscriptions = pd.DataFrame({
|
|
@@ -204,30 +203,37 @@ department_use_cases = {
|
|
| 204 |
|
| 205 |
|
| 206 |
def create_subscription_savings_chart(subscription_data):
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
|
|
|
|
|
|
|
|
|
| 210 |
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
current_costs.append(monthly_cost)
|
| 216 |
-
savings.append(monthly_cost * reduction)
|
| 217 |
|
|
|
|
| 218 |
fig = go.Figure()
|
|
|
|
|
|
|
| 219 |
fig.add_trace(
|
| 220 |
go.Bar(x=categories,
|
| 221 |
y=current_costs,
|
| 222 |
name="Current Monthly Cost",
|
| 223 |
marker_color=BRAND_COLORS['primary'],
|
| 224 |
opacity=0.9))
|
|
|
|
| 225 |
fig.add_trace(
|
| 226 |
go.Bar(x=categories,
|
| 227 |
y=savings,
|
| 228 |
name="Potential Monthly Savings",
|
| 229 |
marker_color=BRAND_COLORS['accent'],
|
| 230 |
opacity=0.9))
|
|
|
|
|
|
|
| 231 |
fig.update_layout(
|
| 232 |
title="Potential Monthly Subscription Savings with AI",
|
| 233 |
barmode='group',
|
|
@@ -238,15 +244,16 @@ def create_subscription_savings_chart(subscription_data):
|
|
| 238 |
y=1.02,
|
| 239 |
xanchor="center",
|
| 240 |
x=0.5,
|
| 241 |
-
font=dict(color=BRAND_COLORS['light_text'])),
|
| 242 |
template="plotly_white",
|
| 243 |
font=dict(family="Inter, sans-serif",
|
| 244 |
size=12,
|
| 245 |
-
color=BRAND_COLORS['light_text']),
|
| 246 |
paper_bgcolor=BRAND_COLORS['dark_bg'],
|
| 247 |
plot_bgcolor=BRAND_COLORS['dark_bg'],
|
| 248 |
-
margin=dict(l=40, r=40, t=80, b=40)
|
| 249 |
)
|
|
|
|
| 250 |
return fig
|
| 251 |
|
| 252 |
|
|
@@ -345,11 +352,11 @@ def recommend_preamble_solution(industry,
|
|
| 345 |
description = f"""### ⚡ Guardrails Only
|
| 346 |
Perfect for integrating with your existing AI application:
|
| 347 |
- Quick API integration.
|
| 348 |
-
- Pre-built security
|
| 349 |
- Basic compliance templates.
|
| 350 |
- Agentless operation.
|
| 351 |
- Free Trial available.
|
| 352 |
-
- {shadow_ai_blocker}
|
| 353 |
$0.005 per API call (Est. monthly cost: ${monthly_cost:,.2f} at {api_calls:,} calls/month)"""
|
| 354 |
image = "🛡️"
|
| 355 |
else:
|
|
@@ -361,7 +368,7 @@ def recommend_preamble_solution(industry,
|
|
| 361 |
- Protection for up to 25 AI applications.
|
| 362 |
- Secure Knowledge Base.
|
| 363 |
- SaaS Hosting.
|
| 364 |
-
- {shadow_ai_blocker}
|
| 365 |
$50 per user/month"""
|
| 366 |
image = "🏢"
|
| 367 |
elif org_size >= 1000 or industry in high_risk_industries:
|
|
@@ -369,11 +376,12 @@ def recommend_preamble_solution(industry,
|
|
| 369 |
description = f"""### 🏢 Enterprise License
|
| 370 |
Perfect for large or high-risk organizations:
|
| 371 |
- Complete compliance controls.
|
| 372 |
-
- Custom
|
| 373 |
- Dedicated support team.
|
| 374 |
-
-
|
|
|
|
| 375 |
- Private cloud/on-premise options.
|
| 376 |
-
- {shadow_ai_blocker}
|
| 377 |
Starting at $27,000/month with discounts for multi-year deals"""
|
| 378 |
image = "🚀"
|
| 379 |
elif org_size >= 100:
|
|
@@ -382,10 +390,11 @@ def recommend_preamble_solution(industry,
|
|
| 382 |
Perfect for teams getting started with AI:
|
| 383 |
- Full platform features.
|
| 384 |
- Standard compliance templates.
|
| 385 |
-
-
|
|
|
|
| 386 |
- Secure Knowledge Base.
|
| 387 |
- SaaS Hosting.
|
| 388 |
-
- {shadow_ai_blocker}
|
| 389 |
$50 per user/month"""
|
| 390 |
image = "🏢"
|
| 391 |
|
|
@@ -395,11 +404,11 @@ def recommend_preamble_solution(industry,
|
|
| 395 |
description = f"""### ⚡ Guardrails Only
|
| 396 |
Perfect for integrating with your existing AI application:
|
| 397 |
- Quick API integration.
|
| 398 |
-
- Pre-built security
|
| 399 |
- Basic compliance templates.
|
| 400 |
- Agentless operation.
|
| 401 |
- Free Trial available.
|
| 402 |
-
- {shadow_ai_blocker}
|
| 403 |
$0.005 per API call (Est. monthly cost: ${monthly_cost:,.2f} at {api_calls:,} calls/month)"""
|
| 404 |
image = "🛡️"
|
| 405 |
return {"solution": solution, "description": description, "image": image}
|
|
@@ -567,11 +576,11 @@ def generate_recommendations(industry,
|
|
| 567 |
f"**Industry:** {industry}\n**Organization Size:** {org_size:,} employees\n"
|
| 568 |
f"**Monthly Budget:** ${monthly_budget:,.2f}\n"
|
| 569 |
f"**Existing AI Application:** {'Yes' if has_ai_app else 'No'}\n"
|
| 570 |
-
f"**Total Potential Annual Savings:** ${total_dept_savings + subscription_savings['total_savings'] + compliance_savings['total_savings']:,.2f}\n"
|
| 571 |
-
f"
|
| 572 |
f"{build_vs_buy_text}\n"
|
| 573 |
-
f"## Department Recommendations\nThe following departments show the highest potential ROI for AI implementation:\n{dept_recommendations}"
|
| 574 |
-
f"{subscription_text}{compliance_text}{security_text}\n## Implementation Roadmap\n\n"
|
| 575 |
f"1. **Phase 1: Security Foundation** (1-2 months)\n"
|
| 576 |
f" - Deploy Preamble {solution_rec['solution']}\n"
|
| 577 |
f" - Establish AI governance framework\n"
|
|
@@ -1231,28 +1240,10 @@ def create_app():
|
|
| 1231 |
Based on your inputs, we've generated a comprehensive AI security implementation plan tailored to your organization's needs, budget, and industry requirements.
|
| 1232 |
</div>""")
|
| 1233 |
|
| 1234 |
-
|
| 1235 |
-
|
| 1236 |
-
|
| 1237 |
-
|
| 1238 |
-
|
| 1239 |
-
with gr.Tab("Savings Analysis"):
|
| 1240 |
-
gr.Markdown("### Potential Cost Savings",
|
| 1241 |
-
elem_classes="subsection-title")
|
| 1242 |
-
gr.Markdown(
|
| 1243 |
-
"""This chart illustrates the potential monthly savings across your different tool categories by implementing AI solutions."""
|
| 1244 |
-
)
|
| 1245 |
-
subscription_chart = gr.Plot(
|
| 1246 |
-
elem_classes="chart-container")
|
| 1247 |
-
|
| 1248 |
-
with gr.Tab("Build vs Buy Comparison"):
|
| 1249 |
-
gr.Markdown("### Build vs Buy Analysis",
|
| 1250 |
-
elem_classes="subsection-title")
|
| 1251 |
-
gr.Markdown(
|
| 1252 |
-
"""This chart compares the cost of building and maintaining your own AI security platform versus using Preamble's enterprise solution over 3 years."""
|
| 1253 |
-
)
|
| 1254 |
-
build_vs_buy_chart = gr.Plot(
|
| 1255 |
-
elem_classes="chart-container")
|
| 1256 |
|
| 1257 |
gr.Markdown(
|
| 1258 |
"""<div class="helper-text" style="margin-top: 20px; text-align: center;">
|
|
@@ -1278,18 +1269,30 @@ def create_app():
|
|
| 1278 |
|
| 1279 |
def go_to_step2(org_size, step):
|
| 1280 |
indicators = update_progress_indicator(2)
|
| 1281 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1282 |
updated_departments = default_departments.copy()
|
| 1283 |
-
if total_employees != updated_departments[
|
| 1284 |
-
'Number of Employees'].sum():
|
| 1285 |
-
updated_departments.loc[
|
| 1286 |
-
updated_departments.index[-1],
|
| 1287 |
-
'Number of Employees'] += total_employees - updated_departments[
|
| 1288 |
-
'Number of Employees'].sum()
|
| 1289 |
-
|
| 1290 |
updated_subscriptions = default_subscriptions.copy()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1291 |
updated_subscriptions['Number of Users'] = total_employees
|
| 1292 |
|
|
|
|
| 1293 |
return (gr.update(visible=False), gr.update(visible=True),
|
| 1294 |
gr.update(visible=False), gr.update(visible=False),
|
| 1295 |
gr.update(visible=False), gr.update(value=2),
|
|
@@ -1326,11 +1329,10 @@ def create_app():
|
|
| 1326 |
dept_roi_results,
|
| 1327 |
sub_savings, comp_savings,
|
| 1328 |
api_calls)[0] # Only get the report
|
| 1329 |
-
chart = create_subscription_savings_chart(subscription_df)
|
| 1330 |
indicators = update_progress_indicator(4)
|
| 1331 |
return (gr.update(visible=False), gr.update(visible=False),
|
| 1332 |
gr.update(visible=False), gr.update(visible=False),
|
| 1333 |
-
gr.update(visible=True), report,
|
| 1334 |
|
| 1335 |
def generate_recommendations_with_comparison(
|
| 1336 |
industry, org_size, monthly_budget, has_ai_app, api_calls,
|
|
@@ -1345,13 +1347,10 @@ def create_app():
|
|
| 1345 |
dept_roi_results, sub_savings, comp_savings, api_calls,
|
| 1346 |
initial_dev_cost, num_ai_personnel, avg_annual_salary,
|
| 1347 |
annual_maintenance, security_compliance)
|
| 1348 |
-
subscription_chart = create_subscription_savings_chart(subscription_df)
|
| 1349 |
-
comparison_chart = create_build_vs_buy_chart(comparison)
|
| 1350 |
indicators = update_progress_indicator(4)
|
| 1351 |
return (gr.update(visible=False), gr.update(visible=False),
|
| 1352 |
gr.update(visible=False), gr.update(visible=False),
|
| 1353 |
-
gr.update(visible=True), report,
|
| 1354 |
-
comparison_chart, *indicators)
|
| 1355 |
|
| 1356 |
|
| 1357 |
next_button1.click(fn=go_to_step2,
|
|
@@ -1413,8 +1412,7 @@ def create_app():
|
|
| 1413 |
],
|
| 1414 |
outputs=[
|
| 1415 |
step1, step2, step3, step3_5, step4,
|
| 1416 |
-
recommendation_output,
|
| 1417 |
-
subscription_chart, build_vs_buy_chart, step1_indicator,
|
| 1418 |
step2_indicator, step3_indicator, step4_indicator
|
| 1419 |
])
|
| 1420 |
|
|
@@ -1429,8 +1427,7 @@ def create_app():
|
|
| 1429 |
],
|
| 1430 |
outputs=[
|
| 1431 |
step1, step2, step3, step3_5, step4,
|
| 1432 |
-
recommendation_output,
|
| 1433 |
-
build_vs_buy_chart, step1_indicator, step2_indicator,
|
| 1434 |
step3_indicator, step4_indicator
|
| 1435 |
]
|
| 1436 |
)
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import pandas as pd
|
| 3 |
import numpy as np
|
|
|
|
| 25 |
|
| 26 |
default_departments = pd.DataFrame({
|
| 27 |
"Department": ["IT", "Finance", "HR", "Marketing", "Sales", "Operations"],
|
| 28 |
+
"Number of Employees": [10, 15, 8, 12, 20, 25],
|
| 29 |
"Average Salary": [95000, 85000, 70000, 75000, 85000, 65000],
|
| 30 |
+
"Hours Per Week on Manual Tasks": [20, 20, 15, 10, 12, 18]
|
| 31 |
})
|
| 32 |
|
| 33 |
default_subscriptions = pd.DataFrame({
|
|
|
|
| 203 |
|
| 204 |
|
| 205 |
def create_subscription_savings_chart(subscription_data):
|
| 206 |
+
# Use pandas vectorized operations instead of loop
|
| 207 |
+
df = subscription_data.copy()
|
| 208 |
+
|
| 209 |
+
# Calculate costs and savings in one go
|
| 210 |
+
df['monthly_cost'] = df["Current Monthly Cost per User"] * df["Number of Users"]
|
| 211 |
+
df['savings'] = df['monthly_cost'] * (df["Estimated Reduction %"] / 100)
|
| 212 |
|
| 213 |
+
# Convert to lists for plotly
|
| 214 |
+
categories = df["Tool Category"].tolist()
|
| 215 |
+
current_costs = df['monthly_cost'].tolist()
|
| 216 |
+
savings = df['savings'].tolist()
|
|
|
|
|
|
|
| 217 |
|
| 218 |
+
# Create the figure with all styling applied at once
|
| 219 |
fig = go.Figure()
|
| 220 |
+
|
| 221 |
+
# Add both traces at once
|
| 222 |
fig.add_trace(
|
| 223 |
go.Bar(x=categories,
|
| 224 |
y=current_costs,
|
| 225 |
name="Current Monthly Cost",
|
| 226 |
marker_color=BRAND_COLORS['primary'],
|
| 227 |
opacity=0.9))
|
| 228 |
+
|
| 229 |
fig.add_trace(
|
| 230 |
go.Bar(x=categories,
|
| 231 |
y=savings,
|
| 232 |
name="Potential Monthly Savings",
|
| 233 |
marker_color=BRAND_COLORS['accent'],
|
| 234 |
opacity=0.9))
|
| 235 |
+
|
| 236 |
+
# Set layout all at once
|
| 237 |
fig.update_layout(
|
| 238 |
title="Potential Monthly Subscription Savings with AI",
|
| 239 |
barmode='group',
|
|
|
|
| 244 |
y=1.02,
|
| 245 |
xanchor="center",
|
| 246 |
x=0.5,
|
| 247 |
+
font=dict(color=BRAND_COLORS['light_text'])),
|
| 248 |
template="plotly_white",
|
| 249 |
font=dict(family="Inter, sans-serif",
|
| 250 |
size=12,
|
| 251 |
+
color=BRAND_COLORS['light_text']),
|
| 252 |
paper_bgcolor=BRAND_COLORS['dark_bg'],
|
| 253 |
plot_bgcolor=BRAND_COLORS['dark_bg'],
|
| 254 |
+
margin=dict(l=40, r=40, t=80, b=40)
|
| 255 |
)
|
| 256 |
+
|
| 257 |
return fig
|
| 258 |
|
| 259 |
|
|
|
|
| 352 |
description = f"""### ⚡ Guardrails Only
|
| 353 |
Perfect for integrating with your existing AI application:
|
| 354 |
- Quick API integration.
|
| 355 |
+
- Pre-built security and privacy guardrails.
|
| 356 |
- Basic compliance templates.
|
| 357 |
- Agentless operation.
|
| 358 |
- Free Trial available.
|
| 359 |
+
- Free Shadow AI Tool {shadow_ai_blocker}
|
| 360 |
$0.005 per API call (Est. monthly cost: ${monthly_cost:,.2f} at {api_calls:,} calls/month)"""
|
| 361 |
image = "🛡️"
|
| 362 |
else:
|
|
|
|
| 368 |
- Protection for up to 25 AI applications.
|
| 369 |
- Secure Knowledge Base.
|
| 370 |
- SaaS Hosting.
|
| 371 |
+
- Free Shadow AI Tool {shadow_ai_blocker}
|
| 372 |
$50 per user/month"""
|
| 373 |
image = "🏢"
|
| 374 |
elif org_size >= 1000 or industry in high_risk_industries:
|
|
|
|
| 376 |
description = f"""### 🏢 Enterprise License
|
| 377 |
Perfect for large or high-risk organizations:
|
| 378 |
- Complete compliance controls.
|
| 379 |
+
- Custom AI Assistant Development Support.
|
| 380 |
- Dedicated support team.
|
| 381 |
+
- Private AI Marketplace.
|
| 382 |
+
- Custom integrations.
|
| 383 |
- Private cloud/on-premise options.
|
| 384 |
+
- Free Shadow AI Tool {shadow_ai_blocker}
|
| 385 |
Starting at $27,000/month with discounts for multi-year deals"""
|
| 386 |
image = "🚀"
|
| 387 |
elif org_size >= 100:
|
|
|
|
| 390 |
Perfect for teams getting started with AI:
|
| 391 |
- Full platform features.
|
| 392 |
- Standard compliance templates.
|
| 393 |
+
- Custom AI Assistants.
|
| 394 |
+
- Safe AI Search Agent
|
| 395 |
- Secure Knowledge Base.
|
| 396 |
- SaaS Hosting.
|
| 397 |
+
- Free Shadow AI Tool {shadow_ai_blocker}
|
| 398 |
$50 per user/month"""
|
| 399 |
image = "🏢"
|
| 400 |
|
|
|
|
| 404 |
description = f"""### ⚡ Guardrails Only
|
| 405 |
Perfect for integrating with your existing AI application:
|
| 406 |
- Quick API integration.
|
| 407 |
+
- Pre-built security and privacy guardrails.
|
| 408 |
- Basic compliance templates.
|
| 409 |
- Agentless operation.
|
| 410 |
- Free Trial available.
|
| 411 |
+
- Free Shadow AI Tool {shadow_ai_blocker}
|
| 412 |
$0.005 per API call (Est. monthly cost: ${monthly_cost:,.2f} at {api_calls:,} calls/month)"""
|
| 413 |
image = "🛡️"
|
| 414 |
return {"solution": solution, "description": description, "image": image}
|
|
|
|
| 576 |
f"**Industry:** {industry}\n**Organization Size:** {org_size:,} employees\n"
|
| 577 |
f"**Monthly Budget:** ${monthly_budget:,.2f}\n"
|
| 578 |
f"**Existing AI Application:** {'Yes' if has_ai_app else 'No'}\n"
|
| 579 |
+
f"**Total Potential Annual Savings:** ${total_dept_savings + subscription_savings['total_savings'] + compliance_savings['total_savings']:,.2f}\n\n"
|
| 580 |
+
f"## Recommended Preamble Solution\n{solution_rec['image']} {solution_rec['description']}\n\n"
|
| 581 |
f"{build_vs_buy_text}\n"
|
| 582 |
+
f"## Department Recommendations\nThe following departments show the highest potential ROI for AI implementation:\n{dept_recommendations}\n"
|
| 583 |
+
f"{subscription_text}{compliance_text}{security_text}\n\n## Implementation Roadmap\n\n"
|
| 584 |
f"1. **Phase 1: Security Foundation** (1-2 months)\n"
|
| 585 |
f" - Deploy Preamble {solution_rec['solution']}\n"
|
| 586 |
f" - Establish AI governance framework\n"
|
|
|
|
| 1240 |
Based on your inputs, we've generated a comprehensive AI security implementation plan tailored to your organization's needs, budget, and industry requirements.
|
| 1241 |
</div>""")
|
| 1242 |
|
| 1243 |
+
# Simplified output without tabs and plots for better performance
|
| 1244 |
+
recommendation_output = gr.Markdown(
|
| 1245 |
+
elem_classes="result-card",
|
| 1246 |
+
render=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1247 |
|
| 1248 |
gr.Markdown(
|
| 1249 |
"""<div class="helper-text" style="margin-top: 20px; text-align: center;">
|
|
|
|
| 1269 |
|
| 1270 |
def go_to_step2(org_size, step):
|
| 1271 |
indicators = update_progress_indicator(2)
|
| 1272 |
+
# Ensure org_size is valid
|
| 1273 |
+
try:
|
| 1274 |
+
total_employees = int(org_size) if org_size is not None else 0
|
| 1275 |
+
if total_employees < 0:
|
| 1276 |
+
total_employees = 0
|
| 1277 |
+
except (ValueError, TypeError):
|
| 1278 |
+
total_employees = 0
|
| 1279 |
+
|
| 1280 |
+
# Create copies of dataframes only once
|
| 1281 |
updated_departments = default_departments.copy()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1282 |
updated_subscriptions = default_subscriptions.copy()
|
| 1283 |
+
|
| 1284 |
+
# Update department employee count efficiently
|
| 1285 |
+
if total_employees > 0:
|
| 1286 |
+
current_total = updated_departments['Number of Employees'].sum()
|
| 1287 |
+
if total_employees != current_total:
|
| 1288 |
+
# Add difference to last row
|
| 1289 |
+
diff = total_employees - current_total
|
| 1290 |
+
updated_departments.at[updated_departments.index[-1], 'Number of Employees'] += diff
|
| 1291 |
+
|
| 1292 |
+
# Update all subscription users at once
|
| 1293 |
updated_subscriptions['Number of Users'] = total_employees
|
| 1294 |
|
| 1295 |
+
# Return updates all at once
|
| 1296 |
return (gr.update(visible=False), gr.update(visible=True),
|
| 1297 |
gr.update(visible=False), gr.update(visible=False),
|
| 1298 |
gr.update(visible=False), gr.update(value=2),
|
|
|
|
| 1329 |
dept_roi_results,
|
| 1330 |
sub_savings, comp_savings,
|
| 1331 |
api_calls)[0] # Only get the report
|
|
|
|
| 1332 |
indicators = update_progress_indicator(4)
|
| 1333 |
return (gr.update(visible=False), gr.update(visible=False),
|
| 1334 |
gr.update(visible=False), gr.update(visible=False),
|
| 1335 |
+
gr.update(visible=True), report, *indicators)
|
| 1336 |
|
| 1337 |
def generate_recommendations_with_comparison(
|
| 1338 |
industry, org_size, monthly_budget, has_ai_app, api_calls,
|
|
|
|
| 1347 |
dept_roi_results, sub_savings, comp_savings, api_calls,
|
| 1348 |
initial_dev_cost, num_ai_personnel, avg_annual_salary,
|
| 1349 |
annual_maintenance, security_compliance)
|
|
|
|
|
|
|
| 1350 |
indicators = update_progress_indicator(4)
|
| 1351 |
return (gr.update(visible=False), gr.update(visible=False),
|
| 1352 |
gr.update(visible=False), gr.update(visible=False),
|
| 1353 |
+
gr.update(visible=True), report, *indicators)
|
|
|
|
| 1354 |
|
| 1355 |
|
| 1356 |
next_button1.click(fn=go_to_step2,
|
|
|
|
| 1412 |
],
|
| 1413 |
outputs=[
|
| 1414 |
step1, step2, step3, step3_5, step4,
|
| 1415 |
+
recommendation_output, step1_indicator,
|
|
|
|
| 1416 |
step2_indicator, step3_indicator, step4_indicator
|
| 1417 |
])
|
| 1418 |
|
|
|
|
| 1427 |
],
|
| 1428 |
outputs=[
|
| 1429 |
step1, step2, step3, step3_5, step4,
|
| 1430 |
+
recommendation_output, step1_indicator, step2_indicator,
|
|
|
|
| 1431 |
step3_indicator, step4_indicator
|
| 1432 |
]
|
| 1433 |
)
|