mirofish-simulator 0.8.0__tar.gz
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.
- mirofish_simulator-0.8.0/.gitignore +60 -0
- mirofish_simulator-0.8.0/CHANGELOG.md +67 -0
- mirofish_simulator-0.8.0/INCEPTBENCH_INTEGRATION.md +162 -0
- mirofish_simulator-0.8.0/PKG-INFO +290 -0
- mirofish_simulator-0.8.0/PLAN_v2.md +927 -0
- mirofish_simulator-0.8.0/README.md +262 -0
- mirofish_simulator-0.8.0/demo_accessibility.py +161 -0
- mirofish_simulator-0.8.0/docs/API.md +306 -0
- mirofish_simulator-0.8.0/examples/agentic_demo.py +73 -0
- mirofish_simulator-0.8.0/pyproject.toml +46 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/__init__.py +254 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/__init__.py +95 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/analyzer.py +348 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/archetypes.py +284 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/cognitive_load.py +354 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/prior_knowledge.py +406 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/reading_level.py +470 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/recommendations.py +307 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/vocabulary.py +322 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/vocabulary_data/__init__.py +59 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/vocabulary_data/academic.py +211 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/vocabulary_data/core_words.py +194 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/vocabulary_data/subject_specific.py +250 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/accessibility/vocabulary_data/suggestions.py +165 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/__init__.py +80 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/knowledge.py +546 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/perception.py +369 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/runner.py +302 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/student_agent.py +277 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/v2/__init__.py +79 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/v2/agentic_orchestrator.py +229 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/v2/answer_agent.py +358 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/v2/distractor_agent.py +260 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/v2/knowledge_agent.py +309 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/v2/orchestrator.py +339 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/v2/perception_agent.py +201 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/v2/selector_agent.py +288 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/v2/student_model_agent.py +214 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/agents/v2/verifier_agent.py +216 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/cognition.py +794 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/comparative.py +439 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/misconceptions.py +302 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/profiles.py +198 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/simulator.py +773 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/taxonomies/__init__.py +52 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/taxonomies/ap_government.py +251 -0
- mirofish_simulator-0.8.0/src/mirofish_simulator/taxonomies/mathematics.py +355 -0
- mirofish_simulator-0.8.0/test_agents.py +152 -0
- mirofish_simulator-0.8.0/test_agents_hard.py +90 -0
- mirofish_simulator-0.8.0/test_v2_agents.py +268 -0
- mirofish_simulator-0.8.0/test_wrong_knowledge.py +187 -0
- mirofish_simulator-0.8.0/tests/test_integration.py +167 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# OS
|
|
2
|
+
.DS_Store
|
|
3
|
+
Thumbs.db
|
|
4
|
+
|
|
5
|
+
# 环境变量(保护敏感信息)
|
|
6
|
+
.env
|
|
7
|
+
.env.local
|
|
8
|
+
.env.*.local
|
|
9
|
+
.env.development
|
|
10
|
+
.env.test
|
|
11
|
+
.env.production
|
|
12
|
+
|
|
13
|
+
# Python
|
|
14
|
+
__pycache__/
|
|
15
|
+
*.py[cod]
|
|
16
|
+
*$py.class
|
|
17
|
+
*.so
|
|
18
|
+
.Python
|
|
19
|
+
.venv/
|
|
20
|
+
venv/
|
|
21
|
+
ENV/
|
|
22
|
+
.eggs/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
dist/
|
|
25
|
+
build/
|
|
26
|
+
|
|
27
|
+
# Node.js
|
|
28
|
+
node_modules/
|
|
29
|
+
npm-debug.log*
|
|
30
|
+
yarn-debug.log*
|
|
31
|
+
yarn-error.log*
|
|
32
|
+
|
|
33
|
+
# IDE
|
|
34
|
+
.vscode/
|
|
35
|
+
.idea/
|
|
36
|
+
*.swp
|
|
37
|
+
*.swo
|
|
38
|
+
|
|
39
|
+
# 测试
|
|
40
|
+
.pytest_cache/
|
|
41
|
+
.coverage
|
|
42
|
+
htmlcov/
|
|
43
|
+
|
|
44
|
+
# Cursor
|
|
45
|
+
.cursor/
|
|
46
|
+
.claude/
|
|
47
|
+
|
|
48
|
+
# 文档与测试程序
|
|
49
|
+
mydoc/
|
|
50
|
+
mytest/
|
|
51
|
+
|
|
52
|
+
# 日志文件
|
|
53
|
+
backend/logs/
|
|
54
|
+
*.log
|
|
55
|
+
|
|
56
|
+
# 上传文件
|
|
57
|
+
backend/uploads/
|
|
58
|
+
|
|
59
|
+
# Docker 数据
|
|
60
|
+
data/
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to mirofish-simulator will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.8.0] - 2024-03-16
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Agentic Misconception-Matching Architecture** - New approach that produces realistic wrong answers
|
|
10
|
+
- `AgenticOrchestrator` - Main entry point for student simulation
|
|
11
|
+
- `DistractorAgent` - Maps each wrong answer to the misconception that leads to it
|
|
12
|
+
- `StudentModelAgent` - Models what a student believes (correct and incorrect)
|
|
13
|
+
- `SelectorAgent` - Matches student misconceptions to appropriate answers
|
|
14
|
+
|
|
15
|
+
- **Factual vs Conceptual Question Handling**
|
|
16
|
+
- Distinguishes questions requiring specific knowledge (numbers, dates) from conceptual questions
|
|
17
|
+
- Factual questions require exact knowledge; vague beliefs aren't enough
|
|
18
|
+
|
|
19
|
+
- **Batch Simulation** - `simulate_batch()` method for efficient multi-student simulation
|
|
20
|
+
- Distractor analysis done once and reused for all students
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Default architecture is now agentic misconception-matching (previous approach moved to legacy)
|
|
25
|
+
- Improved student differentiation by grade and archetype
|
|
26
|
+
- Better handling of high-familiarity students who have correct beliefs
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- LLM "cheating" problem - the new architecture doesn't try to make the LLM "not know" things
|
|
31
|
+
- Inconsistency between reasoning and selection in SelectorAgent
|
|
32
|
+
|
|
33
|
+
### Deprecated
|
|
34
|
+
|
|
35
|
+
- `StudentSimulator` (v2 legacy) - Still available but AgenticOrchestrator is recommended
|
|
36
|
+
- `simulate_student()` / `simulate_classroom()` - Use AgenticOrchestrator instead
|
|
37
|
+
|
|
38
|
+
## [0.7.0] - 2024-03-15
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- Multi-agent architecture with verification
|
|
43
|
+
- KnowledgeAgent, PerceptionAgent, AnswerAgent, VerifierAgent
|
|
44
|
+
- Catches LLM "cheating" via consistency verification
|
|
45
|
+
|
|
46
|
+
## [0.6.0] - 2024-03-14
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- Agent-based simulation (single agent approach)
|
|
51
|
+
- Accessibility analysis module
|
|
52
|
+
|
|
53
|
+
## [0.5.0] - 2024-03-13
|
|
54
|
+
|
|
55
|
+
### Added
|
|
56
|
+
|
|
57
|
+
- Misconception analysis
|
|
58
|
+
- Comparative quiz analysis
|
|
59
|
+
- Subject taxonomies (AP Government, Mathematics)
|
|
60
|
+
|
|
61
|
+
## [0.4.0] - 2024-03-12
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
|
|
65
|
+
- Initial student simulation
|
|
66
|
+
- Student archetypes
|
|
67
|
+
- Basic accessibility analysis
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# MiroFish + InceptBench Integration
|
|
2
|
+
|
|
3
|
+
## What MiroFish Provides
|
|
4
|
+
|
|
5
|
+
InceptBench already has LLM-based distractor analysis. MiroFish adds:
|
|
6
|
+
|
|
7
|
+
### 1. Grade-Level Accessibility Analysis (Reliable)
|
|
8
|
+
**Not duplicated by InceptBench**: Deterministic analysis of whether content is readable at target grade.
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
from mirofish_simulator.accessibility import AccessibilityAnalyzer
|
|
12
|
+
|
|
13
|
+
analyzer = AccessibilityAnalyzer()
|
|
14
|
+
result = await analyzer.analyze(question, target_grade=5)
|
|
15
|
+
|
|
16
|
+
# Returns:
|
|
17
|
+
{
|
|
18
|
+
"reading_level": {
|
|
19
|
+
"flesch_kincaid_grade": 8.3,
|
|
20
|
+
"target_grade": 5,
|
|
21
|
+
"verdict": "too_advanced" # 3+ grades above
|
|
22
|
+
},
|
|
23
|
+
"vocabulary": {
|
|
24
|
+
"issues": [
|
|
25
|
+
{"word": "ratify", "grade_required": 9, "suggestions": ["approve", "accept"]},
|
|
26
|
+
{"word": "electoral", "grade_required": 8, "suggestions": ["voting", "election"]}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"recommendations": [
|
|
30
|
+
{"fix": "Replace 'ratify' with 'approve' or 'agree to'"},
|
|
31
|
+
{"fix": "Simplify sentence structure (current: 17 words avg)"}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**InceptBench Integration Point**: Add `accessibility` field to question evaluation output.
|
|
37
|
+
|
|
38
|
+
### 2. Vocabulary Database (5000+ words)
|
|
39
|
+
Word-to-grade mapping from Dolch, Fry, AWL word lists.
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from mirofish_simulator.accessibility import get_word_grade_level
|
|
43
|
+
|
|
44
|
+
get_word_grade_level("ratify") # → 9
|
|
45
|
+
get_word_grade_level("vote") # → 4
|
|
46
|
+
get_word_grade_level("dog") # → 1
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 3. Prior Knowledge Requirements
|
|
50
|
+
What concepts a student needs to answer the question.
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
result.prior_knowledge.required_concepts
|
|
54
|
+
# → ["Electoral College mechanics", "How presidents are elected", "State-level voting"]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## What MiroFish Does NOT Provide (Reliably)
|
|
58
|
+
|
|
59
|
+
### ❌ Accuracy Prediction
|
|
60
|
+
LLMs cannot constrain their knowledge through prompting. Agent-based simulation will show artificially high accuracy because the underlying model "knows" correct answers.
|
|
61
|
+
|
|
62
|
+
### ❌ IRT Parameters
|
|
63
|
+
We don't have calibration data. Any difficulty/discrimination values would be fabricated.
|
|
64
|
+
|
|
65
|
+
### ❌ Response Distribution Prediction
|
|
66
|
+
Can't reliably predict which wrong answers students would choose.
|
|
67
|
+
|
|
68
|
+
## Recommended Integration
|
|
69
|
+
|
|
70
|
+
### Option A: Accessibility as Evaluation Dimension
|
|
71
|
+
|
|
72
|
+
Add to existing InceptBench evaluators:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
# In InceptBench evaluation pipeline
|
|
76
|
+
from mirofish_simulator.accessibility import AccessibilityAnalyzer
|
|
77
|
+
|
|
78
|
+
class InceptBenchEvaluator:
|
|
79
|
+
def __init__(self):
|
|
80
|
+
self.accessibility = AccessibilityAnalyzer()
|
|
81
|
+
# ... other evaluators
|
|
82
|
+
|
|
83
|
+
async def evaluate(self, question, target_grade=8):
|
|
84
|
+
result = {
|
|
85
|
+
# Existing dimensions
|
|
86
|
+
"distractor_quality": await self.eval_distractors(question),
|
|
87
|
+
"factual_accuracy": await self.eval_accuracy(question),
|
|
88
|
+
|
|
89
|
+
# NEW: Accessibility dimension
|
|
90
|
+
"accessibility": await self.accessibility.analyze(question, target_grade)
|
|
91
|
+
}
|
|
92
|
+
return result
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Option B: Standalone Accessibility Check
|
|
96
|
+
|
|
97
|
+
Separate endpoint for accessibility validation:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
# POST /api/inceptbench/accessibility
|
|
101
|
+
{
|
|
102
|
+
"question": {...},
|
|
103
|
+
"target_grade": 5
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
# Response
|
|
107
|
+
{
|
|
108
|
+
"readable": false,
|
|
109
|
+
"reading_level": 8.3,
|
|
110
|
+
"target_grade": 5,
|
|
111
|
+
"issues": [...],
|
|
112
|
+
"recommendations": [...]
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Option C: CLI Flag
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
inceptbench evaluate question.json --check-accessibility --grade 5
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## File Changes for Integration
|
|
123
|
+
|
|
124
|
+
### Backend
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
# backend/app/api/inceptbench.py
|
|
128
|
+
|
|
129
|
+
@router.post("/accessibility")
|
|
130
|
+
async def check_accessibility(
|
|
131
|
+
question: QuestionModel,
|
|
132
|
+
target_grade: int = 8,
|
|
133
|
+
):
|
|
134
|
+
from mirofish_simulator.accessibility import AccessibilityAnalyzer
|
|
135
|
+
analyzer = AccessibilityAnalyzer()
|
|
136
|
+
result = await analyzer.analyze(question.dict(), target_grade)
|
|
137
|
+
return result.to_dict()
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Package Export
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
# mirofish_simulator/__init__.py
|
|
144
|
+
|
|
145
|
+
from .accessibility import (
|
|
146
|
+
AccessibilityAnalyzer,
|
|
147
|
+
AccessibilityResult,
|
|
148
|
+
flesch_kincaid_grade,
|
|
149
|
+
get_word_grade_level,
|
|
150
|
+
)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Value Proposition
|
|
154
|
+
|
|
155
|
+
| What InceptBench Has | What MiroFish Adds |
|
|
156
|
+
|---------------------|-------------------|
|
|
157
|
+
| LLM distractor analysis | Deterministic readability scores |
|
|
158
|
+
| Factual accuracy check | Vocabulary-to-grade mapping |
|
|
159
|
+
| Subject/topic tagging | Prior knowledge requirements |
|
|
160
|
+
| - | Actionable simplification recommendations |
|
|
161
|
+
|
|
162
|
+
MiroFish is NOT a replacement for InceptBench evaluation. It's a complementary tool for content accessibility validation.
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mirofish-simulator
|
|
3
|
+
Version: 0.8.0
|
|
4
|
+
Summary: Agentic student simulation using misconception matching - realistic wrong answers without LLM cheating
|
|
5
|
+
Project-URL: Homepage, https://github.com/StanHus/MiroFish
|
|
6
|
+
Project-URL: Documentation, https://github.com/StanHus/MiroFish#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/StanHus/MiroFish
|
|
8
|
+
Author: MiroFish Team
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: ai,education,evaluation,llm,misconceptions,simulation,student-modeling
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Education
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Education
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: openai>=1.0.0
|
|
23
|
+
Requires-Dist: pydantic>=2.0.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# MiroFish Simulator
|
|
30
|
+
|
|
31
|
+
**Agentic student simulation** using misconception matching - produces realistic wrong answers without LLM "cheating".
|
|
32
|
+
|
|
33
|
+
## The Problem
|
|
34
|
+
|
|
35
|
+
Traditional LLM-based student simulation doesn't work: **LLMs know everything**. When you ask GPT-4 to "act like a 5th grader who doesn't know about electoral votes", it still picks 270 because it can't actually "not know" things.
|
|
36
|
+
|
|
37
|
+
## The Solution: Misconception Matching
|
|
38
|
+
|
|
39
|
+
Instead of trying to suppress LLM knowledge (impossible), we use a **multi-agent pipeline** that matches student misconceptions to wrong answers:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
43
|
+
│ AgenticOrchestrator │
|
|
44
|
+
│ │
|
|
45
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
46
|
+
│ │ DISTRACTOR │ │ STUDENT │ │ SELECTOR │ │
|
|
47
|
+
│ │ AGENT │──▶│ MODEL │──▶│ AGENT │ │
|
|
48
|
+
│ │ │ │ AGENT │ │ │ │
|
|
49
|
+
│ │ "What error │ │ "What does │ │ "Match │ │
|
|
50
|
+
│ │ leads to │ │ this student│ │ misconception│ │
|
|
51
|
+
│ │ each wrong │ │ believe?" │ │ to answer" │ │
|
|
52
|
+
│ │ answer?" │ │ │ │ │ │
|
|
53
|
+
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
54
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### How It Works
|
|
58
|
+
|
|
59
|
+
1. **DistractorAgent** - Analyzes each wrong answer to identify what misconception leads to it
|
|
60
|
+
- "Option A (218) catches students who confuse electoral votes with House majority"
|
|
61
|
+
- "Option D (435) catches students who confuse with total Congress members"
|
|
62
|
+
|
|
63
|
+
2. **StudentModelAgent** - Models what a specific student believes and misconceives
|
|
64
|
+
- Grade 5 class_clown: Low familiarity, vague beliefs, common misconceptions
|
|
65
|
+
- Grade 11 honors: High familiarity, specific knowledge, few misconceptions
|
|
66
|
+
|
|
67
|
+
3. **SelectorAgent** - Matches the student's misconceptions to the appropriate answer
|
|
68
|
+
- If student has misconception matching a distractor → pick that distractor
|
|
69
|
+
- If student has correct belief with high familiarity → pick correct answer
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import asyncio
|
|
75
|
+
from mirofish_simulator import AgenticOrchestrator
|
|
76
|
+
|
|
77
|
+
orchestrator = AgenticOrchestrator()
|
|
78
|
+
|
|
79
|
+
question = {
|
|
80
|
+
"text": "How many electoral votes are needed to win the presidency?",
|
|
81
|
+
"options": ["218", "270", "300", "435"],
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async def main():
|
|
85
|
+
# Single student
|
|
86
|
+
result = await orchestrator.simulate(
|
|
87
|
+
question=question,
|
|
88
|
+
correct_answer="B",
|
|
89
|
+
grade=5,
|
|
90
|
+
archetype="class_clown",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
print(f"Selected: {result.selected}") # "C" (wrong!)
|
|
94
|
+
print(f"Correct: {result.is_correct}") # False
|
|
95
|
+
print(f"Familiarity: {result.student_model.topic_familiarity:.0%}") # 40%
|
|
96
|
+
print(f"Misconception: {result.selection_result.misconception_matched}")
|
|
97
|
+
|
|
98
|
+
asyncio.run(main())
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Batch Simulation
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
# Efficient - distractor analysis done once, reused for all students
|
|
105
|
+
results = await orchestrator.simulate_batch(
|
|
106
|
+
question=question,
|
|
107
|
+
correct_answer="B",
|
|
108
|
+
students=[
|
|
109
|
+
{"grade": 5, "archetype": "class_clown"},
|
|
110
|
+
{"grade": 8, "archetype": "average_student"},
|
|
111
|
+
{"grade": 11, "archetype": "honors_overachiever"},
|
|
112
|
+
]
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
for r in results:
|
|
116
|
+
status = "✓" if r.is_correct else "✗"
|
|
117
|
+
print(f"Grade {r.grade} {r.archetype}: {r.selected}) {status}")
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Realistic Results
|
|
121
|
+
|
|
122
|
+
The system produces realistic differentiation:
|
|
123
|
+
|
|
124
|
+
| Student | Electoral Votes (hard) | Branches of Gov (easy) |
|
|
125
|
+
|---------|----------------------|----------------------|
|
|
126
|
+
| Grade 5 class_clown | ✗ | ✓ |
|
|
127
|
+
| Grade 8 average | ✗ | ✓ |
|
|
128
|
+
| Grade 11 honors | ✓ | ✓ |
|
|
129
|
+
|
|
130
|
+
- **Easy questions**: All students get them right (basic civics)
|
|
131
|
+
- **Hard factual questions**: Only students with specific knowledge get them right
|
|
132
|
+
- **Archetypes matter**: class_clown (low familiarity) gets more wrong than honors
|
|
133
|
+
|
|
134
|
+
## Agent Details
|
|
135
|
+
|
|
136
|
+
### DistractorAgent
|
|
137
|
+
|
|
138
|
+
Maps each wrong answer to the misconception that leads to it.
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
from mirofish_simulator import DistractorAgent
|
|
142
|
+
|
|
143
|
+
agent = DistractorAgent()
|
|
144
|
+
analysis = await agent.analyze(question, correct_answer="B")
|
|
145
|
+
|
|
146
|
+
for mapping in analysis.mappings:
|
|
147
|
+
if not mapping.is_correct:
|
|
148
|
+
print(f"{mapping.option}) {mapping.option_text}")
|
|
149
|
+
print(f" Misconception: {mapping.leads_from_misconception}")
|
|
150
|
+
print(f" Grade appeal: {mapping.grade_level_appeal}")
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### StudentModelAgent
|
|
154
|
+
|
|
155
|
+
Models what a student believes (correct and incorrect).
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from mirofish_simulator import StudentModelAgent
|
|
159
|
+
|
|
160
|
+
agent = StudentModelAgent()
|
|
161
|
+
student = await agent.model_student(question, grade=5, archetype="class_clown")
|
|
162
|
+
|
|
163
|
+
print(f"Beliefs: {student.beliefs}")
|
|
164
|
+
print(f"Misconceptions: {student.misconceptions}")
|
|
165
|
+
print(f"Topic familiarity: {student.topic_familiarity:.0%}")
|
|
166
|
+
print(f"Guesses when unsure: {student.guesses_when_unsure}")
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### SelectorAgent
|
|
170
|
+
|
|
171
|
+
Matches student misconceptions to answers.
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
from mirofish_simulator import SelectorAgent
|
|
175
|
+
|
|
176
|
+
agent = SelectorAgent()
|
|
177
|
+
selection = await agent.select(question, distractor_analysis, student_model)
|
|
178
|
+
|
|
179
|
+
print(f"Selected: {selection.selected}")
|
|
180
|
+
print(f"Reason: {selection.selection_reason}")
|
|
181
|
+
print(f"Misconception matched: {selection.misconception_matched}")
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Archetypes
|
|
185
|
+
|
|
186
|
+
| Archetype | Familiarity | Behavior |
|
|
187
|
+
|-----------|-------------|----------|
|
|
188
|
+
| `honors_overachiever` | High (80%+) | Specific knowledge, confident |
|
|
189
|
+
| `average_student` | Medium (60-70%) | Taught content, some gaps |
|
|
190
|
+
| `class_clown` | Low (40%) | Minimal attention, guesses |
|
|
191
|
+
| `esl_student` | Medium | Core concepts solid, vocabulary issues |
|
|
192
|
+
| `disengaged_but_smart` | Variable | Has ability, inconsistent |
|
|
193
|
+
| `quiet_thinker` | Medium | Second-guesses self |
|
|
194
|
+
| `debate_club_kid` | High in interests | Good at arguments |
|
|
195
|
+
|
|
196
|
+
## Installation
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
pip install mirofish-simulator
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Or from source:
|
|
203
|
+
```bash
|
|
204
|
+
cd packages/mirofish-simulator
|
|
205
|
+
pip install -e .
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Environment
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
export OPENAI_API_KEY="sk-..."
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## API Reference
|
|
215
|
+
|
|
216
|
+
### AgenticOrchestrator
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
orchestrator = AgenticOrchestrator(
|
|
220
|
+
api_key: str = None, # Uses OPENAI_API_KEY env var if not provided
|
|
221
|
+
base_url: str = None, # Custom API base URL
|
|
222
|
+
model: str = "gpt-4o-mini",
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# Single simulation
|
|
226
|
+
result = await orchestrator.simulate(
|
|
227
|
+
question: dict, # {"text": "...", "options": [...]}
|
|
228
|
+
correct_answer: str, # "A", "B", "C", or "D"
|
|
229
|
+
grade: int, # 1-12
|
|
230
|
+
archetype: str, # See archetypes above
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Batch simulation (efficient)
|
|
234
|
+
results = await orchestrator.simulate_batch(
|
|
235
|
+
question: dict,
|
|
236
|
+
correct_answer: str,
|
|
237
|
+
students: list, # [{"grade": 5, "archetype": "..."}, ...]
|
|
238
|
+
)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### AgenticSimulationResult
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
result.selected # "A", "B", "C", "D"
|
|
245
|
+
result.selected_text # The full answer text
|
|
246
|
+
result.is_correct # True/False
|
|
247
|
+
result.grade # Student grade
|
|
248
|
+
result.archetype # Student archetype
|
|
249
|
+
|
|
250
|
+
# Agent outputs
|
|
251
|
+
result.distractor_analysis # DistractorAnalysis
|
|
252
|
+
result.student_model # StudentModel
|
|
253
|
+
result.selection_result # SelectionResult
|
|
254
|
+
|
|
255
|
+
# Methods
|
|
256
|
+
result.to_dict() # Full dict representation
|
|
257
|
+
result.summary() # Human-readable summary
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Accessibility Analysis (Static)
|
|
261
|
+
|
|
262
|
+
For deterministic content analysis without LLM:
|
|
263
|
+
|
|
264
|
+
```python
|
|
265
|
+
from mirofish_simulator import AccessibilityAnalyzer
|
|
266
|
+
|
|
267
|
+
analyzer = AccessibilityAnalyzer()
|
|
268
|
+
result = await analyzer.analyze(content, target_grade=5)
|
|
269
|
+
|
|
270
|
+
print(f"Reading Level: Grade {result.reading_level.flesch_kincaid_grade}")
|
|
271
|
+
print(f"Vocabulary Issues: {len(result.vocabulary.issues)}")
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Version History
|
|
275
|
+
|
|
276
|
+
### v0.8.0 (Current)
|
|
277
|
+
- **Agentic misconception-matching architecture**
|
|
278
|
+
- DistractorAgent, StudentModelAgent, SelectorAgent
|
|
279
|
+
- Factual vs conceptual question handling
|
|
280
|
+
- Realistic wrong answers without LLM cheating
|
|
281
|
+
|
|
282
|
+
### v0.7.0
|
|
283
|
+
- Multi-agent with verification (deprecated approach)
|
|
284
|
+
|
|
285
|
+
### v0.6.0
|
|
286
|
+
- Single agent simulation
|
|
287
|
+
|
|
288
|
+
## License
|
|
289
|
+
|
|
290
|
+
MIT
|