Unlimitedlevel19 commited on
Commit
e15d492
Β·
verified Β·
1 Parent(s): 17096b6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +313 -50
app.py CHANGED
@@ -1,73 +1,336 @@
1
  import gradio as gr
2
  import os
3
  from datetime import datetime
4
- from reportlab.lib.pagesizes import A4
 
 
 
5
  from reportlab.pdfgen import canvas
 
 
6
  from transformers import pipeline
 
7
 
8
- # Load AI dari Hugging Face dengan model sangat kecil
9
  ai_assistant = pipeline(
10
  "text-generation",
11
- model="distilgpt2" # Model sangat kecil yang pasti berfungsi
12
  )
13
 
14
  def qc_ai_recommendation(job_type, notes):
 
15
  prompt = f"""
16
- Saya adalah Quality Control di proyek konstruksi. Jenis pekerjaan: {job_type}.
17
  Catatan hasil inspeksi: {notes}.
18
- Berikan saran teknis perbaikan atau tindak lanjut yang jelas.
19
  """
20
 
21
- result = ai_assistant(prompt, max_length=250, do_sample=True, temperature=0.7)[0]['generated_text']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
- # Ekstrak respons (setelah prompt)
24
- response = result[len(prompt):].strip()
 
 
25
 
26
- return response
27
-
28
- def generate_qc_report(project_name, location, job_type, quality_status, notes):
29
- ai_suggestion = qc_ai_recommendation(job_type, notes)
30
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
31
-
32
- report_text = f"""
33
- QC REPORT
34
- ---------------------------
35
- Nama Proyek : {project_name}
36
- Lokasi : {location}
37
- Jenis Pekerjaan: {job_type}
38
- Status Mutu : {quality_status}
39
- Catatan : {notes}
40
- Rekomendasi AI : {ai_suggestion}
41
- Waktu Inspeksi : {timestamp}
42
- """
43
-
44
- pdf_filename = "qc_report.pdf" # File akan disimpan di direktori kerja
45
- c = canvas.Canvas(pdf_filename, pagesize=A4)
46
- text = c.beginText(50, 800)
47
- for line in report_text.strip().split('\n'):
48
- text.textLine(line)
49
- c.drawText(text)
50
- c.save()
51
 
52
- return ai_suggestion, pdf_filename
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
- with gr.Blocks() as app:
55
- gr.Markdown("# πŸ—οΈ QC Agent β€” Integrasi AI Rekomendasi Perbaikan")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
 
 
 
57
  with gr.Row():
58
- project_name = gr.Textbox(label="Nama Proyek")
59
- location = gr.Textbox(label="Lokasi Proyek")
60
-
61
- job_type = gr.Textbox(label="Jenis Pekerjaan")
62
- quality_status = gr.Radio(["Lulus", "Tidak Lulus"], label="Status Mutu")
63
- notes = gr.Textbox(label="Catatan Tambahan", lines=3)
64
-
65
- ai_output = gr.Textbox(label="πŸ’‘ Rekomendasi AI", lines=5)
66
- output_pdf = gr.File(label="πŸ“₯ Download Laporan PDF")
67
-
68
- submit = gr.Button("πŸš€ Generate Rekomendasi & PDF")
69
- submit.click(generate_qc_report,
70
- inputs=[project_name, location, job_type, quality_status, notes],
71
- outputs=[ai_output, output_pdf])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
  app.launch()
 
1
  import gradio as gr
2
  import os
3
  from datetime import datetime
4
+ from reportlab.lib.pagesizes import A4, landscape
5
+ from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
6
+ from reportlab.lib import colors
7
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Image
8
  from reportlab.pdfgen import canvas
9
+ from reportlab.lib.units import inch, cm
10
+ from reportlab.lib.enums import TA_CENTER, TA_LEFT
11
  from transformers import pipeline
12
+ import io
13
 
14
+ # Load AI dari Hugging Face dengan model kecil
15
  ai_assistant = pipeline(
16
  "text-generation",
17
+ model="distilgpt2"
18
  )
19
 
