141 lines
4.5 KiB
Python
141 lines
4.5 KiB
Python
import os
|
|
from dotenv import load_dotenv
|
|
|
|
from nicegui import ui, app
|
|
from langfuse import get_client
|
|
from pydantic_ai.agent import Agent
|
|
|
|
from components import Header, Sidebar
|
|
from pages import DashboardPage, OllamaManagerPage
|
|
from utils import GPUMonitor, SystemMonitor, OllamaMonitor
|
|
import logging
|
|
|
|
from tools import TOOLS
|
|
from tools.base_tool import ToolContext, set_tool_context
|
|
|
|
load_dotenv()
|
|
|
|
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
)
|
|
logging.getLogger('watchfiles').setLevel(logging.WARNING)
|
|
|
|
if all(var in os.environ for var in ['LANGFUSE_PUBLIC_KEY', 'LANGFUSE_SECRET_KEY', 'LANGFUSE_HOST']):
|
|
langfuse = get_client()
|
|
|
|
if langfuse.auth_check():
|
|
print("Langfuse client is authenticated and ready!")
|
|
else:
|
|
print("Authentication failed. Please check your credentials and host.")
|
|
|
|
Agent.instrument_all()
|
|
|
|
app.add_static_files('/static', 'src/static')
|
|
|
|
|
|
# Create monitor instances (bindable dataclasses)
|
|
system_monitor = SystemMonitor()
|
|
gpu_monitor = GPUMonitor()
|
|
ollama_monitor = OllamaMonitor()
|
|
|
|
app.timer(2.0, system_monitor.update)
|
|
app.timer(2.0, gpu_monitor.update)
|
|
app.timer(2.0, ollama_monitor.update)
|
|
|
|
# Initialize tool context
|
|
tool_context = ToolContext(
|
|
system_monitor=system_monitor,
|
|
gpu_monitor=gpu_monitor,
|
|
ollama_monitor=ollama_monitor
|
|
)
|
|
set_tool_context(tool_context)
|
|
|
|
|
|
def create_layout(current_route='/'):
|
|
# Force dark mode
|
|
ui.dark_mode(True)
|
|
ui.query('.nicegui-content').classes('p-0 m-0')
|
|
|
|
# Add custom CSS
|
|
ui.add_head_html('<link rel="stylesheet" type="text/css" href="/static/style.css">')
|
|
|
|
Header(system_monitor, gpu_monitor, ollama_monitor)
|
|
Sidebar(current_route)
|
|
|
|
|
|
# Create tool routes with sub-pages support
|
|
for tool_baseroute, tool in TOOLS.items():
|
|
# Register all routes defined by the tool
|
|
for sub_path, handler in tool.routes.items():
|
|
# Construct full route path
|
|
full_route = tool.baseroute + sub_path if sub_path else tool.baseroute
|
|
|
|
# Create a closure to capture the current handler and route
|
|
def create_route_handler(route, handler_func):
|
|
@ui.page(route)
|
|
async def tool_page():
|
|
create_layout(route)
|
|
await handler_func()
|
|
return tool_page
|
|
|
|
# Register the route
|
|
create_route_handler(full_route, handler)
|
|
|
|
|
|
@ui.page('/')
|
|
async def index_page():
|
|
create_layout('/')
|
|
DashboardPage(system_monitor, gpu_monitor, ollama_monitor)
|
|
|
|
|
|
@ui.page('/ollama')
|
|
async def ollama_page():
|
|
create_layout('/ollama')
|
|
await OllamaManagerPage.create()
|
|
|
|
# await page._load_models()
|
|
|
|
|
|
@ui.page('/settings')
|
|
async def settings_page():
|
|
create_layout('/settings')
|
|
with ui.element('div').classes('main-content w-full'):
|
|
with ui.column().classes('w-full max-w-4xl mx-auto p-6 gap-6'):
|
|
ui.label('Settings').classes('text-2xl font-bold text-white')
|
|
|
|
with ui.card().classes('metric-card p-6'):
|
|
ui.label('Refresh Intervals').classes('text-lg font-bold text-white mb-4')
|
|
|
|
with ui.column().classes('gap-4'):
|
|
with ui.row().classes('items-center justify-between'):
|
|
ui.label('System Stats').classes('text-white')
|
|
ui.select(['1s', '2s', '5s', '10s'], value='2s').props('outlined dense color=cyan')
|
|
|
|
with ui.row().classes('items-center justify-between'):
|
|
ui.label('GPU Temperature').classes('text-white')
|
|
ui.select(['1s', '2s', '5s', '10s'], value='5s').props('outlined dense color=cyan')
|
|
|
|
with ui.card().classes('metric-card p-6 mt-4'):
|
|
ui.label('About').classes('text-lg font-bold text-white mb-4')
|
|
|
|
with ui.column().classes('gap-2'):
|
|
with ui.row().classes('items-center gap-2'):
|
|
ui.icon('computer', color='cyan')
|
|
ui.label('ArchGPU Frontend v0.1.0').classes('text-white')
|
|
|
|
with ui.row().classes('items-center gap-2'):
|
|
ui.icon('smart_toy', color='orange')
|
|
ui.label('Ollama v0.11.11').classes('text-white')
|
|
|
|
|
|
if __name__ in {"__main__", "__mp_main__"}:
|
|
ui.run(
|
|
title=os.getenv('APP_TITLE', 'ArchGPU Frontend'),
|
|
storage_secret=os.getenv('APP_STORAGE_SECRET'),
|
|
port=int(os.getenv('APP_PORT', '8080')),
|
|
show=os.getenv("APP_SHOW", 'false').lower() == "true",
|
|
dark=True
|
|
)
|