shahidshaikh commited on
Commit
3407b8d
·
verified ·
1 Parent(s): a5cc352

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +35 -29
app.py CHANGED
@@ -2,37 +2,45 @@ import os, json, shutil
2
  import pandas as pd
3
  import gradio as gr
4
  from agent import chat_with_agent
5
- from tools import CSV_PATH, OUT_DIR, PDF_DIR, _embed, HEADERS, PERSISTENT_BASE
6
 
7
  try: _embed()
8
  except Exception as e: print(f">>> WARNING: Embedding pre-load failed: {e}")
9
 
10
- IS_PERSISTENT = PERSISTENT_BASE == "/data"
11
- STATUS_TAG = '<span style="background:#0ea5e8;color:white;padding:2px 6px;border-radius:4px;font-size:0.5em;vertical-align:middle;margin-left:8px">PERSISTENT</span>' if IS_PERSISTENT else ""
12
-
13
  CSS = """
14
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Manrope:wght@600;700&display=swap');
15
- :root { --primary: #0f172a; --secondary: #712ae2; --secondary-container: #8a4cfc; --surface: #f7f9fb; }
16
- body, .gradio-container { font-family: 'Inter', sans-serif !important; background-color: var(--surface) !important; color: #191c1e !important; }
17
- .hdr { font-family: 'Manrope', sans-serif !important; font-size: 3.5rem !important; font-weight: 700; color: var(--primary); margin-bottom: 24px; letter-spacing: -0.02em; }
18
- .sub-hdr { font-family: 'Manrope', sans-serif !important; font-size: 1.75rem !important; font-weight: 600; margin-bottom: 16px; }
19
- button.primary { background: linear-gradient(135deg, var(--secondary), var(--secondary-container)) !important; color: white !important; border-radius: 12px !important; border: none !important; box-shadow: none !important; transition: opacity 0.2s; }
20
- button.primary:hover { opacity: 0.9; }
21
- button.secondary { background: transparent !important; color: var(--primary) !important; border: none !important; box-shadow: none !important; }
22
- button.secondary:hover { background: rgba(15,23,42,0.05) !important; }
23
- .sidebar { background: rgba(19, 27, 46, 0.03) !important; border-radius: 16px !important; padding: 24px !important; box-shadow: none !important; border: none !important; }
24
- .main-content { background: white !important; border-radius: 16px !important; padding: 32px !important; box-shadow: 0 20px 50px -12px rgba(15, 23, 42, 0.08) !important; border: none !important; }
25
- input, textarea { background-color: rgba(255,255,255,0.7) !important; border-radius: 0 !important; border: none !important; border-bottom: 2px solid rgba(15,23,42,0.1) !important; box-shadow: none !important; }
26
- input:focus, textarea:focus { border-bottom: 2px solid var(--secondary) !important; }
27
- .tab-nav { border-bottom: 1px solid rgba(15,23,42,0.08) !important; }
28
- .label-sm { font-size: 0.6875rem !important; font-weight: 500 !important; letter-spacing: 0.05em !important; text-transform: uppercase !important; }
 
29
  """
30
- HDR = f'<div class="hdr">The Digital Curator{STATUS_TAG}</div>'
31
- PRG = '<div class="label-sm" style="margin-bottom: 24px; color: #64748b;">① Ingestion &gt; ② Algorithmic Coding &gt; ③ Thematic Abstraction &gt; ④ Taxonomy Alignment &gt; ⑥ Report Narrative</div>'
 
 
 
 
 
32
 
33
  PHASE_FILE = {"CODES": "_labels.json", "THEMES": "_themes.json", "PAJAIS": "_taxonomy.json"}
34
  NEXT_PHASE = {"CODES": "THEMES", "THEMES": "PAJAIS", "PAJAIS": "REPORT"}
35
 
 
 
 
 
 
36
  def init_analysis(query, csv_file, chat_hist):
37
  # 1. Clear old outputs
38
  if os.path.exists(OUT_DIR):
@@ -91,7 +99,7 @@ def init_analysis(query, csv_file, chat_hist):
91
  feedback = (f"Detected Mode: {mode}\nSources:\n{source_lines}\nTotal: {total_papers} papers\n\n👉 Preparing dataset... Proceeding to Phase 2")
92
 
93
  new_hist = chat_hist + [{"role":"user","content": f"Init {mode}"}, {"role":"assistant","content": feedback + "\n\n" + res}]
94
- return "", new_hist, _load_table("abstract", "CODES")
95
 
96
  def handle_pdf_upload(files):
97
  if not files: return "No files selected."
@@ -153,12 +161,13 @@ def _show_chart(m, t):
153
  path = os.path.join(OUT_DIR, f"{m}_{t}.html")
