rairo commited on
Commit
cdff30c
·
verified ·
1 Parent(s): 14bcf8b

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +117 -3
main.py CHANGED
@@ -619,7 +619,7 @@ def create_project():
619
  }
620
  db_ref.child(f'projects/{project_id}').set(project_data)
621
 
622
- user_ref.update({'credits': user_data.get('credits', 1) - 1})
623
  return jsonify(project_data), 201
624
 
625
  except Exception as e:
@@ -629,19 +629,54 @@ def create_project():
629
 
630
  @app.route('/api/projects/<string:project_id>/approve', methods=['PUT'])
631
  def approve_project_plan(project_id):
 
 
 
 
 
632
  uid = verify_token(request.headers.get('Authorization'))
633
  if not uid:
 
634
  return jsonify({'error': 'Unauthorized'}), 401
 
 
 
 
 
 
 
 
 
 
 
 
635
 
 
 
636
  project_ref = db_ref.child(f'projects/{project_id}')
637
  project_data = project_ref.get()
638
  if not project_data or project_data.get('uid') != uid:
 
639
  return jsonify({'error': 'Project not found or access denied'}), 404
 
 
640
 
 
641
  selected_option = request.json.get('selectedOption')
 
 
 
642
  response = requests.get(project_data['userImageURL'])
 
 
 
 
643
  pil_image = Image.open(io.BytesIO(response.content)).convert('RGB')
 
 
644
 
 
 
