Spaces:
Sleeping
Sleeping
| import re | |
| import gradio as gr | |
| import spaces | |
| import torch | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| MODEL_ID = "shibsankardhara2/Qwen2.5-Coder-1.5B-Java-CSharp_V5" | |
| print("Loading tokenizer...") | |
| tokenizer = AutoTokenizer.from_pretrained(MODEL_ID) | |
| if tokenizer.pad_token_id is None: | |
| tokenizer.pad_token_id = tokenizer.eos_token_id | |
| 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.") | |
| def add_java_hint(instruction: str) -> str: | |
| 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: | |
| 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" | |
| "Translate the following Java code into equivalent C#. " | |
| "Write the solution in C#.\n\n" | |
| "### Java\n" | |
| f"{user_input}\n\n" | |
| "### Response\n" | |
| ) | |
| def clean_output(text: str) -> str: | |
| 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 generate_code(task: str, user_input: str) -> str: | |
| 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: | |
| 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.eos_token_id, | |
| eos_token_id=tokenizer.eos_token_id, | |
| ) | |
| generated_tokens = outputs[0][inputs["input_ids"].shape[1]:] | |
| generated_text = tokenizer.decode( | |
| generated_tokens, | |
| skip_special_tokens=True, | |
| ) | |
| code = _clean_csharp_output(generated_text) | |
| if not code: | |
| return "The model returned an empty response. Please try again." | |
| language = "java" if task == "Natural Language β Java" else "csharp" | |
| return f"```{language}\n{code}\n```" | |
| except Exception as error: | |
| return f"Generation failed: {type(error).__name__}: {error}" | |
| finally: | |
| model.to("cpu") | |
| torch.cuda.empty_cache() | |
| def update_input(task: str): | |
| 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="", | |
| ) | |
| 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() | |
| 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.", | |
| ], | |
| [ | |
| "Java β C#", | |
| """public static int factorial(int n) { | |
| int result = 1; | |
| for (int i = 2; i <= n; i++) { | |
| result *= i; | |
| } | |
| return result; | |
| }""", | |
| ], | |
| ], | |
| inputs=[ | |
| task, | |
| user_input, | |
| ], | |
| ) | |
| def _clean_csharp_output(code: str) -> str: | |
| """ | |
| Remove spurious `virtual` / `override` modifiers the model adds to bare | |
| (class-less) method snippets. | |
| The model was trained on C# methods that usually live inside a class, where | |
| `public virtual ...` is common. When it translates a *standalone* Java method | |
| it carries the `virtual` keyword over β but `virtual`/`override` are only | |
| valid on members of a class, so on a bare snippet they are invalid C#. | |
| We therefore strip them ONLY when the snippet has no enclosing type | |
| declaration (class / struct / interface / record / enum). | |
| """ | |
| if re.search(r"\b(class|struct|interface|record|enum)\b", code): | |
| return code # real type present β leave modifiers intact | |
| # Drop 'virtual'/'override' after an access modifier: 'public virtual int' -> 'public int'. | |
| code = re.sub(r"\b(public|private|protected|internal)\s+(?:virtual|override)\s+", | |
| r"\1 ", code) | |
| # Drop a leading 'virtual'/'override' with no access modifier. | |
| code = re.sub(r"(^|\n)(\s*)(?:virtual|override)\s+", r"\1\2", code) | |
| return code | |
| if __name__ == "__main__": | |
| demo.queue( | |
| default_concurrency_limit=1, | |
| max_size=10, | |
| ).launch() |