n8n / src /streamlit_app.py
poemsforaphrodite's picture
Update src/streamlit_app.py
96df3e7 verified
import os
# -----------------------------------------------------------------------------
# Streamlit runtime fixes
# Some container environments (e.g., read-only root) may not set $HOME, causing
# Streamlit to attempt writing to '/.streamlit' and fail with PermissionError.
# We set fallback directories under /tmp before importing Streamlit.
# -----------------------------------------------------------------------------
# Disable telemetry completely
os.environ["STREAMLIT_BROWSER_GATHER_USAGE_STATS"] = "false"
# Ensure writable directories for Streamlit telemetry & state
os.environ.setdefault("HOME", "/tmp")
os.environ.setdefault("XDG_STATE_HOME", "/tmp/.state")
os.environ.setdefault("XDG_CONFIG_HOME", "/tmp/.config")
os.environ.setdefault("XDG_DATA_HOME", "/tmp/.data")
# Create streamlit directory to prevent permission errors
os.makedirs("/tmp/.streamlit", exist_ok=True)
# Monkey-patch Path.home() so that Streamlit (which calls pathlib.Path.home)
# resolves to /tmp instead of the container default (/).
from pathlib import Path
def _tmp_home() -> Path: # type: ignore
return Path("/tmp")
Path.home = _tmp_home # type: ignore
import streamlit as st
import requests
from typing import Tuple
# -----------------------------
# Configuration
# -----------------------------
ENDPOINT_URL = "https://n8n.flintstorage812.com/webhook/universal-ingest"
# -----------------------------
# Helper Functions
# -----------------------------
def send_file(file_bytes: bytes, filename: str, mime_type: str) -> Tuple[bool, dict]:
"""Send a file to the universal-ingest endpoint.
Returns (success, response_json)
"""
try:
files = {"file": (filename, file_bytes, mime_type)}
response = requests.post(ENDPOINT_URL, files=files, timeout=60)
response.raise_for_status()
return True, response.json()
except Exception as e:
return False, {"error": str(e)}
def send_url(url: str) -> Tuple[bool, dict]:
"""Send a website URL as JSON to the universal-ingest endpoint."""
try:
headers = {"Content-Type": "application/json"}
response = requests.post(ENDPOINT_URL, json={"url": url}, headers=headers, timeout=60)
response.raise_for_status()
return True, response.json()
except Exception as e:
return False, {"error": str(e)}
# -----------------------------
# Local file persistence
# -----------------------------
FILE_SAVE_DIR = "files"
try:
os.makedirs(FILE_SAVE_DIR, exist_ok=True)
except Exception as e:
# If creation fails, we alert via Streamlit later
print(f"[warning] Could not create {FILE_SAVE_DIR}: {e}")
def save_to_disk(content: bytes, filename: str) -> str:
"""Save uploaded content to ./files and return the absolute path."""
path = os.path.join(FILE_SAVE_DIR, filename)
with open(path, "wb") as f:
f.write(content)
return path
# -----------------------------
# Streamlit UI
# -----------------------------
st.set_page_config(page_title="Universal RAG Ingestion", page_icon="🪄", layout="centered")
st.title("🪄 Universal RAG Ingestion Client")
st.markdown(
"Upload PDF / video / audio **or** enter a website URL to start the universal ingestion workflow.\n"
"All requests are sent to:** `{}`".format(ENDPOINT_URL)
)
mode = st.radio(
"Select input type:",
(
"📄 Upload PDF",
"🎬 Upload Video / Audio",
"🌐 Website URL",
),
horizontal=True,
)
if mode.startswith("📄"):
st.subheader("Upload PDF")
pdf_file = st.file_uploader("Choose a PDF file", type=["pdf"])
if pdf_file is not None:
if st.button("Send to Ingestion API"):
with st.spinner("Uploading and processing…"):
file_bytes = pdf_file.read()
saved_path = save_to_disk(file_bytes, pdf_file.name)
st.write(f"Saved to {saved_path}")
success, resp = send_file(file_bytes, pdf_file.name, "application/pdf")
if success:
st.success("✅ Success! Response:")
st.json(resp)
else:
st.error("❌ Error while sending file")
st.json(resp)
elif mode.startswith("🎬"):
st.subheader("Upload Video / Audio")
media_file = st.file_uploader("Choose a media file", type=["mp4", "mov", "avi", "wav", "mp3", "m4a"])
if media_file is not None:
if st.button("Send to Ingestion API"):
with st.spinner("Uploading and processing…"):
bytes_data = media_file.read()
saved_path = save_to_disk(bytes_data, media_file.name)
st.write(f"Saved to {saved_path}")
mime_type = "video/mp4" # Fallback; Streamlit doesn't expose MIME. n8n relies on filename extension.
success, resp = send_file(bytes_data, media_file.name, mime_type)
if success:
st.success("✅ Success! Response:")
st.json(resp)
else:
st.error("❌ Error while sending file")
st.json(resp)
else: # Website URL
st.subheader("Submit Website URL")
url_input = st.text_input("Enter full URL (including https://)")
if st.button("Send to Ingestion API") and url_input:
with st.spinner("Submitting URL …"):
success, resp = send_url(url_input)
if success:
st.success("✅ Success! Response:")
st.json(resp)
else:
st.error("❌ Error while submitting URL")
st.json(resp)
st.caption("Built with Streamlit · © 2025")