Omartificial-Intelligence-Space commited on
Commit
a819b46
·
verified ·
1 Parent(s): 1ed7d4b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -99
app.py CHANGED
@@ -6,6 +6,7 @@ import os
6
  import io
7
  import httpx
8
  import uuid
 
9
  from datetime import datetime, timezone, timedelta
10
  from dotenv import load_dotenv
11
  import json
@@ -330,7 +331,7 @@ HTML_TEMPLATE = """
330
  <div class="container">
331
  <div class="header">
332
  <h1>📚 Smart Document Analysis Platform</h1>
333
- <p>Upload substantial PDF documents (5MB+ recommended) for efficient context caching with Gemini API</p>
334
  <p style="font-size: 0.9em; opacity: 0.8; margin-top: 5px;">💡 Context caching requires minimum token thresholds - larger documents work better</p>
335
  </div>
336
 
@@ -467,7 +468,7 @@ HTML_TEMPLATE = """
467
  document.getElementById('cacheId').textContent = result.cache_id;
468
  document.getElementById('tokenCount').textContent = result.token_count;
469
  document.getElementById('documentName').textContent = result.document_name;
470
- document.getElementById('modelUsed').textContent = result.model_used || 'gemini-2.5-flash-001';
471
  document.getElementById('cacheInfo').style.display = 'block';
472
  showSuccess('PDF uploaded and cached successfully!');
473
 
