Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
586 changes: 233 additions & 353 deletions README.md

Large diffs are not rendered by default.

885 changes: 885 additions & 0 deletions backend/api/main.py

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions backend/api/test_openapi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""
Test script to check OpenAPI schema generation
Run this to diagnose Swagger UI issues
"""
import sys
from pathlib import Path

# Add project root to path
project_root = Path(__file__).parent.parent.parent
sys.path.insert(0, str(project_root))

try:
print("Importing FastAPI app...")
from backend.api.main import app
print("✅ App imported successfully")

print("\nGenerating OpenAPI schema...")
schema = app.openapi()
print("✅ OpenAPI schema generated successfully")

print(f"\nSchema info:")
print(f" - Title: {schema.get('info', {}).get('title')}")
print(f" - Version: {schema.get('info', {}).get('version')}")
print(f" - Paths: {len(schema.get('paths', {}))}")

print("\nAvailable endpoints:")
for path, methods in schema.get('paths', {}).items():
for method in methods.keys():
print(f" {method.upper()} {path}")

print("\n✅ All checks passed! Swagger UI should work.")

except Exception as e:
print(f"❌ Error: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
8 changes: 8 additions & 0 deletions backend/core/dependencies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""
Core dependencies for backend routers
"""

from backend.utils.dependencies import get_neurax_service

# Re-export for compatibility
__all__ = ['get_neurax_service']
15 changes: 15 additions & 0 deletions backend/core/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""
Backend exceptions
"""

from enum import Enum

class ErrorCode(str, Enum):
"""Error codes"""
UNKNOWN = "UNKNOWN"
VALIDATION_ERROR = "VALIDATION_ERROR"
NOT_FOUND = "NOT_FOUND"

class EvaluationError(Exception):
"""Evaluation error"""
pass
31 changes: 31 additions & 0 deletions backend/core/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""
Backend settings and configuration
"""

from pathlib import Path
from dataclasses import dataclass

@dataclass
class Settings:
"""Application settings"""
paths: 'Paths'
evaluation: 'EvaluationSettings'

@dataclass
class Paths:
"""Path settings"""
data_dir: Path = Path("data")

@dataclass
class EvaluationSettings:
"""Evaluation settings"""
enabled: bool = True
sample_rate: float = 0.1
track_latency_metrics: bool = True
track_retrieval_metrics: bool = True
track_generation_metrics: bool = True

settings = Settings(
paths=Paths(),
evaluation=EvaluationSettings()
)
47 changes: 47 additions & 0 deletions backend/services/neurax_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""
NeuraX Service - Main service orchestrator
"""

import time
from typing import Dict, Any, Optional
from datetime import datetime

from loguru import logger


class NeuraxService:
"""Main service that orchestrates all NeuraX components"""

def __init__(self):
self.start_time = time.time()
self.initialized = False
self.component_status = {}
self.component_errors = []

async def get_health_status(self) -> Dict[str, Any]:
"""Get comprehensive health status"""
uptime = time.time() - self.start_time

return {
'overall_status': 'healthy' if self.initialized else 'initializing',
'uptime': uptime,
'component_status': self.component_status,
'component_errors': self.component_errors,
'initialized': self.initialized
}

async def search(
self,
query: str,
k: int = 10,
similarity_threshold: float = 0.5,
generate_response: bool = True
) -> Dict[str, Any]:
"""Perform a search query"""
# This would integrate with query_processor
# For now, return a placeholder
return {
"query": query,
"results": [],
"generated_response": None
}
17 changes: 17 additions & 0 deletions backend/utils/dependencies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""
Dependency injection utilities for FastAPI
"""

from typing import Optional
from backend.services.neurax_service import NeuraxService

# Global service instance
_neurax_service: Optional[NeuraxService] = None


def get_neurax_service() -> NeuraxService:
"""Get or create NeuraxService instance"""
global _neurax_service
if _neurax_service is None:
_neurax_service = NeuraxService()
return _neurax_service
10 changes: 10 additions & 0 deletions neurax-frontend/.env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# API Configuration
NEXT_PUBLIC_API_URL=http://localhost:8000
NEXT_PUBLIC_WS_URL=ws://localhost:8000
NEXT_PUBLIC_LM_STUDIO_URL=http://localhost:1234

# File Upload Configuration
NEXT_PUBLIC_MAX_FILE_SIZE=104857600

