dineshb commited on
Commit
fd9e620
Β·
verified Β·
1 Parent(s): dd39e2e

Upload 3 files

Browse files

Updated app.py files by adding OCR Recognition Toggle bar

Files changed (3) hide show
  1. DEPLOYMENT.md +8 -3
  2. README.md +1 -1
  3. app.py +20 -3
DEPLOYMENT.md CHANGED
@@ -4,7 +4,7 @@ This guide covers deploying DocuChat_AI as a Streamlit app on Hugging Face Space
4
 
5
  ## 1. Recommended Hugging Face Setup
6
 
7
- For the standard app:
8
 
9
  ```text
10
  SDK: Streamlit
@@ -48,7 +48,7 @@ Pillow
48
  Tesseract OCR binary
49
  ```
50
 
51
- Python packages are installed from `requirements.txt`, but the Tesseract system binary may not be available in a normal Streamlit Space.
52
 
53
  For best OCR support, deploy using the included `Dockerfile`, which installs:
54
 
@@ -66,6 +66,12 @@ Hardware: CPU Upgrade if processing larger scanned PDFs
66
 
67
  If OCR dependencies are missing, the app fails gracefully and still works for normal text-based PDFs, DOCX, and TXT files.
68
 
 
 
 
 
 
 
69
  ## 3. Evaluation Dashboard
70
 
71
  The Evaluation tab supports labeled RAG testing with CSV files.
@@ -117,4 +123,3 @@ The correctness and faithfulness scores are LLM-judged and should be treated as
117
  - Add `APP_PASSWORD` for portfolio demos shared with recruiters.
118
  - Use the Evaluation tab with a small labeled test set before demos.
119
  - Use CPU Upgrade for larger PDFs or frequent OCR use.
120
-
 
4
 
5
  ## 1. Recommended Hugging Face Setup
6
 
7
+ For the standard app without scanned PDF OCR:
8
 
9
  ```text
10
  SDK: Streamlit
 
48
  Tesseract OCR binary
49
  ```
50
 
51
+ Python packages are installed from `requirements.txt`, but the Tesseract system binary is usually not available in a normal Streamlit SDK Space.
52
 
53
  For best OCR support, deploy using the included `Dockerfile`, which installs:
54
 
 
66
 
67
  If OCR dependencies are missing, the app fails gracefully and still works for normal text-based PDFs, DOCX, and TXT files.
68
 
69
+ Important:
70
+
71
+ ```text
72
+ If your scanned PDF returns "No readable text found", switch the Space SDK to Docker or create a new Docker Space using this repository.
73
+ ```
74
+
75
  ## 3. Evaluation Dashboard
76
 
77
  The Evaluation tab supports labeled RAG testing with CSV files.
 
123
  - Add `APP_PASSWORD` for portfolio demos shared with recruiters.
124
  - Use the Evaluation tab with a small labeled test set before demos.
125
  - Use CPU Upgrade for larger PDFs or frequent OCR use.
 
README.md CHANGED
@@ -267,7 +267,7 @@ GROQ_API_KEY = your_key_here
267
  5. Optional: add `APP_PASSWORD` in **Settings -> Secrets** to protect the app.
268
  6. Restart the Space after dependency changes.
269
 
270
- For scanned PDF OCR, use the included Dockerfile because OCR needs system packages such as Tesseract.
271
 
272
  See [DEPLOYMENT.md](DEPLOYMENT.md) for the full deployment guide.
273
 
 
267
  5. Optional: add `APP_PASSWORD` in **Settings -> Secrets** to protect the app.
268
  6. Restart the Space after dependency changes.
269
 
270
+ For scanned PDF OCR, use the included Dockerfile because OCR needs the Tesseract system binary. Normal Streamlit SDK Spaces may not include it.
271
 
272
  See [DEPLOYMENT.md](DEPLOYMENT.md) for the full deployment guide.
273
 
app.py CHANGED
@@ -390,6 +390,9 @@ def ocr_pdf_pages(pdf_path: str, source_name: str, max_pages: int = 8) -> list:
390
  )
391
  return docs
392
 
 
 
 
393
  def normalize_source_metadata(docs: list, source_name: str, file_type: str, extraction: str = "text") -> list:
394
  for doc in docs:
395
  doc.metadata["source"] = source_name
@@ -421,6 +424,7 @@ def load_documents(files, use_ocr: bool = False, ocr_page_limit: int = 8) -> lis
421
  if extracted_chars < 250:
422
  st.write(f"πŸ” Running OCR for scanned PDF: {file.name}")
423
  loaded = ocr_pdf_pages(temp_path, file.name, max_pages=ocr_page_limit)
 
424
  docs.extend(loaded[:MAX_PAGES])
425
  except Exception as e:
426
  st.error(f"⚠️ Error loading `{file.name}`: {e}")
