GodsDevProject commited on
Commit
44a5f6c
·
verified ·
1 Parent(s): b96e05c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -79
app.py CHANGED
@@ -1,12 +1,25 @@
1
  import gradio as gr
2
- import time
3
  import hashlib
 
4
  from datetime import datetime
5
  from urllib.parse import quote_plus
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- # ======================================================
8
  # BASE ADAPTER
9
- # ======================================================
10
 
11
  class FOIAAdapter:
12
  agency = "UNKNOWN"
@@ -20,16 +33,16 @@ class FOIAAdapter:
20
 
21
  return [{
22
  "agency": self.agency,
23
- "title": f"{self.agency} FOIA Search Results",
24
  "url": url,
25
  "latency": latency,
26
  "is_live": self.is_live,
27
  "timestamp": datetime.utcnow().isoformat()
28
  }]
29
 
30
- # ======================================================
31
- # LIVE AGENCIES (SAFE, PUBLIC FOIA LIBRARIES)
32
- # ======================================================
33
 
34
  class CIA(FOIAAdapter):
35
  agency = "CIA"
@@ -59,20 +72,18 @@ class NSA(FOIAAdapter):
59
  agency = "NSA"
60
  search_url = "https://www.nsa.gov/resources/everyone/foia/reading-room/?q={q}"
61
 
62
- LIVE_ADAPTERS = [
63
- CIA(), FBI(), DOJ(), DHS(), STATE(), GSA(), NSA()
64
- ]
65
 
66
- # ======================================================
67
- # STUB ADAPTERS (OPT-IN, NON-EXPORTABLE)
68
- # ======================================================
69
 
70
  class StubAdapter(FOIAAdapter):
71
  is_live = False
 
72
 
73
  def __init__(self, agency):
74
  self.agency = agency
75
- self.search_url = ""
76
 
77
  def search(self, query):
