import os
import pandas as pd
import streamlit as st
from pipeline import run
st.set_page_config(page_title="Concord Data Agents | Legacy ETL", page_icon="🧬", layout="wide")
# ---------------------------------------------------------------------------
# Theme: teal / deep blue-green, clinical, calm -- healthcare/insurance feel
# ---------------------------------------------------------------------------
st.markdown(
"""
""",
unsafe_allow_html=True,
)
st.markdown('
Concord Data Agents
', unsafe_allow_html=True)
st.markdown(
'A two-agent pipeline that scans undocumented legacy tables, maps them to a '
'clean schema, and auto-generates the cleaning rules — no manual data dictionary required.
',
unsafe_allow_html=True,
)
st.write("")
with st.sidebar:
st.markdown("### 🧬 Pipeline")
st.caption(
"Agent 1 scans the undocumented legacy table and infers a schema. "
"Agent 2 generates and executes per-column cleaning rules. A quality "
"dashboard scores the data before and after."
)
csv_path = os.path.join(os.path.dirname(__file__), "data", "legacy_claims_raw.csv")
st.caption(f"Dataset: `data/legacy_claims_raw.csv` (synthetic, {sum(1 for _ in open(csv_path)) - 1} rows)")
run_btn = st.button("â–¶ Run pipeline", type="primary")
if "pipeline_out" not in st.session_state:
st.session_state.pipeline_out = None
if run_btn:
st.session_state.pipeline_out = run(csv_path)
out = st.session_state.pipeline_out
if out is None:
st.info("Click **Run pipeline** in the sidebar to scan and clean the synthetic legacy dataset.")
st.markdown("#### Raw legacy data preview")
st.dataframe(pd.read_csv(csv_path, dtype=str, keep_default_na=False).head(15), use_container_width=True)
else:
tab1, tab2, tab3, tab4 = st.tabs([
"1. Agent 1 — Schema Scan", "2. Agent 2 — Cleaning Log", "3. Quality Dashboard", "4. Before / After Data"
])
with tab1:
st.markdown("Agent 1 scanned each undocumented column and inferred its semantic meaning, type, and issues.")
rows = []
for p in out.profiles:
rows.append({
"Raw column": p.raw_name,
"Inferred field": p.canonical_name,
"Type": p.inferred_type,
"Distinct raw values": p.n_distinct,
"Missing/sentinel count": p.n_missing_like,
"Issues detected": "; ".join(p.issues) if p.issues else "none",
})
st.dataframe(pd.DataFrame(rows), use_container_width=True, hide_index=True)
with tab2:
st.markdown("Agent 2 generated and executed a cleaning rule per column based on Agent 1's schema map.")
for entry in out.cleaning_log:
st.markdown(
f'{entry.canonical_name} '
f'(from {entry.column})
'
f'{entry.action}
',
unsafe_allow_html=True,
)
with tab3:
st.markdown("#### Completeness: before vs. after")
before_map = {q.column: q.completeness_pct for q in out.raw_quality}
after_by_canonical = {q.column: q.completeness_pct for q in out.cleaned_quality}
comp_rows = []
for p in out.profiles:
comp_rows.append({
"Field": p.canonical_name,
"Completeness before (%)": before_map.get(p.raw_name, None),
"Completeness after (%)": after_by_canonical.get(p.canonical_name, None),
})
comp_df = pd.DataFrame(comp_rows).drop_duplicates(subset="Field")
st.dataframe(comp_df, use_container_width=True, hide_index=True)
st.bar_chart(comp_df.set_index("Field")[["Completeness before (%)", "Completeness after (%)"]])
m1, m2, m3 = st.columns(3)
m1.metric("Rows before", len(out.raw_df))
m2.metric("Rows after (deduped)", len(out.cleaned_df))
m3.metric("Duplicate rows removed", len(out.raw_df) - len(out.cleaned_df))
with tab4:
c1, c2 = st.columns(2)
with c1:
st.markdown("**Raw (legacy) data**")
st.dataframe(out.raw_df.head(20), use_container_width=True, hide_index=True)
with c2:
st.markdown("**Cleaned data**")
st.dataframe(out.cleaned_df.head(20), use_container_width=True, hide_index=True)