Spaces:
Running on Zero
Running on Zero
Upload 4 files
Browse files- badge_game_manager.py +11 -3
- question_bank_builder.py +95 -9
- question_bank_manager.py +9 -1
- strategy_manager.py +7 -2
badge_game_manager.py
CHANGED
|
@@ -39,7 +39,7 @@ except Exception:
|
|
| 39 |
class BadgeGameManager:
|
| 40 |
"""مدير لعبة الوسام والتشخيص التفاعلي."""
|
| 41 |
|
| 42 |
-
VERSION = "
|
| 43 |
UNKNOWN_LABEL = "لا أعلم"
|
| 44 |
UNKNOWN_GUIDANCE = (
|
| 45 |
"لا تخمّن. إذا لم تكن متأكدًا من الإجابة اختر «لا أعلم»؛ "
|
|
@@ -653,6 +653,9 @@ class BadgeGameManager:
|
|
| 653 |
options.sort()
|
| 654 |
return "|".join([
|
| 655 |
str(q.get("skill_id") or ""),
|
|
|
|
|
|
|
|
|
|
| 656 |
str(q.get("media_fact_name") or q.get("question_type") or q.get("item_type") or ""),
|
| 657 |
self.normalize_answer(q.get("correct_answer") or q.get("answer") or ""),
|
| 658 |
*options,
|
|
@@ -688,8 +691,13 @@ class BadgeGameManager:
|
|
| 688 |
old_sig = str(old.get("runtime_evidence_signature") or "").strip()
|
| 689 |
if runtime_sig and old_sig and runtime_sig == old_sig:
|
| 690 |
return {"success": False, "error": "duplicate_evidence_signature", "runtime_evidence_signature": runtime_sig, "version": self.version}
|
| 691 |
-
|
| 692 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 693 |
|
| 694 |
state_dict.setdefault("questions", []).append(cleaned)
|
| 695 |
state_dict["total_questions"] = len(state_dict.get("questions") or [])
|
|
|
|
| 39 |
class BadgeGameManager:
|
| 40 |
"""مدير لعبة الوسام والتشخيص التفاعلي."""
|
| 41 |
|
| 42 |
+
VERSION = "badge_game_manager_v32_evidence_signature_dedup"
|
| 43 |
UNKNOWN_LABEL = "لا أعلم"
|
| 44 |
UNKNOWN_GUIDANCE = (
|
| 45 |
"لا تخمّن. إذا لم تكن متأكدًا من الإجابة اختر «لا أعلم»؛ "
|
|
|
|
| 653 |
options.sort()
|
| 654 |
return "|".join([
|
| 655 |
str(q.get("skill_id") or ""),
|
| 656 |
+
str(q.get("condition_slot_id") or (q.get("stimulus_plan") or {}).get("condition_slot_id") or ""),
|
| 657 |
+
str(q.get("diagnostic_condition") or (q.get("stimulus_plan") or {}).get("diagnostic_condition") or ""),
|
| 658 |
+
str(q.get("stimulus_identity_group") or ""),
|
| 659 |
str(q.get("media_fact_name") or q.get("question_type") or q.get("item_type") or ""),
|
| 660 |
self.normalize_answer(q.get("correct_answer") or q.get("answer") or ""),
|
| 661 |
*options,
|
|
|
|
| 691 |
old_sig = str(old.get("runtime_evidence_signature") or "").strip()
|
| 692 |
if runtime_sig and old_sig and runtime_sig == old_sig:
|
| 693 |
return {"success": False, "error": "duplicate_evidence_signature", "runtime_evidence_signature": runtime_sig, "version": self.version}
|
| 694 |
+
|
| 695 |
+
# إذا كان السؤالان يحملان Evidence Signature صحيحة ومختلفة،
|
| 696 |
+
# لا نرفضهما بسبب صياغة/خيارات متشابهة؛ الاختلاف في stimulus/slot
|
| 697 |
+
# قد يكون هو الدليل التشخيصي المقصود.
|
| 698 |
+
if not (runtime_sig and old_sig):
|
| 699 |
+
if not fresh_recheck_role and semantic_key and semantic_key == self._adaptive_probe_semantic_key(old):
|
| 700 |
+
return {"success": False, "error": "duplicate_diagnostic_probe", "semantic_key": semantic_key, "version": self.version}
|
| 701 |
|
| 702 |
state_dict.setdefault("questions", []).append(cleaned)
|
| 703 |
state_dict["total_questions"] = len(state_dict.get("questions") or [])
|
question_bank_builder.py
CHANGED
|
@@ -48,7 +48,7 @@ def _fmt(value: Any) -> str:
|
|
| 48 |
return f"{value:.3f}".rstrip("0").rstrip(".")
|
| 49 |
return str(value)
|
| 50 |
|
| 51 |
-
VERSION = "
|
| 52 |
|
| 53 |
_RUNTIME_CLARIFICATION_SERVICE = None
|
| 54 |
_RUNTIME_QUESTION_GENERATION_CALLBACK = None
|
|
@@ -2503,6 +2503,18 @@ class QuestionBankBuilder(_GeneratorBase):
|
|
| 2503 |
"remedial_practice": ["applied", "direct", "contrast"],
|
| 2504 |
"prerequisite_probe": ["direct", "foundation"],
|
| 2505 |
"micro_step_probe": ["direct", "guided"],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2506 |
# compatibility with older names
|
| 2507 |
"diagnostic_probe": ["direct", "contrast"],
|
| 2508 |
"guided_practice": ["direct", "applied", "contrast"],
|
|
@@ -2545,17 +2557,30 @@ class QuestionBankBuilder(_GeneratorBase):
|
|
| 2545 |
or ""
|
| 2546 |
).strip().lower()
|
| 2547 |
|
| 2548 |
-
|
|
|
|
| 2549 |
item for item in templates
|
| 2550 |
-
if
|
| 2551 |
]
|
| 2552 |
-
if
|
| 2553 |
-
templates =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2554 |
|
| 2555 |
excluded_template_set = {str(x) for x in (exclude_template_ids or []) if str(x).strip()}
|
| 2556 |
if excluded_template_set:
|
| 2557 |
templates = [x for x in templates if str(x.get("template_id") or "") not in excluded_template_set]
|
| 2558 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2559 |
if condition_slot_id:
|
| 2560 |
matched = [
|
| 2561 |
x for x in templates
|
|
@@ -2563,6 +2588,8 @@ class QuestionBankBuilder(_GeneratorBase):
|
|
| 2563 |
]
|
| 2564 |
if matched:
|
| 2565 |
templates = matched
|
|
|
|
|
|
|
| 2566 |
|
| 2567 |
if diagnostic_condition_family:
|
| 2568 |
matched = [
|
|
@@ -2571,6 +2598,8 @@ class QuestionBankBuilder(_GeneratorBase):
|
|
| 2571 |
]
|
| 2572 |
if matched:
|
| 2573 |
templates = matched
|
|
|
|
|
|
|
| 2574 |
|
| 2575 |
if primary_target_attribute:
|
| 2576 |
matched = [x for x in templates if str(x.get("primary_target_attribute") or "") == str(primary_target_attribute)]
|
|
@@ -3541,6 +3570,10 @@ class QuestionBankBuilder(_GeneratorBase):
|
|
| 3541 |
|
| 3542 |
stable_seed = (
|
| 3543 |
f"{skill_id}|{template_id}|{sequence}|"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3544 |
f"{fact_name}|{answer}|{prompt}"
|
| 3545 |
)
|
| 3546 |
question_id = (
|
|
@@ -3583,6 +3616,8 @@ class QuestionBankBuilder(_GeneratorBase):
|
|
| 3583 |
"generation_mode": "media_ground_truth_direct",
|
| 3584 |
"generator_owner": "QuestionBankBuilder",
|
| 3585 |
"generator_version": VERSION,
|
|
|
|
|
|
|
| 3586 |
"answer_source": "media_ground_truth",
|
| 3587 |
"media_fact_name": fact_name,
|
| 3588 |
"media_ground_truth": dict(ground_truth),
|
|
@@ -3609,6 +3644,8 @@ class QuestionBankBuilder(_GeneratorBase):
|
|
| 3609 |
f"MEDIA_GROUND_TRUTH_ITEM_BUILT=True "
|
| 3610 |
f"QUESTION_ID={question_id} "
|
| 3611 |
f"FACT={fact_name} "
|
|
|
|
|
|
|
| 3612 |
f"ANSWER={answer!r} "
|
| 3613 |
f"CHOICES={len(options)} "
|
| 3614 |
f"SEQUENCE={sequence} "
|
|
@@ -3655,6 +3692,10 @@ class QuestionBankBuilder(_GeneratorBase):
|
|
| 3655 |
(
|
| 3656 |
f"{request.get('skill_id','')}|"
|
| 3657 |
f"{request.get('template_id','')}|"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3658 |
f"{index + 1}"
|
| 3659 |
).encode("utf-8")
|
| 3660 |
).hexdigest()[:14]
|
|
@@ -4028,6 +4069,8 @@ class QuestionBankBuilder(_GeneratorBase):
|
|
| 4028 |
error_target=error_target,
|
| 4029 |
)
|
| 4030 |
request.update({
|
|
|
|
|
|
|
| 4031 |
"difficulty": difficulty,
|
| 4032 |
"representation_type": representation_type,
|
| 4033 |
"cognitive_domain": cognitive_domain,
|
|
@@ -4266,14 +4309,55 @@ class QuestionBankBuilder(_GeneratorBase):
|
|
| 4266 |
|
| 4267 |
@staticmethod
|
| 4268 |
def question_fingerprint(question: Dict[str, Any]) -> str:
|
| 4269 |
-
"""
|
| 4270 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4271 |
text = re.sub(
|
| 4272 |
r"\s+",
|
| 4273 |
" ",
|
| 4274 |
-
str(
|
| 4275 |
)
|
| 4276 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4277 |
|
| 4278 |
def get_challenge_questions(
|
| 4279 |
self,
|
|
@@ -4947,6 +5031,8 @@ def generate_by_contract(
|
|
| 4947 |
|
| 4948 |
item["question_role"] = question_role
|
| 4949 |
item["question_kind"] = question_role
|
|
|
|
|
|
|
| 4950 |
|
| 4951 |
ok, reason = _contract_question_is_acceptable(item, c)
|
| 4952 |
if not ok:
|
|
|
|
| 48 |
return f"{value:.3f}".rstrip("0").rstrip(".")
|
| 49 |
return str(value)
|
| 50 |
|
| 51 |
+
VERSION = "question_bank_builder_v30_strict_arabic_probe_identity"
|
| 52 |
|
| 53 |
_RUNTIME_CLARIFICATION_SERVICE = None
|
| 54 |
_RUNTIME_QUESTION_GENERATION_CALLBACK = None
|
|
|
|
| 2503 |
"remedial_practice": ["applied", "direct", "contrast"],
|
| 2504 |
"prerequisite_probe": ["direct", "foundation"],
|
| 2505 |
"micro_step_probe": ["direct", "guided"],
|
| 2506 |
+
|
| 2507 |
+
# canonical diagnostic compatibility vocabulary
|
| 2508 |
+
"screening_probe": ["direct"],
|
| 2509 |
+
"diagnostic_discrimination": ["contrast", "applied", "direct"],
|
| 2510 |
+
"diagnostic_confirmation": ["contrast", "evidence", "applied"],
|
| 2511 |
+
"representation_probe": ["contrast", "applied"],
|
| 2512 |
+
"transfer_probe": ["transfer"],
|
| 2513 |
+
"parallel_reassessment": ["recheck"],
|
| 2514 |
+
"progress_monitoring_probe": ["recheck", "applied"],
|
| 2515 |
+
"spaced_recheck_probe": ["recheck"],
|
| 2516 |
+
"maintenance_worksheet": ["recheck", "applied"],
|
| 2517 |
+
|
| 2518 |
# compatibility with older names
|
| 2519 |
"diagnostic_probe": ["direct", "contrast"],
|
| 2520 |
"guided_practice": ["direct", "applied", "contrast"],
|
|
|
|
| 2557 |
or ""
|
| 2558 |
).strip().lower()
|
| 2559 |
|
| 2560 |
+
requested_role = str(question_role or "").strip()
|
| 2561 |
+
exact_role_filtered = [
|
| 2562 |
item for item in templates
|
| 2563 |
+
if str(item.get("question_role") or "").strip() == requested_role
|
| 2564 |
]
|
| 2565 |
+
if exact_role_filtered:
|
| 2566 |
+
templates = exact_role_filtered
|
| 2567 |
+
else:
|
| 2568 |
+
role_filtered = [
|
| 2569 |
+
item for item in templates
|
| 2570 |
+
if template_kind(item) in wanted_kinds
|
| 2571 |
+
]
|
| 2572 |
+
if role_filtered:
|
| 2573 |
+
templates = role_filtered
|
| 2574 |
|
| 2575 |
excluded_template_set = {str(x) for x in (exclude_template_ids or []) if str(x).strip()}
|
| 2576 |
if excluded_template_set:
|
| 2577 |
templates = [x for x in templates if str(x.get("template_id") or "") not in excluded_template_set]
|
| 2578 |
|
| 2579 |
+
strict_arabic_diagnostic = (
|
| 2580 |
+
str(skill_id or "").startswith("AR-")
|
| 2581 |
+
and str(assessment_mode or "").strip().lower() == "diagnostic"
|
| 2582 |
+
)
|
| 2583 |
+
|
| 2584 |
if condition_slot_id:
|
| 2585 |
matched = [
|
| 2586 |
x for x in templates
|
|
|
|
| 2588 |
]
|
| 2589 |
if matched:
|
| 2590 |
templates = matched
|
| 2591 |
+
elif strict_arabic_diagnostic:
|
| 2592 |
+
return []
|
| 2593 |
|
| 2594 |
if diagnostic_condition_family:
|
| 2595 |
matched = [
|
|
|
|
| 2598 |
]
|
| 2599 |
if matched:
|
| 2600 |
templates = matched
|
| 2601 |
+
elif strict_arabic_diagnostic:
|
| 2602 |
+
return []
|
| 2603 |
|
| 2604 |
if primary_target_attribute:
|
| 2605 |
matched = [x for x in templates if str(x.get("primary_target_attribute") or "") == str(primary_target_attribute)]
|
|
|
|
| 3570 |
|
| 3571 |
stable_seed = (
|
| 3572 |
f"{skill_id}|{template_id}|{sequence}|"
|
| 3573 |
+
f"{request.get('condition_slot_id','')}|"
|
| 3574 |
+
f"{request.get('diagnostic_condition','')}|"
|
| 3575 |
+
f"{request.get('runtime_generation_seed','')}|"
|
| 3576 |
+
f"{request.get('runtime_generation_attempt','')}|"
|
| 3577 |
f"{fact_name}|{answer}|{prompt}"
|
| 3578 |
)
|
| 3579 |
question_id = (
|
|
|
|
| 3616 |
"generation_mode": "media_ground_truth_direct",
|
| 3617 |
"generator_owner": "QuestionBankBuilder",
|
| 3618 |
"generator_version": VERSION,
|
| 3619 |
+
"diagnostic_runtime_schema": "arabic_diag_runtime_v2",
|
| 3620 |
+
"runtime_generation_seed": str(request.get("runtime_generation_seed") or ""),
|
| 3621 |
"answer_source": "media_ground_truth",
|
| 3622 |
"media_fact_name": fact_name,
|
| 3623 |
"media_ground_truth": dict(ground_truth),
|
|
|
|
| 3644 |
f"MEDIA_GROUND_TRUTH_ITEM_BUILT=True "
|
| 3645 |
f"QUESTION_ID={question_id} "
|
| 3646 |
f"FACT={fact_name} "
|
| 3647 |
+
f"SOUND_PRESENT={ground_truth.get('sound_present') if isinstance(ground_truth.get('sound_present'), bool) else ''} "
|
| 3648 |
+
f"DIAG_CONDITION={actual_diagnostic_condition} "
|
| 3649 |
f"ANSWER={answer!r} "
|
| 3650 |
f"CHOICES={len(options)} "
|
| 3651 |
f"SEQUENCE={sequence} "
|
|
|
|
| 3692 |
(
|
| 3693 |
f"{request.get('skill_id','')}|"
|
| 3694 |
f"{request.get('template_id','')}|"
|
| 3695 |
+
f"{request.get('condition_slot_id','')}|"
|
| 3696 |
+
f"{request.get('diagnostic_condition','')}|"
|
| 3697 |
+
f"{request.get('runtime_generation_seed','')}|"
|
| 3698 |
+
f"{request.get('runtime_generation_attempt','')}|"
|
| 3699 |
f"{index + 1}"
|
| 3700 |
).encode("utf-8")
|
| 3701 |
).hexdigest()[:14]
|
|
|
|
| 4069 |
error_target=error_target,
|
| 4070 |
)
|
| 4071 |
request.update({
|
| 4072 |
+
"runtime_generation_seed": str(seed or ""),
|
| 4073 |
+
"runtime_generation_attempt": int(attempts),
|
| 4074 |
"difficulty": difficulty,
|
| 4075 |
"representation_type": representation_type,
|
| 4076 |
"cognitive_domain": cognitive_domain,
|
|
|
|
| 4309 |
|
| 4310 |
@staticmethod
|
| 4311 |
def question_fingerprint(question: Dict[str, Any]) -> str:
|
| 4312 |
+
"""
|
| 4313 |
+
بصمة السؤال.
|
| 4314 |
+
|
| 4315 |
+
في السؤال التشخيصي لا يجوز اعتبار نفس الصياغة مع Stimulus/Condition
|
| 4316 |
+
مختلف سؤالًا مكررًا؛ Evidence Signature هي التي تحسم الاستقلال.
|
| 4317 |
+
"""
|
| 4318 |
+
q = question if isinstance(question, dict) else {}
|
| 4319 |
+
skill_id = str(q.get("skill_id") or "").strip()
|
| 4320 |
text = re.sub(
|
| 4321 |
r"\s+",
|
| 4322 |
" ",
|
| 4323 |
+
str(q.get("question") or q.get("prompt") or "").strip().lower(),
|
| 4324 |
)
|
| 4325 |
+
slot = str(
|
| 4326 |
+
q.get("condition_slot_id")
|
| 4327 |
+
or (q.get("stimulus_plan") or {}).get("condition_slot_id")
|
| 4328 |
+
or ""
|
| 4329 |
+
).strip()
|
| 4330 |
+
condition = str(
|
| 4331 |
+
q.get("diagnostic_condition")
|
| 4332 |
+
or (q.get("stimulus_plan") or {}).get("diagnostic_condition")
|
| 4333 |
+
or ""
|
| 4334 |
+
).strip()
|
| 4335 |
+
|
| 4336 |
+
media_tokens = []
|
| 4337 |
+
for asset in q.get("media_assets") or []:
|
| 4338 |
+
if not isinstance(asset, dict):
|
| 4339 |
+
continue
|
| 4340 |
+
token = (
|
| 4341 |
+
asset.get("remote_path")
|
| 4342 |
+
or asset.get("source_id")
|
| 4343 |
+
or asset.get("path")
|
| 4344 |
+
or asset.get("url")
|
| 4345 |
+
or asset.get("asset_id")
|
| 4346 |
+
)
|
| 4347 |
+
if token:
|
| 4348 |
+
media_tokens.append(str(token))
|
| 4349 |
+
|
| 4350 |
+
if slot or condition or media_tokens:
|
| 4351 |
+
payload = "|".join([
|
| 4352 |
+
skill_id,
|
| 4353 |
+
text,
|
| 4354 |
+
f"slot={slot}",
|
| 4355 |
+
f"condition={condition}",
|
| 4356 |
+
"media=" + "|".join(sorted(media_tokens)),
|
| 4357 |
+
])
|
| 4358 |
+
else:
|
| 4359 |
+
payload = f"{skill_id}|{text}"
|
| 4360 |
+
return hashlib.sha256(payload.encode("utf-8")).hexdigest()[:24]
|
| 4361 |
|
| 4362 |
def get_challenge_questions(
|
| 4363 |
self,
|
|
|
|
| 5031 |
|
| 5032 |
item["question_role"] = question_role
|
| 5033 |
item["question_kind"] = question_role
|
| 5034 |
+
if str(item.get("skill_id") or "").startswith("AR-") and str(c.get("assessment_mode") or "") == "diagnostic":
|
| 5035 |
+
item["diagnostic_runtime_schema"] = "arabic_diag_runtime_v2"
|
| 5036 |
|
| 5037 |
ok, reason = _contract_question_is_acceptable(item, c)
|
| 5038 |
if not ok:
|
question_bank_manager.py
CHANGED
|
@@ -18,7 +18,7 @@ import json, os, threading
|
|
| 18 |
from pathlib import Path
|
| 19 |
from typing import Any, Dict, Iterable, List, Optional
|
| 20 |
|
| 21 |
-
VERSION = "
|
| 22 |
|
| 23 |
BANK_PERSISTENCE_OWNER = "QuestionBankManager"
|
| 24 |
QUESTION_BANK_REPO_KEY = (
|
|
@@ -811,6 +811,14 @@ class QuestionBankManager:
|
|
| 811 |
|
| 812 |
c = dict(c or {})
|
| 813 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 814 |
sid = str(
|
| 815 |
c.get("skill_id")
|
| 816 |
or c.get("target_skill_id")
|
|
|
|
| 18 |
from pathlib import Path
|
| 19 |
from typing import Any, Dict, Iterable, List, Optional
|
| 20 |
|
| 21 |
+
VERSION = "question_bank_manager_v30_arabic_runtime_schema_guard"
|
| 22 |
|
| 23 |
BANK_PERSISTENCE_OWNER = "QuestionBankManager"
|
| 24 |
QUESTION_BANK_REPO_KEY = (
|
|
|
|
| 811 |
|
| 812 |
c = dict(c or {})
|
| 813 |
|
| 814 |
+
# أسئلة العربية التشخيصية القديمة V29 قد تشترك في media path واحد
|
| 815 |
+
# لأن هوية الـstimulus لم تكن تتضمن condition/seed. لا نعيد استخدامها.
|
| 816 |
+
requested_subject = _norm_subject(c.get("subject"))
|
| 817 |
+
requested_mode = str(c.get("assessment_mode") or "").strip().lower()
|
| 818 |
+
if requested_subject == "arabic" and requested_mode == "diagnostic":
|
| 819 |
+
if str(row.get("diagnostic_runtime_schema") or "").strip() != "arabic_diag_runtime_v2":
|
| 820 |
+
return False
|
| 821 |
+
|
| 822 |
sid = str(
|
| 823 |
c.get("skill_id")
|
| 824 |
or c.get("target_skill_id")
|
strategy_manager.py
CHANGED
|
@@ -42,7 +42,7 @@ except Exception:
|
|
| 42 |
|
| 43 |
|
| 44 |
STRATEGY_MANAGER_VERSION = "strategy_manager_v14_arabic_qmatrix_conditions_runtime"
|
| 45 |
-
STRATEGY_SCHEMA_VERSION = "
|
| 46 |
|
| 47 |
|
| 48 |
class StrategyManager:
|
|
@@ -773,7 +773,12 @@ class StrategyManager:
|
|
| 773 |
"representation": str(template.get("representation") or ""),
|
| 774 |
"modality": str(template.get("modality") or ""),
|
| 775 |
"response_mode": str(template.get("response_mode") or ""),
|
| 776 |
-
"cognitive_domain": str(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 777 |
"preferred_question_types": [str(template.get("item_type"))] if template.get("item_type") else [],
|
| 778 |
"hypothesis_to_test": str(hypothesis or ""),
|
| 779 |
"exclude_question_ids": excluded_ids,
|
|
|
|
| 42 |
|
| 43 |
|
| 44 |
STRATEGY_MANAGER_VERSION = "strategy_manager_v14_arabic_qmatrix_conditions_runtime"
|
| 45 |
+
STRATEGY_SCHEMA_VERSION = "strategy_schema_v15"
|
| 46 |
|
| 47 |
|
| 48 |
class StrategyManager:
|
|
|
|
| 773 |
"representation": str(template.get("representation") or ""),
|
| 774 |
"modality": str(template.get("modality") or ""),
|
| 775 |
"response_mode": str(template.get("response_mode") or ""),
|
| 776 |
+
"cognitive_domain": str(
|
| 777 |
+
template.get("normalized_cognitive_domain")
|
| 778 |
+
or (row.get("cognitive_domain_profile") or {}).get("primary")
|
| 779 |
+
or contract.get("cognitive_domain")
|
| 780 |
+
or "applying"
|
| 781 |
+
),
|
| 782 |
"preferred_question_types": [str(template.get("item_type"))] if template.get("item_type") else [],
|
| 783 |
"hypothesis_to_test": str(hypothesis or ""),
|
| 784 |
"exclude_question_ids": excluded_ids,
|