This commit is contained in:
BobAi 2025-08-15 14:08:15 +10:00
commit 1e9eb9bc1a
8 changed files with 80 additions and 43 deletions

View File

@ -103,6 +103,10 @@ rag.bat # Interactive interface
rag.bat index C:\my-project # Index your project first rag.bat index C:\my-project # Index your project first
rag.bat search C:\my-project "query" # Fast search rag.bat search C:\my-project "query" # Fast search
rag.bat explore C:\my-project # Interactive exploration rag.bat explore C:\my-project # Interactive exploration
# Direct Python entrypoint (after install):
rag-mini index C:\my-project
rag-mini search C:\my-project "query"
``` ```
That's it. No external dependencies, no configuration required, no PhD in computer science needed. That's it. No external dependencies, no configuration required, no PhD in computer science needed.
@ -234,12 +238,12 @@ This implementation prioritizes:
## Documentation ## Documentation
- **[Quick Start Guide](docs/QUICK_START.md)** - Get running in 5 minutes - **[Getting Started](docs/GETTING_STARTED.md)** - Get running in 5 minutes
- **[Visual Diagrams](docs/DIAGRAMS.md)** - 📊 System flow charts and architecture diagrams - **[Visual Diagrams](docs/DIAGRAMS.md)** - 📊 System flow charts and architecture diagrams
- **[TUI Guide](docs/TUI_GUIDE.md)** - Complete walkthrough of the friendly interface - **[TUI Guide](docs/TUI_GUIDE.md)** - Complete walkthrough of the friendly interface
- **[Technical Guide](docs/TECHNICAL_GUIDE.md)** - How the system actually works - **[Technical Guide](docs/TECHNICAL_GUIDE.md)** - How the system actually works
- **[Configuration Guide](docs/CONFIGURATION.md)** - Customizing for your needs - **[Troubleshooting](docs/TROUBLESHOOTING.md)** - Fix common issues
- **[Development Guide](docs/DEVELOPMENT.md)** - Extending and modifying the code - **[Beginner Glossary](docs/BEGINNER_GLOSSARY.md)** - Friendly terms and concepts
## License ## License

View File

@ -0,0 +1,2 @@
Welcome to FSS Mini RAG. This app makes your files searchable by meaning, not just keywords. On first launch, youll see three simple choices. Lite mode is the smallest download. It works great for search on any computer and is ready in minutes. Full offline mode adds a small local AI model so you can ask deeper questions without any internet. This is a larger download, but once its installed youre fully offline. If you prefer cloud quality with a tiny download, choose the API option and paste your key from a provider like OpenAI. After you pick a mode, choose a folder, and click Index. That builds a private, local index on your machine. Then, ask a question like “Show me the authentication flow” or “Where do we write to the database?” Youll get results with paths and line numbers, and you can ask follow-ups in Explore mode to get explanations with sources. Everything stays on your device unless you opt into a cloud provider. If youre new, try the Demo button first to see it in action in under a minute. FSS Mini RAG—search smarter, learn faster, and stay in control of your data.

View File

