-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstreamlit_app.py
More file actions
117 lines (95 loc) · 3.87 KB
/
Copy pathstreamlit_app.py
File metadata and controls
117 lines (95 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
from pathlib import Path
from tempfile import NamedTemporaryFile
import streamlit as st
from app.config import get_settings
from app.ingest import ingest_local_file
from app.network import clear_dead_local_proxy
from app.rag import answer_query
from app.utils import SUPPORTED_FILE_EXTENSIONS
get_settings.cache_clear()
cleared_proxy_vars = clear_dead_local_proxy()
st.set_page_config(
page_title="Multilingual RAG",
layout="wide",
)
def show_health() -> None:
settings = get_settings()
st.success("Application is running.")
st.json(
{
"status": "ok",
"collection": settings.CHROMA_COLLECTION,
"persist_dir": settings.CHROMA_PERSIST_DIR,
"embedding_model": settings.EMBEDDING_MODEL,
"llm_provider": "gemini",
"gemini_model": settings.GEMINI_MODEL,
"gemini_key_configured": bool(settings.GEMINI_API_KEY),
}
)
def save_uploaded_file(uploaded_file) -> Path:
suffix = Path(uploaded_file.name).suffix
with NamedTemporaryFile(delete=False, suffix=suffix) as temp_file:
temp_file.write(uploaded_file.getbuffer())
return Path(temp_file.name)
st.title("Multilingual RAG")
st.caption("Upload PDF, TXT, or Markdown files, then ask questions across languages.")
with st.sidebar:
st.header("Status")
if st.button("Check Health", use_container_width=True):
st.session_state.health_checked = True
if st.session_state.get("health_checked"):
show_health()
st.divider()
st.header("Settings")
settings = get_settings()
st.write(f"Collection: `{settings.CHROMA_COLLECTION}`")
st.write(f"LLM: `gemini`")
st.write(f"Top K default: `{settings.TOP_K}`")
if cleared_proxy_vars:
st.caption("Ignored dead local proxy settings for model downloads.")
tab_ingest, tab_query = st.tabs(["Ingest File", "Ask Question"])
with tab_ingest:
st.subheader("Upload and Ingest")
uploaded_file = st.file_uploader(
"Choose a file",
type=[extension.lstrip(".") for extension in SUPPORTED_FILE_EXTENSIONS],
)
if uploaded_file is not None:
st.write(f"Selected: `{uploaded_file.name}`")
if st.button("Ingest Uploaded File", type="primary", disabled=uploaded_file is None):
temp_path: Path | None = None
try:
temp_path = save_uploaded_file(uploaded_file)
with st.spinner("Embedding and storing chunks. First run may download the embedding model."):
chunks_added = ingest_local_file(temp_path, uploaded_file.name)
st.success(f"Ingestion complete. Added {chunks_added} chunks.")
except Exception as exc:
st.error(f"Ingestion failed: {exc}")
finally:
if temp_path is not None:
temp_path.unlink(missing_ok=True)
with tab_query:
st.subheader("Ask a Question")
query = st.text_area(
"Question",
placeholder="Example: What does the Hindi document say about AI?",
height=120,
)
top_k = st.slider("Number of chunks to retrieve", min_value=1, max_value=20, value=settings.TOP_K)
if st.button("Get Answer", type="primary", disabled=not query.strip()):
try:
with st.spinner("Retrieving context and generating answer."):
answer, sources = answer_query(query.strip(), top_k)
st.markdown("### Answer")
st.write(answer)
st.markdown("### Sources")
if not sources:
st.info("No sources returned.")
for index, source in enumerate(sources, start=1):
metadata = source.metadata
label = metadata.get("source", f"Source {index}")
with st.expander(f"{index}. {label}"):
st.json(metadata)
st.write(source.content)
except Exception as exc:
st.error(f"Query failed: {exc}")