leotsha / wire_eduintel.py
Sediba-AI
Initial Morutabana deployment: XLM-R + EduIntel + sentiment classifier
9d3f668
Raw
History Blame Contribute Delete
7.17 kB
#!/usr/bin/env python3
"""
wire_eduintel.py
Wires EduIntel into the Morutabana teacher dashboard.
Edits 3 files: views_teacher.py, urls.py, teacher_hub.html
Usage:
cd ~/leotsha_project
python3 wire_eduintel.py
"""
import re
from pathlib import Path
BASE = Path("/home/sediba/leotsha_project")
# โ”€โ”€ 1. Add eduintel view to views_teacher.py โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
VIEWS_FILE = BASE / "leotsha/views_teacher.py"
views_content = VIEWS_FILE.read_text()
EDUINTEL_VIEW = '''
# โ”€โ”€ EduIntel API โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def teacher_eduintel(request):
"""API endpoint: teacher asks EduIntel a curriculum question."""
from django.http import JsonResponse
import subprocess, os, re as _re
teacher = get_teacher(request)
if not teacher:
return JsonResponse({"error": "not authenticated"}, status=401)
query = request.GET.get("q", "").strip()
if not query:
return JsonResponse({"error": "no query"})
try:
result = subprocess.run(
["python3", "eduintel_generate.py", query],
capture_output=True,
text=True,
timeout=120,
cwd="/home/sediba/leotsha_project",
env={**os.environ},
)
output = result.stdout
# Extract just the answer (between โ”€โ”€โ”€ separator and final โ”โ”โ”)
sep = "โ”€" * 20
end = "โ”" * 20
if sep in output:
answer = output.split(sep)[-1]
answer = answer.split(end)[0].strip()
else:
answer = output.strip()
if not answer:
answer = "EduIntel could not find relevant content. Try rephrasing."
except subprocess.TimeoutExpired:
answer = "EduIntel is processing. Please try a shorter question."
except Exception as e:
answer = f"Error: {str(e)}"
return JsonResponse({"answer": answer, "query": query})
'''
if "def teacher_eduintel" in views_content:
print(" โญ teacher_eduintel already in views_teacher.py")
else:
VIEWS_FILE.write_text(views_content + EDUINTEL_VIEW)
print(" โœ“ teacher_eduintel added to views_teacher.py")
# โ”€โ”€ 2. Add URL route to leotsha/urls.py โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
URLS_FILE = BASE / "leotsha/urls.py"
urls_content = URLS_FILE.read_text()
OLD_URL = ' path("leave/", t.learner_leave, name="learner_leave"),'
NEW_URL = ''' path("leave/", t.learner_leave, name="learner_leave"),
path("teacher/eduintel/", t.teacher_eduintel, name="teacher_eduintel"),'''
if "teacher_eduintel" in urls_content:
print(" โญ teacher_eduintel already in urls.py")
elif OLD_URL in urls_content:
URLS_FILE.write_text(urls_content.replace(OLD_URL, NEW_URL))
print(" โœ“ URL route added to leotsha/urls.py")
else:
print(" โš  Could not find anchor in urls.py โ€” adding at end")
URLS_FILE.write_text(urls_content.rstrip() + "\n # EduIntel\n path(\"teacher/eduintel/\", t.teacher_eduintel, name=\"teacher_eduintel\"),\n]\n")
print(" โœ“ URL route added to end of urls.py")
# โ”€โ”€ 3. Add EduIntel section to teacher_hub.html โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
TEMPLATE_FILE = BASE / "templates/teacher_hub.html"
template_content = TEMPLATE_FILE.read_text()
EDUINTEL_HTML = '''
<!-- EDUINTEL -->
<div class="section-lbl" style="margin-top:8px">Ask EduIntel ๐Ÿค–</div>
<div class="card" id="ei-card">
<div style="font-size:13px;color:#555;margin-bottom:10px">
Ask anything about your Sepedi curriculum, Grade 10-12 content, or lesson planning.
</div>
<div style="display:flex;gap:8px;margin-bottom:10px">
<input
id="ei-input"
type="text"
placeholder="e.g. What should I teach Grade 11 HL this term?"
style="flex:1;padding:10px 12px;border:1.5px solid #e5e5e0;border-radius:10px;font-size:14px;outline:none"
onkeydown="if(event.key==='Enter')askEduIntel()"
>
<button
onclick="askEduIntel()"
style="background:#1D9E75;color:#fff;border:none;border-radius:10px;padding:10px 16px;font-size:14px;font-weight:600;cursor:pointer;white-space:nowrap"
>Ask</button>
</div>
<div id="ei-loading" style="display:none;text-align:center;padding:12px;color:#999;font-size:13px">
โณ EduIntel is thinking...
</div>
<div id="ei-result" style="display:none;background:#f8f9f6;border-radius:10px;padding:14px;font-size:13px;line-height:1.7;color:#222;white-space:pre-wrap;max-height:400px;overflow-y:auto"></div>
<div id="ei-suggestions" style="margin-top:8px;display:flex;flex-wrap:wrap;gap:6px">
<button onclick="askSuggestion(this)" class="ei-pill">What to teach Grade 11 HL this term?</button>
<button onclick="askSuggestion(this)" class="ei-pill">Explain ancestors theme in Badimo</button>
<button onclick="askSuggestion(this)" class="ei-pill">Grade 12 prescribed poems?</button>
<button onclick="askSuggestion(this)" class="ei-pill">How to teach oral assessment?</button>
</div>
</div>
<style>
.ei-pill{background:#E1F5EE;color:#0F6E56;border:none;border-radius:99px;padding:6px 12px;font-size:12px;cursor:pointer}
.ei-pill:active{background:#c5ece0}
</style>
<script>
function askEduIntel() {
const input = document.getElementById('ei-input');
const loading = document.getElementById('ei-loading');
const result = document.getElementById('ei-result');
const sugg = document.getElementById('ei-suggestions');
const query = input.value.trim();
if (!query) return;
loading.style.display = 'block';
result.style.display = 'none';
sugg.style.display = 'none';
fetch('/teacher/eduintel/?q=' + encodeURIComponent(query))
.then(r => r.json())
.then(data => {
loading.style.display = 'none';
result.style.display = 'block';
// Basic markdown: **bold** and bullet points
let html = (data.answer || 'No answer returned.')
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
.replace(/^- /gm, 'โ€ข ');
result.innerHTML = html;
})
.catch(err => {
loading.style.display = 'none';
result.style.display = 'block';
result.textContent = 'Error: ' + err.message;
});
}
function askSuggestion(btn) {
document.getElementById('ei-input').value = btn.textContent;
askEduIntel();
}
</script>
'''
ANCHOR = "<!-- NAV -->"
if "Ask EduIntel" in template_content:
print(" โญ EduIntel section already in teacher_hub.html")
elif ANCHOR in template_content:
TEMPLATE_FILE.write_text(template_content.replace(ANCHOR, EDUINTEL_HTML + ANCHOR))
print(" โœ“ EduIntel section added to teacher_hub.html")
else:
print(" โš  Nav anchor not found โ€” adding before </body>")
TEMPLATE_FILE.write_text(template_content.replace("</body>", EDUINTEL_HTML + "</body>"))
print(" โœ“ EduIntel section added to teacher_hub.html")
print("\nโœ… All three files updated.")
print("\nNow run:")
print(" cd ~/leotsha_project && python3 manage.py runserver")
print(" Open: http://localhost:8000/teacher/dashboard/")