QuizGenerator 0.6.2__py3-none-any.whl → 0.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. QuizGenerator/contentast.py +2198 -2213
  2. QuizGenerator/misc.py +1 -1
  3. QuizGenerator/mixins.py +64 -64
  4. QuizGenerator/premade_questions/basic.py +16 -16
  5. QuizGenerator/premade_questions/cst334/languages.py +26 -26
  6. QuizGenerator/premade_questions/cst334/math_questions.py +42 -42
  7. QuizGenerator/premade_questions/cst334/memory_questions.py +124 -124
  8. QuizGenerator/premade_questions/cst334/persistence_questions.py +48 -48
  9. QuizGenerator/premade_questions/cst334/process.py +38 -38
  10. QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py +45 -45
  11. QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py +34 -34
  12. QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py +53 -53
  13. QuizGenerator/premade_questions/cst463/gradient_descent/misc.py +2 -2
  14. QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py +65 -65
  15. QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py +39 -39
  16. QuizGenerator/premade_questions/cst463/models/attention.py +36 -36
  17. QuizGenerator/premade_questions/cst463/models/cnns.py +26 -26
  18. QuizGenerator/premade_questions/cst463/models/rnns.py +36 -36
  19. QuizGenerator/premade_questions/cst463/models/text.py +32 -32
  20. QuizGenerator/premade_questions/cst463/models/weight_counting.py +15 -15
  21. QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py +124 -124
  22. QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py +161 -161
  23. QuizGenerator/question.py +41 -41
  24. QuizGenerator/quiz.py +7 -7
  25. QuizGenerator/typst_utils.py +2 -2
  26. {quizgenerator-0.6.2.dist-info → quizgenerator-0.7.0.dist-info}/METADATA +1 -1
  27. {quizgenerator-0.6.2.dist-info → quizgenerator-0.7.0.dist-info}/RECORD +30 -30
  28. {quizgenerator-0.6.2.dist-info → quizgenerator-0.7.0.dist-info}/WHEEL +0 -0
  29. {quizgenerator-0.6.2.dist-info → quizgenerator-0.7.0.dist-info}/entry_points.txt +0 -0
  30. {quizgenerator-0.6.2.dist-info → quizgenerator-0.7.0.dist-info}/licenses/LICENSE +0 -0
@@ -6,7 +6,7 @@ import numpy as np
6
6
  from typing import List, Tuple
7
7
 
8
8
  from QuizGenerator.question import Question, QuestionRegistry
9
- from QuizGenerator.contentast import ContentAST, AnswerTypes
9
+ import QuizGenerator.contentast as ca
10
10
  from QuizGenerator.constants import MathRanges
11
11
  from QuizGenerator.mixins import TableQuestionMixin
12
12
 
@@ -61,25 +61,25 @@ class AttentionForwardPass(MatrixQuestion, TableQuestionMixin):
61
61
  ## Answers:
62
62
  # Q, K, V, output, weights
63
63
 
64
- self.answers["weights"] = AnswerTypes.Matrix(self.weights, label="Weights")
65
- self.answers["output"] = AnswerTypes.Matrix(self.output, label="Output")
64
+ self.answers["weights"] = ca.AnswerTypes.Matrix(self.weights, label="Weights")
65
+ self.answers["output"] = ca.AnswerTypes.Matrix(self.output, label="Output")
66
66
 
67
67
  return True
68
68
 
69
- def _get_body(self, **kwargs) -> Tuple[ContentAST.Section, List[ContentAST.Answer]]:
69
+ def _get_body(self, **kwargs) -> Tuple[ca.Section, List[ca.Answer]]:
70
70
  """Build question body and collect answers."""
71
- body = ContentAST.Section()
71
+ body = ca.Section()
72
72
  answers = []
73
73
 
74
74
  body.add_element(
75
- ContentAST.Text("Given the below information about a self attention layer, please calculate the output sequence.")
75
+ ca.Text("Given the below information about a self attention layer, please calculate the output sequence.")
76
76
  )
