Spaces:
Runtime error
Runtime error
Upload 8 files
Browse files- .streamlit/config.toml +19 -0
- Dockerfile +5 -0
- app.py +110 -4
.streamlit/config.toml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[server]
|
| 2 |
+
headless = true
|
| 3 |
+
port = 7860
|
| 4 |
+
enableCORS = false
|
| 5 |
+
enableXsrfProtection = false
|
| 6 |
+
|
| 7 |
+
[browser]
|
| 8 |
+
gatherUsageStats = false
|
| 9 |
+
serverAddress = "0.0.0.0"
|
| 10 |
+
|
| 11 |
+
[theme]
|
| 12 |
+
primaryColor = "#1f6feb"
|
| 13 |
+
backgroundColor = "#0e1117"
|
| 14 |
+
secondaryBackgroundColor = "#161b22"
|
| 15 |
+
textColor = "#ffffff"
|
| 16 |
+
|
| 17 |
+
[client]
|
| 18 |
+
showErrorDetails = false
|
| 19 |
+
toolbarMode = "minimal"
|
Dockerfile
CHANGED
|
@@ -6,6 +6,11 @@ ENV PYTHONUNBUFFERED=1 \
|
|
| 6 |
PORT=7860 \
|
| 7 |
HOME=/home/user
|
| 8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
# Create user for HF Spaces (UID 1000 required)
|
| 10 |
RUN useradd -m -u 1000 user
|
| 11 |
|
|
|
|
| 6 |
PORT=7860 \
|
| 7 |
HOME=/home/user
|
| 8 |
|
| 9 |
+
# Install system dependencies
|
| 10 |
+
RUN apt-get update && apt-get install -y \
|
| 11 |
+
curl \
|
| 12 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 13 |
+
|
| 14 |
# Create user for HF Spaces (UID 1000 required)
|
| 15 |
RUN useradd -m -u 1000 user
|
| 16 |
|
app.py
CHANGED
|
@@ -28,6 +28,9 @@ st.markdown("""
|
|
| 28 |
.source-file {background-color: #1f6feb; color: white;}
|
| 29 |
.source-web {background-color: #238636; color: white;}
|
| 30 |
.source-youtube {background-color: #da3633; color: white;}
|
|
|
|
|
|
|
|
|
|
| 31 |
</style>
|
| 32 |
""", unsafe_allow_html=True)
|
| 33 |
|
|
@@ -147,7 +150,7 @@ else:
|
|
| 147 |
st.title(f"π RAG SaaS Platform")
|
| 148 |
|
| 149 |
# Main tabs
|
| 150 |
-
tab1, tab2, tab3, tab4 = st.tabs(["π¬ Ask Questions", "π Manage Sources", "π Metrics", "βΉοΈ About"])
|
| 151 |
|
| 152 |
# Tab 1: Ask Questions
|
| 153 |
with tab1:
|
|
@@ -466,8 +469,110 @@ else:
|
|
| 466 |
except Exception as e:
|
| 467 |
st.error(f"Error loading sources: {e}")
|
| 468 |
|
| 469 |
-
# Tab 3:
|
| 470 |
with tab3:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 471 |
st.header("π Your Metrics")
|
| 472 |
|
| 473 |
# Time range selector
|
|
@@ -538,14 +643,15 @@ else:
|
|
| 538 |
except Exception as e:
|
| 539 |
st.warning(f"Cache stats unavailable: {e}")
|
| 540 |
|
| 541 |
-
# Tab
|
| 542 |
-
with
|
| 543 |
st.header("βΉοΈ About RAG SaaS Platform")
|
| 544 |
|
| 545 |
st.markdown("""
|
| 546 |
### Features
|
| 547 |
|
| 548 |
β
**Multi-Source Retrieval** - Unified search across documents, URLs, and YouTube videos
|
|
|
|
| 549 |
β
**Tenant Isolation** - Complete data and metrics separation per tenant
|
| 550 |
β
**Optimized Performance** - Model caching with 70-90% latency reduction
|
| 551 |
β
**Compliant YouTube** - Captions-first with transcript upload fallback
|
|
|
|
| 28 |
.source-file {background-color: #1f6feb; color: white;}
|
| 29 |
.source-web {background-color: #238636; color: white;}
|
| 30 |
.source-youtube {background-color: #da3633; color: white;}
|
| 31 |
+
.source-gdrive {background-color: #34a853; color: white;}
|
| 32 |
+
.source-onedrive {background-color: #0078d4; color: white;}
|
| 33 |
+
.source-dropbox {background-color: #0061ff; color: white;}
|
| 34 |
</style>
|
| 35 |
""", unsafe_allow_html=True)
|
| 36 |
|
|
|
|
| 150 |
st.title(f"π RAG SaaS Platform")
|
| 151 |
|
| 152 |
# Main tabs
|
| 153 |
+
tab1, tab2, tab3, tab4, tab5 = st.tabs(["π¬ Ask Questions", "π Manage Sources", "βοΈ Cloud Connectors", "π Metrics", "βΉοΈ About"])
|
| 154 |
|
| 155 |
# Tab 1: Ask Questions
|
| 156 |
with tab1:
|
|
|
|
| 469 |
except Exception as e:
|
| 470 |
st.error(f"Error loading sources: {e}")
|
| 471 |
|
| 472 |
+
# Tab 3: Cloud Connectors
|
| 473 |
with tab3:
|
| 474 |
+
st.header("βοΈ Cloud Connectors")
|
| 475 |
+
st.write("Connect to your enterprise cloud storage to sync documents directly.")
|
| 476 |
+
|
| 477 |
+
# Connect New Account
|
| 478 |
+
st.subheader("Connect New Account")
|
| 479 |
+
col1, col2, col3 = st.columns(3)
|
| 480 |
+
|
| 481 |
+
with col1:
|
| 482 |
+
if st.button("π Connect Google Drive", use_container_width=True):
|
| 483 |
+
try:
|
| 484 |
+
res = requests.get(f"{api_url}/v1/connectors/gdrive/oauth/start?tenant_id={st.session_state.tenant_id}")
|
| 485 |
+
if res.status_code == 200:
|
| 486 |
+
st.markdown(f"[Click here to authorize Google Drive]({res.json()['auth_url']})")
|
| 487 |
+
else:
|
| 488 |
+
st.error("Failed to start GDrive OAuth")
|
| 489 |
+
except Exception as e:
|
| 490 |
+
st.error(f"Error: {e}")
|
| 491 |
+
|
| 492 |
+
with col2:
|
| 493 |
+
if st.button("π Connect OneDrive", use_container_width=True):
|
| 494 |
+
try:
|
| 495 |
+
res = requests.get(f"{api_url}/v1/connectors/onedrive/oauth/start?tenant_id={st.session_state.tenant_id}")
|
| 496 |
+
if res.status_code == 200:
|
| 497 |
+
st.markdown(f"[Click here to authorize OneDrive]({res.json()['auth_url']})")
|
| 498 |
+
else:
|
| 499 |
+
st.error("Failed to start OneDrive OAuth")
|
| 500 |
+
except Exception as e:
|
| 501 |
+
st.error(f"Error: {e}")
|
| 502 |
+
|
| 503 |
+
with col3:
|
| 504 |
+
if st.button("π Connect Dropbox", use_container_width=True):
|
| 505 |
+
try:
|
| 506 |
+
res = requests.get(f"{api_url}/v1/connectors/dropbox/oauth/start?tenant_id={st.session_state.tenant_id}")
|
| 507 |
+
if res.status_code == 200:
|
| 508 |
+
st.markdown(f"[Click here to authorize Dropbox]({res.json()['auth_url']})")
|
| 509 |
+
else:
|
| 510 |
+
st.error("Failed to start Dropbox OAuth")
|
| 511 |
+
except Exception as e:
|
| 512 |
+
st.error(f"Error: {e}")
|
| 513 |
+
|
| 514 |
+
st.divider()
|
| 515 |
+
|
| 516 |
+
# Manage Existing Connectors
|
| 517 |
+
st.subheader("Your Connected Accounts")
|
| 518 |
+
try:
|
| 519 |
+
response = requests.get(
|
| 520 |
+
f"{api_url}/v1/connectors/",
|
| 521 |
+
params={"tenant_id": st.session_state.tenant_id}
|
| 522 |
+
)
|
| 523 |
+
if response.status_code == 200:
|
| 524 |
+
connectors = response.json()
|
| 525 |
+
if connectors:
|
| 526 |
+
for conn in connectors:
|
| 527 |
+
with st.expander(f"{conn['provider'].upper()} - {conn['display_name']}"):
|
| 528 |
+
col_a, col_b, col_c = st.columns([2, 1, 1])
|
| 529 |
+
with col_a:
|
| 530 |
+
st.write(f"**Status:** {conn['sync_status'].upper()}")
|
| 531 |
+
if conn['last_sync']:
|
| 532 |
+
st.write(f"**Last Sync:** {conn['last_sync']}")
|
| 533 |
+
|
| 534 |
+
with col_b:
|
| 535 |
+
if st.button("π Trigger Sync", key=f"sync_{conn['id']}"):
|
| 536 |
+
sync_res = requests.post(f"{api_url}/v1/connectors/{conn['id']}/sync")
|
| 537 |
+
if sync_res.status_code == 200:
|
| 538 |
+
st.success("Sync triggered!")
|
| 539 |
+
else:
|
| 540 |
+
st.error("Failed to trigger sync")
|
| 541 |
+
|
| 542 |
+
with col_c:
|
| 543 |
+
if st.button("π Manage Targets", key=f"targets_{conn['id']}"):
|
| 544 |
+
st.session_state[f"show_targets_{conn['id']}"] = True
|
| 545 |
+
|
| 546 |
+
# Target Selection Mock/Simplified
|
| 547 |
+
if st.session_state.get(f"show_targets_{conn['id']}"):
|
| 548 |
+
st.info("Loading roots...")
|
| 549 |
+
roots_res = requests.get(f"{api_url}/v1/connectors/{conn['id']}/roots")
|
| 550 |
+
if roots_res.status_code == 200:
|
| 551 |
+
roots = roots_res.json()
|
| 552 |
+
target_ids = st.multiselect(
|
| 553 |
+
"Select Folders/Drives to sync",
|
| 554 |
+
options=[r['id'] for r in roots],
|
| 555 |
+
format_func=lambda x: next(r['name'] for r in roots if r['id'] == x),
|
| 556 |
+
key=f"ms_{conn['id']}"
|
| 557 |
+
)
|
| 558 |
+
if st.button("Save Targets", key=f"save_{conn['id']}"):
|
| 559 |
+
selected_targets = [{"id": tid, "type": "folder"} for tid in target_ids]
|
| 560 |
+
save_res = requests.post(
|
| 561 |
+
f"{api_url}/v1/connectors/{conn['id']}/targets",
|
| 562 |
+
params={"tenant_id": st.session_state.tenant_id},
|
| 563 |
+
json=selected_targets
|
| 564 |
+
)
|
| 565 |
+
if save_res.status_code == 200:
|
| 566 |
+
st.success("Targets updated!")
|
| 567 |
+
st.session_state[f"show_targets_{conn['id']}"] = False
|
| 568 |
+
st.rerun()
|
| 569 |
+
else:
|
| 570 |
+
st.info("No cloud accounts connected yet.")
|
| 571 |
+
except Exception as e:
|
| 572 |
+
st.error(f"Error fetching connectors: {e}")
|
| 573 |
+
|
| 574 |
+
# Tab 4: Metrics
|
| 575 |
+
with tab4:
|
| 576 |
st.header("π Your Metrics")
|
| 577 |
|
| 578 |
# Time range selector
|
|
|
|
| 643 |
except Exception as e:
|
| 644 |
st.warning(f"Cache stats unavailable: {e}")
|
| 645 |
|
| 646 |
+
# Tab 5: About
|
| 647 |
+
with tab5:
|
| 648 |
st.header("βΉοΈ About RAG SaaS Platform")
|
| 649 |
|
| 650 |
st.markdown("""
|
| 651 |
### Features
|
| 652 |
|
| 653 |
β
**Multi-Source Retrieval** - Unified search across documents, URLs, and YouTube videos
|
| 654 |
+
β
**Enterprise Cloud Connectors** - Native sync with Google Drive, OneDrive, and Dropbox
|
| 655 |
β
**Tenant Isolation** - Complete data and metrics separation per tenant
|
| 656 |
β
**Optimized Performance** - Model caching with 70-90% latency reduction
|
| 657 |
β
**Compliant YouTube** - Captions-first with transcript upload fallback
|