walidsobhie-code
reorganize: consolidate root level to 20 folders
b8e3e42
#!/usr/bin/env python3
"""
Stack 2.9 CLI - Terminal User Interface
Main entry point for interacting with Stack 2.9
"""
import os
import sys
import argparse
from pathlib import Path
from typing import Optional
# Add parent directories to path
sys.path.insert(0, str(Path(__file__).parent))
sys.path.insert(0, str(Path(__file__).parent.parent / "stack" / "eval"))
sys.path.insert(0, str(Path(__file__).parent.parent / "stack" / "training"))
from model_client import create_model_client, ChatMessage
from pattern_miner import PatternMiner
from data_quality import DataQualityAnalyzer
class Stack29CLI:
"""Stack 2.9 Terminal User Interface"""
def __init__(self, provider: str = None, model: str = None):
self.provider = provider or os.environ.get("MODEL_PROVIDER", "ollama")
self.model = model or os.environ.get("MODEL_NAME", "")
self.client = None
self.agent = None
self.miner = PatternMiner()
self.chat_history = []
# Colors
self.BLUE = '\033[94m'
self.GREEN = '\033[92m'
self.YELLOW = '\033[93m'
self.RED = '\033[91m'
self.END = '\033[0m'
self.BOLD = '\033[1m'
def print_header(self):
"""Print CLI header"""
print(f"""
{self.BLUE}╔═══════════════════════════════════════════════════════╗
{self.BOLD}Stack 2.9 - Self-Evolving AI{self.END}{self.BLUE}
{self.YELLOW}Your AI coding companion{self.END}{self.BLUE}
╚═══════════════════════════════════════════════════════╝{self.END}
""")
def print_menu(self):
"""Print main menu"""
print(f"""
{self.BOLD}Main Menu:{self.END}
{self.GREEN}[1]{self.END} Chat with Stack 2.9
{self.GREEN}[2]{self.END} Run Evaluation (Benchmarks)
{self.GREEN}[3]{self.END} Manage Patterns (Self-Evolution)
{self.GREEN}[4]{self.END} Train Model (LoRA Fine-tuning)
{self.GREEN}[5]{self.END} Settings
{self.GREEN}[0]{self.END} Exit
""")
def init_client(self):
"""Initialize model client"""
try:
self.client = create_model_client(self.provider, self.model)
print(f"{self.GREEN}{self.END} Connected to {self.provider}: {self.client.get_model_name()}")
except Exception as e:
print(f"{self.RED}{self.END} Failed to connect: {e}")
print(f"{self.YELLOW}!{self.END} Make sure {self.provider} is running")
self.client = None
def chat_mode(self):
"""Interactive chat mode using agent with tool calling"""
if not self.client:
print(f"{self.RED}No model connected!{self.END}")
return
print(f"\n{self.BLUE}=== Chat Mode ==={self.END}")
print("Type 'exit' to return to menu, 'clear' to clear history\n")
# Initialize agent if not done
if not hasattr(self, 'agent') or self.agent is None:
from cli.agent import StackAgent
self.agent = StackAgent(workspace='/Users/walidsobhi/stack-2.9')
print(f"{self.GREEN}{self.END} Agent initialized")
while True:
try:
user_input = input(f"{self.GREEN}You:{self.END} ").strip()
if not user_input:
continue
if user_input.lower() in ['exit', 'quit', 'q']:
break
if user_input.lower() == 'clear':
print("Chat cleared.\n")
continue
# Process through agent (handles tool calling)
print(f"{self.BLUE}Stack 2.9:{self.END} ", end="", flush=True)
try:
response = self.agent.process(user_input)
print(response.content)
except Exception as e:
print(f"{self.RED}Error: {e}{self.END}")
except Exception as e:
print(f"{self.RED}Error: {e}{self.END}")
print()
except KeyboardInterrupt:
print("\n")
break
def eval_mode(self):
"""Run evaluation benchmarks"""
print(f"\n{self.BLUE}=== Evaluation ==={self.END}")
print(f"{self.GREEN}[1]{self.END} MBPP (Code Generation)")
print(f"{self.GREEN}[2]{self.END} HumanEval (Python)")
print(f"{self.GREEN}[3]{self.END} GSM8K (Math)")
print(f"{self.GREEN}[4]{self.END} Run All")
print(f"{self.GREEN}[0]{self.END} Back")
choice = input("\nSelect: ").strip()
if choice == '0':
return
benchmarks = {
'1': ('mbpp', 'MBPP'),
'2': ('human_eval', 'HumanEval'),
'3': ('gsm8k', 'GSM8K'),
'4': ('all', 'All')
}
if choice not in benchmarks:
print(f"{self.RED}Invalid choice{self.END}")
return
bench_name, bench_label = benchmarks[choice]
print(f"\n{self.YELLOW}Running {bench_label} benchmark...{self.END}")
try:
if bench_name == 'all':
from benchmarks.mbpp import MBPP
from benchmarks.human_eval import HumanEval
from benchmarks.gsm8k import GSM8K
for name, Benchmark in [('MBPP', MBPP), ('HumanEval', HumanEval), ('GSM8K', GSM8K)]:
print(f"\n--- {name} ---")
b = Benchmark(model_provider=self.provider, model_name=self.model)
results = b.evaluate()
print(f" Accuracy: {results['accuracy']*100:.1f}%")
else:
module = __import__(f'benchmarks.{bench_name}', fromlist=['MBPP', 'HumanEval', 'GSM8K'])
Benchmark = getattr(module, bench_name.upper() if bench_name != 'mbpp' else 'MBPP')
b = Benchmark(model_provider=self.provider, model_name=self.model)
results = b.evaluate()
print(f"\n{self.GREEN}Results:{self.END}")
print(f" Accuracy: {results['accuracy']*100:.1f}%")
print(f" Passed: {results['pass_at_1']}/{results['total_cases']}")
except Exception as e:
print(f"{self.RED}Error: {e}{self.END}")
input("\nPress Enter to continue...")
def pattern_mode(self):
"""Manage patterns for self-evolution"""
print(f"\n{self.BLUE}=== Pattern Manager ==={self.END}")
print(f"{self.GREEN}[1]{self.END} View Patterns")
print(f"{self.GREEN}[2]{self.END} View Statistics")
print(f"{self.GREEN}[3]{self.END} Generate Synthetic Data")
print(f"{self.GREEN}[4]{self.END} Clear Patterns")
print(f"{self.GREEN}[0]{self.END} Back")
choice = input("\nSelect: ").strip()
if choice == '0':
return
if choice == '1':
patterns = self.miner.get_relevant_patterns(limit=20)
print(f"\n{self.YELLOW}Stored Patterns ({len(patterns)}):{self.END}")
for p in patterns:
print(f" [{p.pattern_type}] {p.code_snippet[:50]}... (rate: {p.success_rate:.0%})")
elif choice == '2':
stats = self.miner.get_statistics()
print(f"\n{self.YELLOW}Statistics:{self.END}")
print(f" Total Feedback: {stats['total_feedback']}")
print(f" Success Rate: {stats['success_rate']:.1%}")
print(f" Total Patterns: {stats['total_patterns']}")
print(f" By Type: {stats['patterns_by_type']}")
elif choice == '3':
try:
count = int(input("Number of examples: ").strip())
self.miner.store_feedback(
problem_type="synthetic",
solution="# Synthetic pattern",
success=True
)
print(f"{self.GREEN}{self.END} Generated {count} synthetic patterns")
except ValueError:
print(f"{self.RED}Invalid number{self.END}")
elif choice == '4':
confirm = input("Clear all patterns? (y/n): ").strip().lower()
if confirm == 'y':
# Note: This would need a clear method in PatternMiner
print(f"{self.YELLOW}Feature not implemented{self.END}")
input("\nPress Enter to continue...")
def train_mode(self):
"""Train model with LoRA"""
print(f"\n{self.BLUE}=== Training ==={self.END}")
print(f"{self.YELLOW}Note: Requires GPU and training data{self.END}")
print(f"\n{self.GREEN}[1]{self.END} Prepare Data")
print(f"{self.GREEN}[2]{self.END} Train LoRA")
print(f"{self.GREEN}[3]{self.END} Merge Adapter")
print(f"{self.GREEN}[0]{self.END} Back")
choice = input("\nSelect: ").strip()
if choice == '0':
return
if choice == '1':
print(f"\n{self.YELLOW}Preparing training data...{self.END}")
try:
from prepare_data import prepare_data
result = prepare_data()
print(f"{self.GREEN}{self.END} Prepared {result['train_samples']} training samples")
except Exception as e:
print(f"{self.RED}Error: {e}{self.END}")
elif choice == '2':
print(f"\n{YELLOW}Training LoRA...{self.END}")
print(f"{self.YELLOW}Note: This requires significant GPU resources{self.END}")
confirm = input("Continue? (y/n): ").strip().lower()
if confirm == 'y':
try:
from train_lora import train_lora
trainer = train_lora()
print(f"{self.GREEN}{self.END} Training complete")
except Exception as e:
print(f"{self.RED}Error: {e}{self.END}")
input("\nPress Enter to continue...")
def settings_mode(self):
"""Configure settings"""
print(f"\n{self.BLUE}=== Settings ==={self.END}")
print(f"Provider: {self.provider}")
print(f"Model: {self.model}")
print(f"\n{self.GREEN}[1]{self.END} Change Provider")
print(f"{self.GREEN}[2]{self.END} Change Model")
print(f"{self.GREEN}[0]{self.END} Back")
choice = input("\nSelect: ").strip()
if choice == '1':
print("Providers: ollama, openai, anthropic")
new_provider = input("Provider: ").strip()
if new_provider in ['ollama', 'openai', 'anthropic']:
self.provider = new_provider
self.init_client()
elif choice == '2':
new_model = input("Model name: ").strip()
if new_model:
self.model = new_model
self.init_client()
def run(self):
"""Run the CLI"""
self.print_header()
self.init_client()
while True:
self.print_menu()
choice = input(f"{self.GREEN}Select>{self.END} ").strip()
if choice == '0':
print(f"\n{self.BLUE}Thanks for using Stack 2.9!{self.END}\n")
break
if choice == '1':
self.chat_mode()
elif choice == '2':
self.eval_mode()
elif choice == '3':
self.pattern_mode()
elif choice == '4':
self.train_mode()
elif choice == '5':
self.settings_mode()
else:
print(f"{self.RED}Invalid option{self.END}")
def main():
parser = argparse.ArgumentParser(description="Stack 2.9 CLI")
parser.add_argument("--provider", "-p", choices=["ollama", "openai", "anthropic"],
help="Model provider")
parser.add_argument("--model", "-m", type=str, help="Model name")
parser.add_argument("--chat", "-c", action="store_true", help="Start in chat mode")
parser.add_argument("--eval", "-e", choices=["mbpp", "human_eval", "gsm8k", "all"],
help="Run evaluation")
args = parser.parse_args()
cli = Stack29CLI(provider=args.provider, model=args.model)
if args.chat:
cli.init_client()
cli.chat_mode()
elif args.eval:
cli.init_client()
cli.eval_mode()
else:
cli.run()
if __name__ == "__main__":
main()