TaruniSwathi commited on
Commit
dfffab1
·
verified ·
1 Parent(s): 962dcef

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -56
app.py CHANGED
@@ -19,14 +19,17 @@ MODEL_ID = "shibsankardhara2/Qwen2.5-Coder-1.5B-Java-CSharp_V5"
19
 
20
  print("Loading tokenizer...")
21
 
22
- tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
 
 
 
23
 
24
  if tokenizer.pad_token_id is None:
25
  tokenizer.pad_token_id = tokenizer.eos_token_id
26
 
27
 
28
  # ============================================================
29
- # LOAD MODEL
30
  # ============================================================
31
 
32
  print("Loading model on CPU...")
@@ -35,6 +38,7 @@ model = AutoModelForCausalLM.from_pretrained(
35
  MODEL_ID,
36
  torch_dtype=torch.float16,
37
  low_cpu_mem_usage=True,
 
38
  )
39
 
40
  model.eval()
@@ -48,8 +52,8 @@ print("Model loaded successfully.")
48
 
49
  def add_java_hint(instruction: str) -> str:
50
  """
51
- Add an explicit Java instruction when the user has not
52
- mentioned Java in the natural-language requirement.
53
  """
54
  instruction = instruction.strip()
55
 
@@ -61,7 +65,7 @@ def add_java_hint(instruction: str) -> str:
61
 
62
  def build_prompt(task: str, user_input: str) -> str:
63
  """
64
- Build the appropriate prompt based on the selected task.
65
  """
66
  user_input = user_input.strip()
67
 
@@ -83,25 +87,30 @@ def build_prompt(task: str, user_input: str) -> str:
83
 
84
 
85
  # ============================================================
86
- # OUTPUT CLEANING
87
  # ============================================================
88
 
89
- def clean_output(text: str) -> str:
90
  """
91
- Remove Markdown code fences, repeated prompt sections,
92
- and model-specific special tokens from the generated output.
93
  """
94
- text = text.strip()
 
 
 
95
 
96
- fenced = re.search(
 
97
  r"```(?:java|csharp|cs|c#)?\s*(.*?)```",
98
- text,
99
  flags=re.DOTALL | re.IGNORECASE,
100
  )
101
 
102
- if fenced:
103
- text = fenced.group(1).strip()
104
 
 
105
  stop_markers = [
106
  "### Instruction:",
107
  "### Instruction\n",
@@ -111,24 +120,49 @@ def clean_output(text: str) -> str:
111
  "### Response\n",
112
  "<|im_start|>",
113
  "<|im_end|>",
 
114
  ]
115
 
116
  for marker in stop_markers:
117
- if marker in text:
118
- text = text.split(marker, 1)[0].strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
- return text
121
 
 
 
 
122
 
123
- def clean_csharp_output(code: str) -> str:
124
  """
125
- Remove unnecessary `virtual` and `override` modifiers from
126
- standalone C# method snippets.
127
 
128
- These modifiers are preserved when the generated code contains
129
- a class, struct, interface, record, or enum declaration.
130
  """
131
- code = code.strip()
 
 
 
 
132
 
