Spaces:
Runtime error
Runtime error
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 |
+
)
|
|
|
|