File size: 6,105 Bytes
70b1647
df91366
1894e93
 
70b1647
08b38c5
 
 
 
 
 
 
 
 
 
1894e93
08b38c5
1894e93
08b38c5
 
1894e93
08b38c5
 
 
70b1647
08b38c5
 
 
 
526351c
df91366
08b38c5
 
 
ec8810f
08b38c5
 
 
ec8810f
08b38c5
 
 
ec8810f
08b38c5
 
ec8810f
 
08b38c5
ec8810f
df91366
08b38c5
 
 
 
526351c
08b38c5
526351c
08b38c5
526351c
ec8810f
70b1647
df91366
08b38c5
df91366
08b38c5
 
 
 
 
 
 
 
 
 
 
 
 
 
df91366
08b38c5
526351c
df91366
526351c
 
 
 
 
 
 
1894e93
 
ec8810f
08b38c5
 
526351c
 
08b38c5
526351c
df91366
08b38c5
df91366
 
 
08b38c5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df91366
ec8810f
df91366
08b38c5
df91366
08b38c5
ec8810f
 
08b38c5
df91366
 
08b38c5
df91366
08b38c5
 
 
df91366
 
08b38c5
 
 
df91366
08b38c5
df91366
08b38c5
 
df91366
 
ec8810f
df91366
 
ec8810f
df91366
08b38c5
 
 
 
 
df91366
 
 
 
 
08b38c5
 
 
df91366
ec8810f
08b38c5
ec8810f
08b38c5
ec8810f
08b38c5
 
df91366
08b38c5
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
import gradio as gr
import torch
import sys
import subprocess

# Install required packages
def install_packages():
    packages = ["peft==0.7.0", "sentencepiece==0.1.99", "protobuf==3.20.3"]
    for package in packages:
        try:
            __import__(package.split('==')[0])
            print(f"βœ… {package} already installed")
        except ImportError:
            print(f"πŸ“¦ Installing {package}...")
            subprocess.check_call([sys.executable, "-m", "pip", "install", package])

install_packages()

from transformers import T5Tokenizer, T5ForConditionalGeneration
from peft import PeftModel

# Configuration
PEFT_MODEL_ID = "daffaaditya/daffa-ai"
BASE_MODEL = "t5-small"

print("=" * 50)
print(f"πŸš€ Loading PEFT Adapter: {PEFT_MODEL_ID}")
print(f"πŸ“¦ Base Model: {BASE_MODEL}")
print("=" * 50)

try:
    # Load tokenizer dari BASE MODEL, bukan dari adapter
    print("1. Loading tokenizer from base model...")
    tokenizer = T5Tokenizer.from_pretrained(BASE_MODEL)
    
    # Load base model
    print("2. Loading base model...")
    base_model = T5ForConditionalGeneration.from_pretrained(BASE_MODEL)
    
    # Load adapter
    print("3. Loading adapter...")
    model = PeftModel.from_pretrained(base_model, PEFT_MODEL_ID)
    
    # Merge adapter (optional, tapi lebih cepat untuk inference)
    print("4. Merging adapter with base model...")
    model = model.merge_and_unload()
    
    print("βœ… SUCCESS: PEFT model loaded and merged!")
    
except Exception as e:
    print(f"❌ Error: {e}")
    print("πŸ”„ Falling back to plain T5-small without adapter...")
    tokenizer = T5Tokenizer.from_pretrained(BASE_MODEL)
    model = T5ForConditionalGeneration.from_pretrained(BASE_MODEL)

# Setup device
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"πŸ“± Device: {device}")
model.to(device)
model.eval()

def generate_code(instruction, max_length=150, temperature=0.7):
    """Generate Python code from instruction"""
    try:
        # Clean instruction
        instruction = instruction.strip()
        
        # Format prompt lebih baik
        if "prima" in instruction.lower():
            prompt = "Write a Python function to check if a number is prime:"
        elif "faktorial" in instruction.lower():
            prompt = "Write a Python function to calculate factorial:"
        elif "reverse" in instruction.lower():
            prompt = "Write a Python function to reverse a string:"
        elif "lingkaran" in instruction.lower() or "circle" in instruction.lower():
            prompt = "Write a Python function to calculate circle area:"
        else:
            prompt = f"Write Python code for: {instruction}"
        
        # Tokenize
        inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=128).to(device)
        
        # Generate
        with torch.no_grad():
            outputs = model.generate(
                **inputs,
                max_length=max_length,
                temperature=temperature,
                do_sample=True,
                num_return_sequences=1,
                pad_token_id=tokenizer.pad_token_id,
                eos_token_id=tokenizer.eos_token_id,
                repetition_penalty=1.3,
                no_repeat_ngram_size=3
            )
        
        # Decode
        generated = tokenizer.decode(outputs[0], skip_special_tokens=True)
        
        # Clean output
        if generated.startswith(prompt):
            generated = generated[len(prompt):].strip()
        
        # Jika output kosong atau pendek
        if len(generated) < 10:
            # Fallback templates
            fallbacks = {
                "prima": """def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return False
    return True""",
                "faktorial": """def factorial(n):
    if n == 0:
        return 1
    return n * factorial(n-1)""",
                "reverse": """def reverse_string(s):
    return s[::-1]"""
            }
            
            for key, code in fallbacks.items():
                if key in instruction.lower():
                    return code
        
        return generated
        
    except Exception as e:
        return f"# Error\n# {str(e)}\n\nPlease try a different prompt."

# Create Gradio Interface
with gr.Blocks(title="Daffa AI Coder") as demo:
    gr.Markdown("# 🐍 Daffa AI Coder")
    gr.Markdown("Fine-tuned T5 model for Python code generation")
    
    with gr.Row():
        with gr.Column():
            instruction = gr.Textbox(
                label="Instruction (Indonesian/English)",
                placeholder="Example: buat fungsi untuk cek bilangan prima",
                lines=3
            )
            
            with gr.Accordion("βš™οΈ Settings", open=False):
                max_length = gr.Slider(50, 300, value=150, label="Max Length")
                temperature = gr.Slider(0.1, 1.5, value=0.7, label="Temperature")
            
            generate_btn = gr.Button("Generate Code", variant="primary")
        
        with gr.Column():
            output = gr.Code(
                label="Generated Python Code",
                language="python",
                lines=15
            )
    
    # Examples
    examples = [
        ["buat fungsi untuk cek bilangan prima"],
        ["create a function to calculate factorial"],
        ["write a function to reverse a string"],
        ["fungsi untuk menghitung luas lingkaran"],
        ["function to convert celsius to fahrenheit"]
    ]
    
    gr.Examples(
        examples=examples,
        inputs=instruction,
        outputs=output,
        fn=lambda x: generate_code(x, 150, 0.7),
        label="Try these examples:"
    )
    
    # Footer
    gr.Markdown("---")
    gr.Markdown(f"**Model:** {PEFT_MODEL_ID} | **Base:** {BASE_MODEL} | **Status:** {'Adapter Loaded' if 'PeftModel' in str(type(model)) else 'Base Model Only'}")
    
    # Events
    generate_btn.click(generate_code, [instruction, max_length, temperature], output)

demo.launch()