CodeConverter / app.py
CultriX's picture
Update app.py
cd4b4ee verified
raw
history blame
8.38 kB
import gradio as gr
import openai
from gradio.themes.base import Base
from gradio.themes.utils import colors, fonts, sizes
# --- Custom Theme Definition ---
class NordTheme(Base):
"""
A custom Gradio theme inspired by the Nord color palette.
"""
def __init__(self):
super().__init__(
primary_hue=colors.blue,
secondary_hue=colors.sky,
neutral_hue=colors.slate,
font=(fonts.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"),
font_mono=(fonts.GoogleFont("Fira Code"), "ui-monospace", "monospace"),
)
self.set(
body_background_fill="#2E3440",
body_text_color="#ECEFF4",
block_background_fill="#3B4252",
block_border_width="1px",
block_border_color="#4C566A",
block_label_background_fill="#434C5E",
block_label_text_color="#ECEFF4",
input_background_fill="#434C5E",
input_border_color="transparent",
button_primary_background_fill="#5E81AC",
button_primary_background_fill_hover="#81A1C1",
button_primary_text_color="#ECEFF4",
button_secondary_background_fill="#4C566A",
button_secondary_background_fill_hover="#5a657a",
button_secondary_text_color="#ECEFF4",
border_color_accent="#5E81AC",
background_fill_primary_dark="#2E3440",
color_accent_soft="#4c566a",
block_radius="12px",
button_radius="8px",
)
# --- UI Configuration ---
# UPDATED: "Natural Language" is added to the list.
LANGUAGES = [
'Natural Language', 'Python', 'JavaScript', 'TypeScript', 'Java', 'C++', 'C#',
'C', 'Go', 'Rust', 'Swift', 'Kotlin', 'PHP', 'Ruby', 'Scala', 'R', 'MATLAB',
'Perl', 'Haskell', 'Lua', 'Dart', 'Elixir', 'F#', 'Clojure', 'SQL'
]
MODELS = sorted([
"agentica-org/deepcoder-14b-preview:free", "deepseek/deepseek-chat-v3:free",
"deepseek/deepseek-r1-0528:free", "google/gemma-3-27b-it:free",
"google/gemini-2.0-flash-exp:free", "meta-llama/llama-3.3-70b-instruct:free",
"mistralai/devstral-small-2505:free", "mistralai/mistral-small-3.2-24b-instruct-2506:free",
"moonshotai/kimi-dev-72b:free", "openrouter/cypher-alpha:free",
"qwen/qwen-2.5-coder-32b-instruct:free", "qwen/qwen3-235b-a22b-04-28:free",
"qwen/qwq-32b:free",
])
DEFAULT_SOURCE_CODE = """# Example Python code
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))"""
# --- Core Conversion Logic ---
def convert_code(
source_code: str, source_lang: str, target_lang: str, model: str, api_key: str
):
"""
Handles three conversion scenarios:
1. Natural Language -> Code
2. Code -> Natural Language
3. Code -> Code
"""
if not source_code.strip():
raise gr.Error("Please enter some code or a description to convert.")
if not api_key.strip():
raise gr.Error("OpenRouter API key is required.")
if not model or not model.strip():
raise gr.Error("Please select or enter a model for the conversion.")
# Handle the edge case where both are "Natural Language"
if source_lang == "Natural Language" and target_lang == "Natural Language":
raise gr.Error("Please select a programming language for either the source or the target.")
client = openai.OpenAI(base_url="https://openrouter.ai/api/v1", api_key=api_key)
# UPDATED: Logic to generate a prompt based on the conversion type
if source_lang == "Natural Language":
# Scenario 1: Natural Language -> Code
prompt = (
f"You are a programming expert. Based on the following description, write a complete and functional code snippet in {target_lang}. "
f"The user's request is: '{source_code}'.\n\n"
f"Your response must only contain the raw {target_lang} code without any explanations, comments, or markdown formatting (like ```)."
)
elif target_lang == "Natural Language":
# Scenario 2: Code -> Natural Language
prompt = (
f"You are a programming expert. Explain the following {source_lang} code in simple, natural English. "
f"Describe what the code does, its main logic, its inputs, and what it outputs. Do not include any code in your explanation.\n\n"
f"--- Start of {source_lang} Code ---\n"
f"{source_code}\n"
f"--- End of {source_lang} Code ---"
)
else:
# Scenario 3: Code -> Code (original logic)
prompt = (
f"You are an expert programmer. Convert the following {source_lang} code to {target_lang}. "
"Your response must only contain the raw, converted code. Do not include any explanations, comments, or markdown formatting (like ```)."
f"\n\n--- Start of {source_lang} Code ---\n"
f"{source_code}\n"
f"--- End of {source_lang} Code ---"
)
try:
completion = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
temperature=0.1, max_tokens=2048
)
return completion.choices[0].message.content.strip()
except openai.AuthenticationError:
raise gr.Error("Authentication failed. Check your OpenRouter API key.")
except Exception as e:
raise gr.Error(f"An error occurred: {e}")
# --- Gradio User Interface ---
# Helper function to update Code component's language
def update_code_language(lang: str):
if lang == "Natural Language":
return gr.update(language="text", placeholder="Describe the code you want here...")
return gr.update(language=lang.lower(), placeholder=f"Enter your {lang} code here...")
with gr.Blocks(theme=NordTheme()) as app:
# Header
gr.HTML(
"""
<div style="display: flex; align-items: center; gap: 12px; padding: 10px;">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#81A1C1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 16 4-4-4-4"/><path d="m6 8-4 4 4 4"/><path d="m14.5 4-5 16"/></svg>
<div>
<h1 style="font-size: 1.5rem; font-weight: 700; color: #ECEFF4; margin: 0;">CodeVerter</h1>
<p style="font-size: 0.875rem; color: #D8DEE9; margin: 0;">Code & Natural Language Converter</p>
</div>
</div>
"""
)
with gr.Accordion("⚙️ Configuration", open=True):
openrouter_key = gr.Textbox(label="OpenRouter API Key", placeholder="Enter your OpenRouter API key...", type="password")
model_selection = gr.Dropdown(label="Select or Enter a Model Name", choices=MODELS, value=MODELS[0] if MODELS else None, allow_custom_value=True)
with gr.Row(equal_height=False):
with gr.Column(scale=1):
source_lang_selection = gr.Dropdown(label="Source Language", choices=LANGUAGES, value="Python")
source_code_input = gr.Code(label="Source", language="python", value=DEFAULT_SOURCE_CODE, lines=15)
with gr.Column(scale=1):
target_lang_selection = gr.Dropdown(label="Target Language", choices=LANGUAGES, value="JavaScript")
target_code_output = gr.Code(label="Result", language="javascript", lines=15, interactive=False)
# UPDATED: Use a helper function for cleaner UI logic
source_lang_selection.change(fn=update_code_language, inputs=source_lang_selection, outputs=source_code_input)
target_lang_selection.change(lambda lang: gr.update(language=lang.lower() if lang != "Natural Language" else "text"), inputs=target_lang_selection, outputs=target_code_output)
convert_button = gr.Button("Convert", variant="primary", scale=1)
convert_button.click(
fn=convert_code,
inputs=[source_code_input, source_lang_selection, target_lang_selection, model_selection, openrouter_key],
outputs=target_code_output,
api_name="convert"
)
gr.HTML(
"""<div style="text-align: center; margin-top: 24px; color: #a0aec0; font-size: 0.875rem;">
<p>Powered by OpenRouter. Results may require manual review.</p>
</div>"""
)
if __name__ == "__main__":
app.launch()