OUAREDAEK commited on
Commit
a71412e
Β·
verified Β·
1 Parent(s): 99952ca

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +179 -0
app.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ from datetime import datetime
4
+ from flask import Flask, request, jsonify, render_template
5
+
6
+ # ==================================================
7
+ # πŸ”’ FILE LOCK (PORTALOCKER IF AVAILABLE, ELSE FALLBACK)
8
+ # ==================================================
9
+ try:
10
+ import portalocker
11
+ USE_PORTALOCKER = True
12
+ except ImportError:
13
+ USE_PORTALOCKER = False
14
+ import threading
15
+ _GLOBAL_LOCK = threading.Lock()
16
+
17
+ def lock_file(f, exclusive=True):
18
+ if USE_PORTALOCKER:
19
+ portalocker.lock(
20
+ f,
21
+ portalocker.LOCK_EX if exclusive else portalocker.LOCK_SH
22
+ )
23
+ else:
24
+ _GLOBAL_LOCK.acquire()
25
+
26
+ def unlock_file(f):
27
+ if USE_PORTALOCKER:
28
+ portalocker.unlock(f)
29
+ else:
30
+ _GLOBAL_LOCK.release()
31
+
32
+ # ==================================================
33
+ # πŸ”’ SAFE JSON IO
34
+ # ==================================================
35
+ def read_json_safe(path, default):
36
+ if not os.path.exists(path):
37
+ return default
38
+
39
+ with open(path, "r", encoding="utf-8") as f:
40
+ lock_file(f, exclusive=False)
41
+ try:
42
+ return json.load(f)
43
+ finally:
44
+ unlock_file(f)
45
+
46
+ def write_json_safe(path, data):
47
+ with open(path, "w", encoding="utf-8") as f:
48
+ lock_file(f, exclusive=True)
49
+ try:
50
+ json.dump(data, f, indent=2, ensure_ascii=False)
51
+ finally:
52
+ unlock_file(f)
53
+
54
+ # ==================================================
55
+ # βš™οΈ CONFIGURATION
56
+ # ==================================================
57
+ PORT = int(os.environ.get("PORT", 7860))
58
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
59
+
60
+ DATA_DIR = os.path.join(BASE_DIR, "data")
61
+ TEMPLATES_DIR = os.path.join(BASE_DIR, "templates")
62
+
63
+ os.makedirs(DATA_DIR, exist_ok=True)
64
+ os.makedirs(TEMPLATES_DIR, exist_ok=True)
65
+
66
+ SCENARIOS_FILE = os.path.join(DATA_DIR, "scenarios.json")
67
+ STATS_FILE = os.path.join(DATA_DIR, "trust_stats.json")
68
+ REVIEWS_FILE = os.path.join(DATA_DIR, "reviews.json")
69
+ CALIBRATION_FILE = os.path.join(DATA_DIR, "calibration.json")
70
+
71
+ # ==================================================
72
+ # πŸš€ FLASK APP
73
+ # ==================================================
74
+ app = Flask(__name__, template_folder=TEMPLATES_DIR)
75
+
76
+ # ==================================================
77
+ # 🌐 HOME (INDEX.HTML)
78
+ # ==================================================
79
+ @app.route("/")
80
+ def index():
81
+ return render_template("index.html")
82
+
83
+ # ==================================================
84
+ # 🌍 GLOBAL SCENARIOS
85
+ # ==================================================
86
+ @app.route("/api/scenarios", methods=["GET", "POST"])
87
+ def scenarios():
88
+ if request.method == "POST":
89
+ scenario = request.json
90
+ scenario["created_at"] = datetime.now().isoformat()
91
+
92
+ data = read_json_safe(SCENARIOS_FILE, {"scenarios": []})
93
+ data["scenarios"].append(scenario)
94
+ write_json_safe(SCENARIOS_FILE, data)
95
+
96
+ return jsonify({"status": "ok"})
97
+
98
+ return jsonify(read_json_safe(SCENARIOS_FILE, {"scenarios": []}))
99
+
100
+ # ==================================================
101
+ # πŸ”§ TRUST CALIBRATION (GLOBAL)
102
+ # ==================================================
103
+ @app.route("/api/trust/calibration", methods=["GET", "POST"])
104
+ def calibration():
105
+ if request.method == "POST":
106
+ write_json_safe(CALIBRATION_FILE, request.json)
107
+ return jsonify({"status": "ok"})
108
+
109
+ return jsonify(read_json_safe(CALIBRATION_FILE, {}))
110
+
111
+ # ==================================================
112
+ # πŸ’Ύ TRUST EVALUATIONS
113
+ # ==================================================
114
+ @app.route("/api/trust", methods=["POST"])
115
+ def save_trust():
116
+ data = request.json
117
+
118
+ record = {
119
+ "scenario_id": data.get("scenario_id"),
120
+ "metrics": data.get("metrics", {}),
121
+ "score": data.get("score"),
122
+ "comment": data.get("comment"),
123
+ "timestamp": datetime.now().isoformat()
124
+ }
125
+
126
+ stats = read_json_safe(STATS_FILE, {"evaluations": []})
127
+ stats["evaluations"].append(record)
128
+ write_json_safe(STATS_FILE, stats)
129
+
130
+ return jsonify({"status": "ok"})
131
+
132
+ # ==================================================
133
+ # πŸ“ REVIEWS
134
+ # ==================================================
135
+ @app.route("/api/reviews", methods=["GET", "POST"])
136
+ def reviews():
137
+ if request.method == "POST":
138
+ review = request.json
139
+ review["timestamp"] = datetime.now().isoformat()
140
+
141
+ data = read_json_safe(REVIEWS_FILE, {"reviews": []})
142
+ data["reviews"].append(review)
143
+ write_json_safe(REVIEWS_FILE, data)
144
+
145
+ return jsonify({"status": "ok"})
146
+
147
+ return jsonify(read_json_safe(REVIEWS_FILE, {"reviews": []}))
148
+
149
+ # ==================================================
150
+ # 🏁 MAIN
151
+ # ==================================================
152
+ if __name__ == "__main__":
153
+
154
+ defaults = {
155
+ SCENARIOS_FILE: {"scenarios": []},
156
+ STATS_FILE: {"evaluations": []},
157
+ REVIEWS_FILE: {"reviews": []},
158
+ CALIBRATION_FILE: {
159
+ "metrics": {
160
+ "AR": {"min": 0, "max": 5, "weight": 1},
161
+ "AE": {"min": 0, "max": 5, "weight": 1},
162
+ "ESR": {"min": 0, "max": 5, "weight": 1},
163
+ "SDM": {"min": 0, "max": 5, "weight": 1},
164
+ "SM": {"min": 0, "max": 5, "weight": 1}
165
+ }
166
+ }
167
+ }
168
+
169
+ for path, content in defaults.items():
170
+ if not os.path.exists(path):
171
+ write_json_safe(path, content)
172
+
173
+ print(f"πŸš€ Application globale active : http://127.0.0.1:{PORT}")
174
+ app.run(
175
+ host="0.0.0.0",
176
+ port=PORT,
177
+ debug=True,
178
+ use_reloader=False # IMPORTANT pour Spyder
179
+ )