Spaces:
Sleeping
Sleeping
Added a stub for logging and long term storage.
Browse files- main.py +64 -6
- requirements.txt +2 -1
- storage.py +12 -0
main.py
CHANGED
@@ -2,12 +2,17 @@ import json
|
|
2 |
import uuid
|
3 |
import os
|
4 |
import pathlib
|
5 |
-
|
6 |
from datetime import datetime
|
|
|
|
|
7 |
from fasthtml.common import *
|
|
|
8 |
from sqlite_minutils.db import Database
|
|
|
9 |
|
10 |
import eval_code
|
|
|
11 |
|
12 |
# the secrets. Will be loaded from HF, or for docker --env-file or from IDE
|
13 |
|
@@ -15,16 +20,40 @@ OAUTH_CLIENT_ID = os.environ.get('OAUTH_CLIENT_ID')
|
|
15 |
OAUTH_SCOPES = os.environ.get('OAUTH_SCOPES')
|
16 |
OAUTH_CLIENT_SECRET = os.environ.get('OAUTH_CLIENT_SECRET')
|
17 |
OPENID_PROVIDER_URL = os.environ.get('OPENID_PROVIDER_URL')
|
18 |
-
SPACE_HOST = os.environ.get('SPACE_HOST')
|
|
|
|
|
|
|
19 |
|
20 |
-
|
21 |
|
|
|
22 |
|
23 |
if "localhost" in SPACE_HOST:
|
24 |
DATABASE_NAME = "data/sessions_meta.db"
|
|
|
25 |
pathlib.Path(DATABASE_NAME).unlink(missing_ok=True)
|
26 |
else:
|
27 |
-
DATABASE_NAME = "/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
global_database = Database(DATABASE_NAME)
|
30 |
global_database_tables = global_database.t
|
@@ -74,6 +103,19 @@ else:
|
|
74 |
REFRESH_TIME = 1
|
75 |
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
def vallidate_and_get_question_evaluation_objectid(session, qe_id:int):
|
78 |
if 'session_id' not in session: return None
|
79 |
session_id = session["session_id"]
|
@@ -93,7 +135,7 @@ def vallidate_and_get_question_evaluation_objectid(session, qe_id:int):
|
|
93 |
return True, qe_obj
|
94 |
|
95 |
|
96 |
-
def html_create_feedback_updown_button(qe_id, ans_id, selected=0, disabled=
|
97 |
html_target_id = f"buttons_{ans_id}"
|
98 |
colors = ["grey", "blue"]
|
99 |
up_col = colors[0]
|
@@ -151,6 +193,11 @@ def put(session, qe_id:int, ans_id:int, which:int):
|
|
151 |
if qe_id != qe_obj.id:
|
152 |
print(f"QE {qe_id} does not belong to {qe_obj.id}")
|
153 |
return None
|
|
|
|
|
|
|
|
|
|
|
154 |
answer_eval_js = json.loads(qe_obj.answer_eval_text)
|
155 |
crt_selection = answer_eval_js[ans_id]["EVAL"]
|
156 |
input_button = which
|
@@ -179,8 +226,12 @@ def html_get_textual_feedback_form(qe_obj, thank=False):
|
|
179 |
|
180 |
@rt("/submit_feedback/{qe_id}")
|
181 |
def post(session, qe_id:int, freeform_feedback:str):
|
182 |
-
print(qe_id, freeform_feedback)
|
183 |
# Update the object
|
|
|
|
|
|
|
|
|
|
|
184 |
is_ok, qe_obj = vallidate_and_get_question_evaluation_objectid(session, qe_id)
|
185 |
if not is_ok:
|
186 |
return "Error"
|
@@ -350,6 +401,9 @@ def get(session):
|
|
350 |
if 'session_id' not in session:
|
351 |
session['session_id'] = str(uuid.uuid4())
|
352 |
session_id = session["session_id"]
|
|
|
|
|
|
|
353 |
title = Title('C code review for students')
|
354 |
preamble = [H1("Evaluate your C code!"),
|
355 |
P("Enter your code in the textbox below and wait for answers."),
|
@@ -424,6 +478,10 @@ def post(ccodetoeval:str, session):
|
|
424 |
def get(session):
|
425 |
if 'session_id' not in session: return P("Bad call. No session ID")
|
426 |
session_id = session["session_id"]
|
|
|
|
|
|
|
|
|
427 |
# insert a row to "cancel"/reset the current request
|
428 |
session_obj = Session_State_cls(
|
429 |
session_id=session_id,
|
|
|
2 |
import uuid
|
3 |
import os
|
4 |
import pathlib
|
5 |
+
from uuid import uuid4
|
6 |
from datetime import datetime
|
7 |
+
import dataclasses
|
8 |
+
|
9 |
from fasthtml.common import *
|
10 |
+
from fastcore.all import typedispatch
|
11 |
from sqlite_minutils.db import Database
|
12 |
+
from huggingface_hub import CommitScheduler
|
13 |
|
14 |
import eval_code
|
15 |
+
import storage
|
16 |
|
17 |
# the secrets. Will be loaded from HF, or for docker --env-file or from IDE
|
18 |
|
|
|
20 |
OAUTH_SCOPES = os.environ.get('OAUTH_SCOPES')
|
21 |
OAUTH_CLIENT_SECRET = os.environ.get('OAUTH_CLIENT_SECRET')
|
22 |
OPENID_PROVIDER_URL = os.environ.get('OPENID_PROVIDER_URL')
|
23 |
+
SPACE_HOST = os.environ.get('SPACE_HOST', "none")
|
24 |
+
HF_DATASET_AUTH_TOKEN = os.environ.get('HF_DATASET_AUTH_TOKEN')
|
25 |
+
|
26 |
+
assert SPACE_HOST is not "none", "Please set the corrent ENV variables!!!"
|
27 |
|
28 |
+
LOCAL_STORAGE_PATH = ""
|
29 |
|
30 |
+
FILE_EVENTS = f"events-{datetime.utcnow()}-{uuid4()}.json"
|
31 |
|
32 |
if "localhost" in SPACE_HOST:
|
33 |
DATABASE_NAME = "data/sessions_meta.db"
|
34 |
+
LOCAL_STORAGE_PATH = Path("data/persistent/")
|
35 |
pathlib.Path(DATABASE_NAME).unlink(missing_ok=True)
|
36 |
else:
|
37 |
+
DATABASE_NAME = "/tmp/cache/sessions_meta.db"
|
38 |
+
LOCAL_STORAGE_PATH = Path("/tmp/cache/persistent")
|
39 |
+
|
40 |
+
|
41 |
+
LOCAL_STORAGE_PATH.mkdir(exist_ok=True, parents=True)
|
42 |
+
EVENTS_FILE_PATH = LOCAL_STORAGE_PATH / FILE_EVENTS
|
43 |
+
|
44 |
+
|
45 |
+
scheduler = CommitScheduler(
|
46 |
+
repo_id="ml-visoft/c-reviewer",
|
47 |
+
repo_type="dataset",
|
48 |
+
folder_path=LOCAL_STORAGE_PATH,
|
49 |
+
every=100,
|
50 |
+
path_in_repo="raw_data",
|
51 |
+
token=HF_DATASET_AUTH_TOKEN,
|
52 |
+
allow_patterns=".jslines",
|
53 |
+
squash_history=False
|
54 |
+
)
|
55 |
+
|
56 |
+
|
57 |
|
58 |
global_database = Database(DATABASE_NAME)
|
59 |
global_database_tables = global_database.t
|
|
|
103 |
REFRESH_TIME = 1
|
104 |
|
105 |
|
106 |
+
def untyped_save_to_storage(dc, filename):
|
107 |
+
with scheduler.lock:
|
108 |
+
js_str = json.dumps(dataclasses.asdict(dc)) + "\n"
|
109 |
+
with open(filename, "a") as f:
|
110 |
+
f.write(js_str)
|
111 |
+
|
112 |
+
|
113 |
+
@typedispatch
|
114 |
+
def save_to_storage(nav_event:storage.NavigationEvent):
|
115 |
+
untyped_save_to_storage(nav_event, EVENTS_FILE_PATH)
|
116 |
+
|
117 |
+
|
118 |
+
|
119 |
def vallidate_and_get_question_evaluation_objectid(session, qe_id:int):
|
120 |
if 'session_id' not in session: return None
|
121 |
session_id = session["session_id"]
|
|
|
135 |
return True, qe_obj
|
136 |
|
137 |
|
138 |
+
def html_create_feedback_updown_button(qe_id, ans_id, selected=0, disabled=False):
|
139 |
html_target_id = f"buttons_{ans_id}"
|
140 |
colors = ["grey", "blue"]
|
141 |
up_col = colors[0]
|
|
|
193 |
if qe_id != qe_obj.id:
|
194 |
print(f"QE {qe_id} does not belong to {qe_obj.id}")
|
195 |
return None
|
196 |
+
|
197 |
+
# save_to_storage(
|
198 |
+
# storage.NavigationEvent(event_type="/", event_session_id=session_id, event_params={"qe_id":qe_id})
|
199 |
+
# )
|
200 |
+
|
201 |
answer_eval_js = json.loads(qe_obj.answer_eval_text)
|
202 |
crt_selection = answer_eval_js[ans_id]["EVAL"]
|
203 |
input_button = which
|
|
|
226 |
|
227 |
@rt("/submit_feedback/{qe_id}")
|
228 |
def post(session, qe_id:int, freeform_feedback:str):
|
|
|
229 |
# Update the object
|
230 |
+
session_id = session.get("session_id", "Not set")
|
231 |
+
save_to_storage(
|
232 |
+
storage.NavigationEvent(event_type="/submit_feedback", event_session_id=session_id,
|
233 |
+
event_params={"qe_id":qe_id})
|
234 |
+
)
|
235 |
is_ok, qe_obj = vallidate_and_get_question_evaluation_objectid(session, qe_id)
|
236 |
if not is_ok:
|
237 |
return "Error"
|
|
|
401 |
if 'session_id' not in session:
|
402 |
session['session_id'] = str(uuid.uuid4())
|
403 |
session_id = session["session_id"]
|
404 |
+
save_to_storage(
|
405 |
+
storage.NavigationEvent(event_type="/", event_session_id=session_id)
|
406 |
+
)
|
407 |
title = Title('C code review for students')
|
408 |
preamble = [H1("Evaluate your C code!"),
|
409 |
P("Enter your code in the textbox below and wait for answers."),
|
|
|
478 |
def get(session):
|
479 |
if 'session_id' not in session: return P("Bad call. No session ID")
|
480 |
session_id = session["session_id"]
|
481 |
+
save_to_storage(
|
482 |
+
storage.NavigationEvent(event_type="/clear_area", event_session_id=session_id)
|
483 |
+
)
|
484 |
+
|
485 |
# insert a row to "cancel"/reset the current request
|
486 |
session_obj = Session_State_cls(
|
487 |
session_id=session_id,
|
requirements.txt
CHANGED
@@ -1,2 +1,3 @@
|
|
1 |
python-fasthtml
|
2 |
-
fastsql==1.0.1
|
|
|
|
1 |
python-fasthtml
|
2 |
+
fastsql==1.0.1
|
3 |
+
huggingface_hub==-0.24.5
|
storage.py
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import dataclasses
|
2 |
+
from datetime import datetime
|
3 |
+
|
4 |
+
|
5 |
+
@dataclasses.dataclass(slots=True)
|
6 |
+
class NavigationEvent():
|
7 |
+
version:int = 1
|
8 |
+
event_type:str = '(none)'
|
9 |
+
event_date:str = datetime.isoformat(datetime.utcnow())
|
10 |
+
event_session_id:str = ""
|
11 |
+
event_params:dict=dataclasses.field(default_factory=dict)
|
12 |
+
|