TaruniSwathi's picture
Update app.py
962dcef verified
Raw
History Blame
9.76 kB
import re
import gradio as gr
import spaces
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
# ============================================================
# MODEL CONFIGURATION
# ============================================================
MODEL_ID = "shibsankardhara2/Qwen2.5-Coder-1.5B-Java-CSharp_V5"
# ============================================================
# LOAD TOKENIZER
# ============================================================
print("Loading tokenizer...")
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
if tokenizer.pad_token_id is None:
tokenizer.pad_token_id = tokenizer.eos_token_id
# ============================================================
# LOAD MODEL
# ============================================================
print("Loading model on CPU...")
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
torch_dtype=torch.float16,
low_cpu_mem_usage=True,
)
model.eval()
print("Model loaded successfully.")
# ============================================================
# PROMPT FUNCTIONS
# ============================================================
def add_java_hint(instruction: str) -> str:
"""
Add an explicit Java instruction when the user has not
mentioned Java in the natural-language requirement.
"""
instruction = instruction.strip()
if "java" in instruction.lower():
return instruction
return f"{instruction} Write the solution in Java."
def build_prompt(task: str, user_input: str) -> str:
"""
Build the appropriate prompt based on the selected task.
"""
user_input = user_input.strip()
if task == "Natural Language β†’ Java":
return (
"### Instruction:\n\n"
f"{add_java_hint(user_input)}\n\n"
"### Response:\n\n"
)
return (
"### Instruction:\n\n"
"Translate the following Java code into equivalent C#. "
"Write only the C# solution.\n\n"
"### Java:\n\n"
f"{user_input}\n\n"
"### Response:\n\n"
)
# ============================================================
# OUTPUT CLEANING
# ============================================================
def clean_output(text: str) -> str:
"""
Remove Markdown code fences, repeated prompt sections,
and model-specific special tokens from the generated output.
"""
text = text.strip()
fenced = re.search(
r"```(?:java|csharp|cs|c#)?\s*(.*?)```",
text,
flags=re.DOTALL | re.IGNORECASE,
)
if fenced:
text = fenced.group(1).strip()
stop_markers = [
"### Instruction:",
"### Instruction\n",
"### Java:",
"### Java\n",
"### Response:",
"### Response\n",
"<|im_start|>",
"<|im_end|>",
]
for marker in stop_markers:
if marker in text:
text = text.split(marker, 1)[0].strip()
return text
def clean_csharp_output(code: str) -> str:
"""
Remove unnecessary `virtual` and `override` modifiers from
standalone C# method snippets.
These modifiers are preserved when the generated code contains
a class, struct, interface, record, or enum declaration.
"""
code = code.strip()
has_type_declaration = re.search(
r"\b(class|struct|interface|record|enum)\b",
code,
flags=re.IGNORECASE,
)
if has_type_declaration:
return code
# Example:
# public virtual int Add(...) -> public int Add(...)
code = re.sub(
r"\b(public|private|protected|internal)\s+"
r"(?:virtual|override)\s+",
r"\1 ",
code,
flags=re.IGNORECASE,
)
# Example:
# virtual int Add(...) -> int Add(...)
code = re.sub(
r"(^|\n)(\s*)(?:virtual|override)\s+",
r"\1\2",
code,
flags=re.IGNORECASE,
)
return code.strip()
# ============================================================
# CODE GENERATION
# ============================================================
@spaces.GPU(duration=120)
def generate_code(task: str, user_input: str) -> str:
"""
Generate Java code from natural language or translate
Java code into C#.
"""
if not user_input or not user_input.strip():
return "Please enter a requirement or Java code."
prompt = build_prompt(task, user_input)
if task == "Natural Language β†’ Java":
max_new_tokens = 300
else:
max_new_tokens = 400
try:
# Move the model to the GPU only during generation.
model.to("cuda")
inputs = tokenizer(
prompt,
return_tensors="pt",
truncation=True,
max_length=2048,
).to("cuda")
with torch.inference_mode():
outputs = model.generate(
**inputs,
max_new_tokens=max_new_tokens,
do_sample=False,
pad_token_id=tokenizer.pad_token_id,
eos_token_id=tokenizer.eos_token_id,
)
# Remove the original input prompt from the generated sequence.
prompt_length = inputs["input_ids"].shape[1]
generated_tokens = outputs[0][prompt_length:]
generated_text = tokenizer.decode(
generated_tokens,
skip_special_tokens=True,
)
# Clean repeated prompts, code fences, and special tokens.
code = clean_output(generated_text)
# Apply the C# modifier cleanup only for Java β†’ C#.
if task == "Java β†’ C#":
code = clean_csharp_output(code)
language = "csharp"
else:
language = "java"
if not code:
return (
"The model returned an empty response. "
"Please try again."
)
return f"```{language}\n{code}\n```"
except Exception as error:
return (
"Generation failed: "
f"{type(error).__name__}: {error}"
)
finally:
# Move the model back to CPU to release the ZeroGPU allocation.
model.to("cpu")
if torch.cuda.is_available():
torch.cuda.empty_cache()
# ============================================================
# GRADIO INPUT UPDATE
# ============================================================
def update_input(task: str):
"""
Change the textbox label and placeholder based on the
selected task.
"""
if task == "Natural Language β†’ Java":
return gr.update(
label="Natural-language requirement",
placeholder=(
"Example: Write a Java method to check whether "
"a number is prime."
),
value="",
)
return gr.update(
label="Java code",
placeholder=(
"Example:\n"
"public static int factorial(int n) {\n"
" int result = 1;\n"
" for (int i = 2; i <= n; i++) {\n"
" result *= i;\n"
" }\n"
" return result;\n"
"}"
),
value="",
)
# ============================================================
# GRADIO INTERFACE
# ============================================================
with gr.Blocks(title="Java and C# CodeGen") as demo:
gr.Markdown(
"""
# Java and C# CodeGen
Generate Java code from natural-language requirements or translate Java code
into equivalent C# using a fine-tuned Qwen2.5-Coder model.
"""
)
task = gr.Dropdown(
choices=[
"Natural Language β†’ Java",
"Java β†’ C#",
],
value="Natural Language β†’ Java",
label="Select task",
)
user_input = gr.Textbox(
label="Natural-language requirement",
placeholder=(
"Example: Write a Java method to check whether "
"a number is prime."
),
lines=14,
)
generate_button = gr.Button(
"Generate Code",
variant="primary",
)
output = gr.Markdown(
value="Generated code will appear here."
)
task.change(
fn=update_input,
inputs=task,
outputs=user_input,
)
generate_button.click(
fn=generate_code,
inputs=[
task,
user_input,
],
outputs=output,
)
gr.Examples(
examples=[
[
"Natural Language β†’ Java",
(
"Write a Java method to calculate factorial "
"of a number using a loop."
),
],
[
"Natural Language β†’ Java",
"Write a Java method to reverse a string.",
],
[
"Natural Language β†’ Java",
(
"Write a Java method to check whether "
"a number is prime."
),
],
[
"Java β†’ C#",
"""public static int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; i++) {
result *= i;
}
return result;
}""",
],
[
"Java β†’ C#",
"""public boolean isEven(int n) {
return n % 2 == 0;
}""",
],
],
inputs=[
task,
user_input,
],
)
# ============================================================
# START APPLICATION
# ============================================================
if __name__ == "__main__":
demo.queue(
default_concurrency_limit=1,
max_size=10,
).launch()