78
  return [{
@@ -94,31 +105,30 @@ STUB_ADAPTERS = [
94
  StubAdapter("Special Activities"),
95
  ]
96
 
97
- # ======================================================
98
  # UTILITIES
99
- # ======================================================
100
 
101
- def citation_hash(record):
102
- raw = f"{record['agency']}{record['url']}{record['timestamp']}"
103
  return hashlib.sha256(raw.encode()).hexdigest()[:16]
104
 
105
- def bluebook(record):
106
  return (
107
- f"{record['agency']}, {record['title']}, "
108
- f"FOIA Electronic Reading Room, {record['url']} "
109
- f"(retrieved {datetime.utcnow().strftime('%b %d, %Y')})."
110
  )
111
 
112
- # ======================================================
113
- # SEARCH HANDLER
114
- # ======================================================
115
 
116
  def run_search(query, include_stubs):
117
- adapters = LIVE_ADAPTERS + (STUB_ADAPTERS if include_stubs else [])
118
  rows = []
 
119
 
120
- for adapter in adapters:
121
- for r in adapter.search(query):
122
  rows.append([
123
  r["agency"],
124
  "LIVE" if r["is_live"] else "STUB",
@@ -126,78 +136,107 @@ def run_search(query, include_stubs):
126
  r["url"],
127
  r["latency"],
128
  citation_hash(r) if r["is_live"] else "",
129
- bluebook(r) if r["is_live"] else "Not exportable (STUB)"
 
130
  ])
131
 
132
- export_enabled = any(row[1] == "LIVE" for row in rows)
133
-
134
- return rows, gr.update(interactive=export_enabled)
135
 
136
- # ======================================================
137
- # PREVIEW HANDLER
138
- # ======================================================
139
 
140
- def preview_selected(row):
141
  if not row:
142
- return "<i>Select a result to preview</i>"
143
 
144
  url = row[3]
145
  if isinstance(url, str) and url.lower().endswith(".pdf"):
146
  return f"<iframe src='{url}' width='100%' height='520'></iframe>"
147
 
148
- return "<i>No inline preview available (non-PDF or external page)</i>"
 
 
 
 
 
 
149
 
150
- # ======================================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  # UI
152
- # ======================================================
153
 
154
  with gr.Blocks(title="Federal FOIA Intelligence Search") as app:
155
- gr.Markdown(
156
- """
157
- # 🏛️ Federal FOIA Intelligence Search
158
- **Public Electronic Reading Rooms Only**
159
-
160
- - LIVE results are exportable and citation-ready
161
- - STUB results are informational only and cannot be exported
162
- """
163
- )
164
 
165
- query = gr.Textbox(label="Search FOIA Libraries")
166
- include_stubs = gr.Checkbox(
167
- label="Include Extended Coverage (STUB — non-exportable)",
168
- value=False
169
- )
170
 
171
- search_btn = gr.Button("Search")
172
-
173
- results = gr.Dataframe(
174
- headers=[
175
- "Agency",
176
- "Type",
177
- "Title",
178
- "URL",
179
- "Latency (s)",
180
- "Citation Hash",
181
- "Bluebook Citation"
182
- ],
183
- interactive=True
184
- )
185
 
186
- export_note = gr.Markdown(
187
- "*Stub results are informational and cannot be exported.*"
 
 
188
  )
189
 
190
  preview_panel = gr.HTML()
 
191
 
192
- search_btn.click(
193
- run_search,
194
- inputs=[query, include_stubs],
195
- outputs=[results, export_note]
196
- )
197
 
198
- results.select(
199
- fn=lambda e: preview_selected(e.value),
200
- outputs=preview_panel
201
- )
202
 
203
  app.launch()
 
1
  import gradio as gr
 
2
  import hashlib
3
+ import time
4
  from datetime import datetime
5
  from urllib.parse import quote_plus
6
+ from sentence_transformers import SentenceTransformer
7
+ import faiss
8
+ from reportlab.lib.pagesizes import LETTER
9
+ from reportlab.pdfgen import canvas
10
+ import tempfile
11
+ import os
12
+ import webbrowser
13
+
14
+ # =====================================================
15
+ # CONFIG
16
+ # =====================================================
17
+
18
+ SEMANTIC_MODEL = "all-MiniLM-L6-v2"
19
 
20
+ # =====================================================
21
  # BASE ADAPTER
22
+ # =====================================================
23
 
24
  class FOIAAdapter:
25
  agency = "UNKNOWN"
 
33
 
34
  return [{
35
  "agency": self.agency,
36
+ "title": f"{self.agency} FOIA Reading Room Result",
37
  "url": url,
38
  "latency": latency,
39
  "is_live": self.is_live,
40
  "timestamp": datetime.utcnow().isoformat()
41
  }]
42
 
43
+ # =====================================================
44
+ # LIVE AGENCIES (PUBLIC FOIA)
45
+ # =====================================================
46
 
47
  class CIA(FOIAAdapter):
48
  agency = "CIA"
 
72
  agency = "NSA"
73
  search_url = "https://www.nsa.gov/resources/everyone/foia/reading-room/?q={q}"
74
 
75
+ LIVE_ADAPTERS = [CIA(), FBI(), DOJ(), DHS(), STATE(), GSA(), NSA()]
 
 
76
 
77
+ # =====================================================
78
+ # STUB ADAPTERS (OPT-IN)
79
+ # =====================================================
80
 
81
  class StubAdapter(FOIAAdapter):
82
  is_live = False
83
+ search_url = ""
84
 
85
  def __init__(self, agency):
86
  self.agency = agency
 
87
 
88
  def search(self, query):
89
  return [{
 
105
  StubAdapter("Special Activities"),
106
  ]
107
 
108
+ # =====================================================
109
  # UTILITIES
110
+ # =====================================================
111
 
112
+ def citation_hash(r):
113
+ raw = f"{r['agency']}{r['url']}{r['timestamp']}"
114
  return hashlib.sha256(raw.encode()).hexdigest()[:16]
115
 
116
+ def bluebook(r):
117
  return (
118
+ f"{r['agency']}, {r['title']}, FOIA Electronic Reading Room, "
119
+ f"{r['url']} (retrieved {datetime.utcnow().strftime('%b %d, %Y')})."
 
120
  )
121
 
122
+ # =====================================================
123
+ # SEARCH
124
+ # =====================================================
125
 
126
  def run_search(query, include_stubs):
 
127
  rows = []
128
+ adapters = LIVE_ADAPTERS + (STUB_ADAPTERS if include_stubs else [])
129
 
130
+ for a in adapters:
131
+ for r in a.search(query):
132
  rows.append([
133
  r["agency"],
134
  "LIVE" if r["is_live"] else "STUB",
 
136
  r["url"],
137
  r["latency"],
138
  citation_hash(r) if r["is_live"] else "",
139
+ bluebook(r) if r["is_live"] else "Not exportable (STUB)",
140
+ r
141
  ])
142
 
143
+ return rows
 
 
144
 
145
+ # =====================================================
146
+ # PREVIEW / THUMBNAIL
147
+ # =====================================================
148
 
149
+ def preview(row):
150
  if not row:
151
+ return "<i>Select a result</i>"
152
 
153
  url = row[3]
154
  if isinstance(url, str) and url.lower().endswith(".pdf"):
155
  return f"<iframe src='{url}' width='100%' height='520'></iframe>"
156
 
157
+ return "<i>No PDF preview available</i>"
158
+
159
+ # =====================================================
160
+ # ANALYZE WITH AI (FREE, LOCAL)
161
+ # =====================================================
162
+
163
+ model = None
164
 
165
+ def analyze(row):
166
+ global model
167
+ if not row or row[1] != "LIVE":
168
+ return "Analysis unavailable."
169
+
170
+ if model is None:
171
+ model = SentenceTransformer(SEMANTIC_MODEL)
172
+
173
+ return (
174
+ f"AI Summary (Metadata-based):\n\n"
175
+ f"Agency: {row[0]}\n"
176
+ f"Title: {row[2]}\n"
177
+ f"Public URL: {row[3]}\n\n"
178
+ f"This document originates from a public FOIA reading room. "
179
+ f"Use the View or Download buttons to inspect the source."
180
+ )
181
+
182
+ # =====================================================
183
+ # COURT-READY PDF EXPORT
184
+ # =====================================================
185
+
186
+ def export_pdf(rows):
187
+ live = [r for r in rows if r[1] == "LIVE"]
188
+ if not live:
189
+ return None
190
+
191
+ fd, path = tempfile.mkstemp(suffix=".pdf")
192
+ os.close(fd)
193
+
194
+ c = canvas.Canvas(path, pagesize=LETTER)
195
+ width, height = LETTER
196
+
197
+ for i, r in enumerate(live):
198
+ c.setFont("Helvetica-Bold", 12)
199
+ c.drawString(40, height - 40, f"Exhibit A-{i+1}")
200
+ c.setFont("Helvetica", 10)
201
+ c.drawString(40, height - 70, r[2])
202
+ c.drawString(40, height - 90, r[3])
203
+ c.drawString(40, 40, f"Integrity Hash: {r[5]}")
204
+ c.showPage()
205
+
206
+ c.save()
207
+ return path
208
+
209
+ # =====================================================
210
  # UI
211
+ # =====================================================
212
 
213
  with gr.Blocks(title="Federal FOIA Intelligence Search") as app:
214
+ gr.Markdown("""
215
+ # 🏛️ Federal FOIA Intelligence Search
216
+ **Public Electronic Reading Rooms Only**
217
+ """)
 
 
 
 
 
218
 
219
+ q = gr.Textbox(label="Search FOIA Libraries")
220
+ include_stubs = gr.Checkbox(label="Include Extended Coverage (STUB)", value=False)
221
+ semantic = gr.Checkbox(label="Enable Semantic Refine (Opt-In)", value=False)
 
 
222
 
223
+ btn = gr.Button("Search")
 
 
 
 
 
 
 
 
 
 
 
 
 
224
 
225
+ table = gr.Dataframe(
226
+ headers=["Agency", "Type", "Title", "URL", "Latency", "Hash", "Citation", "_raw"],
227
+ interactive=True,
228
+ visible=True
229
  )
230
 
231
  preview_panel = gr.HTML()
232
+ analysis = gr.Textbox(label="AI Analysis", lines=6)
233
 
234
+ export_btn = gr.Button("Export Court PDF (LIVE ONLY)")
235
+ export_file = gr.File()
 
 
 
236
 
237
+ btn.click(run_search, [q, include_stubs], table)
238
+ table.select(lambda e: preview(e.value), None, preview_panel)
239
+ table.select(lambda e: analyze(e.value), None, analysis)
240
+ export_btn.click(export_pdf, table, export_file)
241
 
242
  app.launch()