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()