77
77
  body.add_element(
78
78
  self.create_info_table(
79
79
  {
80
- "Q": ContentAST.Matrix(self.Q),
81
- "K": ContentAST.Matrix(self.K),
82
- "V": ContentAST.Matrix(self.V),
80
+ "Q": ca.Matrix(self.Q),
81
+ "K": ca.Matrix(self.K),
82
+ "V": ca.Matrix(self.V),
83
83
  }
84
84
  )
85
85
  )
@@ -87,67 +87,67 @@ class AttentionForwardPass(MatrixQuestion, TableQuestionMixin):
87
87
  answers.append(self.answers["weights"])
88
88
  answers.append(self.answers["output"])
89
89
  body.add_elements([
90
- ContentAST.LineBreak(),
90
+ ca.LineBreak(),
91
91
  self.answers["weights"],
92
- ContentAST.LineBreak(),
92
+ ca.LineBreak(),
93
93
  self.answers["output"],
94
94
  ])
95
95
 
96
96
  return body, answers
97
97
 
98
- def get_body(self, **kwargs) -> ContentAST.Section:
98
+ def get_body(self, **kwargs) -> ca.Section:
99
99
  """Build question body (backward compatible interface)."""
100
100
  body, _ = self._get_body(**kwargs)
101
101
  return body
102
102
 
103
- def _get_explanation(self, **kwargs) -> Tuple[ContentAST.Section, List[ContentAST.Answer]]:
103
+ def _get_explanation(self, **kwargs) -> Tuple[ca.Section, List[ca.Answer]]:
104
104
  """Build question explanation."""
105
- explanation = ContentAST.Section()
106
- digits = ContentAST.Answer.DEFAULT_ROUNDING_DIGITS
105
+ explanation = ca.Section()
106
+ digits = ca.Answer.DEFAULT_ROUNDING_DIGITS
107
107
 
