Spaces:
Paused
Paused
Create dispute_module.py
Browse files- 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
|