ml-visoft commited on
Commit
fb3f5ce
·
1 Parent(s): 3555ea7

Added a stub for logging and long term storage.

Browse files
Files changed (3) hide show
  1. main.py +64 -6
  2. requirements.txt +2 -1
  3. 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
- # The database. In memory bc it is efemerial on HF anyway.
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 = "/data/sessions_meta.db"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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=0):
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
+