import gradio as gr import requests import json import time from faster_whisper import WhisperModel OLLAMA_URL = "http://localhost:11434" MAX_RETRIES = 3 TIMEOUT = 300 MODELS = { "โญ Qwen2.5 Coder 7B (Best)": "qwen2.5-coder:7b", "๐ง DeepSeek Coder 6.7B (Logic)": "deepseek-coder:6.7b", "Qwen2.5 Coder 3B (Fast)": "qwen2.5-coder:3b", "Qwen2.5 Coder 1.5B (Fastest)": "qwen2.5-coder:1.5b", "DeepSeek Coder 1.3B (Fast)": "deepseek-coder:1.3b", "StarCoder2 3B": "starcoder2:3b", "CodeGemma 2B (Fast)": "codegemma:2b", } MODEL_INFO = { "โญ Qwen2.5 Coder 7B (Best)": "๐ Best overall โข ~4.5GB โข Recommended", "๐ง DeepSeek Coder 6.7B (Logic)": "๐ง Best for algorithms & logic โข ~3.8GB", "Qwen2.5 Coder 3B (Fast)": "โ๏ธ Balanced โข ~2GB โข Great all-rounder", "Qwen2.5 Coder 1.5B (Fastest)": "โก Fastest โข ~1GB โข Quick tasks", "DeepSeek Coder 1.3B (Fast)": "โก Fast โข ~0.8GB โข Quick logic", "StarCoder2 3B": "๐ GitHub trained โข ~1.7GB โข Real patterns", "CodeGemma 2B (Fast)": "๐ท Google โข ~1.6GB โข Quick & efficient", } LANGUAGES = [ "Python", "JavaScript", "TypeScript", "Go", "Rust", "Java", "C++", "C#", "C", "PHP", "Ruby", "Swift", "Kotlin", "Scala", "R", "MATLAB", "Julia", "Perl", "HTML/CSS", "SQL", "Bash", "PowerShell", "Lua" ] # ===== WHISPER INIT ===== whisper_model = None def init_whisper(): global whisper_model try: print("Loading Whisper...") whisper_model = WhisperModel("tiny", device="cpu", compute_type="int8") print("โ Whisper ready!") return True except Exception as e: print(f"โ Whisper failed to load: {e}") return False init_whisper() # ===== HELPER FUNCTIONS ===== def check_ollama_health(): try: r = requests.get(f"{OLLAMA_URL}/api/tags", timeout=5) return r.status_code == 200 except: return False def get_status(): try: r = requests.get(f"{OLLAMA_URL}/api/tags", timeout=5) if r.status_code == 200: models = r.json().get("models", []) return f"๐ข Online โข {len(models)} models" except requests.exceptions.ConnectionError: return "๐ด Offline โข Ollama not running" except requests.exceptions.Timeout: return "๐ก Slow โข Connection timeout" except Exception as e: return f"๐ด Error โข {str(e)[:30]}" return "๐ก Starting..." def get_model_info(model_name): return MODEL_INFO.get(model_name, "") def validate_input(text, field_name="Input"): if not text or not text.strip(): return False, f"โ ๏ธ {field_name} cannot be empty." if len(text) > 100000: return False, f"โ ๏ธ {field_name} is too long (max 100KB)." return True, None def transcribe_audio(audio): if audio is None: return "" if whisper_model is None: return "โ Whisper not loaded. Voice input unavailable." try: segments, _ = whisper_model.transcribe(audio) text = " ".join([seg.text for seg in segments]).strip() if not text: return "โ ๏ธ No speech detected. Try again." return text except FileNotFoundError: return "โ Audio file not found." except Exception as e: return f"โ Transcription failed: {str(e)[:50]}" def call_ollama_with_retry(model_name, prompt, temperature=0.7, max_tokens=2048): if not check_ollama_health(): return "โ **Ollama is not running.**\n\nPlease wait for Ollama to start, or check the logs." model = MODELS.get(model_name, "qwen2.5-coder:3b") for attempt in range(MAX_RETRIES): try: r = requests.post( f"{OLLAMA_URL}/api/generate", json={ "model": model, "prompt": prompt, "stream": False, "options": { "temperature": temperature, "num_predict": max_tokens } }, timeout=TIMEOUT ) if r.status_code == 200: response = r.json().get("response", "") if not response.strip(): return "โ ๏ธ Model returned empty response. Try rephrasing your request." return response elif r.status_code == 404: return f"โ **Model not found:** `{model}`\n\nThe model may still be downloading. Check logs or try a different model." elif r.status_code == 500: error_msg = r.text[:200] if r.text else "Unknown server error" if "out of memory" in error_msg.lower(): return "โ **Out of memory.**\n\nTry a smaller model like `Qwen2.5 Coder 1.5B (Fast)`." return f"โ **Server error:** {error_msg}" else: return f"โ **HTTP {r.status_code}:** {r.text[:100]}" except requests.exceptions.Timeout: if attempt < MAX_RETRIES - 1: time.sleep(2) continue return "โ **Request timed out.**\n\nThe model is taking too long. Try:\n- A smaller model\n- Shorter input\n- Lower max tokens" except requests.exceptions.ConnectionError: if attempt < MAX_RETRIES - 1: time.sleep(2) continue return "โ **Connection failed.**\n\nOllama may have crashed. Check the logs." except json.JSONDecodeError: return "โ **Invalid response from Ollama.**\n\nThe model returned malformed data." except Exception as e: return f"โ **Unexpected error:** {str(e)[:100]}" return "โ **Max retries reached.** Please try again." def extract_code(text): if not text or "```" not in text: return text try: parts = text.split("```") if len(parts) >= 2: code = parts[1] if "\n" in code: code = code.split("\n", 1)[-1] return code.strip() except Exception: pass return text # ===== CORE FUNCTIONS ===== def chat_stream(message, history, model_name, temperature, max_tokens): valid, error = validate_input(message, "Message") if not valid: yield history + [[message, error]] return if not check_ollama_health(): yield history + [[message, "โ **Ollama is not running.** Please wait for it to start."]] return model = MODELS.get(model_name, "qwen2.5-coder:3b") messages = [{"role": "system", "content": "You are an expert coding assistant. Provide clear, well-commented code. Always use markdown code blocks with language tags."}] for user_msg, assistant_msg in history: messages.append({"role": "user", "content": user_msg}) if assistant_msg: messages.append({"role": "assistant", "content": assistant_msg}) messages.append({"role": "user", "content": message}) try: response = requests.post( f"{OLLAMA_URL}/api/chat", json={ "model": model, "messages": messages, "stream": True, "options": {"temperature": temperature, "num_predict": max_tokens} }, stream=True, timeout=TIMEOUT ) if response.status_code == 404: yield history + [[message, f"โ **Model not found:** `{model}`\n\nTry a different model."]] return if response.status_code != 200: yield history + [[message, f"โ **Error {response.status_code}:** {response.text[:100]}"]] return full = "" for line in response.iter_lines(): if line: try: data = json.loads(line) if "error" in data: yield history + [[message, f"โ **Model error:** {data['error']}"]] return if "message" in data: full += data["message"].get("content", "") yield history + [[message, full]] except json.JSONDecodeError: continue if not full.strip(): yield history + [[message, "โ ๏ธ Model returned empty response. Try rephrasing."]] except requests.exceptions.Timeout: yield history + [[message, "โ **Request timed out.** Try a smaller model or shorter input."]] except requests.exceptions.ConnectionError: yield history + [[message, "โ **Connection lost.** Ollama may have crashed."]] except Exception as e: yield history + [[message, f"โ **Error:** {str(e)[:100]}"]] def generate_code(prompt, language, model_name, temperature, max_tokens): valid, error = validate_input(prompt, "Description") if not valid: return error full_prompt = ( f"Write {language} code for the following task:\n\n" f"{prompt}\n\n" "Requirements:\n" "- Clean, production-ready code\n" "- Add helpful comments\n" "- Handle edge cases\n" "- Output ONLY the code in a markdown code block" ) result = call_ollama_with_retry(model_name, full_prompt, temperature, max_tokens) if result.startswith("โ") or result.startswith("โ ๏ธ"): return result return extract_code(result) def explain_code(code, model_name, detail_level, max_tokens): valid, error = validate_input(code, "Code") if not valid: return error detail_prompts = { "Brief": "Give a brief 2-3 sentence explanation of what this code does.", "Normal": "Explain what this code does, including the main logic and any important details.", "Detailed": "Give a detailed explanation including: purpose, how it works step-by-step, time/space complexity, and potential improvements." } prompt = detail_prompts.get(detail_level, detail_prompts["Normal"]) + "\n\nCode:\n" + code return call_ollama_with_retry(model_name, prompt, 0.5, max_tokens) def fix_code(code, error_msg, model_name, max_tokens): valid, error = validate_input(code, "Code") if not valid: return error error_text = error_msg if error_msg and error_msg.strip() else "Code is not working as expected" prompt = ( "Fix the following code and explain what was wrong.\n\n" "Code:\n" + code + "\n\n" "Error/Problem: " + error_text + "\n\n" "Provide:\n" "1. The fixed code in a markdown code block\n" "2. Brief explanation of what was wrong\n" "3. Any suggestions to prevent similar issues" ) return call_ollama_with_retry(model_name, prompt, 0.3, max_tokens) def review_code(code, model_name, max_tokens): valid, error = validate_input(code, "Code") if not valid: return error prompt = ( "Review this code and provide feedback on:\n\n" "1. **Code Quality** - Is it clean, readable, well-structured?\n" "2. **Bugs/Issues** - Any potential bugs or problems?\n" "3. **Performance** - Any performance concerns?\n" "4. **Security** - Any security issues?\n" "5. **Suggestions** - How could it be improved?\n\n" "Code:\n" + code ) return call_ollama_with_retry(model_name, prompt, 0.4, max_tokens) def convert_code(code, source_lang, target_lang, model_name, max_tokens): valid, error = validate_input(code, "Code") if not valid: return error if source_lang == target_lang: return "โ ๏ธ Source and target languages are the same." prompt = ( f"Convert this {source_lang} code to {target_lang}.\n\n" "Requirements:\n" f"- Write idiomatic {target_lang} code\n" "- Preserve the functionality exactly\n" "- Add comments explaining any language-specific differences\n" "- Output ONLY the converted code in a markdown code block\n\n" f"{source_lang} Code:\n" + code ) result = call_ollama_with_retry(model_name, prompt, 0.3, max_tokens) if result.startswith("โ") or result.startswith("โ ๏ธ"): return result return extract_code(result) def generate_tests(code, language, framework, model_name, max_tokens): valid, error = validate_input(code, "Code") if not valid: return error frameworks = { "Python": "pytest", "JavaScript": "Jest", "TypeScript": "Jest", "Java": "JUnit", "C#": "NUnit", "Go": "testing package", "Rust": "built-in test framework", "Ruby": "RSpec", "PHP": "PHPUnit", } fw = framework if framework and framework.strip() else frameworks.get(language, "appropriate testing framework") prompt = ( f"Generate comprehensive unit tests for this {language} code using {fw}.\n\n" "Requirements:\n" "- Test all functions/methods\n" "- Include edge cases\n" "- Include both positive and negative tests\n" "- Add descriptive test names\n" "- Output ONLY the test code in a markdown code block\n\n" "Code to test:\n" + code ) result = call_ollama_with_retry(model_name, prompt, 0.3, max_tokens) if result.startswith("โ") or result.startswith("โ ๏ธ"): return result return extract_code(result) def document_code(code, language, style, model_name, max_tokens): valid, error = validate_input(code, "Code") if not valid: return error styles = { "Docstrings": "Add comprehensive docstrings to all functions, classes, and methods", "Comments": "Add inline comments explaining the logic", "Both": "Add both docstrings and inline comments", "README": "Generate a README.md documenting this code" } prompt = ( f"Document this {language} code.\n\n" f"Task: {styles.get(style, styles['Both'])}\n\n" "Requirements:\n" "- Be clear and concise\n" "- Explain parameters, return values, and exceptions\n" "- Include usage examples where helpful\n" "- Output the fully documented code in a markdown code block\n\n" "Code:\n" + code ) result = call_ollama_with_retry(model_name, prompt, 0.4, max_tokens) if style == "README" or result.startswith("โ") or result.startswith("โ ๏ธ"): return result return extract_code(result) def optimize_code(code, language, focus, model_name, max_tokens): valid, error = validate_input(code, "Code") if not valid: return error focus_prompts = { "Performance": "Optimize for speed and efficiency. Reduce time complexity where possible.", "Readability": "Refactor for better readability and maintainability. Follow best practices.", "Memory": "Optimize memory usage. Reduce allocations and improve data structures.", "All": "Optimize for performance, readability, and memory usage." } prompt = ( f"Optimize this {language} code.\n\n" f"Focus: {focus_prompts.get(focus, focus_prompts['All'])}\n\n" "Requirements:\n" "- Explain what you changed and why\n" "- Preserve the original functionality\n" "- Show before/after complexity if relevant\n" "- Output the optimized code in a markdown code block\n\n" "Code:\n" + code ) return call_ollama_with_retry(model_name, prompt, 0.3, max_tokens) def build_regex(description, model_name, max_tokens): valid, error = validate_input(description, "Description") if not valid: return error prompt = ( "Create a regex pattern for the following requirement:\n\n" f"{description}\n\n" "Provide:\n" "1. The regex pattern\n" "2. Explanation of each part\n" "3. Example matches and non-matches\n" "4. Code example in Python showing usage" ) return call_ollama_with_retry(model_name, prompt, 0.3, max_tokens) def build_api(description, framework, model_name, max_tokens): valid, error = validate_input(description, "Description") if not valid: return error prompt = ( f"Create a REST API endpoint using {framework}.\n\n" f"Requirements:\n{description}\n\n" "Include:\n" "- Route definition with proper HTTP methods\n" "- Request validation\n" "- Error handling\n" "- Response formatting\n" "- Brief documentation comments\n" "- Output the code in a markdown code block" ) result = call_ollama_with_retry(model_name, prompt, 0.3, max_tokens) if result.startswith("โ") or result.startswith("โ ๏ธ"): return result return extract_code(result) # ===== PREMIUM CSS ===== css = """ /* ===== GLOBAL ===== */ :root { --primary: #6366f1; --primary-dark: #4f46e5; --secondary: #8b5cf6; --accent: #06b6d4; --bg-dark: #0f172a; --bg-card: #1e293b; --bg-hover: #334155; --text-primary: #f1f5f9; --text-secondary: #94a3b8; --border: #334155; --success: #10b981; --warning: #f59e0b; --error: #ef4444; --gradient: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #06b6d4 100%); } .gradio-container { max-width: 1500px !important; margin: auto !important; background: var(--bg-dark) !important; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important; } /* ===== HEADER ===== */ .header-section { background: var(--gradient); border-radius: 20px; padding: 32px 40px; margin-bottom: 24px; position: relative; overflow: hidden; box-shadow: 0 20px 40px rgba(99, 102, 241, 0.3); } .header-section::before { content: ''; position: absolute; top: -50%; right: -50%; width: 100%; height: 200%; background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 60%); animation: pulse 4s ease-in-out infinite; } @keyframes pulse { 0%, 100% { transform: scale(1); opacity: 0.5; } 50% { transform: scale(1.1); opacity: 0.8; } } .header-content { position: relative; z-index: 1; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 20px; } .header-title { color: white; margin: 0; font-size: 2.8rem; font-weight: 800; letter-spacing: -0.02em; text-shadow: 0 2px 10px rgba(0,0,0,0.2); } .header-subtitle { color: rgba(255,255,255,0.9); margin: 8px 0 0 0; font-size: 1.1rem; font-weight: 400; } .header-badges { display: flex; gap: 10px; flex-wrap: wrap; } .badge { background: rgba(255,255,255,0.2); backdrop-filter: blur(10px); padding: 8px 16px; border-radius: 50px; font-size: 0.85rem; font-weight: 500; color: white; border: 1px solid rgba(255,255,255,0.2); } /* ===== STATUS BAR ===== */ .status-bar { background: var(--bg-card); border: 1px solid var(--border); border-radius: 16px; padding: 16px 24px; margin-bottom: 20px; } /* ===== SETTINGS PANEL ===== */ .settings-panel { background: var(--bg-card); border: 1px solid var(--border); border-radius: 16px; padding: 20px 24px; margin-bottom: 20px; } /* ===== MODEL INFO ===== */ .model-info-box { background: linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, rgba(139, 92, 246, 0.1) 100%); border: 1px solid rgba(99, 102, 241, 0.3); border-radius: 12px; padding: 12px 18px; font-size: 0.9rem; color: var(--text-secondary); margin-top: 12px; margin-bottom: 20px; } /* ===== TABS ===== */ .tab-nav { background: var(--bg-card) !important; border: 1px solid var(--border) !important; border-radius: 16px !important; padding: 8px !important; gap: 6px !important; margin-bottom: 20px !important; flex-wrap: wrap !important; } .tab-nav button { background: transparent !important; border: none !important; border-radius: 12px !important; padding: 12px 20px !important; font-weight: 600 !important; font-size: 0.9rem !important; color: var(--text-secondary) !important; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; } .tab-nav button:hover { background: var(--bg-hover) !important; color: var(--text-primary) !important; } .tab-nav button.selected { background: var(--gradient) !important; color: white !important; box-shadow: 0 4px 15px rgba(99, 102, 241, 0.4) !important; } /* ===== CHATBOT ===== */ .chatbot-container { background: var(--bg-card) !important; border: 1px solid var(--border) !important; border-radius: 16px !important; } /* ===== INPUTS ===== */ textarea, input[type="text"] { background: var(--bg-card) !important; border: 1px solid var(--border) !important; border-radius: 12px !important; color: var(--text-primary) !important; padding: 14px 18px !important; font-size: 0.95rem !important; transition: all 0.2s ease !important; } textarea:focus, input[type="text"]:focus { border-color: var(--primary) !important; box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2) !important; outline: none !important; } /* ===== CODE BLOCKS ===== */ .code-wrap { border-radius: 16px !important; overflow: hidden !important; border: 1px solid var(--border) !important; } /* ===== BUTTONS ===== */ .primary-btn, button.primary { background: var(--gradient) !important; border: none !important; border-radius: 12px !important; padding: 14px 28px !important; font-weight: 600 !important; font-size: 0.95rem !important; color: white !important; cursor: pointer !important; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; box-shadow: 0 4px 15px rgba(99, 102, 241, 0.3) !important; } .primary-btn:hover, button.primary:hover { transform: translateY(-2px) !important; box-shadow: 0 8px 25px rgba(99, 102, 241, 0.4) !important; } .secondary-btn { background: var(--bg-hover) !important; border: 1px solid var(--border) !important; border-radius: 12px !important; padding: 12px 20px !important; font-weight: 500 !important; color: var(--text-secondary) !important; transition: all 0.2s ease !important; } .secondary-btn:hover { background: var(--bg-card) !important; border-color: var(--primary) !important; color: var(--text-primary) !important; } /* ===== MARKDOWN OUTPUT ===== */ .markdown-output { background: var(--bg-card); border: 1px solid var(--border); border-radius: 16px; padding: 24px; color: var(--text-primary); line-height: 1.7; } /* ===== DIVIDER ===== */ .divider { height: 1px; background: var(--border); margin: 24px 0; } /* ===== TOOL SECTION ===== */ .tool-section { background: var(--bg-card); border: 1px solid var(--border); border-radius: 16px; padding: 24px; margin-bottom: 20px; } .tool-title { color: var(--text-primary); font-size: 1.2rem; font-weight: 600; margin-bottom: 16px; } /* ===== FOOTER ===== */ .footer { text-align: center; padding: 24px; color: var(--text-secondary); font-size: 0.85rem; border-top: 1px solid var(--border); margin-top: 32px; } /* ===== SCROLLBAR ===== */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: var(--bg-dark); } ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { background: var(--text-secondary); } /* ===== HIDE DEFAULT FOOTER ===== */ footer { display: none !important; } /* ===== RESPONSIVE ===== */ @media (max-width: 768px) { .header-title { font-size: 2rem; } .header-content { flex-direction: column; text-align: center; } .header-badges { justify-content: center; } .tab-nav button { padding: 10px 14px !important; font-size: 0.8rem !important; } } """ # ===== UI (Gradio 6.0 Compatible) ===== with gr.Blocks(title="Axon v6") as demo: # Header gr.HTML("""
AI-Powered Coding Assistant