SHELLAPANDIANGANHUNGING commited on
Commit
6449b51
·
verified ·
1 Parent(s): 3f86577

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +41 -86
app.py CHANGED
@@ -1981,25 +1981,21 @@ if not df_category.empty:
1981
  else:
1982
  st.info("No data available for non-positive issue categories with 100% coverage and positive trend.")
1983
  # =================== OBJECTIVE 7 — Insight and Recommendation (Agentic AI LLM Style — Final) ===================
 
1984
  st.markdown("<h3 class='section-title'>OBJECTIVE 7 — Insight and Recommendation</h3>", unsafe_allow_html=True)
1985
 
1986
- def extract_agentic_insights_v4(df: pd.DataFrame):
1987
  dev = {
1988
- # 1. 9 lokasi rasio TERENDAH
1989
  "lowest_ratio_9_locs": [],
1990
- # 2a–2d: dari Obj 3a–3d
1991
  "obj3a_lowest_div": None,
1992
  "obj3b_slowest_executor": None,
1993
  "obj3c_lowest_reporter": None,
1994
  "obj3d_slowest_div": None,
1995
- # 3. Non-Positive composition
1996
  "obj4_unsafe_condition_pct": 0.0,
1997
  "obj4_unsafe_action_pct": 0.0,
1998
  "obj4_near_miss_pct": 0.0,
1999
- # 4. Quadrant I & II
2000
  "obj5_q1_divs": [],
2001
  "obj5_q2_divs": [],
2002
- # 5. Top 2 non-Positive categories
2003
  "obj6_top2_categories": [],
2004
  }
2005
 
@@ -2091,7 +2087,7 @@ def extract_agentic_insights_v4(df: pd.DataFrame):
2091
  elif r['Finding Count'] < X_LIMIT and r['Avg Lead Time'] >= Y_LIMIT:
2092
  dev["obj5_q2_divs"].append(r['nama'])
2093
 
2094
- # === 5. Top 2 non-Positive category (Obj 6) ===
2095
  if {'kategori', 'temuan_kategori', 'created_at'}.issubset(df.columns):
2096
  nonpos = df[df['temuan_kategori'] != 'Positive']
2097
  if not nonpos.empty:
@@ -2103,64 +2099,49 @@ def extract_agentic_insights_v4(df: pd.DataFrame):
2103
 
2104
  return dev
2105
 
2106
- # Ekstrak
2107
- dev = extract_agentic_insights_v4(df_filtered)
2108
 
2109
- # 📝 INSIGHT TEXT — STRUKTUR FINAL
2110
  insight_lines = []
2111
 
2112
- # 1. 9 lokasi rasio terendah (semua ditampilkan)
2113
  if dev["lowest_ratio_9_locs"]:
2114
  loc_list = ", ".join([f"<strong>{loc}</strong> ({ratio})" for loc, ratio in dev["lowest_ratio_9_locs"]])
2115
- insight_lines.append(f"1. Sembilan lokasi dengan rasio temuan/orang *terendah* (<0.5): {loc_list}.")
2116
 
2117
- # 2. AGENTIC AI SUMMARY dari 2a–2d (BUKAN insight umum biasa)
2118
- # Ini adalah kunci perbaikan: summary berbasis *capacity-agency-risk mismatch*
2119
- summary_parts = []
2120
  if dev["obj3a_lowest_div"]:
2121
- summary_parts.append(f"divisi {dev['obj3a_lowest_div'][0]} (rasio {dev['obj3a_lowest_div'][1]})")
2122
  if dev["obj3c_lowest_reporter"]:
2123
- summary_parts.append(f"reporter {dev['obj3c_lowest_reporter'][0]} ({dev['obj3c_lowest_reporter'][1]}/bln)")
2124
  if dev["obj3d_slowest_div"]:
2125
- summary_parts.append(f"divisi {dev['obj3d_slowest_div'][0]} ({dev['obj3d_slowest_div'][1]} hari)")
2126
  if dev["obj3b_slowest_executor"]:
2127
- summary_parts.append(f"eksekutor {dev['obj3b_slowest_executor'][0]} ({dev['obj3b_slowest_executor'][1]} hari)")
2128
 
