grants-rag / app /ui_streamlit.py.bak
Gen. Overseer Lupo
WIP before LFS migrate
4a73ab0
# app/ui_streamlit.py
import os, json
from pathlib import Path
import streamlit as st
from app.main import get_env, ensure_index_exists
from app.search import search
# Streamlit config should be the first Streamlit call
st.set_page_config(page_title="Grants Discovery RAG", layout="wide")
# Environment + index
_env = get_env()
ensure_index_exists(_env)
# ---------- helpers ----------
def _dedup_records(rows):
seen, out = set(), []
for r in rows or []:
k = r.get("id") or r.get("url") or r.get("title")
if not k or k in seen:
continue
seen.add(k)
out.append(r)
return out
# ---------- end helpers ----------
# ---------- optional diagnostics ----------
with st.expander("Diagnostics (optional)", expanded=False):
idx = Path(_env["INDEX_DIR"])
st.write("INDEX_DIR:", str(idx))
st.write("faiss.index exists:", (idx / "faiss.index").exists())
st.write("meta.json exists:", (idx / "meta.json").exists())
if (idx / "meta.json").exists():
try:
meta = json.loads((idx / "meta.json").read_text())
st.write("meta.json count:", len(meta))
st.write("meta head:", [{"id": m.get("id"), "title": m.get("title")} for m in meta[:2]])
except Exception as e:
st.error(f"Failed to read meta.json: {e!r}")
try:
demo = search("transportation", _env, top_k=3, filters={})
st.write("sample search('transportation') results:", len(demo))
if demo:
st.write(demo[:3])
except Exception as e:
st.error(f"search() raised: {e!r}")
# ---------- end diagnostics ----------
st.title("Grants Discovery RAG (Capacity Building)")
preset = st.radio(
"Quick topic:",
["General", "Elderly", "Prison Ministry", "Evangelism", "Vehicles/Transport", "FTA 5310"],
horizontal=True
)
default_q = {
"General": "capacity building",
"Elderly": "capacity building for seniors and aging services",
"Prison Ministry": "capacity building for reentry and prison ministry",
"Evangelism": "capacity building for faith and community outreach",
"Vehicles/Transport": "capacity building transportation vehicles vans buses mobility",
"FTA 5310": "5310 Enhanced Mobility Seniors Individuals with Disabilities",
}.get(preset, "capacity building")
# --- controls ---
q = st.text_input("Search query", value=default_q)
# No defaults -> no filtering unless the user selects something
geo = st.multiselect("Geo filter (optional)", options=["US", "MD", "MA"], default=[])
categories = st.multiselect(
"Category filter (optional)",
options=["capacity_building", "elderly", "prison_ministry", "evangelism", "transportation", "vehicle"],
default=[]
)
top_k = st.slider("Results", 5, 50, 15)
# Build filters only when selected
filters = {}
if geo:
filters["geo"] = geo
if categories:
filters["categories"] = categories # <- use 'categories' key (not 'cats')
col1, col2 = st.columns([1, 1])
with col1:
if st.button("Search"):
try:
results = search(q, _env, top_k=top_k, filters=filters)
results = _dedup_records(results)
st.session_state["results"] = results
except Exception as e:
st.error(str(e))
with col2:
if st.button("Export Results to CSV"):
results = st.session_state.get("results", [])
if not results:
st.warning("No results to export. Run a search first.")
else:
os.makedirs(_env["EXPORT_DIR"], exist_ok=True)
out_path = os.path.join(_env["EXPORT_DIR"], "results.csv")
import pandas as pd
pd.DataFrame(results).to_csv(out_path, index=False)
st.success(f"Exported to {out_path}")
st.markdown("---")
results = st.session_state.get("results", [])
if results:
st.caption(f"Results: {len(results)}")
for r in results:
title = r.get("title", "(no title)")
url = r.get("url", "")
cats = r.get("categories") or r.get("cats") or []
geo_tags = r.get("geo") or []
st.markdown(f"### {title}")
st.write(f"**Source:** {r.get('source','')} | **Geo:** {', '.join(geo_tags) if isinstance(geo_tags, list) else geo_tags} | **Categories:** {', '.join(cats) if isinstance(cats, list) else cats}")
if url and not url.startswith("http"):
st.caption("Note: This item may display an ID or number instead of a full link. Open on Grants.gov if needed.")
st.write(f"[Open Link]({url}) \nScore: {r.get('score', 0):.3f}")
st.markdown("---")
else:
st.info("Enter a query and click Search.")