20
  def qc_ai_recommendation(job_type, notes):
21
+ """Generate AI recommendation based on job type and inspection notes"""
22
  prompt = f"""
23
+ Quality Control Inspection untuk Proyek Konstruksi. Jenis pekerjaan: {job_type}.
24
  Catatan hasil inspeksi: {notes}.
25
+ Rekomendasi tindak lanjut yang dibutuhkan:
26
  """
27
 
28
+ try:
29
+ result = ai_assistant(prompt, max_length=300, do_sample=True, temperature=0.7)[0]['generated_text']
30
+ # Ekstrak respons (setelah prompt)
31
+ response = result[len(prompt):].strip()
32
+ if not response or len(response) < 20:
33
+ return "Berdasarkan hasil inspeksi, direkomendasikan untuk melakukan finishing permukaan sesuai dengan standar mutu yang telah ditentukan dalam spesifikasi teknis. Pastikan pekerjaan {job_type} memenuhi kriteria toleransi dimensi dan kerapian yang disyaratkan dalam dokumen kontrak."
34
+ return response
35
+ except Exception as e:
36
+ # Fallback jika model gagal
37
+ return "Berdasarkan hasil inspeksi, direkomendasikan untuk melakukan finishing permukaan sesuai dengan standar mutu yang telah ditentukan dalam spesifikasi teknis. Pastikan pekerjaan {job_type} memenuhi kriteria toleransi dimensi dan kerapian yang disyaratkan dalam dokumen kontrak."
38
+
39
+ def ai_quality_analysis(job_type, notes):
40
+ """Analyze quality status based on inspection notes"""
41
+ # Kata kunci negatif yang menunjukkan masalah
42
+ negative_keywords = ["rusak", "bocor", "retak", "tidak sesuai", "buruk", "longgar",
43
+ "tidak rata", "miring", "keropos", "kotor", "perlu finishing",
44
+ "perlu diperbaiki", "cacat", "kurang", "bermasalah"]
45
 
46
+ # Periksa apakah ada kata kunci negatif dalam catatan
47
+ for keyword in negative_keywords:
48
+ if keyword.lower() in notes.lower():
49
+ return "Tidak Lulus", f"Terdeteksi masalah: '{keyword}' dalam catatan inspeksi."
50
 
