chenguittiMaroua commited on
Commit
ecf4773
·
verified ·
1 Parent(s): 629bda0

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +51 -22
main.py CHANGED
@@ -771,26 +771,57 @@ from fastapi.responses import FileResponse # Add this import at the top
771
 
772
 
773
 
 
 
774
  @app.post("/visualize/natural")
775
  @limiter.limit("5/minute")
776
  async def visualize_with_natural_language(
777
  request: Request,
778
  file: UploadFile = File(...),
779
- prompt: str = Form(""), # Make prompt optional
780
  style: str = Form("seaborn-v0_8")
781
  ):
782
  try:
783
- file_ext, content = await process_uploaded_file(file)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
784
  if file_ext not in {"xlsx", "xls"}:
785
- raise HTTPException(400, "Only Excel files are supported for visualization")
786
-
787
- # Use our robust reader
788
- df = read_any_excel(content)
789
-
 
 
 
 
 
 
 
790
  # Generate smart prompt if none provided
791
  if not prompt.strip():
792
  prompt = generate_smart_prompt(df)
793
-
 
794
  # Generate visualization request
795
  vis_request = interpret_natural_language(prompt, df.columns.tolist())
796
  if not vis_request:
@@ -807,7 +838,11 @@ async def visualize_with_natural_language(
807
 
808
  # Execute the visualization code safely
809
  local_vars = {'plt': plt, 'sns': sns, 'df': df}
810
- exec(visualization_code, globals(), local_vars)
 
 
 
 
811
 
812
  # Save to bytes buffer
813
  buffer = BytesIO()
@@ -825,23 +860,17 @@ async def visualize_with_natural_language(
825
  "interpreted_parameters": vis_request.dict()
826
  }
827
 
828
- except HTTPException:
 
829
  raise
830
  except Exception as e:
831
- logger.error(f"Natural language visualization failed: {str(e)}\n{traceback.format_exc()}")
832
  raise HTTPException(500, detail=f"Visualization failed: {str(e)}")
833
- return {
834
- "status": "success",
835
- "image_data": image_base64,
836
- "code": visualization_code,
837
- "interpreted_parameters": vis_request.dict()
838
- }
839
 
840
- except HTTPException:
841
- raise
842
- except Exception as e:
843
- logger.error(f"Natural language visualization failed: {str(e)}\n{traceback.format_exc()}")
844
- raise HTTPException(500, detail=f"Visualization failed: {str(e)}")
845
  @app.get("/visualize/styles")
846
  @limiter.limit("10/minute")
847
  async def list_available_styles(request: Request):
 
771
 
772
 
773
 
774
+ # [Previous imports remain exactly the same...]
775
+
776
  @app.post("/visualize/natural")
777
  @limiter.limit("5/minute")
778
  async def visualize_with_natural_language(
779
  request: Request,
780
  file: UploadFile = File(...),
781
+ prompt: str = Form(""),
782
  style: str = Form("seaborn-v0_8")
783
  ):
784
  try:
785
+ # First verify the file exists and has content
786
+ if not file.filename:
787
+ raise HTTPException(400, "No file uploaded")
788
+
789
+ # Read content first (don't rely just on extension)
790
+ content = await file.read()
791
+ if not content:
792
+ raise HTTPException(400, "Empty file uploaded")
793
+
794
+ # Verify Excel signature (magic numbers)
795
+ def is_valid_excel(content: bytes) -> bool:
796
+ excel_signatures = [
797
+ b'\x50\x4B\x03\x04', # ZIP header (modern Excel)
798
+ b'\xD0\xCF\x11\xE0' # OLE header (older Excel)
799
+ ]
800
+ return any(content.startswith(sig) for sig in excel_signatures)
801
+
802
+ if not is_valid_excel(content):
803
+ raise HTTPException(400, "File doesn't contain Excel data")
804
+
805
+ # Now check extension for supported types
806
+ file_ext = file.filename.split('.')[-1].lower()
807
  if file_ext not in {"xlsx", "xls"}:
808
+ raise HTTPException(400, "Only Excel files (.xlsx, .xls) are supported for visualization")
809
+
810
+ # Now try to process
811
+ try:
812
+ df = pd.read_excel(BytesIO(content))
813
+ except Exception as e:
814
+ logger.error(f"Excel read error: {str(e)}")
815
+ raise HTTPException(400, f"Invalid Excel file: {str(e)}")
816
+
817
+ if df.empty:
818
+ raise HTTPException(400, "The Excel file contains no data")
819
+
820
  # Generate smart prompt if none provided
821
  if not prompt.strip():
822
  prompt = generate_smart_prompt(df)
823
+ logger.info(f"Generated automatic prompt: {prompt}")
824
+
825
  # Generate visualization request
826
  vis_request = interpret_natural_language(prompt, df.columns.tolist())
827
  if not vis_request:
 
838
 
839
  # Execute the visualization code safely
840
  local_vars = {'plt': plt, 'sns': sns, 'df': df}
841
+ try:
842
+ exec(visualization_code, globals(), local_vars)
843
+ except Exception as e:
844
+ logger.error(f"Visualization code execution failed: {str(e)}")
845
+ raise HTTPException(400, f"Failed to generate visualization: {str(e)}")
846
 
847
  # Save to bytes buffer
848
  buffer = BytesIO()
 
860
  "interpreted_parameters": vis_request.dict()
861
  }
862
 
863
+ except HTTPException as he:
864
+ logger.error(f"HTTPException in visualization: {he.detail}")
865
  raise
866
  except Exception as e:
867
+ logger.error(f"Unexpected error in visualization: {str(e)}\n{traceback.format_exc()}")
868
  raise HTTPException(500, detail=f"Visualization failed: {str(e)}")
 
 
 
 
 
 
869
 
870
+ # [Rest of your code remains exactly the same...]
871
+
872
+
873
+
 
874
  @app.get("/visualize/styles")
875
  @limiter.limit("10/minute")
876
  async def list_available_styles(request: Request):