File size: 7,743 Bytes
cd8c2bb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import json
import hashlib
from typing import List, Dict, Any, Optional
from pathlib import Path
import sqlite3

class KnowledgeBase:
    """Knowledge base for educational content with fact-grounded explanations."""
    
    def __init__(self, db_path: str = "knowledge_base.sqlite"):
        self.db_path = db_path
        self._init_database()
        self._load_sample_content()
    
    def _init_database(self):
        """Initialize SQLite database for knowledge storage."""
        with sqlite3.connect(self.db_path) as conn:
            conn.execute("""
                CREATE TABLE IF NOT EXISTS knowledge_items (
                    id TEXT PRIMARY KEY,
                    skill TEXT NOT NULL,
                    content TEXT NOT NULL,
                    facts TEXT NOT NULL,
                    difficulty REAL DEFAULT 0.5,
                    prerequisite_skills TEXT,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
            """)
            conn.execute("""
                CREATE INDEX IF NOT EXISTS idx_skill ON knowledge_items(skill)
            """)
    
    def _load_sample_content(self):
        """Load sample educational content for testing."""
        sample_items = [
            {
                "id": "algebra_simplify_001",
                "skill": "algebra_simplification",
                "content": "To simplify algebraic expressions, combine like terms by adding or subtracting coefficients of the same variable. For example, 3x + 2x = 5x.",
                "facts": [
                    "Like terms have the same variable raised to the same power",
                    "Coefficients of like terms can be combined through addition",
                    "The variable part remains unchanged when combining like terms"
                ],
                "difficulty": 0.3,
                "prerequisite_skills": ["basic_arithmetic", "variables"]
            },
            {
                "id": "algebra_simplify_002", 
                "skill": "algebra_simplification",
                "content": "When simplifying expressions with division, first combine like terms in the numerator, then divide by the denominator. Example: (3x + 2x) / 5 = 5x / 5 = x.",
                "facts": [
                    "Division applies to the entire expression",
                    "Simplify numerator before dividing",
                    "A term divided by itself equals 1"
                ],
                "difficulty": 0.5,
                "prerequisite_skills": ["algebra_simplification", "division"]
            },
            {
                "id": "linear_eq_001",
                "skill": "linear_equations",
                "content": "To solve linear equations, isolate the variable by performing inverse operations. Add/subtract to isolate the variable term, then multiply/divide to solve for the variable.",
                "facts": [
                    "Inverse operations undo each other (addition ↔ subtraction, multiplication ↔ division)",
                    "Apply the same operation to both sides to maintain equality",
                    "Goal is to isolate the variable on one side"
                ],
                "difficulty": 0.4,
                "prerequisite_skills": ["algebra_simplification"]
            },
            {
                "id": "fraction_div_001",
                "skill": "fraction_operations",
                "content": "To divide fractions, multiply by the reciprocal of the second fraction. The reciprocal of a/b is b/a.",
                "facts": [
                    "Division is equivalent to multiplication by the reciprocal",
                    "Reciprocal flips numerator and denominator",
                    "Multiply numerators together and denominators together"
                ],
                "difficulty": 0.6,
                "prerequisite_skills": ["fraction_multiplication"]
            },
            {
                "id": "ratio_001",
                "skill": "ratios",
                "content": "Ratios compare quantities. To solve ratio problems, set up proportions and cross-multiply. a:b = c:d means a×d = b×c.",
                "facts": [
                    "Ratios show relative sizes of quantities",
                    "Equivalent ratios have the same value when simplified",
                    "Cross-multiplication solves proportion equations"
                ],
                "difficulty": 0.5,
                "prerequisite_skills": ["proportions"]
            }
        ]
        
        with sqlite3.connect(self.db_path) as conn:
            for item in sample_items:
                conn.execute("""
                    INSERT OR REPLACE INTO knowledge_items 
                    (id, skill, content, facts, difficulty, prerequisite_skills)
                    VALUES (?, ?, ?, ?, ?, ?)
                """, (
                    item["id"],
                    item["skill"], 
                    item["content"],
                    json.dumps(item["facts"]),
                    item["difficulty"],
                    json.dumps(item["prerequisite_skills"])
                ))
    
    def retrieve_by_skill(self, skill: str, limit: int = 3) -> List[Dict[str, Any]]:
        """Retrieve knowledge items for a specific skill."""
        with sqlite3.connect(self.db_path) as conn:
            conn.row_factory = sqlite3.Row
            cursor = conn.execute("""
                SELECT * FROM knowledge_items 
                WHERE skill = ? OR skill LIKE ?
                ORDER BY difficulty ASC
                LIMIT ?
            """, (skill, f"%{skill}%", limit))
            
            results = []
            for row in cursor.fetchall():
                results.append({
                    "id": row["id"],
                    "skill": row["skill"],
                    "content": row["content"],
                    "facts": json.loads(row["facts"]),
                    "difficulty": row["difficulty"],
                    "prerequisite_skills": json.loads(row["prerequisite_skills"])
                })
            return results
    
    def retrieve_by_query(self, query: str, limit: int = 3) -> List[Dict[str, Any]]:
        """Retrieve knowledge items based on text search."""
        with sqlite3.connect(self.db_path) as conn:
            conn.row_factory = sqlite3.Row
            cursor = conn.execute("""
                SELECT * FROM knowledge_items 
                WHERE content LIKE ? OR skill LIKE ?
                ORDER BY difficulty ASC
                LIMIT ?
            """, (f"%{query}%", f"%{query}%", limit))
            
            results = []
            for row in cursor.fetchall():
                results.append({
                    "id": row["id"],
                    "skill": row["skill"],
                    "content": row["content"],
                    "facts": json.loads(row["facts"]),
                    "difficulty": row["difficulty"],
                    "prerequisite_skills": json.loads(row["prerequisite_skills"])
                })
            return results
    
    def add_knowledge_item(self, item: Dict[str, Any]):
        """Add a new knowledge item to the database."""
        with sqlite3.connect(self.db_path) as conn:
            conn.execute("""
                INSERT OR REPLACE INTO knowledge_items 
                (id, skill, content, facts, difficulty, prerequisite_skills)
                VALUES (?, ?, ?, ?, ?, ?)
            """, (
                item["id"],
                item["skill"],
                item["content"], 
                json.dumps(item["facts"]),
                item["difficulty"],
                json.dumps(item.get("prerequisite_skills", []))
            ))