@@ -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