# Allowed File Types (comma-separated)
NEXT_PUBLIC_ALLOWED_FILE_TYPES=.pdf,.docx,.doc,.txt,.jpg,.jpeg,.png,.bmp,.tiff,.webp,.wav,.mp3,.m4a,.flac,.ogg
36 changes: 36 additions & 0 deletions neurax-frontend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local
.env

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
2 changes: 2 additions & 0 deletions neurax-frontend/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# npm configuration
legacy-peer-deps=true
100 changes: 100 additions & 0 deletions neurax-frontend/app/(dashboard)/dashboard/analytics/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
"use client"

import { useState, useEffect } from "react"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { MetricsChart } from "@/components/analytics/MetricsChart"
import { UsageStats } from "@/components/analytics/UsageStats"
import { SecurityAlerts } from "@/components/analytics/SecurityAlerts"
import { analyticsApi } from "@/lib/api/analytics"
import toast from "react-hot-toast"
import { Loader2 } from "lucide-react"

export default function AnalyticsPage() {
const [loading, setLoading] = useState(true)
const [metrics, setMetrics] = useState<any>(null)
const [usageStats, setUsageStats] = useState<any>(null)
const [securityEvents, setSecurityEvents] = useState<any>(null)
const [timeRange, setTimeRange] = useState(24)

useEffect(() => {
loadAnalytics()
}, [timeRange])

const loadAnalytics = async () => {
setLoading(true)
try {
const [metricsData, usageData, securityData] = await Promise.all([
analyticsApi.getMetrics(timeRange),
analyticsApi.getUsageStats(timeRange),
analyticsApi.getSecurityEvents(50),
])
setMetrics(metricsData)
setUsageStats(usageData)
setSecurityEvents(securityData)
} catch (error: any) {
toast.error(error.message || "Failed to load analytics")
} finally {
setLoading(false)
}
}

if (loading) {
return (
<div className="flex items-center justify-center h-64">
<Loader2 className="h-8 w-8 animate-spin" />
</div>
)
}

return (
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold tracking-tight">Analytics Dashboard</h1>
<p className="text-muted-foreground">
System performance metrics and usage statistics
</p>
</div>
<select
value={timeRange}
onChange={(e) => setTimeRange(Number(e.target.value))}
className="px-3 py-2 border rounded-md"
>
<option value={1}>Last Hour</option>
<option value={24}>Last 24 Hours</option>
<option value={168}>Last Week</option>
<option value={720}>Last Month</option>
</select>
</div>

<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<Card>
<CardHeader>
<CardTitle>Performance Metrics</CardTitle>
</CardHeader>
<CardContent>
<MetricsChart metrics={metrics} />
</CardContent>
</Card>

<Card>
<CardHeader>
<CardTitle>Usage Statistics</CardTitle>
</CardHeader>
<CardContent>
<UsageStats stats={usageStats} />
</CardContent>
</Card>

<Card className="md:col-span-2 lg:col-span-3">
<CardHeader>
<CardTitle>Security Alerts</CardTitle>
</CardHeader>
<CardContent>
<SecurityAlerts events={securityEvents} />
</CardContent>
</Card>
</div>
</div>
)
}
26 changes: 26 additions & 0 deletions neurax-frontend/app/(dashboard)/dashboard/documents/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"use client"

import { FileUploader } from "@/components/upload/FileUploader"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"

export default function DocumentsPage() {
return (
<div className="space-y-6">
<div>
<h1 className="text-3xl font-bold tracking-tight">Document Management</h1>
<p className="text-muted-foreground">
Upload and manage your documents for indexing
</p>
</div>

<Card>
<CardHeader>
<CardTitle>Upload Documents</CardTitle>
</CardHeader>
<CardContent>
<FileUploader />
</CardContent>
</Card>
</div>
)
}
44 changes: 44 additions & 0 deletions neurax-frontend/app/(dashboard)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"use client"

import { useState } from "react"
import { QueryInput } from "@/components/query/QueryInput"
import { ResultsDisplay } from "@/components/results/ResultsDisplay"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import type { QueryResponse } from "@/lib/types/api"

export default function DashboardPage() {
const [queryResult, setQueryResult] = useState<QueryResponse | null>(null)
const [isLoading, setIsLoading] = useState(false)

const handleQuery = async (result: QueryResponse) => {
setQueryResult(result)
}

return (
<div className="space-y-6">
<div>
<h1 className="text-3xl font-bold tracking-tight">Query Interface</h1>
<p className="text-muted-foreground">
Ask questions about your documents using text, voice, or images
</p>
</div>

<Card>
<CardHeader>
<CardTitle>Enter Your Query</CardTitle>
</CardHeader>
<CardContent>
<QueryInput
onQuery={handleQuery}
isLoading={isLoading}
setIsLoading={setIsLoading}
/>
</CardContent>
</Card>

{queryResult && (
<ResultsDisplay result={queryResult} />
)}
</div>
)
}
Loading