File size: 5,206 Bytes
cca72b6
9b5475f
 
cca72b6
5cb3921
368af95
cca72b6
8957595
 
cca72b6
0f9548d
 
 
 
 
 
 
 
 
 
 
 
9b5475f
 
0f9548d
cca72b6
5cb3921
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368af95
 
 
 
 
 
 
 
9b5475f
 
3da38ba
2d4c02b
9b5475f
 
 
 
368af95
 
9b5475f
2d4c02b
9b5475f
 
 
368af95
 
9b5475f
2d4c02b
9b5475f
 
 
368af95
 
d7afe71
449db6f
8529dbe
be1bad8
c4b795b
02b1fdc
 
64129bb
02b1fdc
c4b795b
9b5475f
cca72b6
9b5475f
3da38ba
9b5475f
 
e282faa
adc8c12
cca72b6
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import gradio as gr
import torch
import spaces
from transformers import AutoTokenizer, AutoModelForCausalLM
import re
import subprocess

tokenizer = AutoTokenizer.from_pretrained("shibsankardhara2/Qwen2.5-Coder-1.5B-Java-CSharp_V5")
model = AutoModelForCausalLM.from_pretrained("shibsankardhara2/Qwen2.5-Coder-1.5B-Java-CSharp_V5")

def single_function(code):
    beg_count = 0
    end_count = 0
    start = 0
    for n, i in enumerate(code):
        if i == '{':
            beg_count += 1
        elif i == '}':
            end_count += 1
        if beg_count == end_count and beg_count > 0:
            start = n
            break
    if start == 0:
        return code
    return code[:start+1]

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

def format_code(code, language="java"):
    extension="java" if language=="java" else "cs"
    result= subprocess.run(
        ["clang-format",f"--assume-filename=file.{extension}", "--style=Google"],
        input=code, capture_output=True, text=True
    )
    return result.stdout if result.returncode == 0 else code

@spaces.GPU
def generate_code(task_type: str, nl_input: str):
    if task_type == "NL to Java" or task_type == "End to End NL to Java to C#":
        prompt = f"### Instruction:\n\n{nl_input} Write the solution in Java with proper indentation.\n\n### Response:\n\n"
        inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
        outputs = model.generate(**inputs, max_new_tokens=128, eos_token_id=tokenizer.eos_token_id, pad_token_id=tokenizer.eos_token_id)
        response = tokenizer.decode(outputs[0], skip_special_tokens=True).split("### Response:\n\n")[-1].strip()
        if task_type == "NL to Java":
            output= _clean_csharp_output(response)
            return format_code(output, language="java")
        else:
            prompt = f"### Instruction:\n\nConvert the below Java Code to C# with proper indentation\n\n{single_function(response)}\n\n### Response:\n\n"
            inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
            outputs = model.generate(**inputs, max_new_tokens=128, eos_token_id=tokenizer.eos_token_id, pad_token_id=tokenizer.eos_token_id)
            response = tokenizer.decode(outputs[0], skip_special_tokens=True).split("### Response:\n\n")[-1].strip()
            output= _clean_csharp_output(response)
            return format_code(output, language="cs")
    elif task_type == "Java to C#":
        prompt = f"### Instruction:\n\nConvert the below Java Code to C# with proper indentation\n\n{nl_input}\n\n### Response:\n\n"
        inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
        outputs = model.generate(**inputs, max_new_tokens=128, eos_token_id=tokenizer.eos_token_id, pad_token_id=tokenizer.eos_token_id)
        response = tokenizer.decode(outputs[0], skip_special_tokens=True).split("### Response:\n\n")[-1].strip()
        output= _clean_csharp_output(response)
        return format_code(output, language="cs")
    elif task_type=="Generate Documentation":
        prompt = f"### Instruction:\n\nWrite a documentation comment with @param and @return tags for the following method:\n\n{nl_input}\n\n### Response:\n\n/**"
        inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
        output=model.generate(**inputs,max_new_tokens=200, eos_token_id=tokenizer.eos_token_id, pad_token_id=tokenizer.eos_token_id)
        response = tokenizer.decode(output[0], skip_special_tokens=True).split("### Response:\n\n")[-1].strip()
        if not response.startswith("/**"):
            response = "/**" + response
        response = response.split("*/")[0] + "*/" if "*/" in response else response
        response = response.replace("**/", "*/")
        return response
demo = gr.Interface(
    fn=generate_code,
    inputs=[
        gr.Dropdown(label="Select Task", choices=["NL to Java", "Java to C#", "End to End NL to Java to C#", "Generate Documentation"], value="NL to Java"),
        gr.Textbox(label="Input")
    ],
    outputs=gr.Code(label="Generated Code"),
    title="CodeGen NL to Java and Java to C#"
)

demo.launch()