pseudo2code / app.py
hamxaameer's picture
Update app.py
f1f85af verified
import gradio as gr
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
import os
# Model configuration
# Since you have all model files in Space root, try loading directly
MODEL_NAME = "." # Load from current directory with all your uploaded files
CUSTOM_WEIGHTS_PATH = "./model.safetensors" # Backup: your custom weights
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
# Global variables for model caching
_model = None
_tokenizer = None
def load_model():
"""Load the model and tokenizer with simple caching"""
global _model, _tokenizer
# Return cached model if already loaded
if _model is not None and _tokenizer is not None:
return _model, _tokenizer
print(f"Loading model from: {MODEL_NAME}")
print(f"Using device: {DEVICE}")
# List available files for debugging
import os
try:
current_files = os.listdir(".")
print("Available files in current directory:")
for f in current_files:
print(f" - {f}")
except Exception as e:
print(f"Could not list directory: {e}")
try:
# First try to load directly from your uploaded files
print("Attempting to load model directly from uploaded files...")
try:
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
model = AutoModelForCausalLM.from_pretrained(MODEL_NAME)
print("✅ Successfully loaded model directly from your uploaded files!")
except Exception as direct_load_error:
print(f"Direct load failed: {direct_load_error}")
print("Falling back to base model + custom weights...")
# Fallback: Load base model and add custom weights
tokenizer = AutoTokenizer.from_pretrained("gpt2")
model = AutoModelForCausalLM.from_pretrained("gpt2")
# Try to load your custom weights
if os.path.exists(CUSTOM_WEIGHTS_PATH):
print(f"Loading custom weights from: {CUSTOM_WEIGHTS_PATH}")
try:
from safetensors.torch import load_file
custom_weights = load_file(CUSTOM_WEIGHTS_PATH)
# Load the weights into the model
missing_keys, unexpected_keys = model.load_state_dict(custom_weights, strict=False)
if missing_keys:
print(f"⚠️ Missing keys: {len(missing_keys)} (this might be normal for LoRA models)")
if unexpected_keys:
print(f"⚠️ Unexpected keys: {len(unexpected_keys)}")
print("✅ Custom weights loaded successfully!")
except Exception as e:
print(f"⚠️ Could not load custom weights: {e}")
print("Using base GPT-2 model instead")
# Set pad token if not set
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
# Move model to device
model = model.to(DEVICE)
print(f"✅ Model loaded successfully on {DEVICE}!")
# Cache the loaded model and tokenizer
_model = model
_tokenizer = tokenizer
return model, tokenizer
except Exception as e:
print(f"❌ Error loading model: {e}")
print("\n🔧 Troubleshooting:")
print("1. Make sure you have uploaded ALL required files:")
print(" - model.safetensors (✅ you have this)")
print(" - config.json (❓ might be missing)")
print(" - tokenizer.json or vocab.json + merges.txt (❓ might be missing)")
print(" - tokenizer_config.json (✅ you have this)")
print("2. Files should be in the Space root directory")
print("3. Check if the model was saved correctly from your notebook")
raise e
# Initialize model and tokenizer
try:
model, tokenizer = load_model()
except Exception as e:
print(f"Failed to load model: {e}")
# Create dummy objects to prevent further errors
model, tokenizer = None, None
def generate_code(pseudocode, indent=1, line=1, temperature=0.7, top_p=0.9, max_length=128):
"""
Generate code from pseudo-code with line and indent information.
Args:
pseudocode: Input pseudo-code string
indent: Indentation level (1-10)
line: Line number (1-100)
temperature: Sampling temperature (0.1-2.0)
top_p: Nucleus sampling parameter (0.1-1.0)
max_length: Maximum length of generated sequence (50-512)
Returns:
Generated code string
"""
try:
# Check if model is loaded
if model is None or tokenizer is None:
return """❌ Model not loaded. Please check:
1. MODEL_NAME in app.py - should be either:
- Your HF repository: "username/model-name"
- Local path: "./model" (if files uploaded to Space)
2. If using HF repository, make sure it exists and is public
3. If using local files, ensure model files are in correct folder
Current MODEL_NAME: """ + MODEL_NAME
# Validate inputs
if not pseudocode.strip():
return "❌ Error: Please enter some pseudocode."
# Format input with line and indent information (matches training format)
prompt = f"Pseudocode: {pseudocode.strip()} | Indent: {indent} | Line: {line}\nCode:"
# Tokenize input
inputs = tokenizer(prompt, return_tensors='pt', padding=True, truncation=True, max_length=256)
inputs = {k: v.to(DEVICE) for k, v in inputs.items()}
# Generate with the model
model.eval()
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=max_length,
temperature=max(0.1, temperature), # Ensure minimum temperature
top_p=max(0.1, top_p), # Ensure minimum top_p
do_sample=True,
pad_token_id=tokenizer.eos_token_id,
eos_token_id=tokenizer.eos_token_id,
num_return_sequences=1,
repetition_penalty=1.1,
no_repeat_ngram_size=2
)
# Decode output
generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
# Extract only the code part (remove the prompt)
if "Code:" in generated_text:
code = generated_text.split("Code:")[-1].strip()
else:
code = generated_text.strip()
# Clean up the output
if code.startswith(prompt):
code = code[len(prompt):].strip()
return code if code else "❌ No code generated. Try adjusting the parameters."
except Exception as e:
return f"❌ Error generating code: {str(e)}"
def create_examples():
"""Create example inputs for the interface"""
return [
["create string s", 1, 1, 0.7, 0.9, 100],
["read input from user", 1, 2, 0.7, 0.9, 100],
["if s is empty", 1, 3, 0.7, 0.9, 100],
["print hello world", 2, 4, 0.7, 0.9, 100],
["for i from 0 to n", 1, 5, 0.7, 0.9, 100],
["declare integer array", 1, 1, 0.5, 0.9, 80],
["while condition is true", 2, 10, 0.8, 0.95, 120]
]
# Create Gradio interface
with gr.Blocks(
theme=gr.themes.Soft(),
title="🐍 Pseudo-Code to Code Generator",
css="""
.gradio-container {
max-width: 1200px;
margin: auto;
}
.header {
text-align: center;
margin-bottom: 30px;
}
.info-box {
background-color: #f0f8f;
color: #FF0000;
padding: 15px;
border-radius: 10px;
margin: 10px 0;
border: 1px solid #ddd;
}
"""
) as demo:
# Header
gr.HTML("""
<div class="header">
<h1>🐍 Pseudo-Code to Code Generator</h1>
<p>Convert natural language pseudo-code to executable code using fine-tuned GPT-2</p>
</div>
""")
# Info box
gr.HTML("""
<div class="info-box">
<h3>📋 How to use:</h3>
<ol>
<li><strong>Enter pseudocode:</strong> Describe what you want the code to do in natural language</li>
<li><strong>Set context:</strong> Adjust indent level and line number for better structure</li>
<li><strong>Tune generation:</strong> Modify temperature and top_p for different creativity levels</li>
<li><strong>Generate:</strong> Click submit to get your code!</li>
</ol>
<p><strong>Note:</strong> This model was trained on the SPOC dataset containing C++ code examples.</p>
</div>
""")
with gr.Row():
# Left column - Inputs
with gr.Column(scale=1):
pseudocode_input = gr.Textbox(
label="📝 Pseudocode",
placeholder="Enter your pseudocode here... (e.g., 'create string variable s')",
lines=3,
value="create string s"
)
with gr.Row():
indent_input = gr.Slider(
minimum=1, maximum=10, value=1, step=1,
label="🔢 Indent Level",
info="Indentation level for the code"
)
line_input = gr.Slider(
minimum=1, maximum=100, value=1, step=1,
label="📍 Line Number",
info="Line number in the program"
)
gr.Markdown("### 🎛️ Generation Parameters")
with gr.Row():
temperature_input = gr.Slider(
minimum=0.1, maximum=2.0, value=0.7, step=0.1,
label="🌡️ Temperature",
info="Higher = more creative, Lower = more focused"
)
top_p_input = gr.Slider(
minimum=0.1, maximum=1.0, value=0.9, step=0.05,
label="🎯 Top-p",
info="Nucleus sampling parameter"
)
max_length_input = gr.Slider(
minimum=50, maximum=512, value=128, step=10,
label="📏 Max Length",
info="Maximum number of tokens to generate"
)
generate_btn = gr.Button("🚀 Generate Code", variant="primary", size="lg")
# Right column - Output
with gr.Column(scale=1):
output = gr.Textbox(
label="💻 Generated Code",
lines=15,
placeholder="Generated code will appear here...",
show_copy_button=True
)
# Examples section
gr.Markdown("### 📚 Example Inputs")
examples = gr.Examples(
examples=create_examples(),
inputs=[pseudocode_input, indent_input, line_input, temperature_input, top_p_input, max_length_input],
outputs=output,
fn=generate_code,
cache_examples=False
)
# Event handlers
generate_btn.click(
fn=generate_code,
inputs=[pseudocode_input, indent_input, line_input, temperature_input, top_p_input, max_length_input],
outputs=output
)
# Also allow Enter key to generate
pseudocode_input.submit(
fn=generate_code,
inputs=[pseudocode_input, indent_input, line_input, temperature_input, top_p_input, max_length_input],
outputs=output
)
# Footer
gr.HTML("""
<div style="text-align: center; margin-top: 30px; padding: 20px; border-top: 1px solid #eee;">
<p>🤖 <strong>Model Details:</strong> Fine-tuned GPT-2 with LoRA on SPOC dataset</p>
<p>📊 <strong>Training:</strong> Pseudo-code to C++ code generation with structural information</p>
<p>⚡ <strong>Powered by:</strong> Transformers, Safetensors, and Gradio</p>
</div>
""")
# Launch configuration
if __name__ == "__main__":
demo.launch(
server_name="0.0.0.0", # Required for Hugging Face Spaces
server_port=7860, # Default port for Spaces
share=False, # Don't create public links in Spaces
show_api=False, # Disable API docs for cleaner interface
show_error=True, # Show errors for debugging
quiet=False # Show startup logs
)