2129
- if summary_parts:
2130
- joined = "; ".join(summary_parts)
2131
  insight_lines.append(
2132
- "2. Sistem mendeteksi *agency-capacity mismatch*: "
2133
- f"<strong>{joined}</strong>. "
2134
- "Ini menunjukkan ketidakseimbangan antara kapasitas pelaporan dan kapasitas resolusi — dua dimensi kritis dalam ekosistem *agentic safety*."
2135
  )
2136
 
2137
- # 2a–2d: detail
2138
- if dev["obj3a_lowest_div"]:
2139
- name, val = dev["obj3a_lowest_div"]
2140
- insight_lines.append(f" 2a. Divisi <strong>{name}</strong> memiliki rasio temuan/orang terendah ({val}), indikasi *low agency* atau *high reporting barrier*.")
2141
-
2142
- if dev["obj3b_slowest_executor"]:
2143
- name, days = dev["obj3b_slowest_executor"]
2144
- insight_lines.append(f" 2b. Eksekutor <strong>{name}</strong> memiliki lead time resolusi tertinggi ({days} hari), berisiko menjadi *bottleneck agent* dalam alur penutupan.")
2145
-
2146
- if dev["obj3c_lowest_reporter"]:
2147
- name, rate = dev["obj3c_lowest_reporter"]
2148
- insight_lines.append(f" 2c. Reporter <strong>{name}</strong> memiliki frekuensi pelaporan terendah ({rate}/bulan), perlu *capacity uplift* melalui *nudge* atau *coaching*.")
2149
-
2150
- if dev["obj3d_slowest_div"]:
2151
- name, days = dev["obj3d_slowest_div"]
2152
- insight_lines.append(f" 2d. Divisi <strong>{name}</strong> memiliki lead time rata-rata tertinggi ({days} hari), menunjukkan *systemic delay* dalam *execution loop*.")
2153
-
2154
  # 3. Komposisi non-Positive
2155
  uc, ua, nm = dev["obj4_unsafe_condition_pct"], dev["obj4_unsafe_action_pct"], dev["obj4_near_miss_pct"]
2156
  if uc + ua + nm > 0:
2157
- insight_lines.append(f"3. Komposisi non-Positive: Unsafe Condition ({uc}%), Unsafe Action ({ua}%), Near Miss ({nm}%). Proporsi Near Miss masih rendah — indikasi *under-reporting of close calls*.")
 
 
 
2158
 
2159
  # 4. Kuadran risiko
2160
  if dev["obj5_q1_divs"] or dev["obj5_q2_divs"]:
2161
  q1 = ", ".join([f"<strong>{d}</strong>" for d in dev["obj5_q1_divs"][:3]])
2162
  q2 = ", ".join([f"<strong>{d}</strong>" for d in dev["obj5_q2_divs"][:3]])
2163
- insight_lines.append(f"4. Divisi risiko tinggi (Kuadran I): {q1 if q1 else ''}. Divisi risiko tersembunyi (Kuadran II): {q2 if q2 else '—'}.")
 
 
2164
 
2165
  # 5. Top 2 kategori
2166
  if dev["obj6_top2_categories"]:
@@ -2169,77 +2150,51 @@ if dev["obj6_top2_categories"]:
2169
 
2170
  insight_text = "<br>".join(insight_lines)
2171
 
2172
- # 🔔 REKOMENDASI AGENTIC AI STYLE (per poin, actionable, closed-loop)
2173
  recs = []
2174
 
2175
- # 1 → 9 lokasi terendah
2176
  if dev["lowest_ratio_9_locs"]:
2177
  recs.append({
2178
  "point": "1",
2179
- "rec": "Luncurkan *Agency Activation Sprint* di 9 lokasi terendah: PIC Area wajib lakukan 1 inspeksi spot/minggu dan catat dalam sistem.",
2180
- "mit": "Aktifkan *QR code checklist* 3-menit + notifikasi WhatsApp otomatis setiap Senin. Target: rasio ≥0.5 dalam 45 hari."
2181
  })
2182
 
