rasAli02 commited on
Commit
8782dd9
Β·
1 Parent(s): 8d2779b

feat: add blueprint tab and pdf report download functionality

Browse files
Files changed (2) hide show
  1. hf_space/app.py +106 -0
  2. hf_space/requirements.txt +0 -0
hf_space/app.py CHANGED
@@ -12,6 +12,8 @@ import time
12
  import uuid
13
  import gradio as gr
14
  from datetime import datetime, timezone
 
 
15
 
16
  # ── Import the agent pipeline ───────────────────────────────────────────────
17
  from agents import run_pipeline, generate_social_post
@@ -50,11 +52,16 @@ async def inspect(image_base64: str, notes: str = "", product_spec: str = "", so
50
  _inspections.insert(0, inspection)
51
 
52
  summary = _summarize(inspection)
 
 
 
 
53
  return json.dumps({
54
  "id": inspection["id"],
55
  "created_at": inspection["created_at"],
56
  "transcript": transcript,
57
  "summary": summary,
 
58
  })
59
 
60
 
@@ -233,6 +240,63 @@ async def _seed_journal():
233
  })
234
 
235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  # ── Helpers ──────────────────────────────────────────────────────────────────
237
  def _summarize(inspection: dict) -> dict:
238
  agents = inspection.get("transcript", {}).get("agents", [])
@@ -368,6 +432,48 @@ with gr.Blocks(title="ForgeSight β€” AMD MI300X QC Copilot") as demo:
368
  return {**h, **m}
369
  status_btn.click(fn=check_status, inputs=[], outputs=status_out)
370
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
 
372
  if __name__ == "__main__":
373
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
12
  import uuid
13
  import gradio as gr
14
  from datetime import datetime, timezone
15
+ import tempfile
16
+ from fpdf import FPDF
17
 
18
  # ── Import the agent pipeline ───────────────────────────────────────────────
19
  from agents import run_pipeline, generate_social_post
 
52
  _inspections.insert(0, inspection)
53
 
54
  summary = _summarize(inspection)
55
+
56
+ # Generate a simple text-based report path (optional placeholder)
57
+ report_path = _generate_pdf_report(inspection)
58
+
59
  return json.dumps({
60
  "id": inspection["id"],
61
  "created_at": inspection["created_at"],
62
  "transcript": transcript,
63
  "summary": summary,
64
+ "report_url": report_path
65
  })
66
 
67
 
 
240
  })
241
 
242
 
243
+ def _generate_pdf_report(inspection: dict) -> str:
244
+ """Generates a PDF report for an inspection and returns the temporary file path."""
245
+ summary = _summarize(inspection)
246
+ transcript = inspection.get("transcript", {})
247
+ agents = transcript.get("agents", [])
248
+
249
+ pdf = FPDF()
250
+ pdf.add_page()
251
+
252
+ # Header
253
+ pdf.set_font("Arial", 'B', 16)
254
+ pdf.cell(190, 10, "ForgeSight Quality Control Report", ln=True, align='C')
255
+ pdf.set_font("Arial", '', 10)
256
+ pdf.cell(190, 10, f"Generated at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", ln=True, align='C')
257
+ pdf.ln(5)
258
+
259
+ # Summary Section
260
+ pdf.set_font("Arial", 'B', 12)
261
+ pdf.set_fill_color(240, 240, 240)
262
+ pdf.cell(190, 10, "1. EXECUTIVE SUMMARY", ln=True, fill=True)
263
+ pdf.set_font("Arial", '', 10)
264
+ pdf.cell(40, 10, "Inspection ID:", border=0)
265
+ pdf.cell(100, 10, summary["id"], ln=True)
266
+ pdf.cell(40, 10, "Verdict:", border=0)
267
+ pdf.set_font("Arial", 'B', 10)
268
+ pdf.cell(100, 10, summary["verdict"].upper(), ln=True)
269
+ pdf.set_font("Arial", '', 10)
270
+ pdf.cell(40, 10, "Confidence:", border=0)
271
+ pdf.cell(100, 10, f"{summary['confidence']:.2%}", ln=True)
272
+ pdf.cell(40, 10, "Headline:", border=0)
273
+ pdf.multi_cell(150, 10, summary["headline"])
274
+ pdf.ln(5)
275
+
276
+ # Agent Findings
277
+ pdf.set_font("Arial", 'B', 12)
278
+ pdf.cell(190, 10, "2. MULTI-AGENT ANALYSIS", ln=True, fill=True)
279
+ for agent in agents:
280
+ role = agent.get("role", "unknown").capitalize()
281
+ pdf.set_font("Arial", 'B', 10)
282
+ pdf.cell(190, 8, f"Agent: {role}", ln=True)
283
+ pdf.set_font("Arial", '', 9)
284
+ output = agent.get("output", {}).get("raw", "No detailed output.")
285
+ # Sanitize for PDF
286
+ output = output.encode('latin-1', 'replace').decode('latin-1')
287
+ pdf.multi_cell(190, 6, output)
288
+ pdf.ln(2)
289
+
290
+ # Footer
291
+ pdf.ln(10)
292
+ pdf.set_font("Arial", 'I', 8)
293
+ pdf.cell(190, 10, "Powered by AMD Instinct MI300X + ROCm | ForgeSight Multi-Agent Pipeline", ln=True, align='C')
294
+
295
+ temp = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
296
+ pdf.output(temp.name)
297
+ return temp.name
298
+
299
+
300
  # ── Helpers ──────────────────────────────────────────────────────────────────
