Spaces:
Paused
Paused
File size: 8,854 Bytes
bc291ca 28a7230 bfdae58 28a7230 25033b2 bfdae58 bc291ca bfdae58 25033b2 bc291ca 25033b2 bc291ca 28a7230 25033b2 28a7230 25033b2 bc291ca 25033b2 bc291ca bfdae58 25033b2 bc291ca bfdae58 25033b2 bc291ca 25033b2 bc291ca 25033b2 bc291ca bfdae58 bc291ca 25033b2 bc291ca bfdae58 25033b2 bfdae58 25033b2 bc291ca bfdae58 bc291ca 28a7230 bfdae58 28a7230 bfdae58 28a7230 bc291ca 28a7230 bfdae58 28a7230 bc291ca 28a7230 bc291ca 28a7230 bfdae58 bc291ca bfdae58 bc291ca | 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 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | # 1. Импорты (все библиотеки)
import streamlit as st
from openai import OpenAI, BadRequestError
from pydantic import BaseModel
import requests
import logging
import os
from dotenv import load_dotenv
# 2. Первая команда Streamlit (ДОЛЖНА БЫТЬ ПЕРВОЙ)
st.set_page_config(page_title="Генератор планов уроков", layout="wide")
# Вот этот волшебный CSS:
st.markdown("""
<style>
/* Полностью отключаем running статус */
[data-testid="stStatusWidget"] {
display: none !important;
}
/* Фикс для полей ввода */
.stTextInput, .stSlider {
opacity: 1 !important;
}
</style>
""", unsafe_allow_html=True)
# Отключаем реактивность формы
st.session_state.setdefault("form_values", {
"subject": "",
"textbook": "",
"students": 10
})
# 4. Настройка логирования
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[logging.StreamHandler()]
)
logger = logging.getLogger(__name__)
# 5. Загрузка переменных окружения
load_dotenv()
API_KEY = os.getenv("API_KEY")
BASE_URL = os.getenv("BASE_URL")
if not API_KEY:
logger.error("API_KEY не найден в переменных окружения")
st.error("Ошибка: API_KEY не найден. Проверьте файл .env")
st.stop()
# 6. Инициализация клиента OpenAI
client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
# 7. Pydantic модель
class TextbookInfo(BaseModel):
subject: str = ""
textbook_name: str = ""
# 8. Функция загрузки изображения
def upload_to_catbox(file_bytes):
try:
with st.spinner("Загрузка изображения на сервер..."):
response = requests.post(
"https://catbox.moe/user/api.php",
files={"fileToUpload": file_bytes},
data={"reqtype": "fileupload"}
)
response.raise_for_status()
url = response.text.strip()
if not url.startswith("https://files.catbox.moe/"):
raise ValueError("Некорректный URL")
return url
except Exception as e:
logger.error(f"Ошибка загрузки: {e}")
st.error("Не удалось загрузить изображение")
return None
# 9. Инициализация состояний
if "textbook_data" not in st.session_state:
st.session_state.textbook_data = TextbookInfo()
if "image_url" not in st.session_state:
st.session_state.image_url = None
if "form_data" not in st.session_state:
st.session_state.form_data = {"subject": "", "textbook": "", "students": 10}
# 10. Основной интерфейс (все st. команды после этого пункта)
left_col, right_col = st.columns([2, 3])
with left_col:
st.header("Загрузка учебника")
uploaded_file = st.file_uploader("Выберите изображение страницы", type=["jpg", "png", "jpeg"])
if uploaded_file and st.session_state.image_url is None:
image_url = upload_to_catbox(uploaded_file.getvalue())
if image_url:
st.session_state.image_url = image_url
st.success("Изображение загружено!")
with st.spinner("Анализ изображения..."):
try:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": image_url}},
{"type": "text", "text": """Определи предмет и учебник. Ответь строго в формате:
Предмет: [название]
Учебник: [название]"""}
]
}
]
)
if response.choices:
text = response.choices[0].message.content
subject = text.split("Предмет:")[1].split("\n")[0].strip() if "Предмет:" in text else ""
textbook = text.split("Учебник:")[1].strip() if "Учебник:" in text else ""
st.session_state.textbook_data = TextbookInfo(
subject=subject,
textbook_name=textbook
)
st.session_state.force_form_update = True # Важная строка!
st.session_state.form_data["subject"] = subject
st.session_state.form_data["textbook"] = textbook
except Exception as e:
logger.error(f"Ошибка анализа: {e}")
st.error("Ошибка при анализе изображения")
if st.session_state.image_url:
st.subheader("Данные учебника")
# Критически важный блок - обновляем form_values при первом показе или изменении textbook_data
if 'form_values' not in st.session_state or st.session_state.get('force_form_update', True):
st.session_state.form_values = {
"subject": st.session_state.textbook_data.subject,
"textbook": st.session_state.textbook_data.textbook_name,
"students": 10
}
st.session_state.force_form_update = False
with st.form(key="lesson_form"):
# Поля ввода
subject = st.text_input(
"Предмет",
value=st.session_state.form_values["subject"],
key="form_subject"
)
textbook_name = st.text_input(
"Название учебника",
value=st.session_state.form_values["textbook"],
key="form_textbook"
)
num_students = st.slider(
"Количество учеников",
1, 40, st.session_state.form_values["students"],
key="form_students"
)
submitted = st.form_submit_button("Создать план урока")
if submitted:
st.session_state.form_values.update({
"subject": subject,
"textbook": textbook_name,
"students": num_students
})
if not subject or not textbook_name:
st.warning("Заполните все поля")
else:
with st.spinner("Генерация плана..."):
try:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "system",
"content": "Ты опытный учитель. Создай план урока на основе представленного материала"
},
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": st.session_state.image_url}},
{"type": "text", "text": f"""
Предмет: {subject}
Учебник: {textbook_name}
Учеников: {num_students}
"""}
]
}
]
)
right_col.markdown(response.choices[0].message.content)
except Exception as e:
st.error(f"Ошибка: {str(e)}")
with right_col:
st.header("План урока")
if not st.session_state.image_url:
st.info("Загрузите изображение учебника") |