133
  has_type_declaration = re.search(
134
  r"\b(class|struct|interface|record|enum)\b",
@@ -139,8 +173,8 @@ def clean_csharp_output(code: str) -> str:
139
  if has_type_declaration:
140
  return code
141
 
142
- # Example:
143
- # public virtual int Add(...) -> public int Add(...)
144
  code = re.sub(
145
  r"\b(public|private|protected|internal)\s+"
146
  r"(?:virtual|override)\s+",
@@ -149,8 +183,8 @@ def clean_csharp_output(code: str) -> str:
149
  flags=re.IGNORECASE,
150
  )
151
 
152
- # Example:
153
- # virtual int Add(...) -> int Add(...)
154
  code = re.sub(
155
  r"(^|\n)(\s*)(?:virtual|override)\s+",
156
  r"\1\2",
@@ -168,66 +202,80 @@ def clean_csharp_output(code: str) -> str:
168
  @spaces.GPU(duration=120)
169
  def generate_code(task: str, user_input: str) -> str:
170
  """
171
- Generate Java code from natural language or translate
172
- Java code into C#.
173
  """
174
  if not user_input or not user_input.strip():
175
  return "Please enter a requirement or Java code."
176
 
177
  prompt = build_prompt(task, user_input)
178
 
179
- if task == "Natural Language → Java":
180
- max_new_tokens = 300
181
- else:
182
- max_new_tokens = 400
 
183
 
184
  try:
185
- # Move the model to the GPU only during generation.
 
 
 
186
  model.to("cuda")
 
187
 
188
- inputs = tokenizer(
189
  prompt,
190
  return_tensors="pt",
191
  truncation=True,
192
  max_length=2048,
193
- ).to("cuda")
 
 
 
 
 
194
 
195
  with torch.inference_mode():
196
- outputs = model.generate(
197
- **inputs,
198
  max_new_tokens=max_new_tokens,
199
  do_sample=False,
 
200
  pad_token_id=tokenizer.pad_token_id,
201
  eos_token_id=tokenizer.eos_token_id,
202
  )
203
 
204
- # Remove the original input prompt from the generated sequence.
205
- prompt_length = inputs["input_ids"].shape[1]
206
 
207
- generated_tokens = outputs[0][prompt_length:]
208
 
209
  generated_text = tokenizer.decode(
210
- generated_tokens,
211
  skip_special_tokens=True,
 
212
  )
213
 
214
- # Clean repeated prompts, code fences, and special tokens.
215
- code = clean_output(generated_text)
216
 
217
- # Apply the C# modifier cleanup only for Java → C#.
218
  if task == "Java → C#":
219
- code = clean_csharp_output(code)
220
- language = "csharp"
221
  else:
222
- language = "java"
223
 
224
- if not code:
225
  return (
226
  "The model returned an empty response. "
227
- "Please try again."
228
  )
229
 
230
- return f"```{language}\n{code}\n```"
 
 
 
 
231
 
232
  except Exception as error:
233
  return (
@@ -236,21 +284,23 @@ def generate_code(task: str, user_input: str) -> str:
236
  )
237
 
238
  finally:
239
- # Move the model back to CPU to release the ZeroGPU allocation.
240
- model.to("cpu")
 
 
 
241
 
242
  if torch.cuda.is_available():
243
  torch.cuda.empty_cache()
244
 
245
 
246
  # ============================================================
247
- # GRADIO INPUT UPDATE
248
  # ============================================================
249
 
250
  def update_input(task: str):
251
  """
252
- Change the textbox label and placeholder based on the
253
- selected task.
254
  """
255
  if task == "Natural Language → Java":
256
  return gr.update(
 
19
 
20
  print("Loading tokenizer...")
21
 
22
+ tokenizer = AutoTokenizer.from_pretrained(
23
+ MODEL_ID,
24
+ trust_remote_code=True,
25
+ )
26
 
27
  if tokenizer.pad_token_id is None:
28
  tokenizer.pad_token_id = tokenizer.eos_token_id
29
 
30
 
31
  # ============================================================
32
+ # LOAD MODEL ON CPU
33
  # ============================================================
34
 
35
  print("Loading model on CPU...")
 
38
  MODEL_ID,
39
  torch_dtype=torch.float16,
40
  low_cpu_mem_usage=True,
41
+ trust_remote_code=True,
42
  )
43
 
44
  model.eval()
 
52
 
53
  def add_java_hint(instruction: str) -> str:
54
  """
55
+ Explicitly mention Java when it is missing from the
56
+ natural-language instruction.
57
  """
58
  instruction = instruction.strip()
59
 
 
65
 
66
  def build_prompt(task: str, user_input: str) -> str:
67
  """
68
+ Construct the prompt expected by the fine-tuned model.
69
  """
70
  user_input = user_input.strip()
71
 
 
87
 
88
 
89
  # ============================================================
90
+ # GENERAL OUTPUT CLEANING
91
  # ============================================================
92
 
93
+ def clean_output(generated_text: str) -> str:
94
  """
95
+ Remove Markdown fences, repeated prompt sections and
96
+ model-specific special tokens.
97
  """
98
+ if not generated_text:
99
+ return ""
100
+
101
+ cleaned_text = generated_text.strip()
102
 
103
+ # Extract the contents of a Markdown code block, when present.
104
+ fenced_match = re.search(
105
  r"```(?:java|csharp|cs|c#)?\s*(.*?)```",
106
+ cleaned_text,
107
  flags=re.DOTALL | re.IGNORECASE,
108
  )
109
 
110
+ if fenced_match:
111
+ cleaned_text = fenced_match.group(1).strip()
112
 
113
+ # Remove prompt sections that the model may generate again.
114
  stop_markers = [
115
  "### Instruction:",
116
  "### Instruction\n",
 
120
  "### Response\n",
121
  "<|im_start|>",
122
  "<|im_end|>",
123
+ "<|endoftext|>",
124
  ]
125
 
126
  for marker in stop_markers:
127
+ marker_position = cleaned_text.find(marker)
128
+
129
+ if marker_position != -1:
130
+ cleaned_text = cleaned_text[:marker_position].strip()
131
+
132
+ # Remove remaining opening or closing fences.
133
+ cleaned_text = re.sub(
134
+ r"^```(?:java|csharp|cs|c#)?\s*",
135
+ "",
136
+ cleaned_text,
137
+ flags=re.IGNORECASE,
138
+ )
139
+
140
+ cleaned_text = re.sub(
141
+ r"\s*```$",
142
+ "",
143
+ cleaned_text,
144
+ )
145
+
146
+ return cleaned_text.strip()
147
 
 
148
 
149
+ # ============================================================
150
+ # C# OUTPUT CLEANING
151
+ # ============================================================
152
 
153
+ def clean_csharp_output(text: str) -> str:
154
  """
155
+ Remove invalid virtual or override modifiers from standalone
156
+ C# method snippets.
157
 
158
+ If the output contains a class, struct, interface, record or
159
+ enum declaration, modifiers are preserved.
160
  """
161
+ if not text:
162
+ return ""
163
+
164
+ # Explicitly initialise code before it is accessed.
165
+ code = text.strip()
166
 
167
  has_type_declaration = re.search(
168
  r"\b(class|struct|interface|record|enum)\b",
 
173
  if has_type_declaration:
174
  return code
175
 
176
+ # public virtual int Method() -> public int Method()
177
+ # protected override void Method() -> protected void Method()
178
  code = re.sub(
179
  r"\b(public|private|protected|internal)\s+"
180
  r"(?:virtual|override)\s+",
 
183
  flags=re.IGNORECASE,
184
  )
185
 
186
+ # virtual int Method() -> int Method()
187
+ # override void Method() -> void Method()
188
  code = re.sub(
189
  r"(^|\n)(\s*)(?:virtual|override)\s+",
190
  r"\1\2",
 
202
  @spaces.GPU(duration=120)
203
  def generate_code(task: str, user_input: str) -> str:
204
  """
205
+ Generate Java from natural language or translate Java to C#.
 
206
  """
207
  if not user_input or not user_input.strip():
208
  return "Please enter a requirement or Java code."
209
 
210
  prompt = build_prompt(task, user_input)
211
 
212
+ max_new_tokens = (
213
+ 300
214
+ if task == "Natural Language → Java"
215
+ else 400
216
+ )
217
 
218
  try:
219
+ if not torch.cuda.is_available():
220
+ return "Generation failed: GPU is not available."
221
+
222
+ # Move the model to the allocated ZeroGPU device.
223
  model.to("cuda")
224
+ model.eval()
225
 
226
+ tokenized_inputs = tokenizer(
227
  prompt,
228
  return_tensors="pt",
229
  truncation=True,
230
  max_length=2048,
231
+ )
232
+
233
+ tokenized_inputs = {
234
+ key: value.to("cuda")
235
+ for key, value in tokenized_inputs.items()
236
+ }
237
 
238
  with torch.inference_mode():
239
+ generated_ids = model.generate(
240
+ **tokenized_inputs,
241
  max_new_tokens=max_new_tokens,
242
  do_sample=False,
243
+ use_cache=True,
244
  pad_token_id=tokenizer.pad_token_id,
245
  eos_token_id=tokenizer.eos_token_id,
246
  )
247
 
248
+ prompt_length = tokenized_inputs["input_ids"].shape[1]
 
249
 
250
+ new_token_ids = generated_ids[0][prompt_length:]
251
 
252
  generated_text = tokenizer.decode(
253
+ new_token_ids,
254
  skip_special_tokens=True,
255
+ clean_up_tokenization_spaces=False,
256
  )
257
 
258
+ # Always run the general output cleaner.
259
+ output_code = clean_output(generated_text)
260
 
261
+ # Run the C#-specific cleaner only for Java → C#.
262
  if task == "Java → C#":
263
+ output_code = clean_csharp_output(output_code)
264
+ markdown_language = "csharp"
265
  else:
266
+ markdown_language = "java"
267
 
268
+ if not output_code:
269
  return (
270
  "The model returned an empty response. "
271
+ "Please try a more specific input."
272
  )
273
 
274
+ return (
275
+ f"```{markdown_language}\n"
276
+ f"{output_code}\n"
277
+ "```"
278
+ )
279
 
280
  except Exception as error:
281
  return (
 
284
  )
285
 
286
  finally:
287
+ # Return the model to CPU after the ZeroGPU request.
288
+ try:
289
+ model.to("cpu")
290
+ except Exception as move_error:
291
+ print(f"Could not move model to CPU: {move_error}")
292
 
293
  if torch.cuda.is_available():
294
  torch.cuda.empty_cache()
295
 
296
 
297
  # ============================================================
298
+ # UPDATE TEXTBOX
299
  # ============================================================
300
 
301
  def update_input(task: str):
302
  """
303
+ Update the input textbox for the selected task.
 
304
  """
305
  if task == "Natural Language → Java":
306
  return gr.update(