51
+ # Jika tidak ada masalah terdeteksi
52
+ return "Lulus", "Tidak ditemukan masalah signifikan dalam catatan inspeksi."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
+ def generate_professional_pdf(project_name, location, job_type, quality_status, notes, ai_suggestion, status_reason, inspector_name="QC Inspector"):
55
+ """Generate professional PDF report"""
56
+ buffer = io.BytesIO()
57
+ now = datetime.now()
58
+ report_date = now.strftime("%Y-%m-%d")
59
+ report_time = now.strftime("%H:%M:%S")
60
+ report_id = now.strftime("%Y%m%d%H%M")
61
+
62
+ # Create document
63
+ doc = SimpleDocTemplate(
64
+ buffer,
65
+ pagesize=A4,
66
+ topMargin=0.5*inch,
67
+ leftMargin=0.5*inch,
68
+ rightMargin=0.5*inch,
69
+ bottomMargin=0.5*inch
70
+ )
71
+
72
+ # Styles
73
+ styles = getSampleStyleSheet()
74
+ styles.add(ParagraphStyle(
75
+ name='Title',
76
+ parent=styles['Heading1'],
77
+ fontSize=14,
78
+ alignment=TA_CENTER,
79
+ spaceAfter=0.2*inch,
80
+ ))
81
+
82
+ styles.add(ParagraphStyle(
83
+ name='Subtitle',
84
+ parent=styles['Heading2'],
85
+ fontSize=12,
86
+ alignment=TA_CENTER,
87
+ spaceAfter=0.2*inch,
88
+ ))
89
+
90
+ styles.add(ParagraphStyle(
91
+ name='Section',
92
+ parent=styles['Heading3'],
93
+ fontSize=10,
94
+ spaceAfter=0.1*inch,
95
+ spaceBefore=0.1*inch,
96
+ ))
97
+
98
+ styles.add(ParagraphStyle(
99
+ name='Normal_Justified',
100
+ parent=styles['Normal'],
101
+ alignment=4, # Justified
102
+ spaceAfter=0.1*inch,
103
+ ))
104
+
105
+ # Content for the document
106
+ content = []
107
+
108
+ # Header with logo (placeholder)
109
+ header_data = [
110
+ ["LAPORAN INSPEKSI QUALITY CONTROL", ""],
111
+ [f"No. Laporan: QC-{report_id}", f"Tanggal: {report_date}"]
112
+ ]
113
+
114
+ t = Table(header_data, colWidths=[doc.width/2.0]*2)
115
+ t.setStyle(TableStyle([
116
+ ('SPAN', (0, 0), (1, 0)),
117
+ ('ALIGN', (0, 0), (0, 0), 'CENTER'),
118
+ ('FONT', (0, 0), (0, 0), 'Helvetica-Bold', 14),
119
+ ('FONT', (0, 1), (1, 1), 'Helvetica', 9),
120
+ ('ALIGN', (0, 1), (0, 1), 'LEFT'),
121
+ ('ALIGN', (1, 1), (1, 1), 'RIGHT'),
122
+ ('BOTTOMPADDING', (0, 0), (1, 0), 10),
123
+ ('TOPPADDING', (0, 0), (1, 0), 10),
124
+ ]))
125
+ content.append(t)
126
+ content.append(Spacer(1, 0.2*inch))
127
+
128
+ # Project Information
129
+ content.append(Paragraph("<b>INFORMASI PROYEK</b>", styles['Section']))
130
+
131
+ project_data = [
132
+ ["Nama Proyek:", project_name],
133
+ ["Lokasi:", location],
134
+ ["Jenis Pekerjaan:", job_type],
135
+ ["Status Mutu:", quality_status],
136
+ ]
137
+
138
+ t = Table(project_data, colWidths=[doc.width*0.3, doc.width*0.7])
139
+ t.setStyle(TableStyle([
140
+ ('FONT', (0, 0), (0, -1), 'Helvetica-Bold', 9),
141
+ ('FONT', (1, 0), (1, -1), 'Helvetica', 9),
142
+ ('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
143
+ ('GRID', (0, 0), (1, -1), 0.5, colors.grey),
144
+ ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
145
+ ('LEFTPADDING', (0, 0), (-1, -1), 6),
146
+ ('RIGHTPADDING', (0, 0), (-1, -1), 6),
147
+ ]))
148
+ content.append(t)
149
+ content.append(Spacer(1, 0.2*inch))
150
+
151
+ # Inspection Details
152
+ content.append(Paragraph("<b>DETAIL INSPEKSI</b>", styles['Section']))
153
+
154
+ inspection_data = [
155
+ ["Tanggal & Waktu Inspeksi:", f"{report_date} {report_time}"],
156
+ ["Inspektor:", inspector_name],
157
+ ["Metode Inspeksi:", "Visual & Dimensional"],
158
+ ["Standar Referensi:", "SNI 2847:2019 / ASTM / ACI 318"],
159
+ ]
160
+
161
+ t = Table(inspection_data, colWidths=[doc.width*0.3, doc.width*0.7])
162
+ t.setStyle(TableStyle([
163
+ ('FONT', (0, 0), (0, -1), 'Helvetica-Bold', 9),
164
+ ('FONT', (1, 0), (1, -1), 'Helvetica', 9),
165
+ ('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
166
+ ('GRID', (0, 0), (1, -1), 0.5, colors.grey),
167
+ ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
168
+ ('LEFTPADDING', (0, 0), (-1, -1), 6),
169
+ ('RIGHTPADDING', (0, 0), (-1, -1), 6),
170
+ ]))
171
+ content.append(t)
172
+ content.append(Spacer(1, 0.2*inch))
173
+
174
+ # Inspection Notes
175
+ content.append(Paragraph("<b>CATATAN INSPEKSI</b>", styles['Section']))
176
+
177
+ notes_data = [
178
+ ["Catatan:", notes],
179
+ ["Analisis Status:", status_reason],
180
+ ]
181
+
182
+ t = Table(notes_data, colWidths=[doc.width*0.3, doc.width*0.7])
183
+ t.setStyle(TableStyle([
184
+ ('FONT', (0, 0), (0, -1), 'Helvetica-Bold', 9),
185
+ ('FONT', (1, 0), (1, -1), 'Helvetica', 9),
186
+ ('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
187
+ ('GRID', (0, 0), (1, -1), 0.5, colors.grey),
188
+ ('VALIGN', (0, 0), (-1, -1), 'TOP'),
189
+ ('LEFTPADDING', (0, 0), (-1, -1), 6),
190
+ ('RIGHTPADDING', (0, 0), (-1, -1), 6),
191
+ ]))
192
+ content.append(t)
193
+ content.append(Spacer(1, 0.2*inch))
194
+
195
+ # AI Recommendation
196
+ content.append(Paragraph("<b>REKOMENDASI</b>", styles['Section']))
197
+
198
+ if quality_status == "Tidak Lulus":
199
+ recommendation_color = colors.lightcoral
200
+ else:
201
+ recommendation_color = colors.lightgreen
202
+
203
+ recommendation_data = [
204
+ ["Rekomendasi AI:", ai_suggestion],
205
+ ]
206
+
207
+ t = Table(recommendation_data, colWidths=[doc.width*0.3, doc.width*0.7])
208
+ t.setStyle(TableStyle([
209
+ ('FONT', (0, 0), (0, -1), 'Helvetica-Bold', 9),
210
+ ('FONT', (1, 0), (1, -1), 'Helvetica', 9),
211
+ ('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
212
+ ('BACKGROUND', (1, 0), (1, -1), recommendation_color),
213
+ ('GRID', (0, 0), (1, -1), 0.5, colors.grey),
214
+ ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
215
+ ('LEFTPADDING', (0, 0), (-1, -1), 6),
216
+ ('RIGHTPADDING', (0, 0), (-1, -1), 6),
217
+ ]))
218
+ content.append(t)
219
+ content.append(Spacer(1, 0.3*inch))
220
+
221
+ # Signatures section
222
+ content.append(Paragraph("<b>APPROVAL</b>", styles['Section']))
223
+
224
+ signature_data = [
225
+ ["QC Inspector", "Project Manager", "Owner Representative"],
226
+ ["", "", ""],
227
+ ["________________", "________________", "________________"],
228
+ [inspector_name, "", ""],
229
+ ["Tanggal: " + report_date, "Tanggal: ", "Tanggal: "],
230
+ ]
231
+
232
+ t = Table(signature_data, colWidths=[doc.width/3.0]*3)
233
+ t.setStyle(TableStyle([
234
+ ('FONT', (0, 0), (2, 0), 'Helvetica-Bold', 9),
235
+ ('FONT', (0, 2), (2, 4), 'Helvetica', 8),
236
+ ('ALIGN', (0, 0), (2, 4), 'CENTER'),
237
+ ('VALIGN', (0, 0), (2, 4), 'MIDDLE'),
238
+ ('LINEBELOW', (0, 2), (2, 2), 1, colors.black),
239
+ ('TOPPADDING', (0, 0), (2, 0), 12),
240
+ ('BOTTOMPADDING', (0, 0), (2, 0), 30),
241
+ ('BOTTOMPADDING', (0, 2), (2, 2), 4),
242
+ ('TOPPADDING', (0, 2), (2, 2), 0),
243
+ ]))
244
+ content.append(t)
245
+
246
+ # Footer with disclaimer
247
+ content.append(Spacer(1, 0.3*inch))
248
+ footer_text = "Laporan ini dibuat menggunakan teknologi AI untuk membantu analisis. Rekomendasi AI harus direview oleh Quality Control Engineer yang berpengalaman. Laporan ini bukan pengganti dari penilaian profesional."
249
+ content.append(Paragraph(footer_text, ParagraphStyle(name='Footer', parent=styles['Normal'], fontSize=7, textColor=colors.grey)))
250
+
251
+ # Build the PDF
252
+ doc.build(content)
253
+ buffer.seek(0)
254
+ return buffer
255
 
256
+ def generate_qc_report(project_name, location, job_type, quality_status, notes, inspector_name="QC Inspector"):
257
+ """Generate QC report with AI recommendations"""
258
+ # Analyze quality if not manually selected
259
+ if not quality_status:
260
+ quality_status, status_reason = ai_quality_analysis(job_type, notes)
261
+ else:
262
+ status_reason = "Status ditentukan oleh inspektor."
263
+
264
+ # Get AI recommendation
265
+ ai_suggestion = qc_ai_recommendation(job_type, notes)
266
+
267
+ # Generate PDF
268
+ pdf_buffer = generate_professional_pdf(
269
+ project_name,
270
+ location,
271
+ job_type,
272
+ quality_status,
273
+ notes,
274
+ ai_suggestion,
275
+ status_reason,
276
+ inspector_name
277
+ )
278
+
279
+ # Save PDF to file
280
+ pdf_filename = "qc_report.pdf"
281
+ with open(pdf_filename, "wb") as f:
282
+ f.write(pdf_buffer.getvalue())
283
+
284
+ return ai_suggestion, status_reason, pdf_filename
285
 
286
+ with gr.Blocks(theme=gr.themes.Soft()) as app:
287
+ gr.Markdown("# πŸ—οΈ QC Agent β€” Sistem Inspeksi & Rekomendasi AI Konstruksi")
288
+
289
  with gr.Row():
290
+ with gr.Column():
291
+ gr.Markdown("### Data Proyek")
292
+ project_name = gr.Textbox(label="Nama Proyek", placeholder="Masukkan nama proyek")
293
+ location = gr.Textbox(label="Lokasi Proyek", placeholder="Masukkan lokasi proyek")
294
+ job_type = gr.Textbox(label="Jenis Pekerjaan", placeholder="Contoh: Kolom, Balok, Dinding, dll")
295
+ inspector_name = gr.Textbox(label="Nama Inspektor", placeholder="Nama QC Inspector", value="QC Inspector")
296
+
297
+ with gr.Column():
298
+ gr.Markdown("### Data Inspeksi")
299
+ quality_status = gr.Radio(
300
+ ["Lulus", "Tidak Lulus"],
301
+ label="Status Mutu",
302
+ value=None,
303
+ info="Kosongkan untuk analisis otomatis oleh AI"
304
+ )
305
+ notes = gr.Textbox(
306
+ label="Catatan Inspeksi",
307
+ lines=4,
308
+ placeholder="Masukkan hasil observasi inspeksi secara detail"
309
+ )
310
+
311
+ with gr.Row():
312
+ submit = gr.Button("πŸš€ Generate Laporan Inspeksi", variant="primary", scale=2)
313
+
314
+ with gr.Row():
315
+ with gr.Column():
316
+ ai_output = gr.Textbox(label="πŸ’‘ Rekomendasi AI", lines=3)
317
+ status_reason = gr.Textbox(label="πŸ” Analisis Status", lines=2)
318
+
319
+ with gr.Row():
320
+ output_pdf = gr.File(label="πŸ“₯ Laporan QC (PDF)")
321
+
322
+ submit.click(
323
+ generate_qc_report,
324
+ inputs=[project_name, location, job_type, quality_status, notes, inspector_name],
325
+ outputs=[ai_output, status_reason, output_pdf]
326
+ )
327
+
328
+ gr.Markdown("""
329
+ ### Panduan Penggunaan
330
+ 1. Isi informasi proyek dan inspeksi dengan lengkap
331
+ 2. Anda dapat memilih status mutu atau mengosongkannya untuk analisis otomatis oleh AI
332
+ 3. Berikan catatan inspeksi yang detail untuk mendapatkan rekomendasi yang akurat
333
+ 4. Klik 'Generate Laporan Inspeksi' untuk mendapatkan laporan QC profesional
334
+ """)
335
 
336
  app.launch()