@@ -989,8 +993,6 @@ with st.sidebar:
989
  with st.expander("βš™οΈ Advanced Settings"):
990
  temperature = st.slider("Temperature", 0.0, 1.0, 0.3, 0.05)
991
  top_k = st.slider("Retrieved Chunks (Top-K)", 2, 10, 4)
992
- use_ocr = st.checkbox("Enable OCR fallback for scanned PDFs", value=False)
993
- ocr_page_limit = st.slider("OCR Page Limit", 1, 25, 8)
994
 
995
  st.divider()
996
 
@@ -1001,6 +1003,11 @@ with st.sidebar:
1001
  accept_multiple_files=True,
1002
  )
1003
 
 
 
 
 
 
1004
  col1, col2 = st.columns(2)
1005
  process_btn = col1.button("πŸ”„ Process", type="primary", use_container_width=True)
1006
  summarize_btn = col2.button("πŸ“œ Summary", use_container_width=True)
@@ -1025,8 +1032,11 @@ with st.sidebar:
1025
  st.write("πŸ“₯ Loading files into memory...")
1026
  raw_docs = load_documents(uploaded_files, use_ocr=use_ocr, ocr_page_limit=ocr_page_limit)
1027
 
1028
- if not raw_docs:
1029
  status.update(label="No content found!", state="error")
 
 
 
1030
  st.stop()
1031
 
1032
  # BUG FIX: Save the full raw text into session state for the summary function
@@ -1040,6 +1050,13 @@ with st.sidebar:
1040
  )
1041
  chunks = splitter.split_documents(raw_docs)
1042
 
 
 
 
 
 
 
 
1043
  st.write("🧠 Generating embeddings...")
1044
  embeddings = get_embeddings()
1045
 
 
390
  )
391
  return docs
392
 
393
+ def has_readable_text(docs: list) -> bool:
394
+ return any(doc.page_content and doc.page_content.strip() for doc in docs)
395
+
396
  def normalize_source_metadata(docs: list, source_name: str, file_type: str, extraction: str = "text") -> list:
397
  for doc in docs:
398
  doc.metadata["source"] = source_name
 
424
  if extracted_chars < 250:
425
  st.write(f"πŸ” Running OCR for scanned PDF: {file.name}")
426
  loaded = ocr_pdf_pages(temp_path, file.name, max_pages=ocr_page_limit)
427
+ loaded = [doc for doc in loaded if doc.page_content and doc.page_content.strip()]
428
  docs.extend(loaded[:MAX_PAGES])
429
  except Exception as e:
430
  st.error(f"⚠️ Error loading `{file.name}`: {e}")
 
993
  with st.expander("βš™οΈ Advanced Settings"):
994
  temperature = st.slider("Temperature", 0.0, 1.0, 0.3, 0.05)
995
  top_k = st.slider("Retrieved Chunks (Top-K)", 2, 10, 4)
 
 
996
 
997
  st.divider()
998
 
 
1003
  accept_multiple_files=True,
1004
  )
1005
 
1006
+ st.subheader("πŸ” Scanned PDF OCR")
1007
+ use_ocr = st.toggle("Enable OCR for scanned PDFs", value=True, help="Use this for image-based PDFs that have no selectable text.")
1008
+ ocr_page_limit = st.slider("OCR page limit", 1, 25, 8, help="Higher values are slower on CPU Spaces.")
1009
+ st.caption("OCR needs Tesseract. Use Docker Space for the most reliable scanned PDF support.")
1010
+
1011
  col1, col2 = st.columns(2)
1012
  process_btn = col1.button("πŸ”„ Process", type="primary", use_container_width=True)
1013
  summarize_btn = col2.button("πŸ“œ Summary", use_container_width=True)
 
1032
  st.write("πŸ“₯ Loading files into memory...")
1033
  raw_docs = load_documents(uploaded_files, use_ocr=use_ocr, ocr_page_limit=ocr_page_limit)
1034
 
1035
+ if not raw_docs or not has_readable_text(raw_docs):
1036
  status.update(label="No content found!", state="error")
1037
+ st.error(
1038
+ "No readable text was found. If this is a scanned PDF, keep OCR enabled and deploy with Docker so Tesseract OCR is installed."
1039
+ )
1040
  st.stop()
1041
 
1042
  # BUG FIX: Save the full raw text into session state for the summary function
 
1050
  )
1051
  chunks = splitter.split_documents(raw_docs)
1052
 
1053
+ if not chunks:
1054
+ status.update(label="No searchable chunks created!", state="error")
1055
+ st.error(
1056
+ "The document loaded, but no searchable text chunks were created. For scanned PDFs, enable OCR and use Docker deployment with Tesseract."
1057
+ )
1058
+ st.stop()
1059
+
1060
  st.write("🧠 Generating embeddings...")
1061
  embeddings = get_embeddings()
1062