Skip to content

Commit 947e45d

Browse files
author
RabidSheep55
committed
add rich feedback handling
1 parent 2ff2b1e commit 947e45d

File tree

1 file changed

+95
-9
lines changed

1 file changed

+95
-9
lines changed

handler.py

Lines changed: 95 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,12 @@ def handle_eval_command(event):
5151
if request_error:
5252
return {"error": request_error}
5353

54-
try:
55-
response = body["response"]
56-
answer = body["answer"]
57-
58-
params = body.get("params", dict())
54+
response = body["response"]
55+
answer = body["answer"]
56+
params = body.get("params", dict())
5957

60-
return {
61-
"command": "eval",
62-
"result": evaluation_function(response, answer, params)
63-
}
58+
try:
59+
result = evaluation_function(response, answer, params)
6460

6561
# Catch the custom EvaluationException (from evaluation_function_utils) first
6662
except EvaluationException as e:
@@ -75,6 +71,96 @@ def handle_eval_command(event):
7571
}
7672
}
7773

74+
# Result already contains feedback generated inside the custom function
75+
if "feedback" in result:
76+
return {"command": "eval", "result": result}
77+
78+
# If a list of "cases" wasn't provided, we don't have any other way to get feedback
79+
cases = params.get("cases", [])
80+
if len(cases) == 0:
81+
return {"command": "eval", "result": result}
82+
83+
# Determine what feedback to provide based on cases
84+
feedback, warnings = feedback_from_cases(response, params, cases)
85+
if feedback:
86+
result["feedback"] = feedback
87+
88+
# Add warnings out output if any were encountered
89+
if len(warnings) != 0:
90+
result["warnings"] = warnings
91+
92+
return {"command": "eval", "result": result}
93+
94+
95+
def feedback_from_cases(response, params, cases):
96+
"""
97+
Attempt to find the correct feedback from a list of cases.
98+
Returns a "feedback" string, and optional list of warnings
99+
"""
100+
101+
# A list of "cases" was provided, try matching to each of them
102+
matches = []
103+
warnings = []
104+
for i, case in enumerate(cases):
105+
# Validate the case block has an answer and feedback
106+
if 'answer' not in case:
107+
warnings += [{"case": i, "message": "Missing answer field"}]
108+
continue
109+
110+
if 'feedback' not in case:
111+
warnings += [{"case": i, "message": "Missing feedback field"}]
112+
continue
113+
114+
# Merge current evaluation params with any specified in case
115+
case_params = case.get('params', {})
116+
117+
# Run the evaluation function based on this case's answer
118+
try:
119+
res = evaluation_function(response, case.get('answer'), {
120+
**params,
121+
**case_params
122+
})
123+
124+
except EvaluationException as e:
125+
warnings += [{"case": i, **e.error_dict}]
126+
continue
127+
128+
except Exception as e:
129+
warnings += [{
130+
"case": i,
131+
"message":
132+
"An exception was raised while executing the evaluation function.",
133+
"detail": str(e) if str(e) != "" else repr(e)
134+
}]
135+
continue
136+
137+
# Function should always return an 'is_correct' if no errors were raised
138+
if not 'is_correct' in res:
139+
warnings += [{
140+
"case": i,
141+
"message": "is_correct missing from function output"
142+
}]
143+
continue
144+
145+
# This case matches the response, add it's index to the list of matches
146+
if res.get('is_correct') == True:
147+
matches += [i]
148+
149+
if len(matches) == 0:
150+
return '', warnings
151+
152+
if len(matches) == 1:
153+
# warnings += [{"case": matches[0]}]
154+
return cases[matches[0]]['feedback'], warnings
155+
156+
else:
157+
s = ', '.join([str(m) for m in matches])
158+
warnings += [{
159+
"message":
160+
f"Cases {s} were matched. Only the first one's feedback was returned"
161+
}]
162+
return cases[matches[0]]['feedback'], warnings
163+
78164

79165
"""
80166
Main Handler Function

0 commit comments

Comments
 (0)