Update app.py
Browse files
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
|
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.
|
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.
|
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 |
-
|
|
|
662 |
|
663 |
-
# Upload to Gemini File API
|
664 |
try:
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
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
|
688 |
-
|
689 |
|
|
|
690 |
cache = client.caches.create(
|
691 |
-
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
|
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 |
-
#
|
|
|
|
|
|
|
828 |
try:
|
829 |
-
|
830 |
-
|
831 |
-
|
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
|
853 |
-
|
854 |
|
|
|
855 |
cache = client.caches.create(
|
856 |
-
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 |
-
#
|
895 |
-
|
|
|
896 |
return jsonify({
|
897 |
'success': False,
|
898 |
-
'error': '
|
899 |
-
'suggestion': 'Try
|
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=
|
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']
|