Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import tensorflow as tf | |
| import keras | |
| import numpy as np | |
| import pickle | |
| from tensorflow.keras.preprocessing.sequence import pad_sequences | |
| import re | |
| import os | |
| # Define and register the custom Perplexity metric | |
| class Perplexity(keras.metrics.Metric): | |
| def __init__(self, name='perplexity', dtype=None, **kwargs): | |
| super().__init__(name=name, dtype=dtype, **kwargs) | |
| self.cross_entropy = keras.metrics.Mean(name='cross_entropy') | |
| def update_state(self, y_true, y_pred, sample_weight=None): | |
| # Calculate cross-entropy | |
| cross_entropy_values = tf.keras.losses.sparse_categorical_crossentropy(y_true, y_pred) | |
| # Update the internal mean metric | |
| self.cross_entropy.update_state(cross_entropy_values, sample_weight) | |
| def result(self): | |
| # Perplexity is the exponential of the cross-entropy | |
| return tf.exp(self.cross_entropy.result()) | |
| def reset_state(self): | |
| self.cross_entropy.reset_state() | |
| def get_config(self): | |
| config = super().get_config() | |
| return config | |
| # Text cleaning function | |
| def clean_text(text): | |
| text = re.sub(r'[^\w\s.,!?]', '', text) | |
| text = re.sub(r'\b\d+\b', '', text) | |
| text = text.replace('co2', 'carbon dioxide') | |
| text = text.lower() | |
| text = ' '.join(text.split()) | |
| return text | |
| # Load models and tokenizers | |
| def load_models(): | |
| print("Loading models and tokenizers...") | |
| # Load models with custom objects for Perplexity | |
| custom_objects = {'Perplexity': Perplexity} | |
| try: | |
| with keras.saving.custom_object_scope(custom_objects): | |
| classifier_model = keras.models.load_model('classifier_model.keras') | |
| textgen_model = keras.models.load_model('textgen_model.keras') | |
| print("Models loaded successfully with custom objects") | |
| except Exception as e: | |
| print(f"Error loading models with custom objects: {e}") | |
| raise | |
| # Load tokenizers | |
| try: | |
| with open('classifier_tokenizer.pkl', 'rb') as handle: | |
| classifier_tokenizer = pickle.load(handle) | |
| with open('textgen_tokenizer.pkl', 'rb') as handle: | |
| textgen_tokenizer = pickle.load(handle) | |
| print("Tokenizers loaded successfully") | |
| except Exception as e: | |
| print(f"Error loading tokenizers: {e}") | |
| raise | |
| return classifier_model, classifier_tokenizer, textgen_model, textgen_tokenizer | |
| # Classification function | |
| def classify_text(text, model, tokenizer): | |
| cleaned_text = clean_text(text) | |
| sequence = tokenizer.texts_to_sequences([cleaned_text]) | |
| padded = pad_sequences(sequence, maxlen=255, padding='pre') | |
| prediction = model.predict(padded)[0] | |
| # Get the highest probability class | |
| class_idx = np.argmax(prediction) | |
| classes = ['Science', 'Maths', 'History'] | |
| confidence = prediction[class_idx] * 100 | |
| return classes[class_idx], confidence | |
| # Text generation function | |
| def generate_text(prompt, model, tokenizer, max_length=50, temperature=0.7): | |
| cleaned_prompt = clean_text(prompt) | |
| input_text = cleaned_prompt | |
| for _ in range(max_length): | |
| token_list = tokenizer.texts_to_sequences([input_text])[0] | |
| token_list = pad_sequences([token_list], maxlen=255, padding='pre') | |
| predicted = model.predict(token_list, verbose=0)[0] | |
| # Apply temperature | |
| predicted = np.log(predicted) / temperature | |
| exp_preds = np.exp(predicted) | |
| predicted = exp_preds / np.sum(exp_preds) | |
| # Sample from the distribution | |
| predicted_index = np.random.choice(len(predicted), p=predicted) | |
| output_word = "" | |
| for word, index in tokenizer.word_index.items(): | |
| if index == predicted_index: | |
| output_word = word | |
| break | |
| if output_word == "": | |
| break | |
| input_text += " " + output_word | |
| return input_text | |
| # Print environment info for debugging | |
| print(f"TensorFlow version: {tf.__version__}") | |
| print(f"Keras version: {tf.keras.__version__}") | |
| print(f"Current directory contents: {os.listdir('.')}") | |
| # Load models with error handling | |
| try: | |
| print("Starting model loading process...") | |
| classifier_model, classifier_tokenizer, textgen_model, textgen_tokenizer = load_models() | |
| print("Models and tokenizers loaded successfully") | |
| except Exception as e: | |
| print(f"Error in model loading process: {e}") | |
| raise | |
| # Create Gradio interface functions | |
| def classify_interface(text): | |
| subject, confidence = classify_text(text, classifier_model, classifier_tokenizer) | |
| return f"Subject: {subject} (Confidence: {confidence:.2f}%)" | |
| def generate_interface(prompt, length=50, temp=0.7): | |
| return generate_text(prompt, textgen_model, textgen_tokenizer, max_length=int(length), temperature=float(temp)) | |
| # Define example inputs for the classifier | |
| classifier_examples = [ | |
| ["The process of photosynthesis converts light energy into chemical energy, producing oxygen as a byproduct."], | |
| ["The Pythagorean theorem states that in a right-angled triangle, the square of the length of the hypotenuse equals the sum of squares of the other two sides."], | |
| ["The Industrial Revolution began in Great Britain in the late 18th century and spread to other parts of Europe and North America."], | |
| ["Atoms consist of a nucleus containing protons and neutrons, surrounded by electrons that orbit in energy levels."], | |
| ["Differential equations are mathematical equations that relate a function with its derivatives, representing rates of change."], | |
| ["The Treaty of Versailles was signed in 1919, officially ending World War I and imposing harsh penalties on Germany."] | |
| ] | |
| # Define example inputs for the text generator | |
| generator_examples = [ | |
| ["Newton's laws of motion explain", 30, 0.8], | |
| ["Climate change affects ecosystems by", 20, 0.7], | |
| ["Quantum mechanics revolutionized physics when", 20, 0.9], | |
| ["Chemical reactions occur when", 25, 0.6] | |
| ] | |
| # Create Gradio interface | |
| with gr.Blocks(title="Science Text Analyzer") as demo: | |
| gr.Markdown("# Science Text Analyzer") | |
| with gr.Tab("Classify Text"): | |
| gr.Markdown("### Classify Academic Text") | |
| gr.Markdown( | |
| "The **Science Text Analyzer** uses an **LSTM-based text classification model** trained on curated academic datasets sourced from **Hugging Face**. " | |
| "It predicts whether input text belongs to **Science**, **Mathematics**, or **History**, leveraging **sequential context** and **language structure** for accurate subject classification." | |
| ) | |
| with gr.Row(): | |
| with gr.Column(): | |
| text_input = gr.Textbox(label="Enter Text", lines=5, placeholder="Paste a sentence or paragraph here...") | |
| classify_button = gr.Button("Classify") | |
| with gr.Column(): | |
| output = gr.Textbox(label="Classification Result", placeholder="The predicted subject and confidence will appear here.") | |
| # Add examples for the classifier | |
| gr.Examples( | |
| examples=classifier_examples, | |
| inputs=text_input, | |
| outputs=output, | |
| fn=classify_interface, | |
| cache_examples=True | |
| ) | |
| classify_button.click(fn=classify_interface, inputs=text_input, outputs=output) | |
| with gr.Tab("Generate Text"): | |
| gr.Markdown("### Generate Academic Text") | |
| gr.Markdown( | |
| "Use this tool to generate educational text based on a given prompt. " | |
| "You can control the output length and creativity using the sliders below. " | |
| "**Note:** Longer text lengths will take more time to generate, so please be patient when requesting extensive outputs." | |
| ) | |
| with gr.Row(): | |
| with gr.Column(): | |
| prompt_input = gr.Textbox(label="Enter a Prompt", lines=3, placeholder="Type an introductory sentence or concept...") | |
| length_slider = gr.Slider(minimum=10, maximum=60, value=50, step=10, label="Maximum Length (words)") | |
| temp_slider = gr.Slider(minimum=0.1, maximum=1.5, value=0.7, step=0.1, label="Temperature (Creativity Level)") | |
| generate_button = gr.Button("Generate") | |
| with gr.Column(): | |
| generated_output = gr.Textbox(label="Generated Text", lines=8, placeholder="The generated text will appear here.") | |
| # Add examples for the text generator | |
| gr.Examples( | |
| examples=generator_examples, | |
| inputs=[prompt_input, length_slider, temp_slider], | |
| outputs=generated_output, | |
| fn=generate_interface, | |
| cache_examples=True | |
| ) | |
| generate_button.click(fn=generate_interface, inputs=[prompt_input, length_slider, temp_slider], outputs=generated_output) | |
| gr.Markdown("### About This App") | |
| gr.Markdown( | |
| "The **Science Text Analyzer** uses deep learning models trained on curated academic datasets to classify and generate content " | |
| "related to academic disciplines. The **classifier** categorizes input text into one of three subjects: **Science**, **Mathematics**, or **History**. " | |
| "The **text generator** produces coherent scientific passages, especially focused on **Physics**, **Chemistry**, and **Biology**, making it a valuable tool " | |
| "for **educational research**, **content creation**, and **curriculum support**." | |
| ) | |
| # Launch the app | |
| demo.launch() | |