Spaces:
Sleeping
Sleeping
import os | |
import gradio as gr | |
from weasyprint import HTML # Use WeasyPrint for HTML to PDF | |
from huggingface_hub import InferenceClient | |
from huggingface_hub.utils import HfHubHTTPError | |
import requests | |
# --- Configuration --- | |
HF_TOKEN = os.getenv("HF_TOKEN") | |
if not HF_TOKEN: | |
raise ValueError("The HF_TOKEN environment variable must be set.") | |
MODEL_NAME = "meta-llama/Llama-3.1-8B-Instruct" | |
MAX_INPUT_LENGTH = 4096 # Maximum characters for lesson content | |
# --- Hugging Face Inference Client --- | |
client = InferenceClient(model=MODEL_NAME, token=HF_TOKEN) # Corrected: Use model and token | |
def call_hf_api(lesson_text: str) -> str: | |
""" | |
Calls the Hugging Face Inference API, generating exercises in SPANISH. | |
""" | |
if not lesson_text.strip(): | |
return "Please provide lesson content." | |
if len(lesson_text) > MAX_INPUT_LENGTH: | |
return f"Error: Lesson content is too long (>{MAX_INPUT_LENGTH} characters). Please shorten it." | |
prompt = f""" | |
You are a helpful assistant that generates structured HSK exercises in HTML format. | |
Use ONLY the following lesson content to create the exercises. Do NOT hallucinate any content. | |
The generated exercises, including all instructions within each exercise, section titles, | |
and questions, MUST be in SPANISH. | |
USER INPUT Lesson Content YOU MUST USE FOR CUSTOMIZING THE EXERCICES OF THE HTML TEMPLATE: | |
{lesson_text} | |
Generate exactly 12 exercise sections in HTML, as shown in the example below. | |
The exercises MUST use the vocabulary and grammar points from the lesson content provided above. | |
Do not include an answer key. | |
Example HTML Output Structure (use this EXACT structure, adapt exercise TYPES and content, and generate content in SPANISH, ACCORDING TO THE INPUT): | |
<!DOCTYPE html> | |
<html lang="es"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>CHINOTOTAL - Lección [Número de Lección]</title> | |
<style> | |
body {{ font-family: Arial, sans-serif; margin: 0 auto; max-width: 800px; line-height: 1.5; }} | |
h1, h2, h3 {{ text-align: center; }} | |
hr {{ margin: 30px 0; }} | |
.exercise-title {{ color: #007BFF; font-weight: bold; }} | |
.instructions {{ font-style: italic; margin-bottom: 10px; }} | |
ol, ul {{ margin-bottom: 20px; }} | |
</style> | |
</head> | |
<body> | |
<h1>CHINOTOTAL - Lección [Número de Lección]</h1> | |
<h2>Ejercicios Completos</h2> | |
<p style="text-align:center; margin:20px 0;">Total de 12 Secciones - La última es escritura.</p> | |
<hr> | |
<!-- SECCIÓN 1: Fill in the Blanks --> | |
<h3>Sección 1: Completa los Espacios en Blanco</h3> | |
<p class="instructions">Completa las siguientes oraciones con la palabra correcta del recuadro.</p> | |
<p>[Palabras del recuadro: (Palabras relevantes de la lección)]</p> | |
<ol> | |
<li>El ______ está en la mesa. (libro, silla, comida)</li> | |
<li>Me gusta ______ música. (escuchar, hablar, comer)</li> | |
</ol> | |
<hr> | |
<!-- SECCIÓN 2: Sentence Ordering --> | |
<h3>Sección 2: Ordena las Oraciones</h3> | |
<p class="instructions">Ordena las siguientes palabras para formar oraciones coherentes.</p> | |
<ol> | |
<li>/ libro / el / es / dónde /</li> | |
<li>/ gusta / me / mucho / este / restaurante /</li> | |
</ol> | |
<hr> | |
<!-- SECCIÓN 3: Multiple Choice --> | |
<h3>Sección 3: Opción Múltiple</h3> | |
<p class="instructions">Elige la opción correcta para completar cada oración.</p> | |
<ol> | |
<li>Voy ______ la biblioteca. (a, en, de)</li> | |
<li>______ es tu nombre? (Cómo, Qué, Quién)</li> | |
</ol> | |
<hr> | |
<!-- SECCIÓN 4: Translation --> | |
<h3>Sección 4: Traducción</h3> | |
<p class="instructions">Traduce las siguientes frases al chino.</p> | |
<ol> | |
<li>I like to read books.</li> | |
<li>Where is the bathroom?</li> | |
</ol> | |
<hr> | |
<!-- SECCIÓN 5: Matching --> | |
<h3>Sección 5: Emparejar</h3> | |
<p class="instructions">Empareja las palabras de la columna A con sus significados en la columna B.</p> | |
<ol> | |
<li>[Palabra 1] A. [Significado A]</li> | |
<li>[Palabra 2] B. [Significado B]</li> | |
</ol> | |
<hr> | |
<!-- SECCIÓN 6: Character Writing --> | |
<h3>Sección 6: Escritura de Caracteres</h3> | |
<p class="instructions">Escribe los siguientes caracteres en los recuadros.</p> | |
<ol> | |
<li>[Caracter 1] [Recuadro para escribir]</li> | |
<li>[Caracter 2] [Recuadro para escribir]</li> | |
</ol> | |
<hr> | |
<!-- SECCIÓN 7: Dialogue Completion --> | |
<h3>Sección 7: Completa el Diálogo</h3> | |
<p class="instructions">Completa el siguiente diálogo con las frases apropiadas.</p> | |
<p>A: ______<br>B: Me llamo Li Hua.</p> | |
<ol> | |
<li>¿Cómo te llamas?</li> | |
<li>¿De dónde eres?</li> | |
</ol> | |
<hr> | |
<!-- SECCIÓN 8: Short Answer --> | |
<h3>Sección 8: Respuesta Corta</h3> | |
<p class="instructions">Responde las siguientes preguntas en español.</p> | |
<ol> | |
<li>¿Qué te gusta hacer en tu tiempo libre?</li> | |
<li>¿Cuál es tu comida favorita?</li> | |
</ol> | |
<hr> | |
<!-- SECCIÓN 9: True/False --> | |
<h3>Sección 9: Verdadero/Falso</h3> | |
<p class="instructions">Indica si las siguientes afirmaciones son verdaderas (V) o falsas (F).</p> | |
<ol> | |
<li>[Afirmación 1] (V/F)</li> | |
<li>[Afirmación 2] (V/F)</li> | |
</ol> | |
<hr> | |
<!-- SECCIÓN 10: Picture Description --> | |
<h3>Sección 10: Descripción de Imagen</h3> | |
<p class="instructions">Describe la siguiente imagen en una oración.</p> | |
<p>[Espacio para la imagen, o una descripción si no se puede incluir la imagen]</p> | |
<p>[ ]</p> | |
<hr> | |
<!-- SECCIÓN 11: Error Correction --> | |
<h3>Sección 11: Corrección de Errores</h3> | |
<p class="instructions">Corrige los errores en las siguientes oraciones.</p> | |
<ol> | |
<li>Yo gusta leer libro.</li> | |
<li>El dónde es el baño.</li> | |
</ol> | |
<hr> | |
<!-- SECCIÓN 12: Writing Prompt --> | |
<h3>Sección 12: Ejercicio de Escritura</h3> | |
<p class="instructions">Escribe un párrafo corto (aproximadamente 50-80 palabras) en chino sobre un tema relacionado con la lección. Usa el vocabulario y las estructuras gramaticales que has aprendido.</p> | |
<p>[Espacio para escribir]</p> | |
<hr> | |
<p style="text-align:center; margin: 30px 0;">— Fin de la Hoja de Ejercicios —</p> | |
</body> | |
</html> | |
Do NOT include any other text outside of the HTML. Output ONLY the HTML. The HTML MUST be different and adapted to the content provided in the `lesson_text` variable. The example serves as a template of the STRUCTURE and TYPES OF EXERCISES. The content MUST be in SPANISH, and related to lesson_text | |
""" | |
messages = [ | |
{ | |
"role": "user", | |
"content": prompt, | |
} | |
] | |
try: | |
# Corrected: Use the text-generation task and pass messages directly | |
generated_text = client.text_generation( | |
prompt=prompt, | |
max_new_tokens=2000, | |
temperature=0.7, | |
top_p=0.9, | |
stop_sequences=["```"], | |
) | |
# HTML Cleanup: | |
if "```html" in generated_text: | |
generated_text = generated_text.split("```html")[1] | |
if "```" in generated_text: | |
generated_text = generated_text.split("```")[0] | |
return generated_text | |
except HfHubHTTPError as e: | |
return f"Error from Hugging Face Hub: {e}" | |
except requests.exceptions.RequestException as e: | |
return f"Network or API error: {e}" | |
except Exception as e: | |
return f"An unexpected error occurred: {e}" | |
def generate_exercises(lesson_text: str) -> str: | |
"""Generates exercises in HTML format.""" | |
return call_hf_api(lesson_text) | |
def create_pdf(exercises_text: str) -> str: | |
"""Creates a PDF from the generated HTML exercises.""" | |
if not exercises_text.strip(): | |
return None | |
try: | |
output_filename = "hsk_exercises.pdf" | |
HTML(string=exercises_text).write_pdf(output_filename) | |
return output_filename | |
except Exception as e: | |
return f"Error during PDF generation: {e}" | |
def copy_text(exercises_text: str) -> str: | |
"""Copies the generated HTML to the clipboard (for display purposes).""" | |
if not exercises_text.strip(): | |
return "No text to copy!" | |
return exercises_text | |
# --- Gradio Interface --- | |
with gr.Blocks(title="HSK Exercise Generator", theme=gr.themes.Soft()) as demo: | |
gr.Markdown("# HSK Exercise Generator") | |
gr.Markdown("Paste your lesson content and generate structured HSK exercises.") | |
with gr.Row(): | |
lesson_input = gr.Textbox( | |
lines=10, | |
label="Lesson Content", | |
placeholder=f"Paste lesson content here (max {MAX_INPUT_LENGTH} characters)...", | |
) | |
generate_btn = gr.Button("Generate Exercises") | |
output_html = gr.HTML(label="Generated Exercises") # Use gr.HTML for HTML output | |
with gr.Row(): | |
download_btn = gr.Button("Download as PDF") | |
copy_btn = gr.Button("Copy Text") | |
copy_notice = gr.Textbox( | |
label="Copy/Status", | |
placeholder="Shows copied text or status here.", | |
interactive=False, | |
) | |
generate_btn.click(generate_exercises, inputs=lesson_input, outputs=output_html) | |
download_btn.click(create_pdf, inputs=output_html, outputs=gr.File()) | |
copy_btn.click(copy_text, inputs=output_html, outputs=copy_notice) | |
gr.Markdown( | |
""" | |
Usage: | |
1. Set your Hugging Face token: `export HF_TOKEN=hf_yourRealToken` | |
2. Install required packages: `pip install gradio huggingface_hub requests weasyprint` | |
3. Run the script: `python exercise_generator.py` | |
4. Open the provided local URL in your browser. | |
5. Paste your lesson content (make sure it's not too long). | |
6. Click "Generate Exercises". | |
7. The generated exercises (in Spanish) will appear in the output area. | |
8. You can then download them as a PDF or copy the text. | |
""" | |
) | |
if __name__ == "__main__": | |
demo.launch() |