j-js commited on
Commit
2b74f91
·
verified ·
1 Parent(s): 1f49ca6

Update conversation_logic.py

Browse files
Files changed (1) hide show
  1. conversation_logic.py +117 -48
conversation_logic.py CHANGED
@@ -1,16 +1,49 @@
1
  from __future__ import annotations
2
 
3
- from context_parser import (
4
- mentions_choice_letter,
5
- parse_hidden_context,
6
- user_is_referring_to_existing_question,
7
- )
8
  from formatting import format_reply
9
  from models import SolverResult
10
  from quant_solver import extract_choices, is_quant_question, solve_quant
11
 
12
 
13
- def build_choice_explanation(chosen_letter: str, result: SolverResult, choices: dict[str, str], help_mode: str) -> str:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  choice_text = choices.get(chosen_letter, "").strip()
15
  value_text = result.answer_value.strip() if result.answer_value else ""
16
 
@@ -18,8 +51,8 @@ def build_choice_explanation(chosen_letter: str, result: SolverResult, choices:
18
  if value_text and choice_text:
19
  return f"Work out the value first, then compare it with choice {chosen_letter} ({choice_text})."
20
  if choice_text:
21
- return f"Focus on why choice {chosen_letter} fits the calculation better than the others."
22
- return f"Focus on why choice {chosen_letter} matches the calculation."
23
 
24
  if help_mode == "walkthrough":
25
  if value_text and choice_text:
@@ -29,7 +62,7 @@ def build_choice_explanation(chosen_letter: str, result: SolverResult, choices:
29
  f"That is why {chosen_letter} is the correct answer."
30
  )
31
  if choice_text:
32
- return f"Choice {chosen_letter} matches the result of the calculation, so that is why it is correct."
33
  return f"The solved result matches choice {chosen_letter}, so that is why it is correct."
34
 
35
  if value_text and choice_text:
@@ -39,7 +72,14 @@ def build_choice_explanation(chosen_letter: str, result: SolverResult, choices:
39
  return f"Yes — it’s {chosen_letter}."
40
 
41
 
42
- def handle_conversational_followup(ctx, help_mode: str):
 
 
 
 
 
 
 
43
  user_text = ctx.visible_user_text
44
  lower = user_text.lower().strip()
45
  question_block = ctx.combined_question_block
@@ -51,7 +91,6 @@ def handle_conversational_followup(ctx, help_mode: str):
51
  return None
52
 
53
  solved = solve_quant(question_block, "answer")
54
-
55
  asked_letter = mentions_choice_letter(user_text)
56
  choices = extract_choices(question_block)
57
 
@@ -68,6 +107,7 @@ def handle_conversational_followup(ctx, help_mode: str):
68
 
69
  if asked_letter and solved.answer_letter and asked_letter != solved.answer_letter:
70
  correct_choice_text = choices.get(solved.answer_letter, "").strip()
 
71
  if help_mode == "hint":
72
  reply = f"Check the calculation again and compare your result with choice {solved.answer_letter}, not {asked_letter}."
73
  elif help_mode == "walkthrough":
@@ -78,6 +118,7 @@ def handle_conversational_followup(ctx, help_mode: str):
78
  )
79
  else:
80
  reply = f"It is not {asked_letter} — the correct choice is {solved.answer_letter}."
 
81
  return SolverResult(
82
  reply=reply,
83
  domain="quant",
@@ -87,58 +128,72 @@ def handle_conversational_followup(ctx, help_mode: str):
87
  answer_value=solved.answer_value,
88
  )
89
 
90
- if lower in {"help", "can you help", "help me", "i dont get it", "i don't get it"}:
91
- if help_mode == "hint":
92
- reply = solve_quant(question_block, "hint").reply
93
- elif help_mode == "walkthrough":
94
- reply = solve_quant(question_block, "walkthrough").reply
 
 
 
95
  else:
96
- reply = solve_quant(question_block, "answer").reply
 
 
 
97
  return SolverResult(
98
  reply=reply,
99
  domain="quant",
100
- solved=solved.solved,
101
- help_mode=help_mode,
102
- answer_letter=solved.answer_letter,
103
- answer_value=solved.answer_value,
104
  )
105
 
 
 
 
 
 
 
 
106
  if "first step" in lower or "how do i start" in lower or "what do i do first" in lower:
107
- hint_result = solve_quant(question_block, "hint")
108
- return SolverResult(
109
- reply=hint_result.reply,
110
- domain="quant",
111
- solved=hint_result.solved,
112
- help_mode="hint",
113
- answer_letter=hint_result.answer_letter,
114
- answer_value=hint_result.answer_value,
115
- )
116
 
117
  if "why" in lower or "explain" in lower:
118
  walkthrough_result = solve_quant(question_block, "walkthrough")
119
  if solved.answer_letter and "why is it" not in lower:
120
- choices = extract_choices(question_block)
121
  choice_text = choices.get(solved.answer_letter, "").strip()
122
  if choice_text:
123
- extra = f"\n\nSo the correct choice is {solved.answer_letter} ({choice_text})."
124
  else:
125
- extra = f"\n\nSo the correct choice is {solved.answer_letter}."
126
- walkthrough_result.reply += extra
127
  return walkthrough_result
128
 
129
- if "hint" in lower:
130
- return solve_quant(question_block, "hint")
131
-
132
- if "answer" in lower or "which one" in lower or "are you sure" in lower:
133
  return solve_quant(question_block, "answer")
134
 
 
 
 
 
135
  return None
136
 
137
 
138
  def solve_verbal_or_general(user_text: str, help_mode: str) -> SolverResult:
139
  lower = user_text.lower()
140
 
141
- if any(k in lower for k in ["sentence correction", "grammar", "verbal", "critical reasoning", "reading comprehension"]):
 
 
 
 
 
 
 
 
 
142
  if help_mode == "hint":
143
  reply = (
144
  "First identify the task:\n"
@@ -148,7 +203,7 @@ def solve_verbal_or_general(user_text: str, help_mode: str) -> SolverResult:
148
  )
149
  elif help_mode == "walkthrough":
150
  reply = (
151
- "I can help verbally too, but for now this backend is strongest on quant-style items. "
152
  "For verbal, I’d use elimination based on grammar, logic, scope, or passage support."
153
  )
154
  else:
@@ -157,11 +212,11 @@ def solve_verbal_or_general(user_text: str, help_mode: str) -> SolverResult:
157
  return SolverResult(reply=reply, domain="verbal", solved=False, help_mode=help_mode)
158
 
159
  if help_mode == "hint":
160
- reply = "I can help. Ask for a hint, an explanation, or the answer, and I’ll use the current in-game question context when available."
161
  elif help_mode == "walkthrough":
162
- reply = "I can talk it through step by step using the current in-game question context."
163
  else:
164
- reply = "Send a message naturally and I’ll respond using the current question context."
165
 
166
  return SolverResult(reply=reply, domain="fallback", solved=False, help_mode=help_mode)
167
 
@@ -172,12 +227,26 @@ def generate_response(
172
  verbosity: float,
173
  transparency: float,
174
  help_mode: str,
 
 
 
 
 
 
175
  ) -> SolverResult:
176
- ctx = parse_hidden_context(raw_user_text)
177
- visible_user_text = ctx.visible_user_text.strip()
178
- question_block = ctx.combined_question_block.strip()
 
 
 
 
 
 
 
 
179
 
180
- if not raw_user_text.strip():
181
  result = SolverResult(
182
  reply="Ask a question and I’ll help using the current in-game context.",
183
  domain="fallback",
@@ -202,6 +271,6 @@ def generate_response(
202
  result.reply = format_reply(result.reply, tone, verbosity, transparency, help_mode)
203
  return result
204
 
205
- result = solve_verbal_or_general(visible_user_text or raw_user_text, help_mode)
206
  result.reply = format_reply(result.reply, tone, verbosity, transparency, help_mode)
207
  return result
 
1
  from __future__ import annotations
2
 
3
+ from typing import Any, Dict, List, Optional
4
+
5
+ from context_parser import mentions_choice_letter, user_is_referring_to_existing_question
 
 
6
  from formatting import format_reply
7
  from models import SolverResult
8
  from quant_solver import extract_choices, is_quant_question, solve_quant
9
 
10
 
11
+ class ResponseContext:
12
+ def __init__(
13
+ self,
14
+ visible_user_text: str,
15
+ question_text: str,
16
+ options_text: str,
17
+ question_category: str,
18
+ question_difficulty: str,
19
+ chat_history: Optional[List[Dict[str, Any]]] = None,
20
+ ):
21
+ self.visible_user_text = (visible_user_text or "").strip()
22
+ self.question_text = (question_text or "").strip()
23
+ self.options_text = (options_text or "").strip()
24
+ self.question_category = (question_category or "").strip()
25
+ self.question_difficulty = (question_difficulty or "").strip()
26
+ self.chat_history = chat_history or []
27
+
28
+ @property
29
+ def combined_question_block(self) -> str:
30
+ parts: List[str] = []
31
+
32
+ if self.question_text:
33
+ parts.append(self.question_text)
34
+
35
+ if self.options_text:
36
+ parts.append(self.options_text)
37
+
38
+ return "\n".join(parts).strip()
39
+
40
+
41
+ def build_choice_explanation(
42
+ chosen_letter: str,
43
+ result: SolverResult,
44
+ choices: dict[str, str],
45
+ help_mode: str,
46
+ ) -> str:
47
  choice_text = choices.get(chosen_letter, "").strip()
48
  value_text = result.answer_value.strip() if result.answer_value else ""
49
 
 
51
  if value_text and choice_text:
52
  return f"Work out the value first, then compare it with choice {chosen_letter} ({choice_text})."
53
  if choice_text:
54
+ return f"Focus on why choice {chosen_letter} fits better than the others."
55
+ return f"Focus on whether choice {chosen_letter} matches the result."
56
 
57
  if help_mode == "walkthrough":
58
  if value_text and choice_text:
 
62
  f"That is why {chosen_letter} is the correct answer."
63
  )
64
  if choice_text:
65
+ return f"Choice {chosen_letter} matches the result, so that is why it is correct."
66
  return f"The solved result matches choice {chosen_letter}, so that is why it is correct."
67
 
68
  if value_text and choice_text:
 
72
  return f"Yes — it’s {chosen_letter}."
73
 
74
 
75
+ def get_last_assistant_message(chat_history: List[Dict[str, Any]]) -> str:
76
+ for item in reversed(chat_history or []):
77
+ if str(item.get("role", "")).strip().lower() == "assistant":
78
+ return str(item.get("text", "")).strip()
79
+ return ""
80
+
81
+
82
+ def handle_conversational_followup(ctx: ResponseContext, help_mode: str) -> Optional[SolverResult]:
83
  user_text = ctx.visible_user_text
84
  lower = user_text.lower().strip()
85
  question_block = ctx.combined_question_block
 
91
  return None
92
 
93
  solved = solve_quant(question_block, "answer")
 
94
  asked_letter = mentions_choice_letter(user_text)
95
  choices = extract_choices(question_block)
96
 
 
107
 
108
  if asked_letter and solved.answer_letter and asked_letter != solved.answer_letter:
109
  correct_choice_text = choices.get(solved.answer_letter, "").strip()
110
+
111
  if help_mode == "hint":
112
  reply = f"Check the calculation again and compare your result with choice {solved.answer_letter}, not {asked_letter}."
113
  elif help_mode == "walkthrough":
 
118
  )
119
  else:
120
  reply = f"It is not {asked_letter} — the correct choice is {solved.answer_letter}."
121
+
122
  return SolverResult(
123
  reply=reply,
124
  domain="quant",
 
128
  answer_value=solved.answer_value,
129
  )
130
 
131
+ if "what is the question asking" in lower or "what is this asking" in lower:
132
+ category = ctx.question_category.lower()
133
+ question_text = ctx.question_text
134
+
135
+ if "variability" in question_text.lower() or "data" in category:
136
+ reply = (
137
+ "It is asking you to compare how spread out each dataset is and decide which one varies the most."
138
+ )
139
  else:
140
+ reply = (
141
+ "It is asking you to identify the main task, extract the relevant numbers or relationships, and then choose the matching option."
142
+ )
143
+
144
  return SolverResult(
145
  reply=reply,
146
  domain="quant",
147
+ solved=False,
148
+ help_mode="hint",
 
 
149
  )
150
 
151
+ if lower in {"help", "can you help", "help me", "i dont get it", "i don't get it"}:
152
+ if help_mode == "hint":
153
+ return solve_quant(question_block, "hint")
154
+ if help_mode == "walkthrough":
155
+ return solve_quant(question_block, "walkthrough")
156
+ return solve_quant(question_block, "answer")
157
+
158
  if "first step" in lower or "how do i start" in lower or "what do i do first" in lower:
159
+ return solve_quant(question_block, "hint")
160
+
161
+ if "hint" in lower:
162
+ return solve_quant(question_block, "hint")
 
 
 
 
 
163
 
164
  if "why" in lower or "explain" in lower:
165
  walkthrough_result = solve_quant(question_block, "walkthrough")
166
  if solved.answer_letter and "why is it" not in lower:
 
167
  choice_text = choices.get(solved.answer_letter, "").strip()
168
  if choice_text:
169
+ walkthrough_result.reply += f"\n\nSo the correct choice is {solved.answer_letter} ({choice_text})."
170
  else:
171
+ walkthrough_result.reply += f"\n\nSo the correct choice is {solved.answer_letter}."
 
172
  return walkthrough_result
173
 
174
+ if "answer" in lower or "which one" in lower or "what answer" in lower or "are you sure" in lower:
 
 
 
175
  return solve_quant(question_block, "answer")
176
 
177
+ last_ai = get_last_assistant_message(ctx.chat_history)
178
+ if last_ai and ("that" in lower or "it" in lower or "why" in lower):
179
+ return solve_quant(question_block, "walkthrough")
180
+
181
  return None
182
 
183
 
184
  def solve_verbal_or_general(user_text: str, help_mode: str) -> SolverResult:
185
  lower = user_text.lower()
186
 
187
+ if any(
188
+ k in lower
189
+ for k in [
190
+ "sentence correction",
191
+ "grammar",
192
+ "verbal",
193
+ "critical reasoning",
194
+ "reading comprehension",
195
+ ]
196
+ ):
197
  if help_mode == "hint":
198
  reply = (
199
  "First identify the task:\n"
 
203
  )
204
  elif help_mode == "walkthrough":
205
  reply = (
206
+ "I can help verbally too, but this backend is strongest on quant-style items. "
207
  "For verbal, I’d use elimination based on grammar, logic, scope, or passage support."
208
  )
209
  else:
 
212
  return SolverResult(reply=reply, domain="verbal", solved=False, help_mode=help_mode)
213
 
214
  if help_mode == "hint":
215
+ reply = "I can help. Ask for a hint, an explanation, or the answer."
216
  elif help_mode == "walkthrough":
217
+ reply = "I can talk it through step by step."
218
  else:
219
+ reply = "Ask naturally and I’ll help from the current question context when available."
220
 
221
  return SolverResult(reply=reply, domain="fallback", solved=False, help_mode=help_mode)
222
 
 
227
  verbosity: float,
228
  transparency: float,
229
  help_mode: str,
230
+ hidden_context: str = "",
231
+ chat_history: Optional[List[Dict[str, Any]]] = None,
232
+ question_text: str = "",
233
+ options_text: str = "",
234
+ question_category: str = "",
235
+ question_difficulty: str = "",
236
  ) -> SolverResult:
237
+ ctx = ResponseContext(
238
+ visible_user_text=raw_user_text,
239
+ question_text=question_text,
240
+ options_text=options_text,
241
+ question_category=question_category,
242
+ question_difficulty=question_difficulty,
243
+ chat_history=chat_history,
244
+ )
245
+
246
+ visible_user_text = ctx.visible_user_text
247
+ question_block = ctx.combined_question_block
248
 
249
+ if not visible_user_text:
250
  result = SolverResult(
251
  reply="Ask a question and I’ll help using the current in-game context.",
252
  domain="fallback",
 
271
  result.reply = format_reply(result.reply, tone, verbosity, transparency, help_mode)
272
  return result
273
 
274
+ result = solve_verbal_or_general(visible_user_text, help_mode)
275
  result.reply = format_reply(result.reply, tone, verbosity, transparency, help_mode)
276
  return result