Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
| 1 |
-
import gradio as gr
|
| 2 |
import pandas as pd
|
| 3 |
import numpy as np
|
| 4 |
import matplotlib.pyplot as plt
|
|
@@ -214,11 +213,7 @@ def generate_project_timeline(boq_file, weather, workforce, location, project_ti
|
|
| 214 |
output_path = os.path.join(temp_dir, output_filename)
|
| 215 |
logger.debug(f"Gantt chart will be saved to: {output_path}")
|
| 216 |
|
| 217 |
-
|
| 218 |
-
df = pd.read_csv(boq_file.name)
|
| 219 |
-
else:
|
| 220 |
-
df = pd.read_csv(boq_file)
|
| 221 |
-
|
| 222 |
if "Task Name" not in df.columns or "Duration" not in df.columns:
|
| 223 |
raise ValueError("CSV must contain 'Task Name' and 'Duration' columns")
|
| 224 |
|
|
@@ -247,96 +242,7 @@ def generate_project_timeline(boq_file, weather, workforce, location, project_ti
|
|
| 247 |
shutil.rmtree(temp_dir)
|
| 248 |
return None, str(e), None
|
| 249 |
|
| 250 |
-
#
|
| 251 |
-
def gradio_interface(boq_file, weather, workforce, location, project_title):
|
| 252 |
-
temp_dir = None
|
| 253 |
-
try:
|
| 254 |
-
logger.info("Starting gradio_interface...")
|
| 255 |
-
|
| 256 |
-
if not boq_file:
|
| 257 |
-
return None, "Error: No BOQ file uploaded"
|
| 258 |
-
|
| 259 |
-
file_path, risk_tags, temp_dir = generate_project_timeline(boq_file, weather, workforce, location, project_title)
|
| 260 |
-
if not file_path:
|
| 261 |
-
return None, f"Error: Failed to generate timeline: {risk_tags}"
|
| 262 |
-
|
| 263 |
-
if hasattr(boq_file, 'name'):
|
| 264 |
-
df = pd.read_csv(boq_file.name)
|
| 265 |
-
else:
|
| 266 |
-
df = pd.read_csv(boq_file)
|
| 267 |
-
estimated_duration = sum(df["Duration"])
|
| 268 |
-
ai_plan_score = min(100, max(0, 100 - (estimated_duration / 100)))
|
| 269 |
-
logger.debug(f"Estimated duration: {estimated_duration}, AI plan score: {ai_plan_score}")
|
| 270 |
-
|
| 271 |
-
record_id = send_to_salesforce(
|
| 272 |
-
project_title=project_title,
|
| 273 |
-
gantt_chart_url="",
|
| 274 |
-
ai_plan_score=ai_plan_score,
|
| 275 |
-
estimated_duration=estimated_duration,
|
| 276 |
-
status="Draft",
|
| 277 |
-
record_id=None,
|
| 278 |
-
location=location,
|
| 279 |
-
weather_type=weather
|
| 280 |
-
)
|
| 281 |
-
|
| 282 |
-
if not record_id:
|
| 283 |
-
return None, f"Error: Failed to create Salesforce record - check logs for details\n\nRisk Tags:\n{risk_tags}"
|
| 284 |
-
|
| 285 |
-
boq_file_path = boq_file.name if hasattr(boq_file, 'name') else boq_file
|
| 286 |
-
work_items_id = upload_file_to_salesforce(boq_file_path, "Boq_data.csv", record_id)
|
| 287 |
-
if not work_items_id:
|
| 288 |
-
logger.warning("Failed to upload BOQ file, but proceeding with record creation")
|
| 289 |
-
|
| 290 |
-
record_data = {
|
| 291 |
-
"project_title": project_title,
|
| 292 |
-
"estimated_duration": estimated_duration,
|
| 293 |
-
"ai_plan_score": ai_plan_score,
|
| 294 |
-
"status": "Draft",
|
| 295 |
-
"risk_tags": risk_tags,
|
| 296 |
-
}
|
| 297 |
-
pdf_file = generate_pdf(record_data)
|
| 298 |
-
if not pdf_file:
|
| 299 |
-
logger.warning("Failed to generate PDF, but proceeding with record creation")
|
| 300 |
-
|
| 301 |
-
pdf_content_id, pdf_url = None, None
|
| 302 |
-
if pdf_file:
|
| 303 |
-
pdf_content_id, pdf_url = upload_pdf_to_salesforce(pdf_file, project_title, record_id)
|
| 304 |
-
if not pdf_content_id:
|
| 305 |
-
logger.warning("Failed to upload PDF, but proceeding with record creation")
|
| 306 |
-
|
| 307 |
-
update_result = send_to_salesforce(
|
| 308 |
-
project_title=project_title,
|
| 309 |
-
gantt_chart_url=pdf_url if pdf_url else "",
|
| 310 |
-
ai_plan_score=ai_plan_score,
|
| 311 |
-
estimated_duration=estimated_duration,
|
| 312 |
-
status="Draft",
|
| 313 |
-
record_id=record_id,
|
| 314 |
-
location=location,
|
| 315 |
-
weather_type=weather,
|
| 316 |
-
work_items_id=work_items_id if work_items_id else ""
|
| 317 |
-
)
|
| 318 |
-
if not update_result:
|
| 319 |
-
logger.warning("Failed to update record with PDF URL, but record was created")
|
| 320 |
-
|
| 321 |
-
image_content_id = upload_file_to_salesforce(file_path, f"{project_title}_Gantt_Chart.png", record_id)
|
| 322 |
-
image_url = None
|
| 323 |
-
if image_content_id:
|
| 324 |
-
sf = get_salesforce_connection()
|
| 325 |
-
if sf:
|
| 326 |
-
image_url = f"https://{sf.sf_instance}/sfc/servlet.shepherd/version/download/{image_content_id}"
|
| 327 |
-
logger.debug(f"Generated image URL: {image_url}")
|
| 328 |
-
|
| 329 |
-
logger.info("Gradio interface completed successfully.")
|
| 330 |
-
return image_url if image_url else file_path, f"Successfully created Salesforce record ID: {record_id}\n\nRisk Tags:\n{risk_tags}"
|
| 331 |
-
except Exception as e:
|
| 332 |
-
logger.error(f"Error in Gradio interface: {str(e)}", exc_info=True)
|
| 333 |
-
return None, f"Error in Gradio interface: {str(e)}"
|
| 334 |
-
finally:
|
| 335 |
-
if temp_dir and os.path.exists(temp_dir):
|
| 336 |
-
shutil.rmtree(temp_dir)
|
| 337 |
-
logger.debug(f"Cleaned up temporary directory: {temp_dir}")
|
| 338 |
-
|
| 339 |
-
# Create a FastAPI app and mount the Gradio app with CORS support
|
| 340 |
app = FastAPI()
|
| 341 |
app.add_middleware(
|
| 342 |
CORSMiddleware,
|
|
@@ -354,7 +260,7 @@ app.mount("/static", StaticFiles(directory=tempfile.gettempdir()), name="static"
|
|
| 354 |
async def health_check():
|
| 355 |
return {"status": "healthy"}
|
| 356 |
|
| 357 |
-
# FastAPI endpoint for Salesforce
|
| 358 |
@app.post("/api/gradio_interface")
|
| 359 |
async def api_gradio_interface(
|
| 360 |
boq_file: UploadFile = File(...),
|
|
@@ -454,34 +360,6 @@ async def api_gradio_interface(
|
|
| 454 |
shutil.rmtree(temp_dir)
|
| 455 |
logger.debug(f"Cleaned up temporary directory: {temp_dir}")
|
| 456 |
|
| 457 |
-
# Create Gradio interface
|
| 458 |
-
demo = gr.Blocks(theme="default")
|
| 459 |
-
with demo:
|
| 460 |
-
gr.Markdown("## AI Civil Work Planner")
|
| 461 |
-
gr.Markdown("Generate a project timeline (Gantt chart) and risk tags based on BOQ data and site parameters.")
|
| 462 |
-
|
| 463 |
-
with gr.Row():
|
| 464 |
-
with gr.Column():
|
| 465 |
-
boq_file = gr.File(label="Upload BOQ Data (CSV format)")
|
| 466 |
-
weather = gr.Dropdown(label="Weather", choices=["sunny", "rainy", "cloudy"], value="sunny")
|
| 467 |
-
workforce = gr.Number(label="Workforce Size", value=10, precision=0)
|
| 468 |
-
location = gr.Textbox(label="Location", placeholder="Enter project location")
|
| 469 |
-
project_title = gr.Textbox(label="Project Title", placeholder="Enter project title")
|
| 470 |
-
submit_btn = gr.Button("Generate Timeline")
|
| 471 |
-
|
| 472 |
-
with gr.Column():
|
| 473 |
-
output_image = gr.Image(label="Gantt Chart")
|
| 474 |
-
risk_tags = gr.Textbox(label="Risk Tags and Salesforce Status")
|
| 475 |
-
|
| 476 |
-
submit_btn.click(
|
| 477 |
-
fn=gradio_interface,
|
| 478 |
-
inputs=[boq_file, weather, workforce, location, project_title],
|
| 479 |
-
outputs=[output_image, risk_tags],
|
| 480 |
-
)
|
| 481 |
-
|
| 482 |
-
# Mount Gradio app
|
| 483 |
-
gradio_app = gr.mount_gradio_app(app, demo, path="/")
|
| 484 |
-
|
| 485 |
if __name__ == "__main__":
|
| 486 |
import uvicorn
|
| 487 |
-
uvicorn.run(
|
|
|
|
|
|
|
| 1 |
import pandas as pd
|
| 2 |
import numpy as np
|
| 3 |
import matplotlib.pyplot as plt
|
|
|
|
| 213 |
output_path = os.path.join(temp_dir, output_filename)
|
| 214 |
logger.debug(f"Gantt chart will be saved to: {output_path}")
|
| 215 |
|
| 216 |
+
df = pd.read_csv(boq_file)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
if "Task Name" not in df.columns or "Duration" not in df.columns:
|
| 218 |
raise ValueError("CSV must contain 'Task Name' and 'Duration' columns")
|
| 219 |
|
|
|
|
| 242 |
shutil.rmtree(temp_dir)
|
| 243 |
return None, str(e), None
|
| 244 |
|
| 245 |
+
# Create a FastAPI app with CORS support
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 246 |
app = FastAPI()
|
| 247 |
app.add_middleware(
|
| 248 |
CORSMiddleware,
|
|
|
|
| 260 |
async def health_check():
|
| 261 |
return {"status": "healthy"}
|
| 262 |
|
| 263 |
+
# FastAPI endpoint for processing BOQ files and interacting with Salesforce
|
| 264 |
@app.post("/api/gradio_interface")
|
| 265 |
async def api_gradio_interface(
|
| 266 |
boq_file: UploadFile = File(...),
|
|
|
|
| 360 |
shutil.rmtree(temp_dir)
|
| 361 |
logger.debug(f"Cleaned up temporary directory: {temp_dir}")
|
| 362 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 363 |
if __name__ == "__main__":
|
| 364 |
import uvicorn
|
| 365 |
+
uvicorn.run(app, host="0.0.0.0", port=7860)
|