645
  context = (
646
  f"The user chose the upcycling project: '{selected_option}'."
647
  if selected_option
@@ -662,13 +697,24 @@ def approve_project_plan(project_id):
662
  1. First step instructions.
663
  2. Second step instructions...
664
  """
 
 
665
 
666
  try:
 
 
 
 
667
  chat = client.chats.create(
668
  model=GENERATION_MODEL,
669
  config=types.GenerateContentConfig(response_modalities=["Text", "Image"])
670
  )
671
  full_resp = chat.send_message([detailed_prompt, pil_image])
 
 
 
 
 
672
  gen_parts = full_resp.candidates[0].content.parts
673
 
674
  combined_text = ""
@@ -681,24 +727,49 @@ def approve_project_plan(project_id):
681
  inline_images.append(img)
682
 
683
  combined_text = combined_text.strip()
 
 
684
 
 
 
685
  tools_section = re.search(r"TOOLS AND MATERIALS:\s*(.*?)\s*STEPS:", combined_text, re.DOTALL).group(1).strip()
686
  steps_section = re.search(r"STEPS:\s*(.*)", combined_text, re.DOTALL).group(1).strip()
687
 
688
  tools_list = [line.strip("- ").strip() for line in tools_section.split('\n') if line.strip()]
689
  parsed_steps = parse_numbered_steps(steps_section)
 
 
690
 
691
  if len(parsed_steps) != len(inline_images):
 
692
  return jsonify({'error': 'AI response mismatch: Steps and images do not match.'}), 500
693
 
 
 
694
  final_steps = []
 
 
 
695
  for i, step_info in enumerate(parsed_steps):
 
 
 
 
696
  img_byte_arr = io.BytesIO()
697
  inline_images[i].save(img_byte_arr, format='JPEG', optimize=True, quality=70)
698
  img_path = f"users/{uid}/projects/{project_id}/steps/step_{i+1}_image.jpg"
699
  img_url = upload_to_storage(img_byte_arr.getvalue(), img_path, 'image/jpeg')
 
 
 
700
 
 
 
701
  narration_url = generate_tts_audio_and_upload(step_info['text'], uid, project_id, i + 1)
 
 
 
 
702
  step_info.update({
703
  "imageUrl": img_url,
704
  "narrationUrl": narration_url,
@@ -707,6 +778,12 @@ def approve_project_plan(project_id):
707
  })
708
  final_steps.append(step_info)
709
 
 
 
 
 
 
 
710
  update_data = {
711
  "status": "ready",
712
  "toolsList": tools_list,
@@ -714,14 +791,51 @@ def approve_project_plan(project_id):
714
  "selectedOption": selected_option or ""
715
  }
716
  project_ref.update(update_data)
 
 
717
 
718
- # Fetch and return the full updated project
 
719
  updated_project = project_ref.get()
720
  updated_project["projectId"] = project_id
721
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
722
  return jsonify(updated_project)
723
 
724
  except Exception as e:
 
 
 
 
 
 
725
  return jsonify({'error': str(e)}), 500
726
 
727
  @app.route('/api/projects', methods=['GET'])
 
619
  }
620
  db_ref.child(f'projects/{project_id}').set(project_data)
621
 
622
+ user_ref.update({'credits': user_data.get('credits', 0) - 1})
623
  return jsonify(project_data), 201
624
 
625
  except Exception as e:
 
629
 
630
  @app.route('/api/projects/<string:project_id>/approve', methods=['PUT'])
631
  def approve_project_plan(project_id):
632
+ start_time = time.time()
633
+ logger.info(f"[PROJECT APPROVAL] Starting approval process for project: {project_id}")
634
+
635
+ # Authorization timing
636
+ auth_start = time.time()
637
  uid = verify_token(request.headers.get('Authorization'))
638
  if not uid:
639
+ logger.error(f"[PROJECT APPROVAL] ERROR: Unauthorized access attempt for project: {project_id}")
640
  return jsonify({'error': 'Unauthorized'}), 401
641
+ auth_time = time.time() - auth_start
642
+ logger.info(f"[PROJECT APPROVAL] Authorization completed in {auth_time:.3f}s for user: {uid}")
643
+
644
+ # User data fetch timing
645
+ user_fetch_start = time.time()
646
+ user_ref = db_ref.child(f'users/{uid}')
647
+ user_data = user_ref.get()
648
+ if not user_data or user_data.get('credits', 0) < 5:
649
+ logger.error(f"[PROJECT APPROVAL] ERROR: Insufficient credits for user: {uid}, credits: {user_data.get('credits', 0) if user_data else 0}")
650
+ return jsonify({'error': 'Insufficient credits'}), 402
651
+ user_fetch_time = time.time() - user_fetch_start
652
+ logger.info(f"[PROJECT APPROVAL] User data fetch completed in {user_fetch_time:.3f}s, credits: {user_data.get('credits', 0)}")
653
 
654
+ # Project data fetch timing
655
+ project_fetch_start = time.time()
656
  project_ref = db_ref.child(f'projects/{project_id}')
657
  project_data = project_ref.get()
658
  if not project_data or project_data.get('uid') != uid:
659
+ logger.error(f"[PROJECT APPROVAL] ERROR: Project not found or access denied - project_id: {project_id}, uid: {uid}")
660
  return jsonify({'error': 'Project not found or access denied'}), 404
661
+ project_fetch_time = time.time() - project_fetch_start
662
+ logger.info(f"[PROJECT APPROVAL] Project data fetch completed in {project_fetch_time:.3f}s for project: {project_data.get('projectTitle', 'Unknown')}")
663
 
664
+ # Image download and processing timing
665
  selected_option = request.json.get('selectedOption')
666
+ logger.info(f"[PROJECT APPROVAL] Selected option: {selected_option}")
667
+
668
+ image_download_start = time.time()
669
  response = requests.get(project_data['userImageURL'])
670
+ image_download_time = time.time() - image_download_start
671
+ logger.info(f"[PROJECT APPROVAL] Image download completed in {image_download_time:.3f}s, size: {len(response.content)} bytes")
672
+
673
+ image_processing_start = time.time()
674
  pil_image = Image.open(io.BytesIO(response.content)).convert('RGB')
675
+ image_processing_time = time.time() - image_processing_start
676
+ logger.info(f"[PROJECT APPROVAL] Image processing completed in {image_processing_time:.3f}s")
677
 
678
+ # Context preparation timing
679
+ context_start = time.time()
680
  context = (
681
  f"The user chose the upcycling project: '{selected_option}'."
682
  if selected_option
 
697
  1. First step instructions.
698
  2. Second step instructions...
699
  """
700
+ context_time = time.time() - context_start
701
+ logger.info(f"[PROJECT APPROVAL] Context preparation completed in {context_time:.3f}s")
702
 
703
  try:
704
+ # AI generation timing
705
+ ai_start = time.time()
706
+ logger.info(f"[PROJECT APPROVAL] Starting AI generation with model: {GENERATION_MODEL}")
707
+
708
  chat = client.chats.create(
709
  model=GENERATION_MODEL,
710
  config=types.GenerateContentConfig(response_modalities=["Text", "Image"])
711
  )
712
  full_resp = chat.send_message([detailed_prompt, pil_image])
713
+ ai_time = time.time() - ai_start
714
+ logger.info(f"[PROJECT APPROVAL] AI generation completed in {ai_time:.3f}s")
715
+
716
+ # Response parsing timing
717
+ parsing_start = time.time()
718
  gen_parts = full_resp.candidates[0].content.parts
719
 
720
  combined_text = ""
 
727
  inline_images.append(img)
728
 
729
  combined_text = combined_text.strip()
730
+ parsing_time = time.time() - parsing_start
731
+ logger.info(f"[PROJECT APPROVAL] Response parsing completed in {parsing_time:.3f}s, found {len(inline_images)} images")
732
 
733
+ # Text extraction timing
734
+ extraction_start = time.time()
735
  tools_section = re.search(r"TOOLS AND MATERIALS:\s*(.*?)\s*STEPS:", combined_text, re.DOTALL).group(1).strip()
736
  steps_section = re.search(r"STEPS:\s*(.*)", combined_text, re.DOTALL).group(1).strip()
737
 
738
  tools_list = [line.strip("- ").strip() for line in tools_section.split('\n') if line.strip()]
739
  parsed_steps = parse_numbered_steps(steps_section)
740
+ extraction_time = time.time() - extraction_start
741
+ logger.info(f"[PROJECT APPROVAL] Text extraction completed in {extraction_time:.3f}s, tools: {len(tools_list)}, steps: {len(parsed_steps)}")
742
 
743
  if len(parsed_steps) != len(inline_images):
744
+ logger.error(f"[PROJECT APPROVAL] ERROR: AI response mismatch - Steps: {len(parsed_steps)}, Images: {len(inline_images)}")
745
  return jsonify({'error': 'AI response mismatch: Steps and images do not match.'}), 500
746
 
747
+ # Step processing timing
748
+ step_processing_start = time.time()
749
  final_steps = []
750
+ total_upload_time = 0
751
+ total_tts_time = 0
752
+
753
  for i, step_info in enumerate(parsed_steps):
754
+ logger.info(f"[PROJECT APPROVAL] Processing step {i+1}/{len(parsed_steps)}")
755
+
756
+ # Image upload timing
757
+ image_upload_start = time.time()
758
  img_byte_arr = io.BytesIO()
759
  inline_images[i].save(img_byte_arr, format='JPEG', optimize=True, quality=70)
760
  img_path = f"users/{uid}/projects/{project_id}/steps/step_{i+1}_image.jpg"
761
  img_url = upload_to_storage(img_byte_arr.getvalue(), img_path, 'image/jpeg')
762
+ image_upload_time = time.time() - image_upload_start
763
+ total_upload_time += image_upload_time
764
+ logger.info(f"[PROJECT APPROVAL] Step {i+1} image upload completed in {image_upload_time:.3f}s")
765
 
766
+ # TTS generation timing
767
+ tts_start = time.time()
768
  narration_url = generate_tts_audio_and_upload(step_info['text'], uid, project_id, i + 1)
769
+ tts_time = time.time() - tts_start
770
+ total_tts_time += tts_time
771
+ logger.info(f"[PROJECT APPROVAL] Step {i+1} TTS generation completed in {tts_time:.3f}s")
772
+
773
  step_info.update({
774
  "imageUrl": img_url,
775
  "narrationUrl": narration_url,
 
778
  })
779
  final_steps.append(step_info)
780
 
781
+ step_processing_time = time.time() - step_processing_start
782
+ logger.info(f"[PROJECT APPROVAL] All steps processing completed in {step_processing_time:.3f}s")
783
+ logger.info(f"[PROJECT APPROVAL] Total upload time: {total_upload_time:.3f}s, Total TTS time: {total_tts_time:.3f}s")
784
+
785
+ # Database update timing
786
+ db_update_start = time.time()
787
  update_data = {
788
  "status": "ready",
789
  "toolsList": tools_list,
 
791
  "selectedOption": selected_option or ""
792
  }
793
  project_ref.update(update_data)
794
+ db_update_time = time.time() - db_update_start
795
+ logger.info(f"[PROJECT APPROVAL] Database update completed in {db_update_time:.3f}s")
796
 
797
+ # Final project fetch timing
798
+ final_fetch_start = time.time()
799
  updated_project = project_ref.get()
800
  updated_project["projectId"] = project_id
801
+ final_fetch_time = time.time() - final_fetch_start
802
+ logger.info(f"[PROJECT APPROVAL] Final project fetch completed in {final_fetch_time:.3f}s")
803
+
804
+ # Credits deduction timing
805
+ credits_update_start = time.time()
806
+ user_ref.update({'credits': user_data.get('credits', 0) - 5})
807
+ credits_update_time = time.time() - credits_update_start
808
+ logger.info(f"[PROJECT APPROVAL] Credits update completed in {credits_update_time:.3f}s")
809
+
810
+ # Total time calculation
811
+ total_time = time.time() - start_time
812
+ logger.info(f"[PROJECT APPROVAL] SUCCESS: Project approval completed in {total_time:.3f}s")
813
+ logger.info(f"[PROJECT APPROVAL] TIMING BREAKDOWN:")
814
+ logger.info(f"[PROJECT APPROVAL] - Authorization: {auth_time:.3f}s")
815
+ logger.info(f"[PROJECT APPROVAL] - User fetch: {user_fetch_time:.3f}s")
816
+ logger.info(f"[PROJECT APPROVAL] - Project fetch: {project_fetch_time:.3f}s")
817
+ logger.info(f"[PROJECT APPROVAL] - Image download: {image_download_time:.3f}s")
818
+ logger.info(f"[PROJECT APPROVAL] - Image processing: {image_processing_time:.3f}s")
819
+ logger.info(f"[PROJECT APPROVAL] - Context prep: {context_time:.3f}s")
820
+ logger.info(f"[PROJECT APPROVAL] - AI generation: {ai_time:.3f}s")
821
+ logger.info(f"[PROJECT APPROVAL] - Response parsing: {parsing_time:.3f}s")
822
+ logger.info(f"[PROJECT APPROVAL] - Text extraction: {extraction_time:.3f}s")
823
+ logger.info(f"[PROJECT APPROVAL] - Step processing: {step_processing_time:.3f}s")
824
+ logger.info(f"[PROJECT APPROVAL] - Total uploads: {total_upload_time:.3f}s")
825
+ logger.info(f"[PROJECT APPROVAL] - Total TTS: {total_tts_time:.3f}s")
826
+ logger.info(f"[PROJECT APPROVAL] - DB update: {db_update_time:.3f}s")
827
+ logger.info(f"[PROJECT APPROVAL] - Final fetch: {final_fetch_time:.3f}s")
828
+ logger.info(f"[PROJECT APPROVAL] - Credits update: {credits_update_time:.3f}s")
829
+
830
  return jsonify(updated_project)
831
 
832
  except Exception as e:
833
+ total_time = time.time() - start_time
834
+ logger.error(f"[PROJECT APPROVAL] ERROR: Exception occurred after {total_time:.3f}s: {e}")
835
+ logger.error(f"[PROJECT APPROVAL] Error type: {type(e).__name__}")
836
+ logger.error(f"[PROJECT APPROVAL] Project ID: {project_id}, User ID: {uid}")
837
+ import traceback
838
+ logger.error(f"[PROJECT APPROVAL] Full traceback: {traceback.format_exc()}")
839
  return jsonify({'error': str(e)}), 500
840
 
841
  @app.route('/api/projects', methods=['GET'])