k-mktr commited on
Commit
baac06c
Β·
verified Β·
1 Parent(s): b49e002

Update model_suggestions.py

Browse files
Files changed (1) hide show
  1. model_suggestions.py +85 -66
model_suggestions.py CHANGED
@@ -1,110 +1,121 @@
1
  from nc_py_api import Nextcloud
2
  import json
3
- from typing import Dict, List
4
- import os
5
- import time
6
  from datetime import datetime
7
- import threading
8
- import arena_config
9
  import re
 
10
 
11
  # Initialize Nextcloud client
12
  nc = Nextcloud(
13
- nextcloud_url=arena_config.NEXTCLOUD_URL,
14
- nc_auth_user=arena_config.NEXTCLOUD_USERNAME,
15
- nc_auth_pass=arena_config.NEXTCLOUD_PASSWORD
16
  )
17
 
18
- SUGGESTIONS_FILE = "model_suggestions.json"
19
- NEXTCLOUD_SUGGESTIONS_PATH = "/gpu_poor_model_suggestions.json"
20
-
21
  def validate_model_url(url: str) -> bool:
22
- """Validate if the provided URL matches the expected HuggingFace format."""
23
- pattern = r'^hf\.co/[\w-]+/[\w\.-]+(?:-GGUF)?:Q[0-9]+(?:_[A-Z0-9_]+)?$'
24
- return bool(re.match(pattern, url))
 
 
 
 
 
 
 
25
 
26
  def load_suggestions() -> Dict:
27
- """Load suggestions from Nextcloud, fallback to local file, or initialize if neither exists."""
28
- suggestions = None
29
-
30
- # First try to load from Nextcloud
31
  try:
32
- remote_data = nc.files.download(NEXTCLOUD_SUGGESTIONS_PATH)
 
33
  if remote_data:
34
  suggestions = json.loads(remote_data.decode('utf-8'))
35
- # Update local file with Nextcloud data
36
- with open(SUGGESTIONS_FILE, 'w') as f:
37
  json.dump(suggestions, f, indent=2)
38
  return suggestions
39
  except Exception as e:
40
  print(f"Could not load from Nextcloud: {e}")
 
 
 
 
 
 
 
 
41
 
42
- # If Nextcloud fails, try local file
43
- if os.path.exists(SUGGESTIONS_FILE):
44
- try:
45
- with open(SUGGESTIONS_FILE, 'r') as f:
46
- suggestions = json.load(f)
47
- return suggestions
48
- except Exception as e:
49
- print(f"Could not load from local file: {e}")
50
-
51
- # If both fail, initialize new suggestions
52
- suggestions = {
53
  "suggestions": {},
54
- "last_updated": datetime.now().isoformat()
 
55
  }
56
-
57
- # Save the new suggestions to both local and Nextcloud
58
- save_suggestions(suggestions)
59
-
60
- return suggestions
61
 
62
- def save_suggestions(suggestions: Dict) -> None:
63
- """Save suggestions to both local file and Nextcloud."""
64
- with open(SUGGESTIONS_FILE, 'w') as f:
65
- json.dump(suggestions, f, indent=2)
66
-
67
- # Upload to Nextcloud
68
  try:
69
- nc.files.upload(
70
- NEXTCLOUD_SUGGESTIONS_PATH,
71
- json.dumps(suggestions, indent=2).encode('utf-8')
72
- )
 
 
 
 
 
 
 
 
 
73
  except Exception as e:
74
- print(f"Error uploading to Nextcloud: {e}")
 
75
 
76
  def add_suggestion(model_url: str) -> str:
77
- """Add a new model suggestion or update existing one."""
 
78
  if not validate_model_url(model_url):
79
- return "❌ Invalid model URL format. Please use the format: hf.co/username/model-name-GGUF:Q4_K_M"
 
 
 
 
 
 
80
 
81
  suggestions = load_suggestions()
 
82
 
83
  if model_url in suggestions["suggestions"]:
84
- suggestions["suggestions"][model_url]["count"] += 1
85
- suggestions["suggestions"][model_url]["last_suggested"] = datetime.now().isoformat()
86
- message = f"✨ Model suggestion updated! This model has been suggested {suggestions['suggestions'][model_url]['count']} times."
 
 
 
87
  else:
88
  suggestions["suggestions"][model_url] = {
89
  "count": 1,
90
- "first_suggested": datetime.now().isoformat(),
91
- "last_suggested": datetime.now().isoformat()
92
  }
