import gradio as gr
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
import time
from typing import Dict, List, Tuple
from code_shower import CodeShower
from file_manager import FileManager
class DualModeAssistant:
def __init__(self):
print("🔄 Loading Llama 3.2 (General purpose)...")
self.llama_model_id = "meta-llama/Llama-3.2-1B-Instruct"
self.llama_pipe = pipeline(
"text-generation",
model=self.llama_model_id,
torch_dtype=torch.bfloat16,
device_map="auto",
token=True # Uses HF_TOKEN from env if available
)
print("💻 Loading Maincoder (Code specialist)...")
self.codex_model_id = "maincode/maincoder-1b"
self.codex_pipe = pipeline(
"text-generation",
model=self.codex_model_id,
torch_dtype=torch.bfloat16,
device_map="auto"
)
self.current_mode = "codex"
self.file_manager = FileManager()
def generate_with_thinking(self, prompt: str, mode: str, history: List = None) -> Dict:
"""Generate with thinking process"""
self.current_mode = mode
# Choose model
if mode == "codex":
pipe = self.codex_pipe
system_prompt = """You are Maincoder, a specialized coding assistant.
When asked to write code, always output complete files with their filenames as markdown code blocks.
Example format:
```python app.py
print("Hello")
html
Hello
```"""
else:
pipe = self.llama_pipe
system_prompt = "You are a helpful general assistant. Answer questions thoroughly."
# Build messages
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": prompt}
]
# Add conversation history if provided
if history:
for h in history[-4:]: # Last 4 exchanges
if isinstance(h, dict):
messages.append(h)
# Generate thinking (using system prompt to encourage reasoning)
full_response = pipe(
messages,
max_new_tokens=1000,
temperature=0.7,
do_sample=True,
top_p=0.95
)[0]['generated_text']
# Extract the assistant's response
if isinstance(full_response, list):
assistant_msg = full_response[-1].get('content', '')
else:
# Parse the full text
assistant_msg = full_response
# Detect and extract code blocks for file tree
files = self.file_manager.extract_files_from_code(assistant_msg)
return {
"response": assistant_msg,
"model_used": "Codex (Coding Specialist)" if mode == "codex" else "Llama (General)",
"files": files
}
# Initialize components
assistant = DualModeAssistant()
code_shower = CodeShower()
# Custom CSS
custom_css = """
"""
# Create the Gradio interface
with gr.Blocks(css=custom_css, title="Llama Codex - Dual Mode Assistant", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🤖 Llama Codex - Dual Mode AI Coding Assistant
**Switch between two specialized AI modes:**
- 🧠**Llama Mode**: General conversations, explanations, Q&A
- 💻 **Codex Mode**: Specialized coding with file extraction and previews
> 💡 Inspired by DeepSeek-R1 - both modes show their reasoning process before responding!
""")
with gr.Row(elem_classes="main-container"):
# Left panel: Chat
with gr.Column(elem_classes="chat-panel", scale=2):
with gr.Row():
mode_selector = gr.Radio(
choices=["💻 Codex Mode (Coding Specialist)", "🧠Llama Mode (General)"],
label="Select AI Mode",
value="💻 Codex Mode (Coding Specialist)",
interactive=True
)
with gr.Row():
thinking_toggle = gr.Checkbox(
label="🧠Show Thinking Process",
value=True,
info="Shows the AI's reasoning before the final answer"
)
chatbot = gr.Chatbot(
label="Assistant",
height=500,
bubble_full_width=False
)
with gr.Row():
msg = gr.Textbox(
label="Your message",
placeholder="Ask me to write code, explain concepts, or help debug...",
scale=4,
lines=3
)
send_btn = gr.Button("Send", variant="primary", scale=1)
with gr.Row():
clear_btn = gr.Button("Clear Chat")
gr.Markdown("""
**Example prompts:**
- "Write a Python function to calculate fibonacci"
- "Create an HTML game of Snake"
- "Explain how recursion works"
- "Debug this: `for i in range(10) print(i)`"
""")
# Right panel: Code Shower
with gr.Column(elem_classes="code-panel", scale=1):
code_shower_ui = code_shower.create_ui()
# Footer with attribution
gr.Markdown("""
---
""")
# State for conversation history
conversation_history = gr.State([])
# Helper functions
def get_model_mode(radio_value: str) -> str:
return "codex" if "Codex" in radio_value else "llama"
def respond(message, history, mode_radio, show_thinking):
if not message.strip():
yield history + [("", "Please enter a message.")], ""
return
# Show thinking indicator
thinking_msg = "🤔 Thinking" + "." * 3
yield history + [("", thinking_msg)], ""
# Get mode
mode = get_model_mode(mode_radio)
# Generate response
result = assistant.generate_with_thinking(message, mode, history)
# Format response
if show_thinking:
# Extract thinking from response (simple heuristic)
response_parts = result["response"].split("\n\n")
thinking_text = "No explicit thinking shown"
# Simple thinking extraction - you can enhance this
if "think" in result["response"].lower() or "step" in result["response"].lower():
thinking_text = result["response"][:300] + "..."
formatted = f"""
💠**Thinking process ({result['model_used']}):**
{thinking_text}
✨ **Response:**
{result["response"]}"""
else:
formatted = result["response"]
# Update code shower with extracted files
if result.get("files") and code_shower:
# Update file tree
code_shower.current_files = result["files"]
file_tree_html = code_shower.update_files_display()
# Update code_shower_ui components
if result["files"]:
first_file = list(result["files"].keys())[0]
preview, code_view, code_content = code_shower.display_file(first_file)
# Note: In full implementation, update the UI components here
# For this example, we'll just update the file tree
# Update chat
new_history = history + [(message, formatted)]
yield new_history, ""
def clear_chat():
return [], ""
# Event handlers
send_btn.click(
respond,
[msg, chatbot, mode_selector, thinking_toggle],
[chatbot, msg]
)
msg.submit(
respond,
[msg, chatbot, mode_selector, thinking_toggle],
[chatbot, msg]
)
clear_btn.click(clear_chat, None, [chatbot, msg])
# Code shower event handlers
code_shower_ui["add_file_btn"].click(
code_shower.add_new_file,
[code_shower_ui["new_lang"], code_shower_ui["new_filename"]],
[code_shower_ui["file_tree"], code_shower_ui["preview_area"], code_shower_ui["code_area"], msg]
)
if __name__ == "__main__":
demo.launch(share=True)