# ai_tutor_full.py import cv2 import numpy as np import re from PIL import Image from pytesseract import image_to_string from datetime import datetime # === Bộ nhớ học sinh === student_memory = [] def log_interaction(student_id, question, answer, correct, topic, emotion): student_memory.append({ "student_id": student_id, "question": question, "answer": answer, "correct": correct, "topic": topic, "emotion": emotion, "timestamp": datetime.now() }) # === Phân tích cảm xúc === def detect_emotion(text): if "giúp" in text or "khó" in text: return "lo lắng" elif "dễ" in text or "biết rồi" in text: return "tự tin" return "trung tính" # === Phân tích đề bài === def detect_subject(text: str) -> str: subjects = { "Ngữ Văn": ["ngữ văn", "văn học", "tập làm văn"], "Toán": ["toán", "số học", "hình học"], "Lịch Sử": ["lịch sử", "sử học"], "Địa Lí": ["địa lí", "địa lý"], "Sinh học": ["sinh học", "sinh vật"], "Vật lí": ["vật lí", "vật lý"], "Hóa học": ["hóa học", "hóa"], "Tiếng Anh": ["tiếng anh", "english"], "GDCD": ["giáo dục công dân", "gdcd"], "Tin học": ["tin học", "công nghệ thông tin"] } for subject, keywords in subjects.items(): for keyword in keywords: if keyword.lower() in text.lower(): return subject return "Không xác định" def detect_grade(text: str) -> str: match = re.search(r"lớp\s*(\d+)", text.lower()) return match.group(1) if match else "Không xác định" def detect_series(text: str) -> str: series_keywords = { "Chân Trời Sáng Tạo": ["chân trời sáng tạo"], "Kết Nối Tri Thức": ["kết nối tri thức"], "Cánh Diều": ["cánh diều"] } for series, keywords in series_keywords.items(): for keyword in keywords: if keyword.lower() in text.lower(): return series return "Không xác định" def detect_metadata(text: str) -> dict: return { "subject": detect_subject(text), "grade": detect_grade(text), "series": detect_series(text) } # === Làm nét ảnh === def enhance_image(image_path: str) -> Image.Image: img = cv2.imread(image_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) contrast = clahe.apply(gray) denoised = cv2.GaussianBlur(contrast, (3, 3), 0) kernel = np.array([[0, -1, 0], [-1, 5,-1], [0, -1, 0]]) sharpened = cv2.filter2D(denoised, -1, kernel) return Image.fromarray(sharpened) # === Trích xuất văn bản từ ảnh === def extract_text_from_image(image: Image.Image) -> str: return image_to_string(image, lang="vie") # === Tìm sách giáo khoa và kiểm tra độ khớp === def verify_alignment(question: str, textbook: str) -> tuple: score = 0.85 if question in textbook else 0.4 return score > 0.6, score def find_and_verify_textbook(subject: str, grade: str, series: str, extracted_text: str) -> dict: pdf_url = f"https://giaovien.net/sach/{subject.lower()}_lop_{grade}_{series.replace(' ', '_')}.pdf" textbook_content = "Nội dung sách giáo khoa giả lập" is_aligned, score = verify_alignment(extracted_text, textbook_content) return { "status": "Tìm thấy sách", "url": pdf_url, "khớp_nội_dung": is_aligned, "độ_tương_đồng": score } # === Chọn mô hình AI phù hợp === def route_to_model(question: str, image_attached: bool = False): if len(question) > 500 or image_attached: return "Gemini 2.5 Pro" return "ChatGPT-5.0" # === Đánh giá độ chắc chắn === def estimate_confidence(answer: str) -> float: return 0.9 if "chắc chắn" in answer else 0.5 # === Học từ lỗi sai === def log_error(student_id: str, question: str): with open("error_log.txt", "a", encoding="utf-8") as f: f.write(f"{student_id} | {question}\n") def retrain_on_correct_data(question: str): correct_answer = "Đáp án đúng từ nguồn xác thực" print(f"✅ Đã cập nhật tri thức cho câu hỏi: {question}") # === Xử lý đề bài === def process_homework(image_path: str, student_id: str): enhanced = enhance_image(image_path) extracted_text = extract_text_from_image(enhanced) metadata = detect_metadata(extracted_text) emotion = detect_emotion(extracted_text) textbook = find_and_verify_textbook( subject=metadata["subject"], grade=metadata["grade"], series=metadata["series"], extracted_text=extracted_text ) model = route_to_model(extracted_text, image_attached=True) answer = f"Giải bằng {model} (giả lập)" confidence = estimate_confidence(answer) if confidence < 0.5: log_error(student_id, extracted_text) retrain_on_correct_data(extracted_text) log_interaction(student_id, extracted_text, answer, confidence > 0.6, metadata["subject"], emotion) return { "student_id": student_id, "question": extracted_text, "metadata": metadata, "emotion": emotion, "model_used": model, "textbook": textbook, "confidence": confidence, "answer": answer }