File size: 4,137 Bytes
7eaced5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
"""
GESDA Knowledge Graph Explorer β€” Streamlit entry point.

Run with:
    streamlit run graphrag_UI/app.py
"""
from __future__ import annotations

import sys
from pathlib import Path

# Ensure graphrag_UI/ is on the path for relative imports inside the package
_HERE = Path(__file__).parent.resolve()
if str(_HERE) not in sys.path:
    sys.path.insert(0, str(_HERE))

import streamlit as st

import config  # noqa: F401 β€” bootstraps project paths + loads .env
from config import APP_TITLE, APP_ICON
from db.neo4j_client import get_neo4j_resources, get_graph_summary
from db.vector_client import get_vector_resources
from queries.schema import NODE_COLORS
from ui.styles import inject_css
import ui.tab_vector_search as tab_vs
import ui.tab_hardcoded as tab_hq
import ui.tab_query_builder as tab_qb

# ---------------------------------------------------------------------------
# Page config (must be first Streamlit call)
# ---------------------------------------------------------------------------

st.set_page_config(
    page_title=APP_TITLE,
    page_icon=APP_ICON,
    layout="wide",
    initial_sidebar_state="expanded",
)

inject_css()

# ---------------------------------------------------------------------------
# Header
# ---------------------------------------------------------------------------

st.markdown(
    """
    <div style="padding: 16px 0 8px 0;">
        <span style="font-size:28px; font-weight:800; color:#1a1e2a;">
            πŸ”¬ GESDA Knowledge Graph Explorer
        </span>
    </div>
    """,
    unsafe_allow_html=True,
)

# ---------------------------------------------------------------------------
# Sidebar β€” connection status
# ---------------------------------------------------------------------------

with st.sidebar:
    st.markdown("### Connection")

    # Neo4j
    summary = get_graph_summary()
    if summary.get("connected"):
        st.markdown(
            '<span class="status-dot ok"></span> **Neo4j** connected',
            unsafe_allow_html=True,
        )
        with st.expander("Graph statistics", expanded=False):
            st.metric("Total nodes", f'{summary["total_nodes"]:,}')
            st.metric("Total relationships", f'{summary["total_relationships"]:,}')
            nt = summary.get("node_types", {})
            if nt:
                rows = sorted(nt.items(), key=lambda x: x[1], reverse=True)
                for label, cnt in rows:
                    color = NODE_COLORS.get(label, "#888")
                    st.markdown(
                        f'<span style="color:{color}; font-size:12px;">● {label}: {cnt:,}</span>',
                        unsafe_allow_html=True,
                    )
    else:
        st.markdown(
            f'<span class="status-dot err"></span> **Neo4j** β€” {summary.get("error", "unavailable")}',
            unsafe_allow_html=True,
        )

    # Vector search
    _, _, vec_err = get_vector_resources()
    if not vec_err:
        st.markdown(
            '<span class="status-dot ok"></span> **Vector search** ready',
            unsafe_allow_html=True,
        )
    else:
        st.markdown(
            '<span class="status-dot warn"></span> **Vector search** unavailable',
            unsafe_allow_html=True,
        )
        with st.expander("Details", expanded=False):
            st.caption(vec_err)

    st.divider()
    st.markdown(
        """
        **Tabs**
        - **Hardcoded Queries** - examples of graph capabilities and explore the relationships
        - **Vector Search** β€” find nodes using non-jargon language
        - **Query Builder** β€” interactive Cypher builder
        """,
        unsafe_allow_html=False,
    )
    st.divider()
    st.caption("GESDA Β· EPFL Β· 2026")

# ---------------------------------------------------------------------------
# Main tabs
# ---------------------------------------------------------------------------

tab_hard, tab_vec, tab_build = st.tabs([
    "πŸ”Ž Hardcoded Queries",
    "πŸ”­ Vector Search",
    "πŸ› οΈ Query Builder",
])

with tab_hard:
    tab_hq.render()

with tab_vec:
    tab_vs.render()

with tab_build:
    tab_qb.render()