Untitled
unknown
python
a year ago
12 kB
8
Indexable
import json
import re
from pathlib import Path
import streamlit as st
from langchain_groq import ChatGroq
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
class LessonContentGenerator:
def __init__(self, api_key):
self.llm = ChatGroq(api_key=api_key)
def generate_content(self, subject, num_lessons, pages_per_lesson, subtitles_per_page, sentences_per_page):
prompt_template = PromptTemplate(
input_variables=["subject", "num_lessons", "pages_per_lesson", "subtitles_per_page", "sentences_per_page"],
template="""
Create a detailed lesson plan on the subject of {subject}.
Provide EXACTLY the following:
1. {num_lessons} lesson titles
2. For each lesson, EXACTLY {pages_per_lesson} page titles
3. For each page, EXACTLY {subtitles_per_page} subtitles
4. For each page, a content summary of EXACTLY {sentences_per_page} sentences
Format your response as a JSON structure with the following format:
{{
"subject": "{subject}",
"lessons": [
{{
"title": "Lesson Title",
"pages": [
{{
"title": "Page Title",
"subtitles": ["Subtitle 1", "Subtitle 2", ...],
"content": "Detailed content for the page (EXACTLY {sentences_per_page} sentences)"
}},
...
]
}},
...
]
}}
Ensure the content is informative, relevant to the subject of {subject}, and follows this exact JSON structure.
Do not use any backslashes in the JSON keys.
IMPORTANT: Strictly adhere to the numbers provided: {num_lessons} lessons, {pages_per_lesson} pages per lesson, {subtitles_per_page} subtitles per page, and {sentences_per_page} sentences per page.
"""
)
chain = LLMChain(llm=self.llm, prompt=prompt_template)
result = chain.invoke({
"subject": subject,
"num_lessons": num_lessons,
"pages_per_lesson": pages_per_lesson,
"subtitles_per_page": subtitles_per_page,
"sentences_per_page": sentences_per_page
})
return self._process_content(result['text'], subject, num_lessons, pages_per_lesson, subtitles_per_page, sentences_per_page)
def _process_content(self, content, subject, num_lessons, pages_per_lesson, subtitles_per_page, sentences_per_page):
try:
content = json.loads(content)
processed_content = {
"subject": subject,
"lessons": []
}
for i in range(num_lessons):
lesson = content['lessons'][i] if i < len(content['lessons']) else {"title": f"Lesson {i+1}", "pages": []}
processed_lesson = {
"title": lesson['title'],
"pages": []
}
for j in range(pages_per_lesson):
page = lesson['pages'][j] if j < len(lesson.get('pages', [])) else {"title": f"Page {j+1}", "subtitles": [], "content": ""}
processed_page = {
"title": page['title'],
"subtitles": page.get('subtitles', [])[:subtitles_per_page],
"content": '. '.join(page.get('content', '').split('.')[:sentences_per_page]) + '.'
}
while len(processed_page['subtitles']) < subtitles_per_page:
processed_page['subtitles'].append(f"Subtitle {len(processed_page['subtitles'])+1}")
processed_lesson['pages'].append(processed_page)
processed_content['lessons'].append(processed_lesson)
return json.dumps(processed_content, indent=2)
except json.JSONDecodeError:
raise ValueError("The generated content is not valid JSON.")
except Exception as e:
raise Exception(f"An error occurred while processing the content: {str(e)}")
class ContentEditor:
def __init__(self, llm):
self.llm = llm
def expand_content(self, subtitle, page_title, content):
prompt = PromptTemplate(
input_variables=["subtitle", "page_title", "content"],
template="Expand on '{subtitle}' in the context of {page_title}. Original content: {content}"
)
chain = LLMChain(llm=self.llm, prompt=prompt)
expanded_content = chain.invoke({
"subtitle": subtitle,
"page_title": page_title,
"content": content
})
return expanded_content['text']
def summarize_content(self, page_title, summary_length, content):
prompt = PromptTemplate(
input_variables=["page_title", "summary_length", "content"],
template="Summarize the content about {page_title} in a {summary_length} summary. Original content: {content}"
)
chain = LLMChain(llm=self.llm, prompt=prompt)
summarized_content = chain.invoke({
"page_title": page_title,
"summary_length": summary_length.lower(),
"content": content
})
return summarized_content['text']
class App:
def __init__(self, api_key):
self.generator = LessonContentGenerator(api_key)
self.editor = ContentEditor(ChatGroq(api_key=api_key))
def run(self):
st.set_page_config(layout="wide")
st.markdown("""
<div style="display: flex; justify-content: space-between; align-items: center;">
<h1 style="margin: 0;">Interactive Lesson Content Editor</h1>
<div id="restart-button-container"></div>
</div>
""", unsafe_allow_html=True)
if 'json_content' not in st.session_state:
st.session_state.json_content = {"subject": "", "lessons": []}
if 'content_generated' not in st.session_state:
st.session_state.content_generated = False
if st.session_state.content_generated:
self._show_restart_button()
self._handle_content_editing()
else:
self._handle_content_generation()
def _show_restart_button(self):
if st.button("Restart and select a new subject"):
st.session_state.clear()
st.rerun()
def _handle_content_generation(self):
subject = st.text_input("Enter the subject for the lesson content:")
col1, col2 = st.columns(2)
with col1:
num_lessons = st.number_input("Number of lesson titles:", min_value=1, value=2, step=1)
pages_per_lesson = st.number_input("Pages per lesson:", min_value=1, value=2, step=1)
with col2:
subtitles_per_page = st.number_input("Subtitles per page:", min_value=1, value=3, step=1)
sentences_per_page = st.number_input("Sentences per page:", min_value=1, value=3, step=1)
if subject and subject != st.session_state.json_content.get("subject", ""):
if st.button("Generate Content"):
with st.spinner("Generating lesson content..."):
try:
generated_content = self.generator.generate_content(
subject, num_lessons, pages_per_lesson, subtitles_per_page, sentences_per_page
)
st.session_state.json_content = json.loads(generated_content)
st.session_state.content_generated = True
st.success("Lesson content generated successfully!")
st.rerun()
except Exception as e:
st.error(f"An error occurred: {str(e)}. Please try again.")
def _handle_content_editing(self):
if not st.session_state.json_content.get("lessons"):
st.warning("No lessons available. Please generate content first.")
return
st.header("Lesson Content Editor")
lesson_title, lesson, page_title, page = self._select_lesson_and_page()
st.subheader(f"📝 Content: {page_title}")
with st.expander("View original content", expanded=True):
st.write(page.get("content", "No content available."))
with st.expander("View subtitles"):
for subtitle in page.get("subtitles", []):
st.write(f"• {subtitle}")
st.subheader("🛠️ Edit Content")
action = st.radio("What would you like to do with the content?", ["Accept", "Expand", "Summarize"])
if action == "Accept":
st.success("Content accepted without changes.")
elif action == "Expand":
self._handle_expand_action(page, page_title)
elif action == "Summarize":
self._handle_summarize_action(page, page_title)
if st.button("Save Changes"):
self._save_changes()
def _select_lesson_and_page(self):
col1, col2 = st.columns(2)
with col1:
lesson_titles = [lesson.get("title", f"Lesson {i+1}") for i, lesson in enumerate(st.session_state.json_content["lessons"])]
lesson_title = st.selectbox("📚 Select a lesson", lesson_titles)
lesson_index = lesson_titles.index(lesson_title)
lesson = st.session_state.json_content["lessons"][lesson_index]
with col2:
if not lesson.get("pages"):
st.warning(f"No pages available for lesson: {lesson_title}")
return None, None, None, None
page_titles = [page.get("title", f"Page {i+1}") for i, page in enumerate(lesson["pages"])]
page_title = st.selectbox("📄 Select a page", page_titles)
page_index = page_titles.index(page_title)
page = lesson["pages"][page_index]
return lesson_title, lesson, page_title, page
def _handle_expand_action(self, page, page_title):
subtitles = page.get("subtitles", [])
if subtitles:
subtitle = st.selectbox("Select a subtitle to expand", subtitles)
if st.button("Expand Content"):
with st.spinner("Expanding content..."):
expanded_content = self.editor.expand_content(subtitle, page_title, page.get("content", ""))
st.subheader("Expanded Content")
st.write(expanded_content)
page["content"] = expanded_content
st.success("Content expanded successfully!")
else:
st.warning("No subtitles available for expansion.")
def _handle_summarize_action(self, page, page_title):
summary_length = st.select_slider("Select summary length", options=["Short", "Medium", "Long"])
if st.button("Summarize Content"):
with st.spinner("Summarizing content..."):
summarized_content = self.editor.summarize_content(page_title, summary_length, page.get("content", ""))
st.subheader("Summarized Content")
st.write(summarized_content)
page["content"] = summarized_content
st.success("Content summarized successfully!")
def _save_changes(self):
filename = f'{st.session_state.json_content["subject"].replace(" ", "_").lower()}_lesson_content.json'
with open(filename, 'w') as f:
json.dump(st.session_state.json_content, f, indent=2)
st.success(f"Changes saved successfully to {filename}!")
if __name__ == "__main__":
api_key = "gsk_8TqmmFKtQlmrXFwwLw8mz63"
app = App(api_key)
app.run()Editor is loading...
Leave a Comment