Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -16,167 +16,174 @@ book_data = {
|
|
| 16 |
"slos": [],
|
| 17 |
"toc": [],
|
| 18 |
"chapters": {},
|
|
|
|
| 19 |
}
|
| 20 |
|
| 21 |
-
#
|
|
|
|
| 22 |
def clean_formatting(text):
|
| 23 |
text = re.sub(r"\*\*(.*?)\*\*", r"\1", text)
|
| 24 |
text = re.sub(r"\*(.*?)\*", r"\1", text)
|
| 25 |
-
text = re.sub(r"[#β’βββ
πΉπΈππππ€π₯β¬οΈπ>]", "", text)
|
| 26 |
text = re.sub(r"\s{2,}", " ", text)
|
| 27 |
return text.strip()
|
| 28 |
|
| 29 |
-
#
|
| 30 |
-
|
|
|
|
| 31 |
book_data["title"] = title.strip()
|
| 32 |
book_data["grade"] = grade.strip()
|
| 33 |
-
slos = [line.strip() for line in slos_input.split('\n') if line.strip()]
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
SLOs:
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
response = client.chat.completions.create(
|
| 43 |
model="llama3-70b-8192",
|
| 44 |
-
messages=[{"role": "user", "content":
|
| 45 |
temperature=0.7
|
| 46 |
)
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
preface =
|
| 50 |
-
|
| 51 |
-
book_data["toc"] = toc.split('\n')
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
| 55 |
def generate_chapter(ch_num):
|
| 56 |
if ch_num in book_data["chapters"]:
|
| 57 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
-
|
| 60 |
-
|
| 61 |
|
| 62 |
-
|
| 63 |
|
| 64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
|
| 66 |
-
Structure the chapter with:
|
| 67 |
-
1. Introduction
|
| 68 |
-
2. Main Concepts and Explanations
|
| 69 |
-
3. Examples or Case Studies
|
| 70 |
-
4. Chapter Summary
|
| 71 |
-
5. Review Questions / Activities (10)
|
| 72 |
-
Maintain academic tone, no markdown, no asterisks. Format clearly as plain text. No emojis.
|
| 73 |
-
"""
|
| 74 |
response = client.chat.completions.create(
|
| 75 |
model="llama3-70b-8192",
|
| 76 |
messages=[{"role": "user", "content": prompt}],
|
| 77 |
temperature=0.7
|
| 78 |
)
|
|
|
|
| 79 |
chapter = clean_formatting(response.choices[0].message.content.strip())
|
| 80 |
book_data["chapters"][ch_num] = chapter
|
| 81 |
return chapter
|
| 82 |
|
| 83 |
-
#
|
|
|
|
| 84 |
def export_book():
|
| 85 |
doc = Document()
|
| 86 |
style = doc.styles['Normal']
|
| 87 |
style.font.name = 'Times New Roman'
|
| 88 |
style.font.size = Pt(12)
|
| 89 |
|
| 90 |
-
def add_paragraph(text, size=12, bold=False
|
| 91 |
p = doc.add_paragraph()
|
| 92 |
run = p.add_run(text.strip())
|
| 93 |
run.font.size = Pt(size)
|
| 94 |
run.bold = bold
|
| 95 |
p.paragraph_format.line_spacing = 1.5
|
| 96 |
-
p.paragraph_format.space_after = Pt(space_after)
|
| 97 |
-
return p
|
| 98 |
|
| 99 |
def add_heading(text, level=1):
|
| 100 |
size = 16 if level == 1 else 14
|
| 101 |
add_paragraph(text.strip(), size=size, bold=True)
|
| 102 |
|
| 103 |
# Title Page
|
| 104 |
-
add_heading(book_data['title']
|
| 105 |
add_paragraph(f"Subject: {book_data['title']}")
|
| 106 |
add_paragraph(f"Grade: {book_data['grade']}")
|
| 107 |
add_paragraph("Author: AI-Generated by Groq-powered App")
|
| 108 |
-
add_paragraph(f"Date
|
| 109 |
doc.add_page_break()
|
| 110 |
|
| 111 |
-
# Preface
|
| 112 |
add_heading("Preface", level=1)
|
| 113 |
-
add_paragraph(
|
| 114 |
doc.add_page_break()
|
| 115 |
|
|
|
|
| 116 |
add_heading("Table of Contents", level=1)
|
| 117 |
-
for line in book_data[
|
| 118 |
-
add_paragraph(
|
| 119 |
doc.add_page_break()
|
| 120 |
|
| 121 |
# SLOs
|
| 122 |
-
add_heading("
|
| 123 |
-
for i, slo in enumerate(book_data[
|
| 124 |
add_paragraph(f"{i}. {slo}")
|
| 125 |
doc.add_page_break()
|
| 126 |
|
| 127 |
# Chapters
|
| 128 |
-
for
|
| 129 |
-
add_heading(f"
|
| 130 |
-
for line in book_data[
|
| 131 |
-
if any(
|
| 132 |
-
add_heading(line
|
| 133 |
else:
|
| 134 |
add_paragraph(line)
|
| 135 |
doc.add_page_break()
|
| 136 |
|
| 137 |
-
file_path = "/tmp/
|
| 138 |
doc.save(file_path)
|
| 139 |
return file_path
|
| 140 |
|
| 141 |
-
#
|
| 142 |
with gr.Blocks() as demo:
|
| 143 |
-
gr.Markdown("## π AI Textbook Generator β
|
| 144 |
-
gr.Markdown("""
|
| 145 |
-
Welcome! This app generates a full textbook from your provided **Subject Title** and **SLOs**.
|
| 146 |
-
|
| 147 |
-
### π§ Instructions:
|
| 148 |
-
1. Enter your **Subject Title**, **Grade**, and **SLOs** (one per line)
|
| 149 |
-
2. Click **Generate Book Structure** (Title Page, TOC, SLOs)
|
| 150 |
-
3. Click each **Chapter button** one by one to generate chapters
|
| 151 |
-
4. Finally, click **Download** to export the complete textbook as a Word file
|
| 152 |
-
""")
|
| 153 |
|
| 154 |
with gr.Row():
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
slos_input = gr.Textbox(label="Paste SLOs (one per line)", lines=10)
|
| 158 |
|
| 159 |
-
|
| 160 |
-
|
|
|
|
| 161 |
|
| 162 |
-
|
| 163 |
|
| 164 |
gr.Markdown("### π₯ Generate Chapters One by One")
|
| 165 |
-
|
| 166 |
-
chapter_output = gr.Textbox(label="π Chapter Preview", lines=25)
|
| 167 |
|
| 168 |
with gr.Row():
|
| 169 |
-
for i in range(1,
|
| 170 |
-
gr.Button(f"Chapter {i}").click(fn=generate_chapter, inputs=gr.Number(value=i, visible=False), outputs=chapter_output)
|
| 171 |
-
|
| 172 |
-
gr.Markdown("### πΎ Export Complete Textbook")
|
| 173 |
|
| 174 |
-
|
|
|
|
| 175 |
download_file = gr.File()
|
| 176 |
|
| 177 |
-
|
| 178 |
|
| 179 |
-
gr.Markdown("---")
|
| 180 |
gr.Markdown("Developed by **Najaf Ali Sharqi** | Powered by **Groq + Gradio**")
|
| 181 |
|
| 182 |
demo.launch()
|
|
|
|
| 16 |
"slos": [],
|
| 17 |
"toc": [],
|
| 18 |
"chapters": {},
|
| 19 |
+
"preface": ""
|
| 20 |
}
|
| 21 |
|
| 22 |
+
# Clean formatting
|
| 23 |
+
|
| 24 |
def clean_formatting(text):
|
| 25 |
text = re.sub(r"\*\*(.*?)\*\*", r"\1", text)
|
| 26 |
text = re.sub(r"\*(.*?)\*", r"\1", text)
|
| 27 |
+
text = re.sub(r"[#β’βββ
πΉπΈππππ€π₯β¬οΈπ>"]", "", text)
|
| 28 |
text = re.sub(r"\s{2,}", " ", text)
|
| 29 |
return text.strip()
|
| 30 |
|
| 31 |
+
# Generate TOC and Preface
|
| 32 |
+
|
| 33 |
+
def generate_book_intro(title, grade, slos_input):
|
| 34 |
book_data["title"] = title.strip()
|
| 35 |
book_data["grade"] = grade.strip()
|
| 36 |
+
book_data["slos"] = [line.strip() for line in slos_input.split('\n') if line.strip()]
|
| 37 |
+
|
| 38 |
+
prompt = f"""
|
| 39 |
+
You are a professional educational author.
|
| 40 |
+
Write the following sections for a textbook titled: "{title}" for Grade {grade}:
|
| 41 |
+
|
| 42 |
+
1. A formal preface aligned with APA 7th Edition style.
|
| 43 |
+
2. A Table of Contents with 6 chapters. Title each chapter clearly according to common educational structure or inferred from the following SLOs:
|
| 44 |
+
|
| 45 |
+
SLOs:
|
| 46 |
+
{slos_input}
|
| 47 |
+
|
| 48 |
+
Do NOT write any chapter content. Only return:
|
| 49 |
+
- Preface
|
| 50 |
+
- Table of Contents
|
| 51 |
+
"""
|
| 52 |
+
|
| 53 |
response = client.chat.completions.create(
|
| 54 |
model="llama3-70b-8192",
|
| 55 |
+
messages=[{"role": "user", "content": prompt}],
|
| 56 |
temperature=0.7
|
| 57 |
)
|
| 58 |
+
|
| 59 |
+
output = response.choices[0].message.content.strip()
|
| 60 |
+
preface, toc = output.split("Table of Contents", 1)
|
| 61 |
+
book_data["preface"] = clean_formatting(preface)
|
| 62 |
+
book_data["toc"] = [clean_formatting(line) for line in toc.strip().split('\n') if line.strip()]
|
| 63 |
+
|
| 64 |
+
return f"Preface:\n\n{book_data['preface']}\n\nTable of Contents:\n\n" + "\n".join(book_data["toc"])
|
| 65 |
+
|
| 66 |
+
# Generate chapter by number
|
| 67 |
+
|
| 68 |
def generate_chapter(ch_num):
|
| 69 |
if ch_num in book_data["chapters"]:
|
| 70 |
+
return book_data["chapters"][ch_num]
|
| 71 |
+
|
| 72 |
+
ch_title = next((line for line in book_data["toc"] if line.startswith(str(ch_num))), f"Chapter {ch_num}")
|
| 73 |
+
slos = book_data["slos"][(ch_num - 1)*5: ch_num*5] # 5 SLOs per chapter
|
| 74 |
+
slo_text = "\n".join(f"- {slo}" for slo in slos)
|
| 75 |
|
| 76 |
+
prompt = f"""
|
| 77 |
+
You are an expert textbook writer. Write Chapter {ch_num} for the book titled "{book_data['title']}" for Grade {book_data['grade']}.
|
| 78 |
|
| 79 |
+
Chapter Title: {ch_title}
|
| 80 |
|
| 81 |
+
Include the following sections:
|
| 82 |
+
- Introduction
|
| 83 |
+
- 5 to 7 Student Learning Outcomes (SLOs):\n{slo_text}
|
| 84 |
+
- Detailed content aligned with each SLO
|
| 85 |
+
- Examples / Case Studies
|
| 86 |
+
- Chapter Summary
|
| 87 |
+
- 10 Review Questions or Activities (no answers)
|
| 88 |
+
|
| 89 |
+
Follow APA 7th edition tone. Do NOT use any asterisks, markdown, emojis, or non-printable characters.
|
| 90 |
+
"""
|
| 91 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
response = client.chat.completions.create(
|
| 93 |
model="llama3-70b-8192",
|
| 94 |
messages=[{"role": "user", "content": prompt}],
|
| 95 |
temperature=0.7
|
| 96 |
)
|
| 97 |
+
|
| 98 |
chapter = clean_formatting(response.choices[0].message.content.strip())
|
| 99 |
book_data["chapters"][ch_num] = chapter
|
| 100 |
return chapter
|
| 101 |
|
| 102 |
+
# Export full textbook to Word
|
| 103 |
+
|
| 104 |
def export_book():
|
| 105 |
doc = Document()
|
| 106 |
style = doc.styles['Normal']
|
| 107 |
style.font.name = 'Times New Roman'
|
| 108 |
style.font.size = Pt(12)
|
| 109 |
|
| 110 |
+
def add_paragraph(text, size=12, bold=False):
|
| 111 |
p = doc.add_paragraph()
|
| 112 |
run = p.add_run(text.strip())
|
| 113 |
run.font.size = Pt(size)
|
| 114 |
run.bold = bold
|
| 115 |
p.paragraph_format.line_spacing = 1.5
|
|
|
|
|
|
|
| 116 |
|
| 117 |
def add_heading(text, level=1):
|
| 118 |
size = 16 if level == 1 else 14
|
| 119 |
add_paragraph(text.strip(), size=size, bold=True)
|
| 120 |
|
| 121 |
# Title Page
|
| 122 |
+
add_heading(book_data['title'], level=1)
|
| 123 |
add_paragraph(f"Subject: {book_data['title']}")
|
| 124 |
add_paragraph(f"Grade: {book_data['grade']}")
|
| 125 |
add_paragraph("Author: AI-Generated by Groq-powered App")
|
| 126 |
+
add_paragraph(f"Date: {datetime.now().strftime('%B %d, %Y')}")
|
| 127 |
doc.add_page_break()
|
| 128 |
|
| 129 |
+
# Preface
|
| 130 |
add_heading("Preface", level=1)
|
| 131 |
+
add_paragraph(book_data['preface'])
|
| 132 |
doc.add_page_break()
|
| 133 |
|
| 134 |
+
# TOC
|
| 135 |
add_heading("Table of Contents", level=1)
|
| 136 |
+
for line in book_data['toc']:
|
| 137 |
+
add_paragraph(line)
|
| 138 |
doc.add_page_break()
|
| 139 |
|
| 140 |
# SLOs
|
| 141 |
+
add_heading("Student Learning Outcomes (SLOs)", level=1)
|
| 142 |
+
for i, slo in enumerate(book_data['slos'], 1):
|
| 143 |
add_paragraph(f"{i}. {slo}")
|
| 144 |
doc.add_page_break()
|
| 145 |
|
| 146 |
# Chapters
|
| 147 |
+
for num in sorted(book_data['chapters'].keys()):
|
| 148 |
+
add_heading(f"{book_data['toc'][num-1]}", level=1)
|
| 149 |
+
for line in book_data['chapters'][num].split('\n'):
|
| 150 |
+
if any(keyword in line.lower() for keyword in ["introduction", "summary", "examples", "review", "student learning outcomes"]):
|
| 151 |
+
add_heading(line, level=2)
|
| 152 |
else:
|
| 153 |
add_paragraph(line)
|
| 154 |
doc.add_page_break()
|
| 155 |
|
| 156 |
+
file_path = "/tmp/Textbook_AI_Generated.docx"
|
| 157 |
doc.save(file_path)
|
| 158 |
return file_path
|
| 159 |
|
| 160 |
+
# Gradio Interface
|
| 161 |
with gr.Blocks() as demo:
|
| 162 |
+
gr.Markdown("## π AI Textbook Generator β Step-by-Step (APA Style)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
|
| 164 |
with gr.Row():
|
| 165 |
+
title = gr.Textbox(label="Subject Title")
|
| 166 |
+
grade = gr.Textbox(label="Grade Level")
|
|
|
|
| 167 |
|
| 168 |
+
slos = gr.Textbox(label="Paste SLOs (One per Line)", lines=10)
|
| 169 |
+
generate_structure = gr.Button("π§ Generate TOC + Preface")
|
| 170 |
+
structure_output = gr.Textbox(label="Generated Preface and TOC", lines=15)
|
| 171 |
|
| 172 |
+
generate_structure.click(fn=generate_book_intro, inputs=[title, grade, slos], outputs=structure_output)
|
| 173 |
|
| 174 |
gr.Markdown("### π₯ Generate Chapters One by One")
|
| 175 |
+
chapter_output = gr.Textbox(label="Generated Chapter Content", lines=25)
|
|
|
|
| 176 |
|
| 177 |
with gr.Row():
|
| 178 |
+
for i in range(1, 7):
|
| 179 |
+
gr.Button(f"Generate Chapter {i}").click(fn=generate_chapter, inputs=gr.Number(value=i, visible=False), outputs=chapter_output)
|
|
|
|
|
|
|
| 180 |
|
| 181 |
+
gr.Markdown("### πΎ Download Complete Textbook")
|
| 182 |
+
download_btn = gr.Button("Download MS Word Textbook")
|
| 183 |
download_file = gr.File()
|
| 184 |
|
| 185 |
+
download_btn.click(fn=export_book, outputs=download_file)
|
| 186 |
|
|
|
|
| 187 |
gr.Markdown("Developed by **Najaf Ali Sharqi** | Powered by **Groq + Gradio**")
|
| 188 |
|
| 189 |
demo.launch()
|