Jaiwincr7 commited on
Commit
dad3b3d
·
1 Parent(s): 5ecaa55

Final local changes before pulling latest remote updates

Browse files
Dockerfile CHANGED
@@ -1,20 +1,27 @@
1
- FROM python:3.13.5-slim
 
2
 
 
3
  WORKDIR /app
4
 
5
- RUN apt-get update && apt-get install -y \
6
- build-essential \
7
- curl \
8
- git \
9
- && rm -rf /var/lib/apt/lists/*
10
-
11
- COPY requirements.txt ./
12
- COPY src/ ./src/
13
 
14
- RUN pip3 install -r requirements.txt
 
15
 
16
- EXPOSE 8501
 
 
 
17
 
18
- HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
 
 
 
 
19
 
20
- ENTRYPOINT ["streamlit", "run", "src/streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]
 
 
 
 
1
+ # Use a Python base image
2
+ FROM python:3.10-slim
3
 
4
+ # Set the working directory
5
  WORKDIR /app
6
 
7
+ # Expose the port Streamlit runs on
8
+ EXPOSE 8501
 
 
 
 
 
 
9
 
10
+ # Copy the requirements file and install dependencies
11
+ COPY requirements.txt .
12
 
13
+ # Install dependencies. We use specific indexes for PyTorch to ensure compatibility
14
+ # and a general upgrade to avoid issues.
15
+ RUN pip install --upgrade pip
16
+ RUN pip install -r requirements.txt
17
 
18
+ # Copy the rest of the application code
19
+ # Assuming the user saved the provided code blocks into these files
20
+ COPY main.py .
21
+ COPY merged.py .
22
+ COPY app.py .
23
 
24
+ # Command to run the Streamlit application
25
+ # We use --server.port 8501 to match the exposed port
26
+ # and --server.address 0.0.0.0 to make it accessible outside the container
27
+ CMD ["streamlit", "run", "app.py", "--server.port", "8501", "--server.address", "0.0.0.0"]
__pycache__/code.cpython-313.pyc ADDED
Binary file (1.34 kB). View file
 
__pycache__/main.cpython-313.pyc ADDED
Binary file (3.23 kB). View file
 
__pycache__/merged.cpython-313.pyc ADDED
Binary file (1.97 kB). View file
 
app.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from merged import load_model_and_tokenizer, generate_code_stream
3
+ from main import test_case # your existing PDF generator
4
+
5
+ st.write("🚀 App started")
6
+ # ---------------- Load model ONCE ----------------
7
+ @st.cache_resource
8
+ def load_model():
9
+ return load_model_and_tokenizer()
10
+
11
+ tokenizer, model = load_model()
12
+
13
+ # ---------------- Session state ----------------
14
+ for key in ["selected_language", "generated_code", "pdf_bytes", "user_input"]:
15
+ if key not in st.session_state:
16
+ st.session_state[key] = "" if key != "selected_language" else None
17
+
18
+ # ---------------- UI helpers ----------------
19
+ def select_language(lang):
20
+ st.session_state.selected_language = lang
21
+ st.session_state.generated_code = ""
22
+ st.session_state.pdf_bytes = ""
23
+ st.session_state.user_input = ""
24
+
25
+ def reset():
26
+ for k in st.session_state:
27
+ st.session_state[k] = "" if k != "selected_language" else None
28
+
29
+ # ---------------- UI ----------------
30
+ st.title("Generate any code and get test case for it")
31
+
32
+ if st.session_state.selected_language is None:
33
+ cols = st.columns(4)
34
+ cols[0].button("Java", on_click=select_language, args=("Java",))
35
+ cols[1].button("React.js", on_click=select_language, args=("React.js",))
36
+ cols[2].button("Python", on_click=select_language, args=("Python",))
37
+ cols[3].button("C++", on_click=select_language, args=("C++",))
38
+
39
+ else:
40
+ lang = st.session_state.selected_language
41
+ st.subheader(f"Selected Language: {lang}")
42
+ st.button("Reset", on_click=reset)
43
+
44
+ st.session_state.user_input = st.text_input(
45
+ "Describe the task",
46
+ value=st.session_state.user_input
47
+ )
48
+
49
+ if st.button("Generate Code"):
50
+ if st.session_state.user_input.strip():
51
+ st.session_state.generated_code = ""
52
+
53
+ st.subheader("Generated Code")
54
+ code_placeholder = st.empty()
55
+
56
+ with st.spinner("Generating code..."):
57
+ for token in generate_code_stream(
58
+ lang,
59
+ st.session_state.user_input,
60
+ tokenizer,
61
+ model
62
+ ):
63
+ st.session_state.generated_code += token
64
+ code_placeholder.code(
65
+ st.session_state.generated_code
66
+ )
67
+
68
+ # Generate test case PDF AFTER code generation
69
+ st.session_state.pdf_bytes = test_case(
70
+ st.session_state.generated_code
71
+ )
72
+
73
+ else:
74
+ st.warning("Please enter a task")
75
+
76
+ if st.session_state.pdf_bytes:
77
+ st.download_button(
78
+ "Download Test Cases PDF",
79
+ st.session_state.pdf_bytes,
80
+ file_name="test_cases.pdf",
81
+ mime="application/pdf"
82
+ )
83
+
finetunned.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import AutoModelForCausalLM, AutoTokenizer
2
+ from peft import PeftModel
3
+ import torch
4
+
5
+ model_id = "Qwen/Qwen2.5-Coder-0.5B-Instruct"
6
+ lora_path = "./Qwen2.5-Coder-0.5B-lora"
7
+
8
+ tokenizer = AutoTokenizer.from_pretrained(
9
+ model_id,
10
+ trust_remote_code=True
11
+ )
12
+ tokenizer.pad_token = tokenizer.eos_token
13
+
14
+ # 🔴 CPU ONLY — NO CUDA, NO device_map
15
+ base_model = AutoModelForCausalLM.from_pretrained(
16
+ model_id,
17
+ trust_remote_code=True,
18
+ torch_dtype=torch.float32,
19
+ low_cpu_mem_usage=True,
20
+ )
21
+
22
+ model = PeftModel.from_pretrained(
23
+ base_model,
24
+ lora_path,
25
+ )
26
+
27
+ print("🔄 Merging LoRA (this will take time on CPU)...")
28
+
29
+ merged_model = model.merge_and_unload()
30
+
31
+ merged_model.save_pretrained("./Qwen2.5-Coder-0.5B-lora-merged")
32
+ tokenizer.save_pretrained("./Qwen2.5-Coder-0.5B-lora-merged")
33
+
34
+ print("✅ Merge complete")
main.py ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.runnables import RunnablePassthrough, RunnableMap
2
+ from langchain_core.output_parsers import StrOutputParser
3
+ from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
4
+ from langchain_huggingface import HuggingFacePipeline
5
+ from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
6
+ import torch
7
+ from fpdf import FPDF
8
+ import re
9
+
10
+ model_id = "deepseek-ai/deepseek-coder-1.3b-instruct"
11
+
12
+ # Load model and tokenizer once
13
+ tokenizer = AutoTokenizer.from_pretrained(model_id)
14
+ model = AutoModelForCausalLM.from_pretrained(
15
+ model_id,
16
+ dtype=torch.float16,
17
+ device_map="auto",
18
+ offload_folder="./offload"
19
+ )
20
+ stop_tokens = ["<|end_of_text|>", "<|end_of_user|>"]
21
+
22
+ # Wrap Transformers pipeline
23
+ pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
24
+ llm = HuggingFacePipeline(
25
+ pipeline=pipe,
26
+ model_kwargs={
27
+ "max_new_tokens": 4096,
28
+ "do_sample": True,
29
+ "temperature": 0.2,
30
+ "repetition_penalty": 1.05,
31
+ "eos_token_id": tokenizer.eos_token_id,
32
+ }
33
+ )
34
+
35
+ def test_case(code):
36
+ test_prompt = ChatPromptTemplate.from_messages(
37
+ [
38
+ (
39
+ "system",
40
+ """You are an expert QA engineer.
41
+ STRICTLY follow these rules for your output:
42
+ - Generate EXACTLY 10 numbered test cases (1–5 functional, 6–10 edge cases).
43
+ - Output ONLY the numbered list.
44
+ - DO NOT include explanations, headers, filler text, or markdown.
45
+ - Each test MUST be a single, concise sentence.
46
+ - Begin your response immediately with '1. '""", # Slightly relaxed constraints
47
+ ),
48
+ (
49
+ "user",
50
+ "Generate test cases for the following code:\n{code}",
51
+ ),
52
+ ]
53
+ )
54
+
55
+ test_chain = test_prompt | llm | StrOutputParser()
56
+ test_cases = test_chain.invoke({"code": code})
57
+
58
+ print("\nGenerated Test Cases (Raw):\n", test_cases)
59
+
60
+ # Aggressive cleaning
61
+ test_cases = re.sub(r"```.*?```", "", test_cases, flags=re.DOTALL)
62
+ test_cases = re.sub(r"```", "", test_cases)
63
+ test_cases = test_cases.strip()
64
+
65
+ # --- ADD THIS CHECK ---
66
+ if not test_cases:
67
+ test_cases = "Error: Test case generation failed or returned empty content."
68
+
69
+ print("\nGenerated Test Cases (Cleaned):\n", test_cases)
70
+ # -----------------------
71
+
72
+ # Encoding step remains the same for FPDF compatibility
73
+ safe_text = test_cases.encode("latin-1", "ignore").decode("latin-1")
74
+
75
+ # If the safe_text is still empty, FPDF will produce an empty PDF
76
+ # It's better to verify the content being passed to FPDF
77
+
78
+ pdf=FPDF()
79
+ pdf.add_page()
80
+ pdf.set_font("Arial", size=12)
81
+ # You can set a title to ensure the PDF isn't blank
82
+ pdf.multi_cell(0, 10, txt="--- Generated Test Cases ---", align='C')
83
+ pdf.multi_cell(0, 10, txt=safe_text)
84
+
85
+ # Use output as a bytes object without saving to disk first
86
+ file = pdf.output(dest='S').encode('latin-1')
87
+
88
+ return file
merged.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from transformers import (
3
+ AutoModelForCausalLM,
4
+ AutoTokenizer,
5
+ TextIteratorStreamer
6
+ )
7
+ from threading import Thread
8
+
9
+ MODEL_PATH = "jaiwinrc7/Qwen2.5-Coder-0.5B-finetunned-merged"
10
+
11
+
12
+ def load_model_and_tokenizer():
13
+ tokenizer = AutoTokenizer.from_pretrained(
14
+ MODEL_PATH,
15
+ trust_remote_code=True
16
+ )
17
+
18
+ model = AutoModelForCausalLM.from_pretrained(
19
+ MODEL_PATH,
20
+ device_map="cpu",
21
+ trust_remote_code=True,
22
+ torch_dtype=torch.float32, # IMPORTANT: faster on CPU
23
+ )
24
+
25
+ model.eval()
26
+ return tokenizer, model
27
+
28
+
29
+ def build_prompt(lang, task):
30
+ # Keep prompt SIMPLE for speed
31
+ return f"""You are a coding assistant.
32
+ Write {lang} code for the following task:
33
+
34
+ {task}
35
+
36
+ Code:
37
+ """
38
+
39
+
40
+ def generate_code_stream(lang, user_input, tokenizer, model):
41
+ prompt = build_prompt(lang, user_input)
42
+ inputs = tokenizer(prompt, return_tensors="pt")
43
+
44
+ streamer = TextIteratorStreamer(
45
+ tokenizer,
46
+ skip_prompt=True,
47
+ skip_special_tokens=True
48
+ )
49
+
50
+ generation_kwargs = dict(
51
+ **inputs,
52
+ max_new_tokens=250,
53
+ do_sample=False,
54
+ temperature=0.0,
55
+ use_cache=True,
56
+ streamer=streamer,
57
+ pad_token_id=tokenizer.eos_token_id,
58
+ )
59
+
60
+ # Run generation in background thread
61
+ thread = Thread(
62
+ target=model.generate,
63
+ kwargs=generation_kwargs
64
+ )
65
+ thread.start()
66
+
67
+ # Yield tokens as they arrive
68
+ for token in streamer:
69
+ yield token