154
  return f'<iframe srcdoc="{open(path, encoding="utf-8").read().replace(chr(34),"&quot;")}" width="100%" height="450"></iframe>' if os.path.exists(path) else "Run Phase 2 first."
155
 
156
- with gr.Blocks(theme=gr.themes.Base(primary_hue="violet", neutral_hue="slate"), css=CSS) as demo:
157
  with gr.Row():
158
  # LEFT SIDEBAR
159
  with gr.Column(scale=1, elem_classes="sidebar"):
160
  gr.HTML(HDR)
161
- gr.HTML('<div class="sub-hdr">Query / Source</div>')
 
162
  input_box = gr.Textbox(placeholder="Enter research topic...", label="Research Query")
163
  start_btn = gr.Button("Execute Discovery", variant="primary")
164
 
@@ -178,8 +187,6 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="violet", neutral_hue="slate"),
178
 
179
  # RIGHT MAIN WORKSPACE
180
  with gr.Column(scale=3, elem_classes="main-content"):
181
- gr.HTML(PRG)
182
-
183
  with gr.Tabs(elem_classes="tab-nav"):
184
  with gr.Tab("💬 Agent Copilot"):
185
  chatbot = gr.Chatbot([], height=500, label="Research Assistant")
@@ -215,7 +222,7 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="violet", neutral_hue="slate"),
215
  btn_refresh_files.click(_get_files, [], [dl])
216
 
217
  # Event Bindings
218
- start_btn.click(init_analysis, [input_box, csv_up, chatbot], [input_box, chatbot, tbl])
219
  send_btn.click(handle_chat, [msg_in, chatbot, mode_btn, ph_state], [msg_in, chatbot, tbl])
220
  btn_ingest.click(handle_chat, [gr.State("Ingest all uploaded PDFs and Word documents into the system."), chatbot, gr.State("abstract"), gr.State("CODES")], [msg_in, chatbot, tbl])
221
  btn_scratch.click(handle_chat, [gr.State("Check the local scratch folder and import any papers found there."), chatbot, gr.State("abstract"), gr.State("CODES")], [msg_in, chatbot, tbl])
@@ -223,5 +230,4 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="violet", neutral_hue="slate"),
223
  sub_btn.click(submit_review, [tbl, chatbot, mode_btn, ph_state], [chatbot, ph_state, tbl]).then(_get_report, [], [report_box])
224
 
225
  if __name__ == "__main__":
226
- server_port = int(os.getenv("PORT", 7860))
227
- demo.launch(server_name="0.0.0.0", server_port=server_port)
 
2
  import pandas as pd
3
  import gradio as gr
4
  from agent import chat_with_agent
5
+ from tools import CSV_PATH, OUT_DIR, PDF_DIR, _embed, HEADERS
6
 
7
  try: _embed()
8
  except Exception as e: print(f">>> WARNING: Embedding pre-load failed: {e}")
9
 
 
 
 
10
  CSS = """
11
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Plus+Jakarta+Sans:wght@600;700&display=swap');
12
+ :root { --primary: #0f172a; --secondary: #6366f1; --accent: #8b5cf6; --bg: #f8fafc; }
13
+ body, .gradio-container { font-family: 'Inter', sans-serif !important; background-color: var(--bg) !important; color: var(--primary) !important; }
14
+ .hdr { font-family: 'Plus Jakarta Sans', sans-serif !important; font-size: 2.25rem !important; font-weight: 700; color: var(--primary) !important; letter-spacing: -0.04em; margin-bottom: 2px !important; }
15
+ .sub-hdr { font-size: 0.875rem !important; color: #64748b !important; margin-bottom: 24px !important; }
16
+ .sidebar { background: white !important; border-right: 1px solid rgba(15,23,42,0.08) !important; padding: 24px !important; }
17
+ .main-content { background: white !important; border-radius: 12px !important; border: 1px solid rgba(15,23,42,0.05) !important; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.05) !important; }
18
+ button.primary { background: var(--primary) !important; color: white !important; border-radius: 8px !important; font-weight: 600 !important; transition: all 0.2s; }
19
+ button.primary:hover { background: #1e293b !important; transform: translateY(-1px); }
20
+ .phase-orb { display: flex; align-items: center; gap: 8px; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: #94a3b8; margin-bottom: 12px; }
21
+ .phase-orb.active { color: var(--secondary); }
22
+ .phase-dot { width: 8px; height: 8px; border-radius: 50%; background: #e2e8f0; }
23
+ .phase-orb.active .phase-dot { background: var(--secondary); box-shadow: 0 0 8px var(--secondary); }
24
+ input, textarea, .gr-box, .gr-form, label, span, p, .markdown-text { color: #0f172a !important; }
25
+ input, textarea { border-radius: 8px !important; border: 1px solid #e2e8f0 !important; background: white !important; }
26
+ input:focus { border-color: var(--secondary) !important; ring: 2px var(--secondary) !important; }
27
  """
