saashley commited on
Commit
e07150a
·
verified ·
1 Parent(s): 217d2d5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +134 -45
app.py CHANGED
@@ -4,84 +4,173 @@ import html
4
 
5
 
6
  municipalities = [
 
7
  "Comun General de Fascia",
8
  "Comune di Capo D'Orlando",
9
  "Comune di Casatenovo",
10
  "Comune di Fonte Nuova",
 
 
11
  "Comune di Gubbio",
 
12
  "Comune di Torre Santa Susanna",
13
  "Comune di Santa Maria Capua Vetere"
14
  ]
15
 
16
- def answer_fn(query: str, municipality: str):
17
- # "All" or empty count as no filter
18
- filters = {}
19
- if municipality and municipality != "All":
20
- filters["municipality"] = municipality
21
-
22
- output = rag_pipeline(query=query, municipality=municipality)
23
-
24
- final_answer = output["final_answer"]
25
- cot = output["chain_of_thought"]
26
-
27
- chunks = output["retrieved_chunks"]
 
 
 
28
  html_blocks = []
29
  for i, c in enumerate(chunks, 1):
30
  text = html.escape(c["chunk_text"])
31
  meta = {
32
- "Document ID": c.get("document_id", "N/A"),
33
- "Municipality": c.get("municipality", "N/A"),
34
- "Section": c.get("section", "N/A"),
35
- "Page": c.get("page", "N/A"),
36
- "Score": f"{c.get('final_score', 0):.4f}"
37
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
- # transforms metadata dictionary into a series of <li> (list) items
40
- meta_lines = "".join(f"<li><b>{k}</b>: {v}</li>" for k, v in meta.items())
41
-
42
- # displays chunk number as header, metadata and text
43
- block = f"""
44
- <div style="margin-bottom:1em;">
45
- <h4>Chunk {i}</h4>
46
- <ul>{meta_lines}</ul>
47
- <p style="white-space: pre-wrap;">{text}</p>
48
- </div>
49
- <hr/>
50
- """
51
- html_blocks.append(block)
52
- chunks_html = "\n".join(html_blocks) or "<i>No chunks retrieved.</i>"
53
-
54
- return final_answer, cot, chunks_html
55
-
 
 
 
 
 
 
 
 
 
 
56
 
 
57
  with gr.Blocks() as demo:
58
  gr.Markdown("## DSPy RAG Demo")
59
 
60
  with gr.Row():
61
- query_input = gr.Textbox(label="Question", placeholder="Type your query here…")
62
  muni_input = gr.Dropdown(
63
- choices=["All"] + municipalities,
64
- value="All",
65
- label="Municipality (optional)"
66
  )
67
 
68
- run_btn = gr.Button("Get Answer")
69
 
70
- ans_out = gr.Textbox(label="Final Answer", lines=3) # answer container
71
 
72
  # CoT container inside its accordion
73
- with gr.Accordion("Chain of Thought Reasoning", open=False):
74
  cot_txt = gr.Textbox(label="", interactive=False, lines=6)
75
 
76
  # chunks HTML container inside its accordion
77
- with gr.Accordion("Retrieved Chunks with Metadata", open=False):
78
  chunks_html = gr.HTML("<i>No data yet.</i>")
79
 
80
- # Wire the button click to the function (with outputs matching the order of returned values)
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  run_btn.click(
82
- fn=answer_fn,
83
  inputs=[query_input, muni_input],
84
- outputs=[ans_out, cot_txt, chunks_html]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  )
86
 
87
  demo.launch(ssr_mode=False)
 
4
 
5
 
6
  municipalities = [
7
+ "Città di Agrigento",
8
  "Comun General de Fascia",
9
  "Comune di Capo D'Orlando",
10
  "Comune di Casatenovo",
11
  "Comune di Fonte Nuova",
12
+ "Comune di Galliate",
13
+ "Comune di Grottaferrata",
14
  "Comune di Gubbio",
15
+ "Comune di Ispica",
16
  "Comune di Torre Santa Susanna",
17
  "Comune di Santa Maria Capua Vetere"
18
  ]
19
 
20
+ def check_muni(muni: str) -> str:
21
+ return "" if muni in (None, "", "Tutti") else muni
22
+
23
+ def _run_rag(raw, muni, feedback):
24
+ """Internal helper: runs your pipeline and returns everything needed."""
25
+ out = rag_pipeline(raw_query=raw, municipality=check_muni(muni), feedback=feedback)
26
+ return {
27
+ "answer": out["final_answer"],
28
+ "cot": out["chain_of_thought"],
29
+ "chunks_html": build_chunks_html(out["retrieved_chunks"]),
30
+ "rewritten": out["rewritten_query"],
31
+ "intent": out["intent"]
32
+ }
33
+
34
+ def build_chunks_html(chunks):
35
  html_blocks = []
36
  for i, c in enumerate(chunks, 1):
37
  text = html.escape(c["chunk_text"])
38
  meta = {
39
+ "Document ID": c.get("document_id","N/A"),
40
+ "Municipality": c.get("municipality","N/A"),
41
+ "Section": c.get("section","N/A"),
42
+ "Page": c.get("page","N/A"),
43
+ "Score": f"{c.get('final_score',0):.4f}"
44
  }
45
+ meta_lines = "".join(f"<li><b>{k}</b>: {v}</li>" for k,v in meta.items())
46
+ html_blocks.append(f"""
47
+ <div style="margin-bottom:1em;">
48
+ <h4>Chunk {i}</h4>
49
+ <ul>{meta_lines}</ul>
50
+ <p style="white-space: pre-wrap;">{text}</p>
51
+ </div><hr/>
52
+ """)
53
+ return "\n".join(html_blocks) or "<i>No chunks retrieved.</i>"
54
+
55
+
56
+ # Stage 1: initial answer
57
+ def stage1(query, municipality):
58
+ result = _run_rag(query, municipality, feedback="")
59
+ return (
60
+ result["answer"],
61
+ result["cot"],
62
+ result["chunks_html"],
63
+ result["rewritten"],
64
+ result["intent"],
65
+ gr.update(visible=True), # show satisfaction
66
+ gr.update(visible=False), # hide feedback
67
+ gr.update(visible=False) # hide refine
68
+ )
69
 
70
+ # When satisfaction changes: show feedback only if “No”
71
+ def on_satisfied_change(sat):
72
+ if sat == "👎 No":
73
+ # show feedback box, show refine button (but keep it disabled)
74
+ return gr.update(visible=True), gr.update(visible=True, interactive=False)
75
+ else:
76
+ # hide both if they say "👍 Sì"
77
+ return gr.update(visible=False), gr.update(visible=False, interactive=False)
78
+
79
+
80
+ # Stage 2: enable refine button only once there's feedback text
81
+ def on_feedback_change(feedback_text):
82
+ return gr.update(interactive=bool(feedback_text.strip()))
83
+
84
+ # Stage 3: refinement pass
85
+ def stage3(query, municipality, satisfaction, feedback):
86
+ result = _run_rag(query, municipality, feedback)
87
+ return (
88
+ result["answer"],
89
+ result["cot"],
90
+ result["chunks_html"],
91
+ result["rewritten"],
92
+ result["intent"],
93
+ gr.update(visible=True), # satisfaction
94
+ gr.update(visible=True), # feedback box
95
+ gr.update(visible=False, interactive=False) # disable refine button
96
+ )
97
 
98
+ # == Gradio Blocks ==
99
  with gr.Blocks() as demo:
100
  gr.Markdown("## DSPy RAG Demo")
101
 
102
  with gr.Row():
103
+ query_input = gr.Textbox(label="Domanda", placeholder="Scrivi la tua domanda qui...")
104
  muni_input = gr.Dropdown(
105
+ choices=["Tutti"] + municipalities,
106
+ value="Tutti",
107
+ label="Comune (facoltativo)"
108
  )
109
 
110
+ run_btn = gr.Button("Cerca")
111
 
112
+ ans_out = gr.Textbox(label="Risposta Finale", lines=3) # answer container
113
 
114
  # CoT container inside its accordion
115
+ with gr.Accordion("Catena di Ragionamento", open=False):
116
  cot_txt = gr.Textbox(label="", interactive=False, lines=6)
117
 
118
  # chunks HTML container inside its accordion
119
+ with gr.Accordion("Chunks Recuperati con Metadata", open=False):
120
  chunks_html = gr.HTML("<i>No data yet.</i>")
121
 
122
+ # Show what the model actually used
123
+ rewritten_out = gr.Textbox(label="Domanda Rielaborata", interactive=False)
124
+ intent_out = gr.Textbox(label="Intento Identificato", interactive=False)
125
+
126
+ # Human feedback step
127
+ satisfaction = gr.Radio(
128
+ ["👍 Sì","👎 No"], label="Sei soddisfatto?", visible=False
129
+ )
130
+ feedback_txt = gr.Textbox(
131
+ label="Cosa non va? (facoltativo)", lines=3, visible=False, interactive=True
132
+ )
133
+ refine_btn = gr.Button("Affina la Domanda", visible=False, interactive=False)
134
+
135
+ # Wire Stage 1
136
  run_btn.click(
137
+ fn=stage1,
138
  inputs=[query_input, muni_input],
139
+ outputs=[
140
+ ans_out, cot_txt, chunks_html,
141
+ rewritten_out, intent_out,
142
+ satisfaction, feedback_txt, refine_btn
143
+ ]
144
+ )
145
+
146
+ # When satisfaction toggles, show/hide feedback
147
+ satisfaction.change(
148
+ fn=on_satisfied_change,
149
+ inputs=[satisfaction],
150
+ outputs=[feedback_txt, refine_btn]
151
+ )
152
+
153
+ # Only enable refine once feedback is non-empty
154
+ feedback_txt.change(
155
+ fn=on_feedback_change,
156
+ inputs=[feedback_txt],
157
+ outputs=[refine_btn]
158
+ )
159
+
160
+ # Wire Stage 3 (refinement)
161
+ refine_btn.click(
162
+ fn=stage3,
163
+ inputs=[query_input, muni_input, satisfaction, feedback_txt],
164
+ outputs=[
165
+ ans_out,
166
+ cot_txt,
167
+ chunks_html,
168
+ rewritten_out,
169
+ intent_out,
170
+ satisfaction, # now reset and visible
171
+ feedback_txt, # still visible
172
+ refine_btn # hidden/disabled
173
+ ]
174
  )
175
 
176
  demo.launch(ssr_mode=False)