@ -135,9 +135,9 @@ def init(path: str, force: bool, reindex: bool, model: Optional[str]):
# Show how to use # Show how to use
console.print("\n[bold]Next steps:[/bold]") console.print("\n[bold]Next steps:[/bold]")
console.print(" • Search your code: [cyan]mini-rag search \"your query\"[/cyan]") console.print(" • Search your code: [cyan]rag-mini search \"your query\"[/cyan]")
console.print(" • Watch for changes: [cyan]mini-rag watch[/cyan]") console.print(" • Watch for changes: [cyan]rag-mini watch[/cyan]")
console.print(" • View statistics: [cyan]mini-rag stats[/cyan]\n") console.print(" • View statistics: [cyan]rag-mini stats[/cyan]\n")
except Exception as e: except Exception as e:
console.print(f"\n[bold red]Error:[/bold red] {e}") console.print(f"\n[bold red]Error:[/bold red] {e}")
@ -166,7 +166,7 @@ def search(query: str, path: str, top_k: int, type: tuple, lang: tuple, show_con
# Check if indexed # Check if indexed
rag_dir = project_path / '.mini-rag' rag_dir = project_path / '.mini-rag'
if not rag_dir.exists(): if not rag_dir.exists():
console.print("[red]Error:[/red] Project not indexed. Run 'mini-rag init' first.") console.print("[red]Error:[/red] Project not indexed. Run 'rag-mini init' first.")
sys.exit(1) sys.exit(1)
# Get performance monitor # Get performance monitor
@ -280,7 +280,7 @@ def stats(path: str):
# Check if indexed # Check if indexed
rag_dir = project_path / '.mini-rag' rag_dir = project_path / '.mini-rag'
if not rag_dir.exists(): if not rag_dir.exists():
console.print("[red]Error:[/red] Project not indexed. Run 'mini-rag init' first.") console.print("[red]Error:[/red] Project not indexed. Run 'rag-mini init' first.")
sys.exit(1) sys.exit(1)
try: try:
@ -350,7 +350,7 @@ def debug_schema(path: str):
rag_dir = project_path / '.mini-rag' rag_dir = project_path / '.mini-rag'
if not rag_dir.exists(): if not rag_dir.exists():
console.print("[red]No RAG index found. Run 'init' first.[/red]") console.print("[red]No RAG index found. Run 'rag-mini init' first.[/red]")
return return
# Connect to database # Connect to database
@ -418,7 +418,7 @@ def watch(path: str, delay: float, silent: bool):
rag_dir = project_path / '.mini-rag' rag_dir = project_path / '.mini-rag'
if not rag_dir.exists(): if not rag_dir.exists():
if not silent: if not silent:
console.print("[red]Error:[/red] Project not indexed. Run 'mini-rag init' first.") console.print("[red]Error:[/red] Project not indexed. Run 'rag-mini init' first.")
sys.exit(1) sys.exit(1)
try: try:
@ -543,7 +543,7 @@ def update(path: str):
# Check if indexed # Check if indexed
rag_dir = project_path / '.mini-rag' rag_dir = project_path / '.mini-rag'
if not rag_dir.exists(): if not rag_dir.exists():
console.print("[red]Error:[/red] Project not indexed. Run 'mini-rag init' first.") console.print("[red]Error:[/red] Project not indexed. Run 'rag-mini init' first.")
sys.exit(1) sys.exit(1)
try: try:
@ -598,7 +598,7 @@ def info(show_code: bool):
console.print("\n[bold]Example Usage:[/bold]\n") console.print("\n[bold]Example Usage:[/bold]\n")
code = """# Initialize a project code = """# Initialize a project
mini-rag init rag-mini init
# Search for code # Search for code
mini-rag search "database connection" mini-rag search "database connection"
@ -609,10 +609,10 @@ mini-rag find-function connect_to_db
mini-rag find-class UserModel mini-rag find-class UserModel
# Watch for changes # Watch for changes
mini-rag watch rag-mini watch
# Get statistics # Get statistics
mini-rag stats""" rag-mini stats"""
syntax = Syntax(code, "bash", theme="monokai") syntax = Syntax(code, "bash", theme="monokai")
console.print(syntax) console.print(syntax)
@ -630,7 +630,7 @@ def server(path: str, port: int):
# Check if indexed # Check if indexed
rag_dir = project_path / '.mini-rag' rag_dir = project_path / '.mini-rag'
if not rag_dir.exists(): if not rag_dir.exists():
console.print("[red]Error:[/red] Project not indexed. Run 'mini-rag init' first.") console.print("[red]Error:[/red] Project not indexed. Run 'rag-mini init' first.")
sys.exit(1) sys.exit(1)
try: try:
@ -692,7 +692,7 @@ def status(path: str, port: int, discovery: bool):
console.print(f" • Error: {e}") console.print(f" • Error: {e}")
else: else:
console.print(" • Status: [red]❌ Not indexed[/red]") console.print(" • Status: [red]❌ Not indexed[/red]")
console.print(" • Run 'rag-start' to initialize") console.print(" • Run 'rag-mini init' to initialize")
# Check server status # Check server status
console.print("\n[bold]🚀 Server Status:[/bold]") console.print("\n[bold]🚀 Server Status:[/bold]")
@ -713,7 +713,7 @@ def status(path: str, port: int, discovery: bool):
console.print(f" • [yellow]Server responding but with issues: {e}[/yellow]") console.print(f" • [yellow]Server responding but with issues: {e}[/yellow]")
else: else:
console.print(f" • Status: [red]❌ Not running on port {port}[/red]") console.print(f" • Status: [red]❌ Not running on port {port}[/red]")
console.print(" • Run 'rag-start' to start server") console.print(" • Run 'rag-mini server' to start the server")
# Run codebase discovery if requested # Run codebase discovery if requested
if discovery and rag_dir.exists(): if discovery and rag_dir.exists():
@ -739,18 +739,18 @@ def status(path: str, port: int, discovery: bool):
elif discovery and not rag_dir.exists(): elif discovery and not rag_dir.exists():
console.print("\n[bold]🧠 Codebase Discovery:[/bold]") console.print("\n[bold]🧠 Codebase Discovery:[/bold]")
console.print(" [yellow]❌ Cannot run discovery - project not indexed[/yellow]") console.print(" [yellow]❌ Cannot run discovery - project not indexed[/yellow]")
console.print(" Run 'rag-start' first to initialize the system") console.print(" Run 'rag-mini init' first to initialize the system")
# Show next steps # Show next steps
console.print("\n[bold]📋 Next Steps:[/bold]") console.print("\n[bold]📋 Next Steps:[/bold]")
if not rag_dir.exists(): if not rag_dir.exists():
console.print(" 1. Run [cyan]rag-start[/cyan] to initialize and start RAG system") console.print(" 1. Run [cyan]rag-mini init[/cyan] to initialize the RAG system")
console.print(" 2. Use [cyan]rag-search \"your query\"[/cyan] to search code") console.print(" 2. Use [cyan]rag-mini search \"your query\"[/cyan] to search code")
elif not client.is_running(): elif not client.is_running():
console.print(" 1. Run [cyan]rag-start[/cyan] to start the server") console.print(" 1. Run [cyan]rag-mini server[/cyan] to start the server")
console.print(" 2. Use [cyan]rag-search \"your query\"[/cyan] to search code") console.print(" 2. Use [cyan]rag-mini search \"your query\"[/cyan] to search code")
else: else:
console.print(" • System ready! Use [cyan]rag-search \"your query\"[/cyan] to search") console.print(" • System ready! Use [cyan]rag-mini search \"your query\"[/cyan] to search")
console.print(" • Add [cyan]--discovery[/cyan] flag to run intelligent codebase analysis") console.print(" • Add [cyan]--discovery[/cyan] flag to run intelligent codebase analysis")
console.print() console.print()

View File

@ -472,23 +472,23 @@ class OllamaEmbedder:
def get_embedding_info(self) -> Dict[str, str]: def get_embedding_info(self) -> Dict[str, str]:
"""Get human-readable embedding system information for installer.""" """Get human-readable embedding system information for installer."""
status = self.get_status() status = self.get_status()
mode = status.get("mode", "unknown")
if status["mode"] == "ollama": if mode == "ollama":
return { return {
"method": f"Ollama ({status['ollama_model']})", "method": f"Ollama ({status['ollama_model']})",
"status": "working" "status": "working"
} }
elif status["mode"] == "ml": # Treat legacy/alternate naming uniformly
if mode in ("fallback", "ml"):
return { return {
"method": f"ML Fallback ({status['fallback_model']})", "method": f"ML Fallback ({status['fallback_model']})",
"status": "working" "status": "working"
} }
elif status["mode"] == "hash": if mode == "hash":
return { return {
"method": "Hash-based (basic similarity)", "method": "Hash-based (basic similarity)",
"status": "working" "status": "working"
} }
else:
return { return {
"method": "Unknown", "method": "Unknown",
"status": "error" "status": "error"

View File

@ -272,7 +272,7 @@ class RAGClient:
except ConnectionRefusedError: except ConnectionRefusedError:
return { return {
'success': False, 'success': False,
'error': 'RAG server not running. Start with: mini-rag server' 'error': 'RAG server not running. Start with: rag-mini server'
} }
except ConnectionError as e: except ConnectionError as e:
# Try legacy mode without message framing # Try legacy mode without message framing

View File

@ -182,13 +182,15 @@ class SimpleTUI:
"Keep current project (go back to main menu)", "Keep current project (go back to main menu)",
"Use current directory (this folder)", "Use current directory (this folder)",
"Enter different project path", "Enter different project path",
"Browse recent projects" "Browse recent projects",
"Open folder picker (GUI)"
] ]
else: else:
options = [ options = [
"Use current directory (perfect for beginners - try the RAG codebase!)", "Use current directory (perfect for beginners - try the RAG codebase!)",
"Enter project path (if you have a specific project)", "Enter project path (if you have a specific project)",
"Browse recent projects" "Browse recent projects",
"Open folder picker (GUI)"
] ]
choice = self.show_menu("Choose project directory", options, show_cli=False, back_option="Back to main menu") choice = self.show_menu("Choose project directory", options, show_cli=False, back_option="Back to main menu")
@ -212,6 +214,12 @@ class SimpleTUI:
elif choice == 3: elif choice == 3:
# Browse recent projects # Browse recent projects
self.browse_recent_projects() self.browse_recent_projects()
elif choice == 4:
picked = self._pick_folder_dialog()
if picked:
self.project_path = Path(picked)
print(f"✅ Selected: {self.project_path}")
self._save_last_project()
else: else:
if choice == 0: if choice == 0:
# Use current directory # Use current directory
@ -224,6 +232,12 @@ class SimpleTUI:
elif choice == 2: elif choice == 2:
# Browse recent projects # Browse recent projects
self.browse_recent_projects() self.browse_recent_projects()
elif choice == 3:
picked = self._pick_folder_dialog()
if picked:
self.project_path = Path(picked)
print(f"✅ Selected: {self.project_path}")
self._save_last_project()
input("\nPress Enter to continue...") input("\nPress Enter to continue...")
@ -503,6 +517,23 @@ class SimpleTUI:
print() print()
input("Press Enter to continue...") input("Press Enter to continue...")
def _pick_folder_dialog(self) -> Optional[str]:
"""Open a minimal cross-platform folder picker dialog and return path or None."""
try:
import tkinter as tk
from tkinter import filedialog
root = tk.Tk()
root.withdraw()
root.update()
directory = filedialog.askdirectory(title="Select project folder to index")
root.destroy()
if directory and Path(directory).exists():
return directory
return None
except Exception:
print("❌ Folder picker not available on this system")
return None
def _show_existing_index_info(self, rag_dir: Path) -> bool: def _show_existing_index_info(self, rag_dir: Path) -> bool:
"""Show essential info about existing index and ask about re-indexing.""" """Show essential info about existing index and ask about re-indexing."""
print("📊 EXISTING INDEX FOUND") print("📊 EXISTING INDEX FOUND")
@ -1309,18 +1340,18 @@ Your suggested question (under 10 words):"""
from mini_rag.ollama_embeddings import OllamaEmbedder from mini_rag.ollama_embeddings import OllamaEmbedder
embedder = OllamaEmbedder() embedder = OllamaEmbedder()
info = embedder.get_status() status = embedder.get_status()
print("🧠 Embedding System:") print("🧠 Embedding System:")
method = info.get('method', 'unknown') mode = status.get('mode', 'unknown')
if method == 'ollama': if mode == 'ollama':
print(" ✅ Ollama (high quality)") print(" ✅ Ollama (high quality)")
elif method == 'ml': elif mode == 'fallback':
print(" ✅ ML fallback (good quality)") print(" ✅ ML fallback (good quality)")
elif method == 'hash': elif mode == 'hash':
print(" ⚠️ Hash fallback (basic quality)") print(" ⚠️ Hash fallback (basic quality)")
else: else:
print(f" ❓ Unknown: {method}") print(f" ❓ Unknown: {mode}")
except Exception as e: except Exception as e:
print(f"🧠 Embedding System: ❌ Error: {e}") print(f"🧠 Embedding System: ❌ Error: {e}")

View File

@ -124,7 +124,7 @@ def main():
project_path = Path(__file__).parent project_path = Path(__file__).parent
if not (project_path / '.mini-rag').exists(): if not (project_path / '.mini-rag').exists():
console.print("[red]Error: No RAG index found. Run 'mini-rag index' first.[/red]") console.print("[red]Error: No RAG index found. Run 'rag-mini index' first.[/red]")
console.print(f"[dim]Looked in: {project_path / '.mini-rag'}[/dim]") console.print(f"[dim]Looked in: {project_path / '.mini-rag'}[/dim]")
return return

View File

@ -328,7 +328,7 @@ def main():
project_path = Path.cwd() project_path = Path.cwd()
if not (project_path / '.mini-rag').exists(): if not (project_path / '.mini-rag').exists():
console.print("[red]Error: No RAG index found. Run 'mini-rag index' first.[/red]") console.print("[red]Error: No RAG index found. Run 'rag-mini index' first.[/red]")
return return
# Create tester # Create tester