301
  def _summarize(inspection: dict) -> dict:
302
  agents = inspection.get("transcript", {}).get("agents", [])
 
432
  return {**h, **m}
433
  status_btn.click(fn=check_status, inputs=[], outputs=status_out)
434
 
435
+ with gr.Tab("πŸ—οΈ Blueprint"):
436
+ gr.Markdown("### ForgeSight Architecture & Tech Stack")
437
+ bp_view_btn = gr.Button("Fetch Blueprint")
438
+ bp_display = gr.JSON(label="System Specs")
439
+
440
+ async def get_bp():
441
+ return json.loads(await blueprint())
442
+
443
+ bp_view_btn.click(fn=get_bp, inputs=[], outputs=bp_display)
444
+
445
+ gr.Markdown("""
446
+ #### Agent Pipeline Flow
447
+ 1. **Inspector**: Vision-reasoning agent identifies defects and assigns a base verdict.
448
+ 2. **Diagnostician**: Correlates defects with product specs and historical maintenance data.
449
+ 3. **Action Agent**: Determines severity and creates high-priority work orders.
450
+ 4. **Reporter**: Generates multi-channel summaries (Social, PDF, Email).
451
+ """)
452
+
453
+ with gr.Tab("πŸ“‹ Inspection Report"):
454
+ gr.Markdown("### Download Inspection Report")
455
+ with gr.Row():
456
+ report_select = gr.Dropdown(label="Select Inspection", choices=[])
457
+ report_refresh = gr.Button("πŸ”„ Refresh List")
458
+
459
+ report_download = gr.File(label="Download PDF Report")
460
+
461
+ async def refresh_inspections():
462
+ data = json.loads(await list_inspections())
463
+ choices = [f"{i['id']} - {i['headline'][:30]}..." for i in data["items"]]
464
+ return gr.update(choices=choices)
465
+
466
+ async def fetch_report(selection):
467
+ if not selection: return None
468
+ iid = selection.split(" - ")[0]
469
+ # Find the inspection in our list
470
+ inspection = next((i for i in _inspections if i["id"] == iid), None)
471
+ if not inspection: return None
472
+ return _generate_pdf_report(inspection)
473
+
474
+ report_refresh.click(fn=refresh_inspections, inputs=[], outputs=report_select)
475
+ report_select.change(fn=fetch_report, inputs=[report_select], outputs=report_download)
476
+
477
 
478
  if __name__ == "__main__":
479
  demo.launch(server_name="0.0.0.0", server_port=7860)
hf_space/requirements.txt CHANGED
Binary files a/hf_space/requirements.txt and b/hf_space/requirements.txt differ