Inframat-x commited on
Commit
1b3c5f8
·
verified ·
1 Parent(s): 42641f9

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +120 -0
app.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py (new UI wrapper)
2
+
3
+ import os
4
+ from pathlib import Path
5
+ import gradio as gr
6
+
7
+ from rag_core import ( # this is your current file, renamed
8
+ rag_reply,
9
+ W_TFIDF_DEFAULT,
10
+ W_BM25_DEFAULT,
11
+ W_EMB_DEFAULT,
12
+ LOG_PATH,
13
+ ARTIFACT_DIR,
14
+ )
15
+ from rag_eval_metrics import evaluate_rag
16
+
17
+ # ------------- RAG chat wrapper ----------------
18
+ def rag_chat_fn(
19
+ message,
20
+ history,
21
+ top_k,
22
+ n_sentences,
23
+ include_passages,
24
+ w_tfidf,
25
+ w_bm25,
26
+ w_emb,
27
+ ):
28
+ if not message or not message.strip():
29
+ return "Ask a literature question (e.g., *How does CNT length affect gauge factor?*)"
30
+ return rag_reply(
31
+ question=message,
32
+ k=int(top_k),
33
+ n_sentences=int(n_sentences),
34
+ include_passages=bool(include_passages),
35
+ use_llm=False,
36
+ model=None,
37
+ temperature=0.2,
38
+ strict_quotes_only=False,
39
+ w_tfidf=float(w_tfidf),
40
+ w_bm25=float(w_bm25),
41
+ w_emb=float(w_emb),
42
+ config_id=None,
43
+ )
44
+
45
+ # ------------- Evaluate wrapper ----------------
46
+ def run_eval_ui(gold_file, k):
47
+ if gold_file is None:
48
+ # Assume default gold.csv at repo root
49
+ gold_path = Path("gold.csv")
50
+ if not gold_path.exists():
51
+ return (
52
+ "**No gold.csv provided or found in the working directory.**\n"
53
+ "Upload a file or place gold.csv next to app.py."
54
+ )
55
+ gold_csv = str(gold_path)
56
+ else:
57
+ gold_csv = gold_file.name
58
+
59
+ logs_jsonl = str(LOG_PATH)
60
+ out_dir = str(ARTIFACT_DIR)
61
+ # This prints to console and writes CSV/JSON; we return a short message for the UI
62
+ evaluate_rag(gold_csv, logs_jsonl, k=int(k), out_dir=out_dir, group_by_weights=True)
63
+ return (
64
+ f"✅ Evaluation finished.\n\n"
65
+ f"- Per-question metrics: `{ARTIFACT_DIR / 'metrics_per_question.csv'}`\n"
66
+ f"- Aggregate metrics: `{ARTIFACT_DIR / 'metrics_aggregate.json'}`\n"
67
+ f"- Config surface: `{ARTIFACT_DIR / 'metrics_by_weights.csv'}`"
68
+ )
69
+
70
+ # ------------- Build Gradio UI -----------------
71
+ with gr.Blocks(title="Self-Sensing Concrete RAG") as demo:
72
+ gr.Markdown(
73
+ "<h1>Self-Sensing Concrete Assistant — Hybrid RAG</h1>"
74
+ "<p>Ask questions about self-sensing concrete; answers are grounded in your local PDFs.</p>"
75
+ )
76
+
77
+ with gr.Tabs():
78
+ # --------- RAG Chat tab ---------
79
+ with gr.Tab("📚 RAG Chat"):
80
+ with gr.Row():
81
+ top_k = gr.Slider(3, 15, value=8, step=1, label="Top-K chunks")
82
+ n_sentences = gr.Slider(2, 8, value=4, step=1, label="Answer length (sentences)")
83
+ include_passages = gr.Checkbox(
84
+ value=False, label="Include supporting passages"
85
+ )
86
+ with gr.Row():
87
+ w_tfidf = gr.Slider(0.0, 1.0, value=W_TFIDF_DEFAULT, step=0.05, label="TF-IDF weight")
88
+ w_bm25 = gr.Slider(0.0, 1.0, value=W_BM25_DEFAULT, step=0.05, label="BM25 weight")
89
+ w_emb = gr.Slider(0.0, 1.0, value=W_EMB_DEFAULT, step=0.05, label="Dense weight")
90
+
91
+ gr.ChatInterface(
92
+ fn=rag_chat_fn,
93
+ additional_inputs=[top_k, n_sentences, include_passages, w_tfidf, w_bm25, w_emb],
94
+ title="Hybrid RAG Q&A",
95
+ description="Hybrid BM25 + TF-IDF + dense retrieval with MMR sentence selection."
96
+ )
97
+
98
+ # --------- Evaluation tab ---------
99
+ with gr.Tab("📏 Evaluate RAG"):
100
+ gr.Markdown(
101
+ "Upload **gold.csv** and compute retrieval metrics against `rag_artifacts/rag_logs.jsonl`."
102
+ )
103
+ gold_file = gr.File(label="gold.csv", file_types=[".csv"])
104
+ k_slider = gr.Slider(3, 15, value=8, step=1, label="k for Hit/Recall/nDCG")
105
+ btn_eval = gr.Button("Run Evaluation")
106
+ eval_out = gr.Markdown(label="Evaluation log")
107
+
108
+ btn_eval.click(
109
+ fn=run_eval_ui,
110
+ inputs=[gold_file, k_slider],
111
+ outputs=eval_out,
112
+ )
113
+
114
+ # ------------- Launch app -----------------
115
+ if __name__ == "__main__":
116
+ demo.queue().launch(
117
+ server_name="0.0.0.0",
118
+ server_port=7860,
119
+ share=False,
120
+ )