93
  message = "βœ… New model suggestion recorded successfully!"
94
 
95
- suggestions["last_updated"] = datetime.now().isoformat()
96
- save_suggestions(suggestions)
97
-
98
- return message
99
 
100
  def get_suggestions_html() -> str:
101
- """Generate HTML table of model suggestions."""
102
  suggestions = load_suggestions()
103
 
104
- # Sort suggestions by count (descending)
105
  sorted_suggestions = sorted(
106
  suggestions["suggestions"].items(),
107
- key=lambda x: x[1]["count"],
108
  reverse=True
109
  )
110
 
@@ -114,10 +125,11 @@ def get_suggestions_html() -> str:
114
  width: 100%;
115
  border-collapse: collapse;
116
  font-family: Arial, sans-serif;
 
117
  }
118
  .suggestions-table th, .suggestions-table td {
119
  border: 1px solid #ddd;
120
- padding: 8px;
121
  text-align: left;
122
  }
123
  .suggestions-table th {
@@ -135,11 +147,15 @@ def get_suggestions_html() -> str:
135
  border-radius: 12px;
136
  font-size: 0.9em;
137
  }
138
- .description-column {
139
  font-size: 0.9em;
140
  color: #888;
 
141
  }
142
  </style>
 
 
 
143
  <table class='suggestions-table'>
144
  <tr>
145
  <th class='rank-column'>Rank</th>
@@ -148,7 +164,10 @@ def get_suggestions_html() -> str:
148
  <th>First Suggested</th>
149
  <th>Last Suggested</th>
150
  </tr>