2183
- # 2 → summary agentic
2184
- if summary_parts:
2185
  recs.append({
2186
  "point": "2",
2187
- "rec": "Integrasikan *Agentic Capacity Dashboard*: real-time monitoring rasio & lead time per individu/divisi. Jika deviasi >20% dari baseline → picu *auto-coaching alert*.",
2188
- "mit": "Sistem akan mengirim notifikasi ke PIC Area & Safety Manager, disertai rekomendasi tindakan berbasis best practice dari division benchmark (misal: divisi dengan rasio ~1.0)."
2189
- })
2190
-
2191
- # 2a–2d → rekomendasi individual
2192
- if dev["obj3a_lowest_div"]:
2193
- recs.append({
2194
- "point": "2a",
2195
- "rec": "Assign *Safety Buddy* dari divisi berkinerja tinggi ke divisi terendah untuk 2 minggu *shadowing & transfer knowledge*.",
2196
- "mit": "Integrasikan *micro-reporting goal*: 1 temuan/minggu/orang. Sistem otomatis lacak progres & kirim apresiasi digital tiap goal tercapai."
2197
- })
2198
- if dev["obj3b_slowest_executor"]:
2199
- recs.append({
2200
- "point": "2b",
2201
- "rec": "Aktifkan *Rapid Closure Protocol* untuk eksekutor terlambat: verifikasi via foto + approval satu tingkat → target ≤3 hari.",
2202
- "mit": "Jika >5 hari, sistem auto-escalate ke Daily Safety Huddle & PIC Area via Telegram."
2203
- })
2204
- if dev["obj3c_lowest_reporter"]:
2205
- recs.append({
2206
- "point": "2c",
2207
- "rec": "Terapkan *Nudge Agent Program*: PIC lokasi bertanggung jawab memastikan semua anggota tim minimal 1x inspeksi/minggu.",
2208
- "mit": "Reward: point redeemable di kantin. Sistem kirim reminder 2x/minggu + contoh temuan sederhana (e.g., APD tidak lengkap)."
2209
- })
2210
- if dev["obj3d_slowest_div"]:
2211
- recs.append({
2212
- "point": "2d",
2213
- "rec": "Lakukan *Process Mining*: petakan alur temuan dari buka → tutup, identifikasi *waste* (waiting, rework, approval bottleneck).",
2214
- "mit": "Terapkan SLA berlapis: High Risk ≤3 hari, Medium/Low ≤7 hari. Jika breach ≥2x/bulan → picu *capacity intervention* otomatis."
2215
  })
2216
 
2217
- # 3 → Near Miss
2218
  if uc + ua + nm > 0:
2219
  recs.append({
2220
  "point": "3",
2221
- "rec": "Luncurkan *Near Miss Amplifier*: setiap laporan Unsafe Condition wajib diikuti minimal 1 Near Miss terkait.",
2222
- "mit": "Sistem blokir submit jika tidak memenuhi. Tampilkan *Near Miss Leaderboard* di dashboard tim."
2223
  })
2224
 
2225
- # 4 → Kuadran
2226
  if dev["obj5_q1_divs"] or dev["obj5_q2_divs"]:
2227
  recs.append({
2228
  "point": "4",
2229
- "rec": "Alokasikan *dedicated safety crew* untuk Kuadran I; terapkan *One Finding, One Day* untuk Kuadran II.",
2230
- "mit": "Jika masuk Kuadran I/II ≥2 bulan berturut-turut → sistem auto-generate *executive escalation report* ke VP Operasi."
2231
  })
2232
 
2233
- # 5 → Top 2 kategori
2234
  if dev["obj6_top2_categories"]:
2235
  c1, c2 = dev["obj6_top2_categories"]
2236
  recs.append({
2237
  "point": "5",
2238
- "rec": f"Bentuk *RCA Task Force* lintas fungsi (SIPIL, ELEKTRIKAL, K3, Kontraktor) untuk {c1[0]} & {c2[0]}.",
2239
  "mit": "Revisi spesifikasi teknis & template tender: semua penawaran wajib menyertakan mitigasi berbasis temuan historis."
2240
  })
2241
 
