Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -45,21 +45,75 @@ async def process_constraints(constraints: InputConstraints):
|
|
| 45 |
|
| 46 |
|
| 47 |
def make_json_serializable(data):
|
| 48 |
-
"""
|
| 49 |
-
Recursively convert tensors to floats in a data structure
|
| 50 |
-
so it can be passed to json.dumps.
|
| 51 |
-
"""
|
| 52 |
if isinstance(data, dict):
|
| 53 |
return {k: make_json_serializable(v) for k, v in data.items()}
|
| 54 |
elif isinstance(data, list):
|
| 55 |
return [make_json_serializable(item) for item in data]
|
| 56 |
elif isinstance(data, tuple):
|
| 57 |
return tuple(make_json_serializable(item) for item in data)
|
| 58 |
-
elif hasattr(data, 'item'):
|
| 59 |
return float(data.item())
|
| 60 |
else:
|
| 61 |
return data
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
def process_input_gradio(problem_description: str):
|
| 64 |
"""
|
| 65 |
Processes the input problem description step-by-step for Gradio.
|
|
@@ -95,49 +149,38 @@ def process_input_gradio(problem_description: str):
|
|
| 95 |
best_technologies = get_technologies_by_id(best_technologies_id, global_tech)
|
| 96 |
|
| 97 |
# Format outputs for Gradio
|
| 98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
-
result_similarities_display = {
|
| 101 |
-
item['id2']: f"{item['constraint']['title']} ({item['similarity'].item():.3f})"
|
| 102 |
-
for item in result_similarities
|
| 103 |
-
}
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
# Convert to JSON-safe format
|
| 107 |
-
safe_best_combinations = make_json_serializable(best_combinations)
|
| 108 |
-
safe_best_technologies = make_json_serializable(best_technologies)
|
| 109 |
-
|
| 110 |
-
# Now this will work safely:
|
| 111 |
-
best_combinations_display = json.dumps(safe_best_combinations, indent=2)
|
| 112 |
-
best_technologies_display = json.dumps(safe_best_technologies, indent=2)
|
| 113 |
-
|
| 114 |
-
print("best combinations")
|
| 115 |
-
print(best_combinations_display)
|
| 116 |
-
print("\nbest technologies")
|
| 117 |
-
print(best_technologies_display)
|
| 118 |
-
|
| 119 |
return (
|
| 120 |
prompt,
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
", ".join(map(str, best_technologies_id)),
|
| 124 |
-
|
| 125 |
)
|
| 126 |
|
|
|
|
| 127 |
# --- Gradio Interface Setup ---
|
| 128 |
-
# Define the input and output components
|
| 129 |
input_problem = gr.Textbox(
|
| 130 |
label="Enter Problem Description",
|
| 131 |
placeholder="e.g., Develop a secure and scalable e-commerce platform with real-time analytics."
|
| 132 |
)
|
| 133 |
|
| 134 |
output_prompt = gr.Textbox(label="1. Generated Prompt", interactive=False)
|
| 135 |
-
output_constraints = gr.
|
| 136 |
-
output_best_combinations = gr.
|
| 137 |
output_selected_ids = gr.Textbox(label="8. Selected Technology IDs", interactive=False)
|
| 138 |
-
output_final_technologies = gr.
|
| 139 |
|
| 140 |
-
# Custom CSS for a professional look
|
| 141 |
custom_css = """
|
| 142 |
/* General Body and Font Styling */
|
| 143 |
body {
|
|
@@ -225,20 +268,105 @@ body {
|
|
| 225 |
font-size: 1.1em;
|
| 226 |
}
|
| 227 |
|
| 228 |
-
/*
|
| 229 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 230 |
background-color: #f8f9fa;
|
|
|
|
| 231 |
border: 1px solid #e9ecef;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 232 |
border-radius: 8px;
|
| 233 |
padding: 15px;
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
}
|
| 240 |
|
| 241 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 242 |
@media (max-width: 768px) {
|
| 243 |
.gradio-container {
|
| 244 |
padding: 15px;
|
|
@@ -250,53 +378,41 @@ body {
|
|
| 250 |
width: 100%;
|
| 251 |
padding: 15px;
|
| 252 |
}
|
|
|
|
|
|
|
|
|
|
| 253 |
}
|
| 254 |
-
|
| 255 |
-
/* Optional: Logo and Branding Placeholder */
|
| 256 |
-
/* You would typically add an image element in your gr.Blocks() for a logo */
|
| 257 |
-
/* Example if you have a logo image: */
|
| 258 |
-
/* .logo {
|
| 259 |
-
display: block;
|
| 260 |
-
margin: 0 auto 20px auto;
|
| 261 |
-
max-width: 200px;
|
| 262 |
-
height: auto;
|
| 263 |
-
} */
|
| 264 |
"""
|
| 265 |
|
| 266 |
# Create the Gradio Blocks demo with custom theme and CSS
|
| 267 |
with gr.Blocks(
|
| 268 |
-
theme=gr.themes.Soft(),
|
| 269 |
css=custom_css
|
| 270 |
) as gradio_app_blocks:
|
| 271 |
-
# Optional: Add your logo here
|
| 272 |
-
# gr.Image("path/to/your/logo.png", width=150, show_label=False, container=False, elem_classes="logo")
|
| 273 |
-
|
| 274 |
gr.Markdown("# Insight Finder: Step-by-Step Technology Selection")
|
| 275 |
gr.Markdown("## Enter a problem description to see how relevant technologies are identified through various processing steps.")
|
| 276 |
|
| 277 |
-
with gr.Row():
|
| 278 |
-
with gr.Column(scale=2):
|
| 279 |
input_problem.render()
|
| 280 |
-
with gr.Column(scale=1):
|
| 281 |
-
gr.
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
gr.Markdown("---") # Separator for visual clarity
|
| 286 |
|
|
|
|
| 287 |
gr.Markdown("### Processing Steps & Results:")
|
| 288 |
|
| 289 |
-
# Group outputs into columns for better organization
|
| 290 |
with gr.Row():
|
| 291 |
with gr.Column():
|
| 292 |
output_prompt.render()
|
| 293 |
-
output_constraints.render()
|
| 294 |
with gr.Column():
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
output_final_technologies.render()
|
| 298 |
|
| 299 |
-
# Link the button to the processing function
|
| 300 |
process_button.click(
|
| 301 |
fn=process_input_gradio,
|
| 302 |
inputs=input_problem,
|
|
@@ -307,6 +423,4 @@ with gr.Blocks(
|
|
| 307 |
output_selected_ids,
|
| 308 |
output_final_technologies
|
| 309 |
]
|
| 310 |
-
)
|
| 311 |
-
|
| 312 |
-
gr.mount_gradio_app(app, gradio_app_blocks, path="/gradio")
|
|
|
|
| 45 |
|
| 46 |
|
| 47 |
def make_json_serializable(data):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
if isinstance(data, dict):
|
| 49 |
return {k: make_json_serializable(v) for k, v in data.items()}
|
| 50 |
elif isinstance(data, list):
|
| 51 |
return [make_json_serializable(item) for item in data]
|
| 52 |
elif isinstance(data, tuple):
|
| 53 |
return tuple(make_json_serializable(item) for item in data)
|
| 54 |
+
elif hasattr(data, 'item'):
|
| 55 |
return float(data.item())
|
| 56 |
else:
|
| 57 |
return data
|
| 58 |
+
|
| 59 |
+
# --- Helper functions to format HTML outputs ---
|
| 60 |
+
def format_constraints_html(constraints: dict) -> str:
|
| 61 |
+
html_content = "<div class='constraints-container'>"
|
| 62 |
+
for title, description in constraints.items():
|
| 63 |
+
html_content += f"""
|
| 64 |
+
<div class='constraint-item'>
|
| 65 |
+
<p><span class='constraint-title'>{title}:</span> <span class='constraint-description'>{description}</span></p>
|
| 66 |
+
</div>
|
| 67 |
+
"""
|
| 68 |
+
html_content += "</div>"
|
| 69 |
+
return html_content
|
| 70 |
+
|
| 71 |
+
def format_best_combinations_html(combinations_data: list) -> str:
|
| 72 |
+
html_content = "<div class='combinations-outer-container'>"
|
| 73 |
+
for i, combination in enumerate(combinations_data):
|
| 74 |
+
problem_title = combination.get("problem", {}).get("title", f"Problem {i+1}")
|
| 75 |
+
technologies = combination.get("technologies", [])
|
| 76 |
+
|
| 77 |
+
html_content += f"""
|
| 78 |
+
<div class='problem-card'>
|
| 79 |
+
<h3 class='problem-card-title'>{problem_title}</h3>
|
| 80 |
+
<div class='technologies-inner-container'>
|
| 81 |
+
"""
|
| 82 |
+
for tech_info_score in technologies:
|
| 83 |
+
tech_info = tech_info_score[0] # The dictionary part
|
| 84 |
+
if isinstance(tech_info, dict):
|
| 85 |
+
html_content += f"""
|
| 86 |
+
<div class='technology-card'>
|
| 87 |
+
<h4 class='tech-card-title'>{tech_info.get('title', 'N/A')}</h4>
|
| 88 |
+
<p><strong>Purpose:</strong> {tech_info.get('purpose', 'N/A')}</p>
|
| 89 |
+
<p><strong>Components:</strong> {tech_info.get('key_components', 'N/A')}</p>
|
| 90 |
+
<p><strong>Advantages:</strong> {tech_info.get('advantages', 'N/A')}</p>
|
| 91 |
+
<p><strong>Limitations:</strong> {tech_info.get('limitations', 'N/A')}</p>
|
| 92 |
+
</div>
|
| 93 |
+
"""
|
| 94 |
+
html_content += """
|
| 95 |
+
</div>
|
| 96 |
+
</div>
|
| 97 |
+
"""
|
| 98 |
+
html_content += "</div>"
|
| 99 |
+
return html_content
|
| 100 |
+
|
| 101 |
+
def format_final_technologies_html(technologies_list: list) -> str:
|
| 102 |
+
html_content = "<div class='final-tech-container'>"
|
| 103 |
+
for tech_info in technologies_list:
|
| 104 |
+
if isinstance(tech_info, dict):
|
| 105 |
+
html_content += f"""
|
| 106 |
+
<div class='final-tech-card'>
|
| 107 |
+
<h4 class='final-tech-title'>{tech_info.get('title', 'N/A')}</h4>
|
| 108 |
+
<p><strong>Purpose:</strong> {tech_info.get('purpose', 'N/A')}</p>
|
| 109 |
+
<p><strong>Components:</strong> {tech_info.get('key_components', 'N/A')}</p>
|
| 110 |
+
<p><strong>Advantages:</strong> {tech_info.get('advantages', 'N/A')}</p>
|
| 111 |
+
<p><strong>Limitations:</strong> {tech_info.get('limitations', 'N/A')}</p>
|
| 112 |
+
</div>
|
| 113 |
+
"""
|
| 114 |
+
html_content += "</div>"
|
| 115 |
+
return html_content
|
| 116 |
+
|
| 117 |
def process_input_gradio(problem_description: str):
|
| 118 |
"""
|
| 119 |
Processes the input problem description step-by-step for Gradio.
|
|
|
|
| 149 |
best_technologies = get_technologies_by_id(best_technologies_id, global_tech)
|
| 150 |
|
| 151 |
# Format outputs for Gradio
|
| 152 |
+
# For Constraints:
|
| 153 |
+
constraints_html = format_constraints_html(constraints_dict)
|
| 154 |
+
|
| 155 |
+
# For Best Combinations:
|
| 156 |
+
best_combinations_html = format_best_combinations_html(best_combinations)
|
| 157 |
+
|
| 158 |
+
# For Final Technologies:
|
| 159 |
+
final_technologies_html = format_final_technologies_html(best_technologies)
|
| 160 |
+
|
| 161 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
return (
|
| 163 |
prompt,
|
| 164 |
+
constraints_html, # Output HTML for constraints
|
| 165 |
+
best_combinations_html, # Output HTML for best combinations
|
| 166 |
+
", ".join(map(str, best_technologies_id)), # Still a simple text list
|
| 167 |
+
final_technologies_html # Output HTML for final technologies
|
| 168 |
)
|
| 169 |
|
| 170 |
+
|
| 171 |
# --- Gradio Interface Setup ---
|
|
|
|
| 172 |
input_problem = gr.Textbox(
|
| 173 |
label="Enter Problem Description",
|
| 174 |
placeholder="e.g., Develop a secure and scalable e-commerce platform with real-time analytics."
|
| 175 |
)
|
| 176 |
|
| 177 |
output_prompt = gr.Textbox(label="1. Generated Prompt", interactive=False)
|
| 178 |
+
output_constraints = gr.HTML(label="2. Retrieved Constraints") # Changed to HTML
|
| 179 |
+
output_best_combinations = gr.HTML(label="7. Best Technology Combinations Found") # Changed to HTML
|
| 180 |
output_selected_ids = gr.Textbox(label="8. Selected Technology IDs", interactive=False)
|
| 181 |
+
output_final_technologies = gr.HTML(label="9. Final Best Technologies") # Changed to HTML
|
| 182 |
|
| 183 |
+
# Custom CSS for a professional look and specific output styling
|
| 184 |
custom_css = """
|
| 185 |
/* General Body and Font Styling */
|
| 186 |
body {
|
|
|
|
| 268 |
font-size: 1.1em;
|
| 269 |
}
|
| 270 |
|
| 271 |
+
/* --- Specific Styling for Outputs --- */
|
| 272 |
+
|
| 273 |
+
/* 2. Retrieved Constraints Styling */
|
| 274 |
+
.constraints-container {
|
| 275 |
+
padding: 15px;
|
| 276 |
+
background-color: #f8f9fa;
|
| 277 |
+
border-radius: 8px;
|
| 278 |
+
border: 1px solid #e9ecef;
|
| 279 |
+
font-family: 'Georgia', serif; /* Different font */
|
| 280 |
+
line-height: 1.6;
|
| 281 |
+
max-height: 300px;
|
| 282 |
+
overflow-y: auto;
|
| 283 |
+
}
|
| 284 |
+
.constraint-item {
|
| 285 |
+
margin-bottom: 10px;
|
| 286 |
+
padding-bottom: 10px;
|
| 287 |
+
border-bottom: 1px dashed #e0e0e0;
|
| 288 |
+
}
|
| 289 |
+
.constraint-item:last-child {
|
| 290 |
+
border-bottom: none;
|
| 291 |
+
margin-bottom: 0;
|
| 292 |
+
padding-bottom: 0;
|
| 293 |
+
}
|
| 294 |
+
.constraint-title {
|
| 295 |
+
font-weight: bold;
|
| 296 |
+
color: #004085; /* Darker blue for constraint titles */
|
| 297 |
+
font-size: 1.1em;
|
| 298 |
+
}
|
| 299 |
+
.constraint-description {
|
| 300 |
+
color: #333;
|
| 301 |
+
font-size: 1em;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
/* 7. Best Technology Combinations Found & 9. Final Best Technologies Styling */
|
| 305 |
+
.combinations-outer-container, .final-tech-container {
|
| 306 |
+
padding: 15px;
|
| 307 |
background-color: #f8f9fa;
|
| 308 |
+
border-radius: 8px;
|
| 309 |
border: 1px solid #e9ecef;
|
| 310 |
+
max-height: 500px; /* Adjust as needed */
|
| 311 |
+
overflow-y: auto;
|
| 312 |
+
font-family: 'Trebuchet MS', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Tahoma, sans-serif; /* Different font */
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
.problem-card {
|
| 316 |
+
background-color: #ffffff;
|
| 317 |
+
border: 1px solid #cfe2ff; /* Light blue border for problem card */
|
| 318 |
+
border-radius: 10px;
|
| 319 |
+
padding: 20px;
|
| 320 |
+
margin-bottom: 20px;
|
| 321 |
+
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
|
| 322 |
+
}
|
| 323 |
+
.problem-card-title {
|
| 324 |
+
color: #0056b3; /* Deep blue for problem title */
|
| 325 |
+
font-size: 1.4em;
|
| 326 |
+
margin-top: 0;
|
| 327 |
+
margin-bottom: 15px;
|
| 328 |
+
border-bottom: 2px solid #cfe2ff;
|
| 329 |
+
padding-bottom: 10px;
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
.technologies-inner-container {
|
| 333 |
+
display: grid;
|
| 334 |
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); /* Responsive grid for technologies */
|
| 335 |
+
gap: 15px;
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
+
.technology-card, .final-tech-card {
|
| 339 |
+
background-color: #f0faff; /* Very light blue for technology cards */
|
| 340 |
+
border: 1px solid #b0d9ff; /* Slightly darker blue border */
|
| 341 |
border-radius: 8px;
|
| 342 |
padding: 15px;
|
| 343 |
+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
|
| 344 |
+
transition: transform 0.2s ease-in-out;
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
.technology-card:hover, .final-tech-card:hover {
|
| 348 |
+
transform: translateY(-3px);
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
.tech-card-title, .final-tech-title {
|
| 352 |
+
color: #007bff; /* Gradio's primary blue */
|
| 353 |
+
font-size: 1.2em;
|
| 354 |
+
margin-top: 0;
|
| 355 |
+
margin-bottom: 10px;
|
| 356 |
+
font-weight: 600;
|
| 357 |
}
|
| 358 |
|
| 359 |
+
.technology-card p, .final-tech-card p {
|
| 360 |
+
font-size: 0.95em;
|
| 361 |
+
line-height: 1.5;
|
| 362 |
+
margin-bottom: 5px;
|
| 363 |
+
color: #555;
|
| 364 |
+
}
|
| 365 |
+
.technology-card p strong, .final-tech-card p strong {
|
| 366 |
+
color: #004085; /* Darker blue for bold labels */
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
/* Responsive adjustments */
|
| 370 |
@media (max-width: 768px) {
|
| 371 |
.gradio-container {
|
| 372 |
padding: 15px;
|
|
|
|
| 378 |
width: 100%;
|
| 379 |
padding: 15px;
|
| 380 |
}
|
| 381 |
+
.technologies-inner-container {
|
| 382 |
+
grid-template-columns: 1fr; /* Stack columns on smaller screens */
|
| 383 |
+
}
|
| 384 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 385 |
"""
|
| 386 |
|
| 387 |
# Create the Gradio Blocks demo with custom theme and CSS
|
| 388 |
with gr.Blocks(
|
| 389 |
+
theme=gr.themes.Soft(),
|
| 390 |
css=custom_css
|
| 391 |
) as gradio_app_blocks:
|
|
|
|
|
|
|
|
|
|
| 392 |
gr.Markdown("# Insight Finder: Step-by-Step Technology Selection")
|
| 393 |
gr.Markdown("## Enter a problem description to see how relevant technologies are identified through various processing steps.")
|
| 394 |
|
| 395 |
+
with gr.Row():
|
| 396 |
+
with gr.Column(scale=2):
|
| 397 |
input_problem.render()
|
| 398 |
+
with gr.Column(scale=1):
|
| 399 |
+
gr.Box(
|
| 400 |
+
gr.Markdown("Click to start the analysis:"),
|
| 401 |
+
process_button := gr.Button("Process Problem", elem_id="process_button")
|
| 402 |
+
)
|
|
|
|
| 403 |
|
| 404 |
+
gr.Markdown("---")
|
| 405 |
gr.Markdown("### Processing Steps & Results:")
|
| 406 |
|
|
|
|
| 407 |
with gr.Row():
|
| 408 |
with gr.Column():
|
| 409 |
output_prompt.render()
|
| 410 |
+
output_constraints.render() # Renders HTML
|
| 411 |
with gr.Column():
|
| 412 |
+
output_selected_ids.render() # This remains a Textbox
|
| 413 |
+
output_best_combinations.render() # Renders HTML
|
| 414 |
+
output_final_technologies.render() # Renders HTML
|
| 415 |
|
|
|
|
| 416 |
process_button.click(
|
| 417 |
fn=process_input_gradio,
|
| 418 |
inputs=input_problem,
|
|
|
|
| 423 |
output_selected_ids,
|
| 424 |
output_final_technologies
|
| 425 |
]
|
| 426 |
+
)
|
|
|
|
|
|