@@ -511,7 +512,7 @@ HTML_TEMPLATE = """
511
  document.getElementById('cacheId').textContent = result.cache_id;
512
  document.getElementById('tokenCount').textContent = result.token_count;
513
  document.getElementById('documentName').textContent = result.document_name;
514
- document.getElementById('modelUsed').textContent = result.model_used || 'gemini-2.5-flash-001';
515
  document.getElementById('cacheInfo').style.display = 'block';
516
  showSuccess('PDF uploaded and cached successfully!');
517
 
@@ -652,48 +653,39 @@ def upload_file():
652
  # Warn about small files that might not cache
653
  if file_size < 1024 * 1024: # Less than 1MB
654
  print(f"Warning: Small file uploaded ({file_size_mb:.1f}MB). May not meet minimum token requirements for caching.")
655
-
656
  # Read file content
657
  file_content = file.read()
658
  if not file_content:
659
  return jsonify({'success': False, 'error': 'File is empty'})
660
 
661
- file_io = io.BytesIO(file_content)
 
662
 
663
- # Upload to Gemini File API
664
  try:
665
- # Save the BytesIO to a temporary file since the API expects a file path
666
- import tempfile
667
- with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as temp_file:
668
- temp_file.write(file_content)
669
- temp_file_path = temp_file.name
670
-
671
- # Upload using file path
672
- document = client.files.upload(path=temp_file_path)
673
  print(f"Document uploaded successfully: {document.name}")
674
-
675
- # Clean up temporary file
676
- import os
677
- os.unlink(temp_file_path)
678
-
679
  except Exception as upload_error:
680
  print(f"Upload error: {upload_error}")
681
  return jsonify({'success': False, 'error': f'Failed to upload file to Gemini: {str(upload_error)}'})
682
 
683
- # Create cache with system instruction
684
  try:
685
  system_instruction = "You are an expert document analyzer. Provide detailed, accurate answers based on the uploaded document content. Always be helpful and thorough in your responses."
686
 
687
- # Use the correct model name - try 2.5 Flash first (lower token requirement)
688
- model = 'gemini-2.5-flash-001'
689
 
 
690
  cache = client.caches.create(
691
- model=model,
692
  config=types.CreateCachedContentConfig(
693
- display_name=f'PDF document cache - {file.filename}',
694
  system_instruction=system_instruction,
695
- contents=[document],
696
- ttl="3600s", # 1 hour TTL
697
  )
698
  )
699
 
@@ -730,50 +722,9 @@ def upload_file():
730
  if "too small" in error_msg or "minimum" in error_msg:
731
  return jsonify({
732
  'success': False,
733
- 'error': f'Document content is insufficient for caching. Gemini 2.5 Flash requires minimum 1,024 tokens (~2-3 pages of text). Your document: {file.filename} ({file_size_mb:.1f}MB)',
734
- 'suggestion': 'Upload a longer document with more text content (recommended: 5MB+ with substantial text).',
735
- 'fallback': 'You can still use the document without caching by implementing direct file processing.'
736
  })
737
- elif "invalid" in error_msg or "model" in error_msg:
738
- # Try fallback to 2.0 Flash
739
- try:
740
- cache_fallback = client.caches.create(
741
- model='gemini-2.0-flash-001',
742
- config=types.CreateCachedContentConfig(
743
- display_name=f'PDF document cache - {file.filename}',
744
- system_instruction=system_instruction,
745
- contents=[document],
746
- ttl="3600s",
747
- )
748
- )
749
- print(f"Fallback cache created with 2.0 Flash: {cache_fallback.name}")
750
-
751
- # Store with fallback model info
752
- cache_id = str(uuid.uuid4())
753
- document_caches[cache_id] = {
754
- 'cache_name': cache_fallback.name,
755
- 'document_name': file.filename,
756
- 'document_file_name': document.name,
757
- 'model': 'gemini-2.0-flash-001',
758
- 'created_at': datetime.now().isoformat()
759
- }
760
-
761
- token_count = 'Unknown'
762
- if hasattr(cache_fallback, 'usage_metadata') and cache_fallback.usage_metadata:
763
- if hasattr(cache_fallback.usage_metadata, 'total_token_count'):
764
- token_count = cache_fallback.usage_metadata.total_token_count
765
-
766
- return jsonify({
767
- 'success': True,
768
- 'cache_id': cache_id,
769
- 'token_count': token_count,
770
- 'document_name': file.filename,
771
- 'model_used': 'gemini-2.0-flash-001'
772
- })
773
-
774
- except Exception as fallback_error:
775
- print(f"Fallback cache error: {fallback_error}")
776
- return jsonify({'success': False, 'error': f'Failed to create cache with both models: {str(fallback_error)}'})
777
  else:
778
  return jsonify({'success': False, 'error': f'Failed to create cache: {str(cache_error)}'})
779
 
@@ -812,8 +763,6 @@ def upload_from_url():
812
  if content_length < 1024 * 1024: # Less than 1MB
813
  print(f"Warning: Small file from URL ({content_length_mb:.1f}MB). May not meet minimum token requirements for caching.")
814
 
815
- file_io = io.BytesIO(response.content)
816
-
817
  except httpx.TimeoutException:
818
  return jsonify({'success': False, 'error': 'Request timeout. Please try a different URL.'})
819
  except httpx.HTTPError as e:
@@ -824,41 +773,33 @@ def upload_from_url():
824
  if not filename.endswith('.pdf'):
825
  filename += '.pdf'
826
 
827
- # Upload to Gemini File API
 
 
 
828
  try:
829
- # Save the BytesIO to a temporary file since the API expects a file path
830
- import tempfile
831
- import os
832
-
833
- with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as temp_file:
834
- temp_file.write(response.content)
835
- temp_file_path = temp_file.name
836
-
837
- # Upload using file path
838
- document = client.files.upload(path=temp_file_path)
839
  print(f"Document uploaded successfully: {document.name}")
840
-
841
- # Clean up temporary file
842
- os.unlink(temp_file_path)
843
-
844
  except Exception as upload_error:
845
  print(f"Upload error: {upload_error}")
846
  return jsonify({'success': False, 'error': f'Failed to upload file to Gemini: {str(upload_error)}'})
847
 
848
- # Create cache with system instruction
849
  try:
850
  system_instruction = "You are an expert document analyzer. Provide detailed, accurate answers based on the uploaded document content. Always be helpful and thorough in your responses."
851
 
852
- # Use the correct model name - try 2.5 Flash first (lower token requirement)
853
- model = 'gemini-2.5-flash-001'
854
 
 
855
  cache = client.caches.create(
856
- model=model,
857
  config=types.CreateCachedContentConfig(
858
- display_name=f'PDF document cache - {filename}',
859
  system_instruction=system_instruction,
860
- contents=[document],
861
- ttl="3600s", # 1 hour TTL
862
  )
863
  )
864
 
@@ -869,7 +810,6 @@ def upload_from_url():
869
  document_caches[cache_id] = {
870
  'cache_name': cache.name,
871
  'document_name': filename,
872
- 'document_file_name': document.name,
873
  'source_url': url,
874
  'created_at': datetime.now().isoformat()
875
  }
@@ -891,12 +831,13 @@ def upload_from_url():
891
 
892
  except Exception as cache_error:
893
  print(f"Cache error: {cache_error}")
894
- # If caching fails due to small content, provide alternative approach
895
- if "too small" in str(cache_error).lower():
 
896
  return jsonify({
897
  'success': False,
898
- 'error': 'PDF content is too small for caching. Please upload a larger document with more text content.',
899
- 'suggestion': 'Try uploading a longer document or combine multiple documents.'
900
  })
901
  else:
902
  return jsonify({'success': False, 'error': f'Failed to create cache: {str(cache_error)}'})
@@ -923,7 +864,7 @@ def ask_question():
923
  # Generate response using cached content with correct model format
924
  try:
925
  response = client.models.generate_content(
926
- model='gemini-2.5-flash-001', # Use 2.5 Flash for consistency
927
  contents=question,
928
  config=types.GenerateContentConfig(
929
  cached_content=cache_info['cache_name']
 
6
  import io
7
  import httpx
8
  import uuid
9
+ import tempfile
10
  from datetime import datetime, timezone, timedelta
11
  from dotenv import load_dotenv
12
  import json
 
331
  <div class="container">
332
  <div class="header">
333
  <h1>📚 Smart Document Analysis Platform</h1>
334
+ <p>Upload substantial PDF documents for efficient context caching with Gemini API</p>
335
  <p style="font-size: 0.9em; opacity: 0.8; margin-top: 5px;">💡 Context caching requires minimum token thresholds - larger documents work better</p>
336
  </div>
337
 
 
468
  document.getElementById('cacheId').textContent = result.cache_id;
469
  document.getElementById('tokenCount').textContent = result.token_count;
470
  document.getElementById('documentName').textContent = result.document_name;
471
+ document.getElementById('modelUsed').textContent = result.model_used || 'gemini-2.0-flash-001';
472
  document.getElementById('cacheInfo').style.display = 'block';
473
  showSuccess('PDF uploaded and cached successfully!');
474
 
 
512
  document.getElementById('cacheId').textContent = result.cache_id;
513
  document.getElementById('tokenCount').textContent = result.token_count;
514
  document.getElementById('documentName').textContent = result.document_name;
515
+ document.getElementById('modelUsed').textContent = result.model_used || 'gemini-2.0-flash-001';
516
  document.getElementById('cacheInfo').style.display = 'block';
517
  showSuccess('PDF uploaded and cached successfully!');
518
 
 
653
  # Warn about small files that might not cache
654
  if file_size < 1024 * 1024: # Less than 1MB
655
  print(f"Warning: Small file uploaded ({file_size_mb:.1f}MB). May not meet minimum token requirements for caching.")
656
+
657
  # Read file content
658
  file_content = file.read()
659
  if not file_content:
660
  return jsonify({'success': False, 'error': 'File is empty'})
661
 
662
+ # Create BytesIO from content as shown in documentation
663
+ doc_io = io.BytesIO(file_content)
664
 
665
+ # Upload to Gemini File API using the exact pattern from documentation
666
  try:
667
+ document = client.files.upload(
668
+ file=doc_io,
669
+ config=dict(mime_type='application/pdf')
670
+ )
 
 
 
 
671
  print(f"Document uploaded successfully: {document.name}")
 
 
 
 
 
672
  except Exception as upload_error:
673
  print(f"Upload error: {upload_error}")
674
  return jsonify({'success': False, 'error': f'Failed to upload file to Gemini: {str(upload_error)}'})
675
 
676
+ # Create cache with system instruction using exact pattern from documentation
677
  try:
678
  system_instruction = "You are an expert document analyzer. Provide detailed, accurate answers based on the uploaded document content. Always be helpful and thorough in your responses."
679
 
680
+ # Use the model name format from documentation
681
+ model_name = "gemini-2.0-flash-001"
682
 
683
+ # Create cached content object exactly as shown in documentation
684
  cache = client.caches.create(
685
+ model=model_name,
686
  config=types.CreateCachedContentConfig(
 
687
  system_instruction=system_instruction,
688
+ contents=[document], # Direct document reference as in docs
 
689
  )
690
  )
691
 
 
722
  if "too small" in error_msg or "minimum" in error_msg:
723
  return jsonify({
724
  'success': False,
725
+ 'error': f'Document content is insufficient for caching. Gemini requires minimum token thresholds. Your document: {file.filename} ({file_size_mb:.1f}MB)',
726
+ 'suggestion': 'Upload a longer document with more text content (recommended: 5MB+ with substantial text).'
 
727
  })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
728
  else:
729
  return jsonify({'success': False, 'error': f'Failed to create cache: {str(cache_error)}'})
730
 
 
763
  if content_length < 1024 * 1024: # Less than 1MB
764
  print(f"Warning: Small file from URL ({content_length_mb:.1f}MB). May not meet minimum token requirements for caching.")
765
 
 
 
766
  except httpx.TimeoutException:
767
  return jsonify({'success': False, 'error': 'Request timeout. Please try a different URL.'})
768
  except httpx.HTTPError as e:
 
773
  if not filename.endswith('.pdf'):
774
  filename += '.pdf'
775
 
776
+ # Create BytesIO from content as shown in documentation
777
+ doc_io = io.BytesIO(response.content)
778
+
779
+ # Upload to Gemini File API using the exact pattern from documentation
780
  try:
781
+ document = client.files.upload(
782
+ file=doc_io,
783
+ config=dict(mime_type='application/pdf')
784
+ )
 
 
 
 
 
 
785
  print(f"Document uploaded successfully: {document.name}")
 
 
 
 
786
  except Exception as upload_error:
787
  print(f"Upload error: {upload_error}")
788
  return jsonify({'success': False, 'error': f'Failed to upload file to Gemini: {str(upload_error)}'})
789
 
790
+ # Create cache with system instruction using exact pattern from documentation
791
  try:
792
  system_instruction = "You are an expert document analyzer. Provide detailed, accurate answers based on the uploaded document content. Always be helpful and thorough in your responses."
793
 
794
+ # Use the model name format from documentation
795
+ model_name = "gemini-2.0-flash-001"
796
 
797
+ # Create cached content object exactly as shown in documentation
798
  cache = client.caches.create(
799
+ model=model_name,
800
  config=types.CreateCachedContentConfig(
 
801
  system_instruction=system_instruction,
802
+ contents=[document], # Direct document reference as in docs
 
803
  )
804
  )
805
 
 
810
  document_caches[cache_id] = {
811
  'cache_name': cache.name,
812
  'document_name': filename,
 
813
  'source_url': url,
814
  'created_at': datetime.now().isoformat()
815
  }
 
831
 
832
  except Exception as cache_error:
833
  print(f"Cache error: {cache_error}")
834
+ # Provide more specific error handling for token requirements
835
+ error_msg = str(cache_error).lower()
836
+ if "too small" in error_msg or "minimum" in error_msg:
837
  return jsonify({
838
  'success': False,
839
+ 'error': f'Document content is insufficient for caching. Gemini requires minimum token thresholds. Document from URL: {filename} ({content_length_mb:.1f}MB)',
840
+ 'suggestion': 'Try a longer document with more text content (recommended: 5MB+ with substantial text).'
841
  })
842
  else:
843
  return jsonify({'success': False, 'error': f'Failed to create cache: {str(cache_error)}'})
 
864
  # Generate response using cached content with correct model format
865
  try:
866
  response = client.models.generate_content(
867
+ model="gemini-2.0-flash-001", # Use model name format from documentation
868
  contents=question,
869
  config=types.GenerateContentConfig(
870
  cached_content=cache_info['cache_name']