Download src/streamlit_app.py from thieuluan/hackathon: direct link, hf CLI and curl.
- Browser
- Download file 3.36 kB
-
https://huggingface.co/spaces/thieuluan/hackathon/resolve/main/src/streamlit_app.py
- Command line
-
hf download hf://spaces/thieuluan/hackathon/src/streamlit_app.py
-
curl -L -o streamlit_app.py https://huggingface.co/spaces/thieuluan/hackathon/resolve/main/src/streamlit_app.py
3.36 kB
| import streamlit as st | |
| import os | |
| import tempfile | |
| from uuid import uuid4 | |
| from concurrent.futures import ThreadPoolExecutor, Future | |
| from ingestion import ingest_pdf | |
| from dotenv import load_dotenv, find_dotenv | |
| load_dotenv(find_dotenv(), override=False) | |
| st.set_page_config(page_title="PDF Ingestion", layout="wide") | |
| if "session_id" not in st.session_state: | |
| st.session_state.session_id = str(uuid4()) | |
| if "ingestion_future" not in st.session_state: | |
| st.session_state.ingestion_future = None | |
| if "last_output" not in st.session_state: | |
| st.session_state.last_output = None | |
| st.title("Ingestion Layer") | |
| st.caption("Upload a PDF to extract, normalize, chunk, and persist for later embedding.") | |
| with st.sidebar: | |
| st.header("Settings") | |
| parser = st.selectbox("Parser", ["pypdf", "pdfplumber"], index=0) | |
| chunk_size = st.number_input("Chunk size (chars)", min_value=500, max_value=10000, value=4000, step=100) | |
| overlap = st.number_input("Overlap (chars)", min_value=0, max_value=2000, value=400, step=50) | |
| uploaded = st.file_uploader("Upload PDF", type=["pdf"]) | |
| def _run_ingestion(tmp_path: str, sid: str, parser: str, chunk_size: int, overlap: int): | |
| return ingest_pdf(tmp_path, sid, parser=parser, chunk_size=chunk_size, overlap=overlap) | |
| col1, col2 = st.columns([2, 1]) | |
| with col1: | |
| if uploaded is not None and st.button("Start Ingestion", type="primary"): | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp: | |
| tmp.write(uploaded.read()) | |
| tmp_path = tmp.name | |
| executor = ThreadPoolExecutor(max_workers=1) | |
| future: Future = executor.submit(_run_ingestion, tmp_path, st.session_state.session_id, parser, int(chunk_size), int(overlap)) | |
| st.session_state.ingestion_future = future | |
| st.info("Ingestion started. Processing in background...") | |
| future: Future = st.session_state.ingestion_future | |
| if future is not None: | |
| if future.done(): | |
| try: | |
| chunks, out_path = future.result() | |
| st.session_state.last_output = (len(chunks), out_path) | |
| st.success(f"Ingestion complete: {len(chunks)} chunks written to {out_path}") | |
| if chunks: | |
| st.subheader("Preview (first chunk)") | |
| st.code(chunks[0].content[:2000]) | |
| except Exception as e: | |
| st.error(f"Ingestion failed: {e}") | |
| finally: | |
| st.session_state.ingestion_future = None | |
| else: | |
| st.status("Processing...", state="running") | |
| with col2: | |
| st.subheader("Session") | |
| st.code(st.session_state.session_id) | |
| if st.session_state.last_output: | |
| cnt, path = st.session_state.last_output | |
| st.metric("Chunks", cnt) | |
| st.write("Output:") | |
| st.code(path) | |
| if uploaded is not None and st.button("Retry with fallback parser"): | |
| fb = "pdfplumber" if parser == "pypdf" else "pypdf" | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp: | |
| tmp.write(uploaded.read()) | |
| tmp_path = tmp.name | |
| executor = ThreadPoolExecutor(max_workers=1) | |
| future: Future = executor.submit(_run_ingestion, tmp_path, st.session_state.session_id, fb, int(chunk_size), int(overlap)) | |
| st.session_state.ingestion_future = future | |
| st.info(f"Retrying with {fb}...") | |