151
- """
 
 
 
152
 
153
  for index, (model_url, data) in enumerate(sorted_suggestions, start=1):
154
  rank_display = {1: "πŸ₯‡", 2: "πŸ₯ˆ", 3: "πŸ₯‰"}.get(index, f"{index}")
 
1
  from nc_py_api import Nextcloud
2
  import json
3
+ from typing import Dict
 
 
4
  from datetime import datetime
5
+ import os
 
6
  import re
7
+ import config
8
 
9
  # Initialize Nextcloud client
10
  nc = Nextcloud(
11
+ nextcloud_url=config.NEXTCLOUD_URL,
12
+ nc_auth_user=config.NEXTCLOUD_USERNAME,
13
+ nc_auth_pass=config.NEXTCLOUD_PASSWORD
14
  )
15
 
 
 
 
16
  def validate_model_url(url: str) -> bool:
17
+ """
18
+ Validate if the provided URL matches the expected format.
19
+ Accepts both direct Ollama models and HuggingFace GGUF models.
20
+ """
21
+ # Pattern for HuggingFace GGUF models
22
+ hf_pattern = r'^hf\.co/[\w-]+/[\w\.-]+(?:-GGUF)?:Q[0-9]+(?:_[A-Z0-9_]+)?$'
23
+ # Pattern for direct Ollama models
24
+ ollama_pattern = r'^[\w\.-]+(?::\d+(?:\.\d+)?[b])?(?:-[\w-]+)?:Q[0-9]+(?:_[A-Z0-9_]+)?$'
25
+
26
+ return bool(re.match(hf_pattern, url) or re.match(ollama_pattern, url))
27
 
28
  def load_suggestions() -> Dict:
29
+ """Load suggestions from Nextcloud with local file fallback."""
 
 
 
30
  try:
31
+ # Try to load from Nextcloud
32
+ remote_data = nc.files.download(config.NEXTCLOUD_SUGGESTIONS_PATH)
33
  if remote_data:
34
  suggestions = json.loads(remote_data.decode('utf-8'))
35
+ # Update local cache
36
+ with open('model_suggestions.json', 'w') as f:
37
  json.dump(suggestions, f, indent=2)
38
  return suggestions
39
  except Exception as e:
40
  print(f"Could not load from Nextcloud: {e}")
41
+
42
+ # Try local cache
43
+ if os.path.exists('model_suggestions.json'):
44
+ try:
45
+ with open('model_suggestions.json', 'r') as f:
46
+ return json.load(f)
47
+ except Exception as e:
48
+ print(f"Could not load from local cache: {e}")
49
 
50
+ # Initialize new suggestions if both attempts fail
51
+ return {
 
 
 
 
 
 
 
 
 
52
  "suggestions": {},
53
+ "last_updated": datetime.now().isoformat(),
54
+ "total_suggestions": 0
55
  }
 
 
 
 
 
56
 
57
+ def save_suggestions(suggestions: Dict) -> bool:
58
+ """Save suggestions to both Nextcloud and local cache."""
 
 
 
 
59
  try:
60
+ # Update metadata
61
+ suggestions["last_updated"] = datetime.now().isoformat()
62
+ suggestions["total_suggestions"] = sum(s["count"] for s in suggestions["suggestions"].values())
63
+
64
+ # Save to Nextcloud
65
+ json_data = json.dumps(suggestions, indent=2)
66
+ nc.files.upload(config.NEXTCLOUD_SUGGESTIONS_PATH, json_data.encode('utf-8'))
67
+
68
+ # Update local cache
69
+ with open('model_suggestions.json', 'w') as f:
70
+ json.dump(suggestions, f, indent=2)
71
+
72
+ return True
73
  except Exception as e:
74
+ print(f"Error saving suggestions: {e}")
75
+ return False
76
 
77
  def add_suggestion(model_url: str) -> str:
78
+ """Add or update a model suggestion with validation."""
79
+ # Validate model URL format
80
  if not validate_model_url(model_url):
81
+ return ("❌ Invalid model URL format. Please use either:\n"
82
+ "- Ollama format: model-name:Q4_K_M\n"
83
+ "- HuggingFace format: hf.co/username/model-name-GGUF:Q4_K_M")
84
+
85
+ # Check if model is already approved
86
+ if model_url in dict(config.get_approved_models()):
87
+ return "ℹ️ This model is already in the arena!"
88
 
89
  suggestions = load_suggestions()
90
+ current_time = datetime.now().isoformat()
91
 
92
  if model_url in suggestions["suggestions"]:
93
+ suggestions["suggestions"][model_url].update({
94
+ "count": suggestions["suggestions"][model_url]["count"] + 1,
95
+ "last_suggested": current_time
96
+ })
97
+ message = (f"✨ Model suggestion updated! "
98
+ f"This model has been suggested {suggestions['suggestions'][model_url]['count']} times.")
99
  else:
100
  suggestions["suggestions"][model_url] = {
101
  "count": 1,
102
+ "first_suggested": current_time,
103
+ "last_suggested": current_time
104
  }
105
  message = "βœ… New model suggestion recorded successfully!"
106
 
107
+ if save_suggestions(suggestions):
108
+ return message
109
+ return "❌ Error saving suggestion. Please try again later."
 
110
 
111
  def get_suggestions_html() -> str:
112
+ """Generate HTML table of model suggestions with improved styling."""
113
  suggestions = load_suggestions()
114
 
115
+ # Sort suggestions by count (descending) and last suggested date
116
  sorted_suggestions = sorted(
117
  suggestions["suggestions"].items(),
118
+ key=lambda x: (x[1]["count"], x[1]["last_suggested"]),
119
  reverse=True
120
  )
121
 
 
125
  width: 100%;
126
  border-collapse: collapse;
127
  font-family: Arial, sans-serif;
128
+ margin-top: 20px;
129
  }
130
  .suggestions-table th, .suggestions-table td {
131
  border: 1px solid #ddd;
132
+ padding: 12px;
133
  text-align: left;
134
  }
135
  .suggestions-table th {
 
147
  border-radius: 12px;
148
  font-size: 0.9em;
149
  }
150
+ .stats-header {
151
  font-size: 0.9em;
152
  color: #888;
153
+ margin-bottom: 10px;
154
  }
155
  </style>
156
+ <div class="stats-header">
157
+ Total Suggestions: {total_suggestions} | Last Updated: {last_updated}
158
+ </div>
159
  <table class='suggestions-table'>
160
  <tr>
161
  <th class='rank-column'>Rank</th>
 
164
  <th>First Suggested</th>
165
  <th>Last Suggested</th>
166
  </tr>
167
+ """.format(
168
+ total_suggestions=suggestions.get("total_suggestions", 0),
169
+ last_updated=suggestions.get("last_updated", "Never").split("T")[0]
170
+ )
171
 
172
  for index, (model_url, data) in enumerate(sorted_suggestions, start=1):
173
  rank_display = {1: "πŸ₯‡", 2: "πŸ₯ˆ", 3: "πŸ₯‰"}.get(index, f"{index}")