28
+ HDR = '<div class="hdr">Digital Curator</div><div class="sub-hdr">Enterprise Agentic Research Platform</div>'
29
+ PRG_TPL = '<div style="display: flex; flex-direction: column; gap: 4px;">' \
30
+ '<div class="phase-orb {a1}"><div class="phase-dot"></div>1. Ingestion</div>' \
31
+ '<div class="phase-orb {a2}"><div class="phase-dot"></div>2. Algorithmic Coding</div>' \
32
+ '<div class="phase-orb {a3}"><div class="phase-dot"></div>3. Thematic Abstraction</div>' \
33
+ '<div class="phase-orb {a4}"><div class="phase-dot"></div>4. Report Narration</div>' \
34
+ '</div>'
35
 
36
  PHASE_FILE = {"CODES": "_labels.json", "THEMES": "_themes.json", "PAJAIS": "_taxonomy.json"}
37
  NEXT_PHASE = {"CODES": "THEMES", "THEMES": "PAJAIS", "PAJAIS": "REPORT"}
38
 
39
+ def get_phase_html(current_phase):
40
+ mapping = {"INGEST": "a1", "CODES": "a2", "THEMES": "a3", "PAJAIS": "a3", "REPORT": "a4"}
41
+ active = mapping.get(current_phase, "a1")
42
+ return PRG_TPL.format(**{k: "active" if k == active else "" for k in ["a1", "a2", "a3", "a4"]})
43
+
44
  def init_analysis(query, csv_file, chat_hist):
45
  # 1. Clear old outputs
46
  if os.path.exists(OUT_DIR):
 
99
  feedback = (f"Detected Mode: {mode}\nSources:\n{source_lines}\nTotal: {total_papers} papers\n\n👉 Preparing dataset... Proceeding to Phase 2")
100
 
101
  new_hist = chat_hist + [{"role":"user","content": f"Init {mode}"}, {"role":"assistant","content": feedback + "\n\n" + res}]
102
+ return "", new_hist, _load_table("abstract", "CODES"), get_phase_html("CODES")
103
 
104
  def handle_pdf_upload(files):
105
  if not files: return "No files selected."
 
161
  path = os.path.join(OUT_DIR, f"{m}_{t}.html")
162
  return f'<iframe srcdoc="{open(path, encoding="utf-8").read().replace(chr(34),"&quot;")}" width="100%" height="450"></iframe>' if os.path.exists(path) else "Run Phase 2 first."
163
 
164
+ with gr.Blocks() as demo:
165
  with gr.Row():
166
  # LEFT SIDEBAR
167
  with gr.Column(scale=1, elem_classes="sidebar"):
168
  gr.HTML(HDR)
169
+ prg_display = gr.HTML(get_phase_html("INGEST"))
170
+ gr.HTML('<div style="height: 24px; border-top: 1px solid #f1f5f9; margin-top: 24px;"></div>')
171
  input_box = gr.Textbox(placeholder="Enter research topic...", label="Research Query")
172
  start_btn = gr.Button("Execute Discovery", variant="primary")
173
 
 
187
 
188
  # RIGHT MAIN WORKSPACE
189
  with gr.Column(scale=3, elem_classes="main-content"):
 
 
190
  with gr.Tabs(elem_classes="tab-nav"):
191
  with gr.Tab("💬 Agent Copilot"):
192
  chatbot = gr.Chatbot([], height=500, label="Research Assistant")
 
222
  btn_refresh_files.click(_get_files, [], [dl])
223
 
224
  # Event Bindings
225
+ start_btn.click(init_analysis, [input_box, csv_up, chatbot], [input_box, chatbot, tbl, prg_display])
226
  send_btn.click(handle_chat, [msg_in, chatbot, mode_btn, ph_state], [msg_in, chatbot, tbl])
227
  btn_ingest.click(handle_chat, [gr.State("Ingest all uploaded PDFs and Word documents into the system."), chatbot, gr.State("abstract"), gr.State("CODES")], [msg_in, chatbot, tbl])
228
  btn_scratch.click(handle_chat, [gr.State("Check the local scratch folder and import any papers found there."), chatbot, gr.State("abstract"), gr.State("CODES")], [msg_in, chatbot, tbl])
 
230
  sub_btn.click(submit_review, [tbl, chatbot, mode_btn, ph_state], [chatbot, ph_state, tbl]).then(_get_report, [], [report_box])
231
 
232
  if __name__ == "__main__":
233
+ demo.launch(server_port=7861, theme=gr.themes.Base(primary_hue="violet", neutral_hue="slate"), css=CSS)