ErNewdev0 commited on
Commit
25e72a3
Β·
verified Β·
1 Parent(s): df7f9ea

chore: initial commit

Browse files
Files changed (3) hide show
  1. README_Version3.md +42 -0
  2. app_Version4.py +402 -0
  3. requirements_Version5.txt +6 -0
README_Version3.md ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # πŸš€ Analisis Repository dengan Ollama
2
+
3
+ Aplikasi web untuk menganalisis repository GitHub menggunakan Ollama API.
4
+
5
+ ## 🌟 Fitur
6
+
7
+ - πŸ“Š Analisis kode repository GitHub
8
+ - πŸ€– Integrasi dengan Ollama API
9
+ - πŸ“ Output dalam format code block yang bisa di-copy
10
+ - πŸ”„ Streaming response untuk hasil real-time
11
+ - 🎨 Dark mode UI
12
+
13
+ ## πŸ› οΈ Teknologi
14
+
15
+ - Gradio
16
+ - Ollama API
17
+ - Python
18
+ - Git
19
+
20
+ ## πŸš€ Deployment
21
+
22
+ Aplikasi ini di-deploy menggunakan Hugging Face Spaces.
23
+
24
+ ## πŸ“ Penggunaan
25
+
26
+ 1. Pilih model yang tersedia
27
+ 2. Masukkan URL repository GitHub
28
+ 3. Pilih file yang akan dianalisis
29
+ 4. Tunggu hasil analisis
30
+
31
+ ## βš™οΈ Environment Variables
32
+
33
+ - `OLLAMA_API`: URL untuk Ollama API
34
+ - `HF_USER`: Username pengguna (opsional)
35
+
36
+ ## πŸ‘₯ Kontributor
37
+
38
+ - ErRickow
39
+
40
+ ## πŸ“„ Lisensi
41
+
42
+ MIT License
app_Version4.py ADDED
@@ -0,0 +1,402 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ from pathlib import Path
4
+ import subprocess
5
+ import requests
6
+ import json
7
+ from datetime import datetime
8
+ import textwrap
9
+ import time
10
+ from tqdm import tqdm
11
+ import html
12
+ from dotenv import load_dotenv
13
+
14
+ # Load environment variables
15
+ load_dotenv()
16
+
17
+ # Metadata
18
+ CURRENT_TIME = "2025-05-22 23:15:49"
19
+ CURRENT_USER = "ErRickow"
20
+
21
+ # Ollama API settings
22
+ OLLAMA_API = os.getenv('OLLAMA_API', "https://9220-34-41-177-252.ngrok-free.app")
23
+
24
+ # Default models
25
+ DEFAULT_MODELS = [
26
+ "llama2",
27
+ "codellama",
28
+ "mistral",
29
+ "neural-chat",
30
+ "starling-lm",
31
+ "dolphin-phi",
32
+ "phi",
33
+ "orca-mini"
34
+ ]
35
+
36
+ # Custom CSS
37
+ CUSTOM_CSS = """
38
+ .output-block {
39
+ background-color: #1e1e1e;
40
+ border-radius: 5px;
41
+ padding: 10px;
42
+ margin: 10px 0;
43
+ font-family: 'Courier New', monospace;
44
+ position: relative;
45
+ }
46
+ .copy-button {
47
+ position: absolute;
48
+ top: 5px;
49
+ right: 5px;
50
+ padding: 5px 10px;
51
+ background-color: #2d2d2d;
52
+ border: none;
53
+ border-radius: 3px;
54
+ color: white;
55
+ cursor: pointer;
56
+ }
57
+ .copy-button:hover {
58
+ background-color: #3d3d3d;
59
+ }
60
+ pre {
61
+ margin: 0;
62
+ white-space: pre-wrap;
63
+ word-wrap: break-word;
64
+ }
65
+ code {
66
+ color: #d4d4d4;
67
+ }
68
+ """
69
+
70
+ def format_code_block(text, language=""):
71
+ """Format text as a code block with copy button"""
72
+ escaped_text = html.escape(text)
73
+ return f"""
74
+ <div class="output-block">
75
+ <button onclick="navigator.clipboard.writeText(`{escaped_text}`)" class="copy-button">
76
+ Copy
77
+ </button>
78
+ <pre><code class="language-{language}">{escaped_text}</code></pre>
79
+ </div>
80
+ """
81
+
82
+ def check_ollama_status():
83
+ try:
84
+ response = requests.get(f"{OLLAMA_API}/api/tags", timeout=10)
85
+ return response.status_code == 200
86
+ except:
87
+ return False
88
+
89
+ def list_available_models():
90
+ try:
91
+ response = requests.get(f"{OLLAMA_API}/api/tags")
92
+ installed_models = [model['name'] for model in response.json().get('models', [])]
93
+ all_models = list(set(installed_models + DEFAULT_MODELS))
94
+ return sorted(all_models)
95
+ except:
96
+ return sorted(DEFAULT_MODELS)
97
+
98
+ def download_model(model_name, progress=gr.Progress()):
99
+ if not model_name:
100
+ return "Silakan pilih model terlebih dahulu"
101
+
102
+ try:
103
+ progress(0, desc=f"Mulai mengunduh {model_name}")
104
+ headers = {"Content-Type": "application/json"}
105
+
106
+ response = requests.post(
107
+ f"{OLLAMA_API}/api/pull",
108
+ headers=headers,
109
+ json={"name": model_name},
110
+ stream=True
111
+ )
112
+
113
+ if response.status_code == 200:
114
+ total_progress = 0
115
+ for line in response.iter_lines():
116
+ if line:
117
+ data = json.loads(line)
118
+ if 'completed' in data and 'total' in data:
119
+ progress = min(data['completed'] / data['total'], 1.0)
120
+ progress(progress, desc=f"Mengunduh {model_name}: {int(progress*100)}%")
121
+ elif 'status' in data:
122
+ progress(total_progress, desc=f"Status: {data['status']}")
123
+ total_progress += 0.1
124
+ if total_progress > 0.9:
125
+ total_progress = 0.1
126
+
127
+ progress(1.0, desc="Selesai!")
128
+ return f"Model {model_name} berhasil diunduh!"
129
+ else:
130
+ return f"Gagal mengunduh model. Status: {response.status_code}"
131
+
132
+ except Exception as e:
133
+ return f"Error saat mengunduh model: {str(e)}"
134
+
135
+ def clone_repository(repo_url, github_token, branch=None):
136
+ repo_name = repo_url.split('/')[-1].replace('.git', '')
137
+ print(f"Mengkloning repository: {repo_url} ke {repo_name}")
138
+
139
+ if os.path.exists(repo_name):
140
+ print(f"Menghapus repository yang sudah ada: {repo_name}")
141
+ subprocess.run(['rm', '-rf', repo_name], check=True)
142
+
143
+ try:
144
+ cmd = ['git', 'clone']
145
+ if branch:
146
+ cmd.extend(['--branch', branch])
147
+
148
+ if github_token:
149
+ owner_repo = '/'.join(repo_url.split('/')[-2:])
150
+ auth_url = f"https://{github_token}@github.com/{owner_repo}"
151
+ cmd.append(auth_url)
152
+ else:
153
+ cmd.append(repo_url)
154
+
155
+ process = subprocess.run(
156
+ cmd,
157
+ capture_output=True,
158
+ text=True,
159
+ env=dict(os.environ, GIT_ASKPASS='echo', GIT_TERMINAL_PROMPT='0')
160
+ )
161
+
162
+ if process.returncode == 0:
163
+ print(f"Berhasil mengkloning repository: {repo_name}")
164
+ return True, repo_name
165
+ else:
166
+ print(f"Gagal mengkloning repository: {process.stderr}")
167
+ return False, process.stderr
168
+ except Exception as e:
169
+ error_msg = f"Error saat mengkloning repository: {str(e)}"
170
+ print(error_msg)
171
+ return False, error_msg
172
+
173
+ def analyze_with_ollama(model_name, text, stream=True):
174
+ print(f"\nMenganalisis dengan {model_name}...")
175
+ try:
176
+ payload = {
177
+ "model": model_name,
178
+ "prompt": text,
179
+ "stream": stream,
180
+ "options": {
181
+ "temperature": 0.7,
182
+ "top_p": 0.9,
183
+ "max_tokens": 2048,
184
+ "stop": None
185
+ }
186
+ }
187
+
188
+ response = requests.post(
189
+ f"{OLLAMA_API}/api/generate",
190
+ headers={"Content-Type": "application/json"},
191
+ json=payload,
192
+ stream=stream,
193
+ timeout=60
194
+ )
195
+
196
+ if response.status_code == 200:
197
+ if stream:
198
+ full_response = ""
199
+ for line in response.iter_lines():
200
+ if line:
201
+ data = json.loads(line)
202
+ if 'response' in data:
203
+ chunk = data['response']
204
+ full_response += chunk
205
+ yield full_response
206
+ return full_response
207
+ else:
208
+ result = response.json()
209
+ if 'response' in result:
210
+ return result['response']
211
+ else:
212
+ return "Error: Format respons tidak sesuai"
213
+ else:
214
+ return f"Error API {response.status_code}: {response.text}"
215
+
216
+ except Exception as e:
217
+ return f"Error saat memproses: {str(e)}"
218
+
219
+ def chunk_text(text, max_length=4000):
220
+ return textwrap.wrap(text, max_length, break_long_words=False, break_on_hyphens=False)
221
+
222
+ def read_file_safely(file_path):
223
+ encodings = ['utf-8', 'latin-1', 'cp1252']
224
+ for encoding in encodings:
225
+ try:
226
+ with open(file_path, 'r', encoding=encoding) as f:
227
+ content = f.read()
228
+ print(f"Berhasil membaca file dengan encoding {encoding}")
229
+ return True, content
230
+ except UnicodeDecodeError:
231
+ continue
232
+ except Exception as e:
233
+ error_msg = f"Error membaca file: {str(e)}"
234
+ print(error_msg)
235
+ return False, error_msg
236
+ return False, "Tidak dapat membaca file dengan encoding yang didukung"
237
+
238
+ def create_ui():
239
+ with gr.Blocks(title="Analisis Repository dengan Ollama", css=CUSTOM_CSS) as app:
240
+ gr.Markdown(f"""
241
+ # πŸš€ Analisis Repository dengan Ollama
242
+
243
+ Waktu Server: {CURRENT_TIME}
244
+ Pengguna: {CURRENT_USER}
245
+ """)
246
+
247
+ with gr.Tab("Manajemen Model"):
248
+ model_status = gr.Textbox(label="Status Ollama", interactive=False)
249
+ available_models = gr.Dropdown(
250
+ label="Model Tersedia",
251
+ choices=DEFAULT_MODELS,
252
+ interactive=True
253
+ )
254
+ with gr.Row():
255
+ download_button = gr.Button("Unduh Model")
256
+ cancel_button = gr.Button("Batalkan")
257
+ download_status = gr.Textbox(label="Status Unduhan", interactive=False)
258
+ progress = gr.Progress()
259
+
260
+ def update_status():
261
+ status = "Terhubung" if check_ollama_status() else "Tidak Terhubung"
262
+ models = list_available_models()
263
+ return status, gr.Dropdown(choices=models)
264
+
265
+ download_button.click(
266
+ fn=download_model,
267
+ inputs=[available_models],
268
+ outputs=[download_status]
269
+ )
270
+
271
+ with gr.Tab("Analisis Repository"):
272
+ with gr.Row():
273
+ repo_url = gr.Textbox(label="URL Repository")
274
+ github_token = gr.Textbox(label="Token GitHub", type="password")
275
+ branch = gr.Textbox(label="Branch (opsional)")
276
+
277
+ clone_button = gr.Button("Clone Repository")
278
+ clone_status = gr.Textbox(label="Status Clone", interactive=False)
279
+
280
+ with gr.Row():
281
+ file_list = gr.Dropdown(
282
+ label="File dalam Repository",
283
+ multiselect=True,
284
+ info="Pilih file yang akan dianalisis"
285
+ )
286
+ selected_model = gr.Dropdown(
287
+ label="Model untuk Analisis",
288
+ choices=DEFAULT_MODELS,
289
+ interactive=True
290
+ )
291
+
292
+ with gr.Row():
293
+ stream_checkbox = gr.Checkbox(
294
+ label="Streaming Response",
295
+ value=True,
296
+ info="Tampilkan hasil analisis secara real-time"
297
+ )
298
+ code_block_checkbox = gr.Checkbox(
299
+ label="Format Output sebagai Code Block",
300
+ value=True,
301
+ info="Tampilkan hasil dalam format code block yang bisa di-copy"
302
+ )
303
+
304
+ analyze_button = gr.Button("Analisis File")
305
+ debug_output = gr.HTML(label="Info Debug")
306
+ analysis_output = gr.HTML()
307
+
308
+ def analyze_files(files, model_name, stream=True, use_code_block=True):
309
+ if not files:
310
+ return ("Silakan pilih file untuk dianalisis",
311
+ format_code_block("Tidak ada file dipilih"))
312
+
313
+ debug_info = []
314
+ results = []
315
+
316
+ debug_info.append(f"Mulai analisis dengan model: {model_name}")
317
+ debug_info.append(f"File yang akan dianalisis: {len(files)}")
318
+
319
+ for file_path in files:
320
+ debug_info.append(f"\nMemproses file: {file_path}")
321
+ success, content = read_file_safely(file_path)
322
+
323
+ if success:
324
+ chunks = chunk_text(content)
325
+ debug_info.append(f"Dibagi menjadi {len(chunks)} bagian")
326
+ analysis = []
327
+
328
+ for i, chunk in enumerate(chunks, 1):
329
+ debug_info.append(f"Menganalisis bagian {i}/{len(chunks)}")
330
+ prompt = f"""
331
+ Analisis kode berikut:
332
+
333
+ File: {file_path}
334
+ Bagian {i} dari {len(chunks)}
335
+
336
+ ```
337
+ {chunk}
338
+ ```
339
+
340
+ Berikan:
341
+ 1. Ringkasan singkat
342
+ 2. Fungsi utama
343
+ 3. Pola dan masalah yang ditemukan
344
+ 4. Saran perbaikan (jika ada)
345
+ """
346
+
347
+ if stream:
348
+ for response_chunk in analyze_with_ollama(model_name, prompt, stream=True):
349
+ formatted_response = (format_code_block(response_chunk)
350
+ if use_code_block else response_chunk)
351
+ yield formatted_response, format_code_block("\n".join(debug_info))
352
+ else:
353
+ response = analyze_with_ollama(model_name, prompt, stream=False)
354
+ analysis.append(response)
355
+ formatted_results = "\n\n---\n\n".join(results + [response])
356
+ if use_code_block:
357
+ formatted_results = format_code_block(formatted_results)
358
+ yield (formatted_results,
359
+ format_code_block("\n".join(debug_info)))
360
+
361
+ if not stream:
362
+ results.append(f"### Analisis {file_path}\n\n" +
363
+ "\n\n=== Bagian Selanjutnya ===\n\n".join(analysis))
364
+ else:
365
+ error_msg = f"Error membaca {file_path}: {content}"
366
+ debug_info.append(error_msg)
367
+ results.append(error_msg)
368
+ formatted_results = "\n\n---\n\n".join(results)
369
+ if use_code_block:
370
+ formatted_results = format_code_block(formatted_results)
371
+ yield formatted_results, format_code_block("\n".join(debug_info))
372
+
373
+ clone_button.click(
374
+ fn=handle_clone,
375
+ inputs=[repo_url, github_token, branch],
376
+ outputs=[clone_status, file_list]
377
+ )
378
+
379
+ analyze_button.click(
380
+ fn=analyze_files,
381
+ inputs=[
382
+ file_list,
383
+ selected_model,
384
+ stream_checkbox,
385
+ code_block_checkbox
386
+ ],
387
+ outputs=[analysis_output, debug_output]
388
+ )
389
+
390
+ app.load(update_status, outputs=[model_status, available_models])
391
+
392
+ return app
393
+
394
+ if __name__ == "__main__":
395
+ print(f"""
396
+ Memulai Analisis Repository
397
+ Waktu: {CURRENT_TIME}
398
+ API: {OLLAMA_API}
399
+ """)
400
+
401
+ app = create_ui()
402
+ app.launch()
requirements_Version5.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ gradio>=4.0.0
2
+ requests>=2.31.0
3
+ python-dotenv>=1.0.0
4
+ tqdm>=4.65.0
5
+ markdown>=3.4.3
6
+ Pygments>=2.15.1