108
108
  explanation.add_element(
109
- ContentAST.Paragraph([
109
+ ca.Paragraph([
110
110
  "Self-attention uses scaled dot-product attention to compute a weighted combination of values based on query-key similarity."
111
111
  ])
112
112
  )
113
113
 
114
114
  # Step 1: Compute attention scores
115
115
  explanation.add_element(
116
- ContentAST.Paragraph([
117
- ContentAST.Text("Step 1: Compute attention scores", emphasis=True)
116
+ ca.Paragraph([
117
+ ca.Text("Step 1: Compute attention scores", emphasis=True)
118
118
  ])
119
119
  )
120
120
 
121
121
  d_k = self.Q.shape[1]
122
122
  explanation.add_element(
123
- ContentAST.Equation(f"\\text{{scores}} = \\frac{{Q K^T}}{{\\sqrt{{d_k}}}} = \\frac{{Q K^T}}{{\\sqrt{{{d_k}}}}}")
123
+ ca.Equation(f"\\text{{scores}} = \\frac{{Q K^T}}{{\\sqrt{{d_k}}}} = \\frac{{Q K^T}}{{\\sqrt{{{d_k}}}}}")
124
124
  )
125
125
 
126
126
  scores = self.Q @ self.K.T / np.sqrt(d_k)
127
127
 
128
128
  explanation.add_element(
129
- ContentAST.Paragraph([
129
+ ca.Paragraph([
130
130
  "Raw scores (scaling by ",
131
- ContentAST.Equation(f'\\sqrt{{{d_k}}}', inline=True),
131
+ ca.Equation(f'\\sqrt{{{d_k}}}', inline=True),
132
132
  " prevents extremely large values):"
133
133
  ])
134
134
  )
135
- explanation.add_element(ContentAST.Matrix(np.round(scores, digits)))
135
+ explanation.add_element(ca.Matrix(np.round(scores, digits)))
136
136
 
137
137
  # Step 2: Apply softmax
138
138
  explanation.add_element(
139
- ContentAST.Paragraph([
140
- ContentAST.Text("Step 2: Apply softmax to get attention weights", emphasis=True)
139
+ ca.Paragraph([
140
+ ca.Text("Step 2: Apply softmax to get attention weights", emphasis=True)
141
141
  ])
142
142
  )
143
143
 
144
144
  explanation.add_element(
145
- ContentAST.Equation(r"\alpha_{ij} = \frac{\exp(\text{score}_{ij})}{\sum_k \exp(\text{score}_{ik})}")
145
+ ca.Equation(r"\alpha_{ij} = \frac{\exp(\text{score}_{ij})}{\sum_k \exp(\text{score}_{ik})}")
146
146
  )
147
147
 
148
148
  # Show ONE example row
149
149
  explanation.add_element(
150
- ContentAST.Paragraph([
150
+ ca.Paragraph([
151
151
  "Example: Row 0 softmax computation"
152
152
  ])
153
153
  )
@@ -160,7 +160,7 @@ class AttentionForwardPass(MatrixQuestion, TableQuestionMixin):
160
160
  exp_terms = " + ".join([f"e^{{{s:.{digits}f}}}" for s in row_scores])
161
161
 
162
162
  explanation.add_element(
163
- ContentAST.Paragraph([
163
+ ca.Paragraph([
164
164
  f"Denominator = {exp_terms} = {sum_exp:.{digits}f}"
165
165
  ])
166
166
  )
@@ -168,39 +168,39 @@ class AttentionForwardPass(MatrixQuestion, TableQuestionMixin):
168
168
  # Format array with proper rounding
169
169
  weights_str = "[" + ", ".join([f"{w:.{digits}f}" for w in weights_row]) + "]"
170
170
  explanation.add_element(
171
- ContentAST.Paragraph([
171
+ ca.Paragraph([
172
172
  f"Resulting weights: {weights_str}"
173
173
  ])
174
174
  )
175
175
 
176
176
  explanation.add_element(
177
- ContentAST.Paragraph([
177
+ ca.Paragraph([
178
178
  "Complete attention weight matrix:"
179
179
  ])
180
180
  )
181
- explanation.add_element(ContentAST.Matrix(np.round(self.weights, digits)))
181
+ explanation.add_element(ca.Matrix(np.round(self.weights, digits)))
182
182
 
183
183
  # Step 3: Weighted sum of values
184
184
  explanation.add_element(
185
- ContentAST.Paragraph([
186
- ContentAST.Text("Step 3: Compute weighted sum of values", emphasis=True)
185
+ ca.Paragraph([
186
+ ca.Text("Step 3: Compute weighted sum of values", emphasis=True)
187
187
  ])
188
188
  )
189
189
 
190
190
  explanation.add_element(
191
- ContentAST.Equation(r"\text{output} = \text{weights} \times V")
191
+ ca.Equation(r"\text{output} = \text{weights} \times V")
192
192
  )
193
193
 
194
194
  explanation.add_element(
195
- ContentAST.Paragraph([
195
+ ca.Paragraph([
196
196
  "Final output:"
197
197
  ])
198
198
  )
199
- explanation.add_element(ContentAST.Matrix(np.round(self.output, digits)))
199
+ explanation.add_element(ca.Matrix(np.round(self.output, digits)))
200
200
 
201
201
  return explanation, []
202
202
 
203
- def get_explanation(self, **kwargs) -> ContentAST.Section:
203
+ def get_explanation(self, **kwargs) -> ca.Section:
204
204
  """Build question explanation (backward compatible interface)."""
205
205
  explanation, _ = self._get_explanation(**kwargs)
206
206
  return explanation
@@ -6,7 +6,7 @@ import numpy as np
6
6
  from typing import List, Tuple
7
7
 
8
8
  from QuizGenerator.question import Question, QuestionRegistry
9
- from QuizGenerator.contentast import ContentAST, AnswerTypes
9
+ import QuizGenerator.contentast as ca
10
10
  from QuizGenerator.constants import MathRanges
11
11
  from .matrices import MatrixQuestion
12
12
 
@@ -65,72 +65,72 @@ class ConvolutionCalculation(MatrixQuestion):
65
65
  self.result = self.conv2d_multi_channel(self.image, self.kernel, stride=self.stride, padding=self.padding)
66
66
 
67
67
  self.answers = {
68
- f"result_{i}" : AnswerTypes.Matrix(self.result[:,:,i], label=f"Result of filter {i}")
68
+ f"result_{i}" : ca.AnswerTypes.Matrix(self.result[:,:,i], label=f"Result of filter {i}")
69
69
  for i in range(self.result.shape[-1])
70
70
  }
71
71
 
72
72
  return True
73
73
 
74
- def _get_body(self, **kwargs) -> Tuple[ContentAST.Section, List[ContentAST.Answer]]:
74
+ def _get_body(self, **kwargs) -> Tuple[ca.Section, List[ca.Answer]]:
75
75
  """Build question body and collect answers."""
76
- body = ContentAST.Section()
76
+ body = ca.Section()
77
77
  answers = []
78
78
 
79
79
  body.add_elements(
80
80
  [
81
- ContentAST.Text("Given image represented as matrix: "),
82
- ContentAST.Matrix(self.image, name="image")
81
+ ca.Text("Given image represented as matrix: "),
82
+ ca.Matrix(self.image, name="image")
83
83
  ]
84
84
  )
85
85
 
86
86
  body.add_elements(
87
87
  [
88
- ContentAST.Text("And convolution filters: "),
88
+ ca.Text("And convolution filters: "),
89
89
  ] + [
90
- ContentAST.Matrix(self.kernel[:, :, i], name=f"Filter {i}")
90
+ ca.Matrix(self.kernel[:, :, i], name=f"Filter {i}")
91
91
  for i in range(self.kernel.shape[-1])
92
92
  ]
93
93
  )
94
94
 
95
95
  body.add_element(
96
- ContentAST.Paragraph(
96
+ ca.Paragraph(
97
97
  [
98
98
  f"Calculate the output of the convolution operation. Assume stride = {self.stride} and padding = {self.padding}."
99
99
  ]
100
100
  )
101
101
  )
102
102
 
103
- body.add_element(ContentAST.LineBreak())
103
+ body.add_element(ca.LineBreak())
104
104
 
105
105
  for i in range(self.result.shape[-1]):
106
106
  answers.append(self.answers[f"result_{i}"])
107
107
  body.add_elements([
108
- ContentAST.Container([
108
+ ca.Container([
109
109
  self.answers[f"result_{i}"],
110
- ContentAST.LineBreak()
110
+ ca.LineBreak()
111
111
  ])
112
112
  ])
113
113
 
114
114
  return body, answers
115
115
 
116
- def get_body(self, **kwargs) -> ContentAST.Section:
116
+ def get_body(self, **kwargs) -> ca.Section:
117
117
  """Build question body (backward compatible interface)."""
118
118
  body, _ = self._get_body(**kwargs)
119
119
  return body
120
120
 
121
- def _get_explanation(self, **kwargs) -> Tuple[ContentAST.Section, List[ContentAST.Answer]]:
121
+ def _get_explanation(self, **kwargs) -> Tuple[ca.Section, List[ca.Answer]]:
122
122
  """Build question explanation."""
123
- explanation = ContentAST.Section()
124
- digits = ContentAST.Answer.DEFAULT_ROUNDING_DIGITS
123
+ explanation = ca.Section()
124
+ digits = ca.Answer.DEFAULT_ROUNDING_DIGITS
125
125
 
126
126
  explanation.add_element(
127
- ContentAST.Paragraph([
127
+ ca.Paragraph([
128
128
  "To compute a 2D convolution, we slide the filter across the input image and compute the element-wise product at each position, then sum the results."
129
129
  ])
130
130
  )
131
131
 
132
132
  explanation.add_element(
133
- ContentAST.Paragraph([
133
+ ca.Paragraph([
134
134
  f"With stride={self.stride} and padding={self.padding}: ",
135
135
  f"stride controls how many pixels the filter moves each step, ",
136
136
  f"and padding adds zeros around the border {'(no border in this case)' if self.padding == 0 else f'({self.padding} pixels)'}."
@@ -140,19 +140,19 @@ class ConvolutionCalculation(MatrixQuestion):
140
140
  # For each filter, show one detailed example computation
141
141
  for f_idx in range(self.kernel.shape[-1]):
142
142
  explanation.add_element(
143
- ContentAST.Paragraph([
144
- ContentAST.Text(f"Filter {f_idx}:", emphasis=True)
143
+ ca.Paragraph([
144
+ ca.Text(f"Filter {f_idx}:", emphasis=True)
145
145
  ])
146
146
  )
147
147
 
148
148
  # Show the filter (rounded)
149
149
  explanation.add_element(
150
- ContentAST.Matrix(np.round(self.kernel[:, :, f_idx], digits), name=f"Filter {f_idx}")
150
+ ca.Matrix(np.round(self.kernel[:, :, f_idx], digits), name=f"Filter {f_idx}")
151
151
  )
152
152
 
153
153
  # Show ONE example computation (position 0,0)
154
154
  explanation.add_element(
155
- ContentAST.Paragraph([
155
+ ca.Paragraph([
156
156
  "Example computation at position (0, 0):"
157
157
  ])
158
158
  )
@@ -177,22 +177,22 @@ class ConvolutionCalculation(MatrixQuestion):
177
177
  result_val = self.result[0, 0, f_idx]
178
178
 
179
179
  explanation.add_element(
180
- ContentAST.Equation(f"{equation_str} = {result_val:.2f}")
180
+ ca.Equation(f"{equation_str} = {result_val:.2f}")
181
181
  )
182
182
 
183
183
  # Show the complete output matrix (rounded)
184
184
  explanation.add_element(
185
- ContentAST.Paragraph([
185
+ ca.Paragraph([
186
186
  "Complete output:"
187
187
  ])
188
188
  )
189
189
  explanation.add_element(
190
- ContentAST.Matrix(np.round(self.result[:, :, f_idx], digits))
190
+ ca.Matrix(np.round(self.result[:, :, f_idx], digits))
191
191
  )
192
192
 
193
193
  return explanation, []
194
194
 
195
- def get_explanation(self, **kwargs) -> ContentAST.Section:
195
+ def get_explanation(self, **kwargs) -> ca.Section:
196
196
  """Build question explanation (backward compatible interface)."""
197
197
  explanation, _ = self._get_explanation(**kwargs)
198
198
  return explanation
@@ -7,7 +7,7 @@ from typing import List, Tuple
7
7
 
8
8
  from .matrices import MatrixQuestion
9
9
  from QuizGenerator.question import Question, QuestionRegistry
10
- from QuizGenerator.contentast import ContentAST, AnswerTypes
10
+ import QuizGenerator.contentast as ca
11
11
  from QuizGenerator.constants import MathRanges
12
12
  from QuizGenerator.mixins import TableQuestionMixin
13
13
 
@@ -64,65 +64,65 @@ class RNNForwardPass(MatrixQuestion, TableQuestionMixin):
64
64
  ## Answers:
65
65
  # x_seq, W_xh, W_hh, b_h, h_0, h_states
66
66
 
67
- self.answers["output_sequence"] = AnswerTypes.Matrix(value=self.h_states, label="Hidden states")
67
+ self.answers["output_sequence"] = ca.AnswerTypes.Matrix(value=self.h_states, label="Hidden states")
68
68
 
69
69
  return True
70
70
 
71
- def _get_body(self, **kwargs) -> Tuple[ContentAST.Section, List[ContentAST.Answer]]:
71
+ def _get_body(self, **kwargs) -> Tuple[ca.Section, List[ca.Answer]]:
72
72
  """Build question body and collect answers."""
73
- body = ContentAST.Section()
73
+ body = ca.Section()
74
74
  answers = []
75
75
 
76
76
  body.add_element(
77
- ContentAST.Paragraph([
78
- ContentAST.Text("Given the below information about an RNN, please calculate the output sequence."),
77
+ ca.Paragraph([
78
+ ca.Text("Given the below information about an RNN, please calculate the output sequence."),
79
79
  "Assume that you are using a tanh activation function."
80
80
  ])
81
81
  )
82
82
  body.add_element(
83
83
  self.create_info_table(
84
84
  {
85
- ContentAST.Container(["Input sequence, ", ContentAST.Equation("x_{seq}", inline=True)]) : ContentAST.Matrix(self.x_seq),
86
- ContentAST.Container(["Input weights, ", ContentAST.Equation("W_{xh}", inline=True)]) : ContentAST.Matrix(self.W_xh),
87
- ContentAST.Container(["Hidden weights, ", ContentAST.Equation("W_{hh}", inline=True)]) : ContentAST.Matrix(self.W_hh),
88
- ContentAST.Container(["Bias, ", ContentAST.Equation("b_{h}", inline=True)]) : ContentAST.Matrix(self.b_h),
89
- ContentAST.Container(["Hidden states, ", ContentAST.Equation("h_{0}", inline=True)]) : ContentAST.Matrix(self.h_0),
85
+ ca.Container(["Input sequence, ", ca.Equation("x_{seq}", inline=True)]) : ca.Matrix(self.x_seq),
86
+ ca.Container(["Input weights, ", ca.Equation("W_{xh}", inline=True)]) : ca.Matrix(self.W_xh),
87
+ ca.Container(["Hidden weights, ", ca.Equation("W_{hh}", inline=True)]) : ca.Matrix(self.W_hh),
88
+ ca.Container(["Bias, ", ca.Equation("b_{h}", inline=True)]) : ca.Matrix(self.b_h),
89
+ ca.Container(["Hidden states, ", ca.Equation("h_{0}", inline=True)]) : ca.Matrix(self.h_0),
90
90
  }
91
91
  )
92
92
  )
93
93
 
94
- body.add_element(ContentAST.LineBreak())
94
+ body.add_element(ca.LineBreak())
95
95
 
96
96
  answers.append(self.answers["output_sequence"])
97
97
  body.add_element(self.answers["output_sequence"])
98
98
 
99
99
  return body, answers
100
100
 
101
- def get_body(self, **kwargs) -> ContentAST.Section:
101
+ def get_body(self, **kwargs) -> ca.Section:
102
102
  """Build question body (backward compatible interface)."""
103
103
  body, _ = self._get_body(**kwargs)
104
104
  return body
105
105
 
106
- def _get_explanation(self, **kwargs) -> Tuple[ContentAST.Section, List[ContentAST.Answer]]:
106
+ def _get_explanation(self, **kwargs) -> Tuple[ca.Section, List[ca.Answer]]:
107
107
  """Build question explanation."""
108
- explanation = ContentAST.Section()
109
- digits = ContentAST.Answer.DEFAULT_ROUNDING_DIGITS
108
+ explanation = ca.Section()
109
+ digits = ca.Answer.DEFAULT_ROUNDING_DIGITS
110
110
 
111
111
  explanation.add_element(
112
- ContentAST.Paragraph([
112
+ ca.Paragraph([
113
113
  "For an RNN forward pass, we compute the hidden state at each time step using:"
114
114
  ])
115
115
  )
116
116
 
117
117
  explanation.add_element(
118
- ContentAST.Equation(r"h_t = \tanh(x_t W_{xh} + h_{t-1} W_{hh} + b_h)")
118
+ ca.Equation(r"h_t = \tanh(x_t W_{xh} + h_{t-1} W_{hh} + b_h)")
119
119
  )
120
120
 
121
121
  explanation.add_element(
122
- ContentAST.Paragraph([
123
- "Where the input contributes via ", ContentAST.Equation("W_{xh}", inline=True),
124
- ", the previous hidden state contributes via ", ContentAST.Equation("W_{hh}", inline=True),
125
- ", and ", ContentAST.Equation("b_h", inline=True), " is the bias."
122
+ ca.Paragraph([
123
+ "Where the input contributes via ", ca.Equation("W_{xh}", inline=True),
124
+ ", the previous hidden state contributes via ", ca.Equation("W_{hh}", inline=True),
125
+ ", and ", ca.Equation("b_h", inline=True), " is the bias."
126
126
  ])
127
127
  )
128
128
 
@@ -137,12 +137,12 @@ class RNNForwardPass(MatrixQuestion, TableQuestionMixin):
137
137
  seq_len = len(self.x_seq)
138
138
  num_examples = min(2, seq_len)
139
139
 
140
- explanation.add_element(ContentAST.Paragraph([""]))
140
+ explanation.add_element(ca.Paragraph([""]))
141
141
 
142
142
  for t in range(num_examples):
143
143
  explanation.add_element(
144
- ContentAST.Paragraph([
145
- ContentAST.Text(f"Example: Timestep {t}", emphasis=True)
144
+ ca.Paragraph([
145
+ ca.Text(f"Example: Timestep {t}", emphasis=True)
146
146
  ])
147
147
  )
148
148
 
@@ -162,53 +162,53 @@ class RNNForwardPass(MatrixQuestion, TableQuestionMixin):
162
162
  h_result = np.tanh(pre_activation)
163
163
 
164
164
  explanation.add_element(
165
- ContentAST.Paragraph([
165
+ ca.Paragraph([
166
166
  "Input contribution: ",
167
- ContentAST.Equation(f'x_{t} W_{{xh}}', inline=True),
167
+ ca.Equation(f'x_{t} W_{{xh}}', inline=True),
168
168
  f" = {format_array(x_contribution)}"
169
169
  ])
170
170
  )
171
171
 
172
172
  explanation.add_element(
173
- ContentAST.Paragraph([
173
+ ca.Paragraph([
174
174
  "Hidden contribution: ",
175
- ContentAST.Equation(f'{h_prev_label} W_{{hh}}', inline=True),
175
+ ca.Equation(f'{h_prev_label} W_{{hh}}', inline=True),
176
176
  f"{h_prev_desc} = {format_array(h_contribution)}"
177
177
  ])
178
178
  )
179
179
 
180
180
  explanation.add_element(
181
- ContentAST.Paragraph([
181
+ ca.Paragraph([
182
182
  f"Pre-activation: {format_array(pre_activation)}"
183
183
  ])
184
184
  )
185
185
 
186
186
  explanation.add_element(
187
- ContentAST.Paragraph([
187
+ ca.Paragraph([
188
188
  "After tanh: ",
189
- ContentAST.Equation(f'h_{t}', inline=True),
189
+ ca.Equation(f'h_{t}', inline=True),
190
190
  f" = {format_array(h_result)}"
191
191
  ])
192
192
  )
193
193
 
194
194
  # Add visual separator between timesteps (except after the last one)
195
195
  if t < num_examples - 1:
196
- explanation.add_element(ContentAST.Paragraph([""]))
196
+ explanation.add_element(ca.Paragraph([""]))
197
197
 
198
198
  # Show complete output sequence (rounded)
199
199
  explanation.add_element(
200
- ContentAST.Paragraph([
200
+ ca.Paragraph([
201
201
  "Complete hidden state sequence (each row is one timestep):"
202
202
  ])
203
203
  )
204
204
 
205
205
  explanation.add_element(
206
- ContentAST.Matrix(np.round(self.h_states, digits))
206
+ ca.Matrix(np.round(self.h_states, digits))
207
207
  )
208
208
 
209
209
  return explanation, []
210
210
 
211
- def get_explanation(self, **kwargs) -> ContentAST.Section:
211
+ def get_explanation(self, **kwargs) -> ca.Section:
212
212
  """Build question explanation (backward compatible interface)."""
213
213
  explanation, _ = self._get_explanation(**kwargs)
214
214
  return explanation