lmcuong199 commited on
Commit
06f00a7
Β·
verified Β·
1 Parent(s): 08aaa9e

Create dispute_module.py

Browse files
Files changed (1) hide show
  1. dispute_module.py +147 -0
dispute_module.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Disclaimer + Right to Reply / Dispute module
2
+ # Mα»₯c Δ‘Γ­ch: Δ‘αΊ£m bαΊ£o tΓ­nh cΓ΄ng bαΊ±ng vΓ  minh bαΊ‘ch cα»§a hệ thα»‘ng
3
+
4
+ DISCLAIMER = """
5
+ ---
6
+ > ⚠️ **Disclaimer:** Results are generated by AI based on publicly available data
7
+ > (visitor reviews, inspection reports, site metadata). EcoVerify AI does not
8
+ > guarantee the absolute accuracy of third-party source data. Risk scores are
9
+ > indicative only and should be used alongside official inspection processes.
10
+ > This tool supports β€” but does not replace β€” formal certification audits.
11
+ ---
12
+ """
13
+
14
+ def get_disclaimer() -> str:
15
+ return DISCLAIMER
16
+
17
+
18
+ def process_dispute(
19
+ site_name: str,
20
+ dispute_reason: str,
21
+ evidence_text: str,
22
+ evidence_image,
23
+ current_nlp_risk: float,
24
+ current_img_risk: float,
25
+ ) -> tuple[str, float, float]:
26
+ """
27
+ Xα»­ lΓ½ dispute tα»« operator.
28
+ - PhΓ’n tΓ­ch evidence_text bαΊ±ng NLP
29
+ - PhΓ’n tΓ­ch evidence_image nαΊΏu cΓ³
30
+ - Điều chỉnh risk score nαΊΏu evidence hợp lệ
31
+ """
32
+
33
+ if not dispute_reason.strip() and not evidence_text.strip():
34
+ return "⚠️ Please provide a reason and/or evidence to submit a dispute.", current_nlp_risk, current_img_risk
35
+
36
+ adjustments = []
37
+ new_nlp_risk = current_nlp_risk
38
+ new_img_risk = current_img_risk
39
+
40
+ # ── PhΓ’n tΓ­ch evidence text ───────────────────────────────────────
41
+ if evidence_text.strip():
42
+ from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
43
+ analyzer = SentimentIntensityAnalyzer()
44
+
45
+ POSITIVE_EVIDENCE = [
46
+ "installed", "improved", "upgraded", "certified", "trained",
47
+ "composting", "recycling", "reduced", "clean", "sorted",
48
+ "hired", "contracted", "fixed", "resolved", "invested",
49
+ "new bins", "waste system", "collection", "audit", "inspection passed"
50
+ ]
51
+
52
+ evidence_lower = evidence_text.lower()
53
+ sentiment = analyzer.polarity_scores(evidence_text)['compound']
54
+ hits = [w for w in POSITIVE_EVIDENCE if w in evidence_lower]
55
+
56
+ # TΓ­nh mα»©c Δ‘iều chỉnh
57
+ text_adjustment = 0.0
58
+ if sentiment > 0.3:
59
+ text_adjustment += 0.08
60
+ if len(hits) >= 3:
61
+ text_adjustment += 0.10
62
+ elif len(hits) >= 1:
63
+ text_adjustment += 0.05
64
+
65
+ if text_adjustment > 0:
66
+ new_nlp_risk = round(max(0.0, current_nlp_risk - text_adjustment), 3)
67
+ adjustments.append(
68
+ f"βœ… Evidence text accepted β€” NLP risk reduced by {text_adjustment:.2f} "
69
+ f"(keywords found: {', '.join(hits[:5])})"
70
+ )
71
+ else:
72
+ adjustments.append("⚠️ Evidence text did not contain sufficient positive indicators.")
73
+
74
+ # ── PhΓ’n tΓ­ch evidence image ──────────────────────────────────────
75
+ if evidence_image is not None:
76
+ try:
77
+ from image_module import analyze_image
78
+ from PIL import Image
79
+ import numpy as np
80
+
81
+ img_output, new_evidence_risk = analyze_image(evidence_image)
82
+
83
+ if new_evidence_risk < current_img_risk:
84
+ reduction = round(current_img_risk - new_evidence_risk, 3)
85
+ new_img_risk = new_evidence_risk
86
+ adjustments.append(
87
+ f"βœ… Evidence image accepted β€” Image risk reduced by {reduction:.3f} "
88
+ f"(new image risk: {new_evidence_risk:.3f})"
89
+ )
90
+ else:
91
+ adjustments.append(
92
+ f"⚠️ Evidence image did not show improvement over original "
93
+ f"(image risk: {new_evidence_risk:.3f} vs original: {current_img_risk:.3f})"
94
+ )
95
+ except Exception as e:
96
+ adjustments.append(f"⚠️ Could not analyze evidence image: {e}")
97
+
98
+ # ── TΓ­nh combined risk mα»›i ────────────────────────────────────────
99
+ new_combined = round((new_nlp_risk + new_img_risk) / 2, 3)
100
+ old_combined = round((current_nlp_risk + current_img_risk) / 2, 3)
101
+ delta = round(old_combined - new_combined, 3)
102
+
103
+ if delta > 0:
104
+ verdict = f"βœ… Dispute accepted β€” risk score updated"
105
+ color = "improved"
106
+ else:
107
+ verdict = "ℹ️ Dispute noted β€” insufficient evidence to update score"
108
+ color = "unchanged"
109
+
110
+ adj_str = "\n".join(adjustments)
111
+
112
+ output = f"""## 🏳️ Dispute / Right to Reply β€” {site_name}
113
+
114
+ ### {verdict}
115
+
116
+ ---
117
+
118
+ ### πŸ“‹ Dispute Summary
119
+ | Field | Value |
120
+ |-------|-------|
121
+ | Reason submitted | {dispute_reason[:100] if dispute_reason else "Not provided"} |
122
+ | Evidence text | {"Provided βœ…" if evidence_text.strip() else "Not provided"} |
123
+ | Evidence image | {"Provided βœ…" if evidence_image is not None else "Not provided"} |
124
+
125
+ ---
126
+
127
+ ### πŸ” AI Review of Evidence
128
+ {adj_str}
129
+
130
+ ---
131
+
132
+ ### πŸ“Š Score Update
133
+ | Metric | Before | After | Change |
134
+ |--------|--------|-------|--------|
135
+ | NLP Risk | {current_nlp_risk:.3f} | {new_nlp_risk:.3f} | {"↓ " + str(round((current_nlp_risk - new_nlp_risk)*100)) + "%" if new_nlp_risk < current_nlp_risk else "β€”"} |
136
+ | Image Risk | {current_img_risk:.3f} | {new_img_risk:.3f} | {"↓ " + str(round((current_img_risk - new_img_risk)*100)) + "%" if new_img_risk < current_img_risk else "β€”"} |
137
+ | **Combined Risk** | **{old_combined:.3f}** | **{new_combined:.3f}** | **{"↓ " + str(delta) if delta > 0 else "No change"}** |
138
+
139
+ ---
140
+
141
+ {DISCLAIMER}
142
+
143
+ > πŸ’‘ **Note:** All disputes are logged for transparency. Updated scores reflect
144
+ > newly submitted evidence and do not erase original analysis. Both original
145
+ > and updated scores are retained in the final report.
146
+ """
147
+ return output, new_nlp_risk, new_img_risk