Skip to content

Commit 31e0e16

Browse files
committed
feat: moved configuration params into answer
1 parent 1b77b39 commit 31e0e16

4 files changed

Lines changed: 159 additions & 119 deletions

File tree

evaluation_function/evaluation.py

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -622,20 +622,54 @@ def _ok() -> Result:
622622
def _err(msg: str) -> Result:
623623
return Result(is_correct=False, feedback_items=[("error", msg)])
624624

625-
# ── parse params FIRST — directed/weighted/multigraph live here ─────
625+
# ── parse answer FIRST — evaluation_type and graph flags now live here ─────
626+
627+
answer_dict = _to_dictish(answer) or {}
628+
629+
if is_frontend_format(answer_dict):
630+
parsed_graph = parse_frontend_graph(answer_dict)
631+
answer_dict = {"graph": parsed_graph.model_dump()}
626632

627-
raw_params = _to_dictish(params) or {}
628633
try:
629-
p = EvaluationParams.model_validate(raw_params)
634+
ans = Answer.model_validate(answer_dict)
630635
except ValidationError as e:
631-
return _err(
632-
"Invalid params schema. Expected e.g. "
633-
"{'evaluation_type': 'connectivity'|'bipartite'|'graph_coloring'|...}. "
634-
f"Error: {e}"
635-
f"response: {response}"
636-
f"answer: {answer}"
637-
f"params: {params}"
638-
)
636+
return _err(f"Invalid answer schema: {e}")
637+
638+
# ── extract evaluation params from answer ─────────────────────────────
639+
# All evaluation configuration now comes from the answer object
640+
641+
eval_params_dict = {}
642+
643+
# Get evaluation_type from answer (required)
644+
if ans.evaluation_type:
645+
eval_params_dict['evaluation_type'] = ans.evaluation_type
646+
elif 'evaluation_type' in answer_dict:
647+
eval_params_dict['evaluation_type'] = answer_dict['evaluation_type']
648+
else:
649+
return _err("evaluation_type is required in answer object")
650+
651+
# Get graph structure flags from answer (with defaults)
652+
eval_params_dict['directed'] = ans.directed if ans.directed is not None else False
653+
eval_params_dict['weighted'] = ans.weighted if ans.weighted is not None else False
654+
eval_params_dict['multigraph'] = ans.multigraph if ans.multigraph is not None else False
655+
656+
# Get optional evaluation sub-params from answer
657+
for key in ['connectivity', 'bipartite', 'graph_coloring', 'cycle_detection',
658+
'isomorphism', 'feedback_level', 'tolerance']:
659+
value = getattr(ans, key, None)
660+
if value is not None:
661+
eval_params_dict[key] = value
662+
663+
# Set defaults for feedback_level and tolerance if not provided
664+
if 'feedback_level' not in eval_params_dict:
665+
eval_params_dict['feedback_level'] = 'standard'
666+
if 'tolerance' not in eval_params_dict:
667+
eval_params_dict['tolerance'] = 1e-9
668+
669+
try:
670+
p = EvaluationParams.model_validate(eval_params_dict)
671+
except ValidationError as e:
672+
return _err(f"Invalid evaluation parameters in answer: {e}")
639673

640674
# ── parse response (student's graph) ─────────────────────────────────
641675

@@ -650,22 +684,9 @@ def _err(msg: str) -> Result:
650684
except ValidationError as e:
651685
return _err(f"Invalid response schema: {e}")
652686

653-
# ── parse answer (teacher's reference) ───────────────────────────────
654-
655-
answer_dict = _to_dictish(answer) or {}
656-
657-
if is_frontend_format(answer_dict):
658-
parsed_graph = parse_frontend_graph(answer_dict)
659-
answer_dict = {"graph": parsed_graph.model_dump()}
660-
661-
try:
662-
ans = Answer.model_validate(answer_dict)
663-
except ValidationError as e:
664-
return _err(f"Invalid answer schema: {e}")
665-
666687
# ── resolve graphs and stamp params flags ─────────────────────────────
667-
# directed/weighted/multigraph come exclusively from params — never from
668-
# the student or teacher payload.
688+
# directed/weighted/multigraph come exclusively from answer object — never from
689+
# the student response payload.
669690

670691
student_graph: Graph = resp.graph
671692
if student_graph is None:

evaluation_function/schemas/params.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class TraversalParams(BaseModel):
7575
class EvaluationParams(BaseModel):
7676
evaluation_type: EvaluationType = Field(..., description="The type of evaluation to perform")
7777

78-
# Graph structure flags — sourced from params, not from the response/answer graph payload
78+
# Graph structure flags — now sourced from the answer object, not from params
7979
directed: bool = Field(False, description="Whether the graph is directed")
8080
weighted: bool = Field(False, description="Whether the graph is weighted")
8181
multigraph: bool = Field(False, description="Whether the graph allows multiple edges")

evaluation_function/schemas/request.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
Request/Response Schemas
33
"""
44

5-
from typing import Optional
5+
from typing import Optional, Literal
66
from pydantic import BaseModel, Field
77

88
from .graph import Graph
9+
from .evaluation_types import EvaluationType
910

1011

1112
class Response(BaseModel):
@@ -34,6 +35,24 @@ class Config:
3435

3536

3637
class Answer(BaseModel):
38+
# Evaluation configuration (moved from params)
39+
evaluation_type: Optional[EvaluationType] = Field(None, description="The type of evaluation to perform")
40+
directed: Optional[bool] = Field(None, description="Whether the graph is directed")
41+
weighted: Optional[bool] = Field(None, description="Whether the graph is weighted")
42+
multigraph: Optional[bool] = Field(None, description="Whether the graph allows multiple edges")
43+
44+
# Optional evaluation sub-params
45+
connectivity: Optional[dict] = Field(None, description="Connectivity evaluation parameters")
46+
bipartite: Optional[dict] = Field(None, description="Bipartite evaluation parameters")
47+
graph_coloring: Optional[dict] = Field(None, description="Graph coloring evaluation parameters")
48+
cycle_detection: Optional[dict] = Field(None, description="Cycle detection parameters")
49+
isomorphism: Optional[dict] = Field(None, description="Isomorphism evaluation parameters")
50+
51+
# Global evaluation params
52+
feedback_level: Optional[Literal["minimal", "standard", "detailed"]] = Field(None, description="Level of detail in feedback")
53+
tolerance: Optional[float] = Field(None, description="Numerical tolerance for comparisons")
54+
55+
# Expected graph and answers
3756
graph: Optional[Graph] = Field(None, description="The expected/correct graph")
3857
is_connected: Optional[bool] = None
3958
is_bipartite: Optional[bool] = None

0 commit comments

Comments
 (0)