Spaces:
Sleeping
Sleeping
| 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, | |
| trust_remote_code=True, | |
| ) | |
| if tokenizer.pad_token_id is None: | |
| tokenizer.pad_token_id = tokenizer.eos_token_id | |
| # ============================================================ | |
| # LOAD MODEL ON CPU | |
| # ============================================================ | |
| print("Loading model on CPU...") | |
| model = AutoModelForCausalLM.from_pretrained( | |
| MODEL_ID, | |
| torch_dtype=torch.float16, | |
| low_cpu_mem_usage=True, | |
| trust_remote_code=True, | |
| ) | |
| model.eval() | |
| print("Model loaded successfully.") | |
| # ============================================================ | |
| # PROMPT FUNCTIONS | |
| # ============================================================ | |
| def add_java_hint(instruction: str) -> str: | |
| """ | |
| Explicitly mention Java when it is missing from the | |
| natural-language instruction. | |
| """ | |
| 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: | |
| """ | |
| Construct the prompt expected by the fine-tuned model. | |
| """ | |
| 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" | |
| ) | |
| # ============================================================ | |
| # GENERAL OUTPUT CLEANING | |
| # ============================================================ | |
| def clean_output(generated_text: str) -> str: | |
| """ | |
| Remove Markdown fences, repeated prompt sections and | |
| model-specific special tokens. | |
| """ | |
| if not generated_text: | |
| return "" | |
| cleaned_text = generated_text.strip() | |
| # Extract the contents of a Markdown code block, when present. | |
| fenced_match = re.search( | |
| r"```(?:java|csharp|cs|c#)?\s*(.*?)```", | |
| cleaned_text, | |
| flags=re.DOTALL | re.IGNORECASE, | |
| ) | |
| if fenced_match: | |
| cleaned_text = fenced_match.group(1).strip() | |
| # Remove prompt sections that the model may generate again. | |
| stop_markers = [ | |
| "### Instruction:", | |
| "### Instruction\n", | |
| "### Java:", | |
| "### Java\n", | |
| "### Response:", | |
| "### Response\n", | |
| "<|im_start|>", | |
| "<|im_end|>", | |
| "<|endoftext|>", | |
| ] | |
| for marker in stop_markers: | |
| marker_position = cleaned_text.find(marker) | |
| if marker_position != -1: | |
| cleaned_text = cleaned_text[:marker_position].strip() | |
| # Remove remaining opening or closing fences. | |
| cleaned_text = re.sub( | |
| r"^```(?:java|csharp|cs|c#)?\s*", | |
| "", | |
| cleaned_text, | |
| flags=re.IGNORECASE, | |
| ) | |
| cleaned_text = re.sub( | |
| r"\s*```$", | |
| "", | |
| cleaned_text, | |
| ) | |
| return cleaned_text.strip() | |
| # ============================================================ | |
| # C# OUTPUT CLEANING | |
| # ============================================================ | |
| def clean_csharp_output(text: str) -> str: | |
| """ | |
| Remove invalid virtual or override modifiers from standalone | |
| C# method snippets. | |
| If the output contains a class, struct, interface, record or | |
| enum declaration, modifiers are preserved. | |
| """ | |
| if not text: | |
| return "" | |
| # Explicitly initialise code before it is accessed. | |
| code = text.strip() | |
| has_type_declaration = re.search( | |
| r"\b(class|struct|interface|record|enum)\b", | |
| code, | |
| flags=re.IGNORECASE, | |
| ) | |
| if has_type_declaration: | |
| return code | |
| # public virtual int Method() -> public int Method() | |
| # protected override void Method() -> protected void Method() | |
| code = re.sub( | |
| r"\b(public|private|protected|internal)\s+" | |
| r"(?:virtual|override)\s+", | |
| r"\1 ", | |
| code, | |
| flags=re.IGNORECASE, | |
| ) | |
| # virtual int Method() -> int Method() | |
| # override void Method() -> void Method() | |
| code = re.sub( | |
| r"(^|\n)(\s*)(?:virtual|override)\s+", | |
| r"\1\2", | |
| code, | |
| flags=re.IGNORECASE, | |
| ) | |
| return code.strip() | |
| # ============================================================ | |
| # CODE GENERATION | |
| # ============================================================ | |
| def generate_code(task: str, user_input: str) -> str: | |
| """ | |
| Generate Java from natural language or translate Java to C#. | |
| """ | |
| if not user_input or not user_input.strip(): | |
| return "Please enter a requirement or Java code." | |
| prompt = build_prompt(task, user_input) | |
| max_new_tokens = ( | |
| 300 | |
| if task == "Natural Language β Java" | |
| else 400 | |
| ) | |
| try: | |
| if not torch.cuda.is_available(): | |
| return "Generation failed: GPU is not available." | |
| # Move the model to the allocated ZeroGPU device. | |
| model.to("cuda") | |
| model.eval() | |
| tokenized_inputs = tokenizer( | |
| prompt, | |
| return_tensors="pt", | |
| truncation=True, | |
| max_length=2048, | |
| ) | |
| tokenized_inputs = { | |
| key: value.to("cuda") | |
| for key, value in tokenized_inputs.items() | |
| } | |
| with torch.inference_mode(): | |
| generated_ids = model.generate( | |
| **tokenized_inputs, | |
| max_new_tokens=max_new_tokens, | |
| do_sample=False, | |
| use_cache=True, | |
| pad_token_id=tokenizer.pad_token_id, | |
| eos_token_id=tokenizer.eos_token_id, | |
| ) | |
| prompt_length = tokenized_inputs["input_ids"].shape[1] | |
| new_token_ids = generated_ids[0][prompt_length:] | |
| generated_text = tokenizer.decode( | |
| new_token_ids, | |
| skip_special_tokens=True, | |
| clean_up_tokenization_spaces=False, | |
| ) | |
| # Always run the general output cleaner. | |
| output_code = clean_output(generated_text) | |
| # Run the C#-specific cleaner only for Java β C#. | |
| if task == "Java β C#": | |
| output_code = clean_csharp_output(output_code) | |
| markdown_language = "csharp" | |
| else: | |
| markdown_language = "java" | |
| if not output_code: | |
| return ( | |
| "The model returned an empty response. " | |
| "Please try a more specific input." | |
| ) | |
| return ( | |
| f"```{markdown_language}\n" | |
| f"{output_code}\n" | |
| "```" | |
| ) | |
| except Exception as error: | |
| return ( | |
| "Generation failed: " | |
| f"{type(error).__name__}: {error}" | |
| ) | |
| finally: | |
| # Return the model to CPU after the ZeroGPU request. | |
| try: | |
| model.to("cpu") | |
| except Exception as move_error: | |
| print(f"Could not move model to CPU: {move_error}") | |
| if torch.cuda.is_available(): | |
| torch.cuda.empty_cache() | |
| # ============================================================ | |
| # UPDATE TEXTBOX | |
| # ============================================================ | |
| def update_input(task: str): | |
| """ | |
| Update the input textbox for 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() |