gpu-poor-llm-arena / model_suggestions.py
k-mktr's picture
Update model_suggestions.py
90f246e verified
from nc_py_api import Nextcloud
import json
from typing import Dict, List
import os
import time
from datetime import datetime
import threading
import arena_config
import re
# Initialize Nextcloud client
nc = Nextcloud(
nextcloud_url=arena_config.NEXTCLOUD_URL,
nc_auth_user=arena_config.NEXTCLOUD_USERNAME,
nc_auth_pass=arena_config.NEXTCLOUD_PASSWORD
)
SUGGESTIONS_FILE = "model_suggestions.json"
NEXTCLOUD_SUGGESTIONS_PATH = "/gpu_poor_model_suggestions.json"
def validate_model_url(url: str) -> bool:
"""Validate if the provided URL matches the expected HuggingFace format."""
pattern = r'^hf\.co/[\w-]+/[\w\.-]+(?:-GGUF)?:Q[0-9]+(?:_[A-Z0-9_]+)?$'
return bool(re.match(pattern, url))
def load_suggestions() -> Dict:
"""Load suggestions from Nextcloud, fallback to local file, or initialize if neither exists."""
suggestions = None
# First try to load from Nextcloud
try:
remote_data = nc.files.download(NEXTCLOUD_SUGGESTIONS_PATH)
if remote_data:
suggestions = json.loads(remote_data.decode('utf-8'))
# Update local file with Nextcloud data
with open(SUGGESTIONS_FILE, 'w') as f:
json.dump(suggestions, f, indent=2)
return suggestions
except Exception as e:
print(f"Could not load from Nextcloud: {e}")
# If Nextcloud fails, try local file
if os.path.exists(SUGGESTIONS_FILE):
try:
with open(SUGGESTIONS_FILE, 'r') as f:
suggestions = json.load(f)
return suggestions
except Exception as e:
print(f"Could not load from local file: {e}")
# If both fail, initialize new suggestions
suggestions = {
"suggestions": {},
"last_updated": datetime.now().isoformat()
}
# Save the new suggestions to both local and Nextcloud
save_suggestions(suggestions)
return suggestions
def save_suggestions(suggestions: Dict) -> None:
"""Save suggestions to both local file and Nextcloud."""
with open(SUGGESTIONS_FILE, 'w') as f:
json.dump(suggestions, f, indent=2)
# Upload to Nextcloud
try:
nc.files.upload(
NEXTCLOUD_SUGGESTIONS_PATH,
json.dumps(suggestions, indent=2).encode('utf-8')
)
except Exception as e:
print(f"Error uploading to Nextcloud: {e}")
def add_suggestion(model_url: str) -> str:
"""Add a new model suggestion or update existing one."""
if not validate_model_url(model_url):
return "❌ Invalid model URL format. Please use the format: hf.co/username/model-name-GGUF:Q4_K_M"
suggestions = load_suggestions()
if model_url in suggestions["suggestions"]:
suggestions["suggestions"][model_url]["count"] += 1
suggestions["suggestions"][model_url]["last_suggested"] = datetime.now().isoformat()
message = f"✨ Model suggestion updated! This model has been suggested {suggestions['suggestions'][model_url]['count']} times."
else:
suggestions["suggestions"][model_url] = {
"count": 1,
"first_suggested": datetime.now().isoformat(),
"last_suggested": datetime.now().isoformat()
}
message = "βœ… New model suggestion recorded successfully!"
suggestions["last_updated"] = datetime.now().isoformat()
save_suggestions(suggestions)
return message
def get_suggestions_html() -> str:
"""Generate HTML table of model suggestions."""
suggestions = load_suggestions()
# Sort suggestions by count (descending)
sorted_suggestions = sorted(
suggestions["suggestions"].items(),
key=lambda x: x[1]["count"],
reverse=True
)
html = """
<style>
.suggestions-table {
width: 100%;
border-collapse: collapse;
font-family: Arial, sans-serif;
}
.suggestions-table th, .suggestions-table td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
.suggestions-table th {
background-color: rgba(255, 255, 255, 0.1);
font-weight: bold;
}
.rank-column {
width: 60px;
text-align: center;
}
.count-badge {
background-color: rgba(34, 87, 122, 0.7);
color: white;
padding: 4px 8px;
border-radius: 12px;
font-size: 0.9em;
}
.description-column {
font-size: 0.9em;
color: #888;
}
</style>
<table class='suggestions-table'>
<tr>
<th class='rank-column'>Rank</th>
<th>Model URL</th>
<th>Suggestions</th>
<th>First Suggested</th>
<th>Last Suggested</th>
</tr>
"""
for index, (model_url, data) in enumerate(sorted_suggestions, start=1):
rank_display = {1: "πŸ₯‡", 2: "πŸ₯ˆ", 3: "πŸ₯‰"}.get(index, f"{index}")
html += f"""
<tr>
<td class='rank-column'>{rank_display}</td>
<td>{model_url}</td>
<td><span class="count-badge">{data['count']}</span></td>
<td>{data['first_suggested'].split('T')[0]}</td>
<td>{data['last_suggested'].split('T')[0]}</td>
</tr>
"""
html += "</table>"
return html