2242
- # 🖼️ TAMPILKAN
2243
  st.markdown(
2244
  f"""
2245
  <div class="card" style="
 
1981
  else:
1982
  st.info("No data available for non-positive issue categories with 100% coverage and positive trend.")
1983
  # =================== OBJECTIVE 7 — Insight and Recommendation (Agentic AI LLM Style — Final) ===================
1984
+ # =================== OBJECTIVE 7 — Insight and Recommendation (Final — Agentic AI, No markdown bold) ===================
1985
  st.markdown("<h3 class='section-title'>OBJECTIVE 7 — Insight and Recommendation</h3>", unsafe_allow_html=True)
1986
 
1987
+ def extract_agentic_insights_v5(df: pd.DataFrame):
1988
  dev = {
 
1989
  "lowest_ratio_9_locs": [],
 
1990
  "obj3a_lowest_div": None,
1991
  "obj3b_slowest_executor": None,
1992
  "obj3c_lowest_reporter": None,
1993
  "obj3d_slowest_div": None,
 
1994
  "obj4_unsafe_condition_pct": 0.0,
1995
  "obj4_unsafe_action_pct": 0.0,
1996
  "obj4_near_miss_pct": 0.0,
 
1997
  "obj5_q1_divs": [],
1998
  "obj5_q2_divs": [],
 
1999
  "obj6_top2_categories": [],
2000
  }
2001
 
 
2087
  elif r['Finding Count'] < X_LIMIT and r['Avg Lead Time'] >= Y_LIMIT:
2088
  dev["obj5_q2_divs"].append(r['nama'])
2089
 
2090
+ # === 5. Top 2 non-Positive category ===
2091
  if {'kategori', 'temuan_kategori', 'created_at'}.issubset(df.columns):
2092
  nonpos = df[df['temuan_kategori'] != 'Positive']
2093
  if not nonpos.empty:
 
2099
 
2100
  return dev
2101
 
2102
+ dev = extract_agentic_insights_v5(df_filtered)
 
2103
 
2104
+ # === INSIGHT BUILD ===
2105
  insight_lines = []
2106
 
2107
+ # 1. 9 lokasi terendah (semua)
2108
  if dev["lowest_ratio_9_locs"]:
2109
  loc_list = ", ".join([f"<strong>{loc}</strong> ({ratio})" for loc, ratio in dev["lowest_ratio_9_locs"]])
2110
+ insight_lines.append(f"1. Sembilan lokasi dengan rasio temuan/orang <em>terendah</em> (<0.5): {loc_list}.")
2111
 
2112
+ # 2. Gabungan 2a–2d satu insight agentic AI
2113
+ parts = []
 
2114
  if dev["obj3a_lowest_div"]:
2115
+ parts.append(f"divisi <strong>{dev['obj3a_lowest_div'][0]}</strong> (rasio {dev['obj3a_lowest_div'][1]})")
2116
  if dev["obj3c_lowest_reporter"]:
2117
+ parts.append(f"reporter <strong>{dev['obj3c_lowest_reporter'][0]}</strong> ({dev['obj3c_lowest_reporter'][1]}/bln)")
2118
  if dev["obj3d_slowest_div"]:
2119
+ parts.append(f"divisi <strong>{dev['obj3d_slowest_div'][0]}</strong> ({dev['obj3d_slowest_div'][1]} hari)")
2120
  if dev["obj3b_slowest_executor"]:
2121
+ parts.append(f"eksekutor <strong>{dev['obj3b_slowest_executor'][0]}</strong> ({dev['obj3b_slowest_executor'][1]} hari)")
2122
 
2123
+ if parts:
2124
+ joined = "; ".join(parts)
2125
  insight_lines.append(
2126
+ f"2. Sistem mendeteksi <em>agency-capacity mismatch</em>: {joined}. "
2127
+ "Ini menunjukkan ketidakseimbangan antara kapasitas pelaporan dan kapasitas resolusi — dua pilar utama ekosistem <em>agentic safety</em>."
 
2128
  )
2129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2130
  # 3. Komposisi non-Positive
2131
  uc, ua, nm = dev["obj4_unsafe_condition_pct"], dev["obj4_unsafe_action_pct"], dev["obj4_near_miss_pct"]
2132
  if uc + ua + nm > 0:
2133
+ insight_lines.append(
2134
+ f"3. Komposisi non-Positive: Unsafe Condition ({uc}%), Unsafe Action ({ua}%), Near Miss ({nm}%). "
2135
+ "Proporsi Near Miss masih rendah — indikasi <em>under-reporting of close calls</em>."
2136
+ )
2137
 
2138
  # 4. Kuadran risiko
2139
  if dev["obj5_q1_divs"] or dev["obj5_q2_divs"]:
2140
  q1 = ", ".join([f"<strong>{d}</strong>" for d in dev["obj5_q1_divs"][:3]])
2141
  q2 = ", ".join([f"<strong>{d}</strong>" for d in dev["obj5_q2_divs"][:3]])
2142
+ q1_str = q1 if q1 else "—"
2143
+ q2_str = q2 if q2 else "—"
2144
+ insight_lines.append(f"4. Divisi risiko tinggi (Kuadran I): {q1_str}. Divisi risiko tersembunyi (Kuadran II): {q2_str}.")
2145
 
2146
  # 5. Top 2 kategori
2147
  if dev["obj6_top2_categories"]:
 
2150
 
2151
  insight_text = "<br>".join(insight_lines)
2152
 
2153
+ # === REKOMENDASI & MITIGASI (Agentic AI Style) ===
2154
  recs = []
2155
 
2156
+ # 1
2157
  if dev["lowest_ratio_9_locs"]:
2158
  recs.append({
2159
  "point": "1",
2160
+ "rec": "Luncurkan <em>Agency Activation Sprint</em> di 9 lokasi terendah: PIC Area wajib lakukan 1 inspeksi spot/minggu.",
2161
+ "mit": "Aktifkan QR code checklist 3-menit + notifikasi WhatsApp otomatis. Target: rasio ≥0.5 dalam 45 hari."
2162
  })
2163
 
2164
+ # 2 → gabungan 2a–2d
2165
+ if parts:
2166
  recs.append({
2167
  "point": "2",
2168
+ "rec": "Aktifkan <em>Agentic Capacity Dashboard</em>: monitor rasio & lead time per individu/divisi secara real-time.",
2169
+ "mit": "Jika deviasi >20% dari baseline → picu <em>auto-coaching alert</em> ke PIC Area & Safety Manager, disertai best practice dari division benchmark."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2170
  })
2171
 
2172
+ # 3
2173
  if uc + ua + nm > 0:
2174
  recs.append({
2175
  "point": "3",
2176
+ "rec": "Luncurkan <em>Near Miss Amplifier</em>: setiap laporan Unsafe Condition wajib diikuti 1 Near Miss terkait.",
2177
+ "mit": "Sistem blokir submit jika tidak memenuhi. Tampilkan <em>Near Miss Leaderboard</em> di dashboard tim."
2178
  })
2179
 
2180
+ # 4
2181
  if dev["obj5_q1_divs"] or dev["obj5_q2_divs"]:
2182
  recs.append({
2183
  "point": "4",
2184
+ "rec": "Alokasikan <em>dedicated safety crew</em> untuk Kuadran I; terapkan <em>One Finding, One Day</em> untuk Kuadran II.",
2185
+ "mit": "Jika masuk Kuadran I/II ≥2 bulan berturut-turut → sistem auto-generate <em>executive escalation report</em> ke VP Operasi."
2186
  })
2187
 
2188
+ # 5
2189
  if dev["obj6_top2_categories"]:
2190
  c1, c2 = dev["obj6_top2_categories"]
2191
  recs.append({
2192
  "point": "5",
2193
+ "rec": f"Bentuk <em>RCA Task Force</em> lintas fungsi (SIPIL, ELEKTRIKAL, K3, Kontraktor) untuk {c1[0]} & {c2[0]}.",
2194
  "mit": "Revisi spesifikasi teknis & template tender: semua penawaran wajib menyertakan mitigasi berbasis temuan historis."
2195
  })
2196
 
2197
+ # === TAMPILKAN ===
2198
  st.markdown(
2199
  f"""
2200
  <div class="card" style="