LiamKhoaLe commited on
Commit
afedd43
·
1 Parent(s): 9da7c31

Upd code viewer

Browse files
Files changed (2) hide show
  1. static/styles.css +122 -17
  2. utils/api/router.py +27 -13
static/styles.css CHANGED
@@ -1077,67 +1077,172 @@
1077
  /* Code blocks with copy button */
1078
  .code-block-wrapper {
1079
  position: relative;
1080
- margin: 16px 0;
1081
- border-radius: var(--radius);
1082
  overflow: hidden;
1083
  border: 1px solid var(--border);
 
 
1084
  }
1085
 
1086
  .code-block-header {
1087
  display: flex;
1088
  justify-content: space-between;
1089
  align-items: center;
1090
- padding: 8px 12px;
1091
- background: var(--bg-secondary);
1092
  border-bottom: 1px solid var(--border);
1093
  font-size: 12px;
1094
  color: var(--muted);
 
1095
  }
1096
 
1097
  .code-block-language {
1098
- font-weight: 600;
1099
  text-transform: uppercase;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1100
  }
1101
 
1102
  .copy-code-btn {
1103
  display: flex;
1104
  align-items: center;
1105
- gap: 4px;
1106
- padding: 4px 8px;
1107
  background: var(--card);
1108
  border: 1px solid var(--border);
1109
- border-radius: var(--radius-sm);
1110
  color: var(--text-secondary);
1111
  font-size: 11px;
 
1112
  cursor: pointer;
1113
- transition: all 0.2s ease;
 
 
 
 
 
 
 
 
 
 
 
 
 
1114
  }
1115
 
1116
  .copy-code-btn:hover {
1117
  background: var(--card-hover);
1118
- border-color: var(--border-light);
1119
  color: var(--text);
 
 
 
 
 
 
1120
  }
1121
 
1122
  .copy-code-btn.copied {
1123
  background: var(--success);
1124
  color: white;
1125
  border-color: var(--success);
 
1126
  }
1127
 
1128
  .copy-code-btn svg {
1129
- width: 12px;
1130
- height: 12px;
 
 
 
 
 
1131
  }
1132
 
1133
  .code-block-content {
1134
- background: var(--code-bg, #1e1e1e);
1135
- color: var(--code-text, #d4d4d4);
1136
- padding: 16px;
1137
  overflow-x: auto;
1138
- font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
1139
  font-size: 14px;
1140
- line-height: 1.5;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1141
  }
1142
 
1143
  /* Download PDF button */
 
1077
  /* Code blocks with copy button */
1078
  .code-block-wrapper {
1079
  position: relative;
1080
+ margin: 20px 0;
1081
+ border-radius: 12px;
1082
  overflow: hidden;
1083
  border: 1px solid var(--border);
1084
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
1085
+ background: var(--card);
1086
  }
1087
 
1088
  .code-block-header {
1089
  display: flex;
1090
  justify-content: space-between;
1091
  align-items: center;
1092
+ padding: 12px 16px;
1093
+ background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--card) 100%);
1094
  border-bottom: 1px solid var(--border);
1095
  font-size: 12px;
1096
  color: var(--muted);
1097
+ font-weight: 500;
1098
  }
1099
 
1100
  .code-block-language {
1101
+ font-weight: 700;
1102
  text-transform: uppercase;
1103
+ letter-spacing: 0.5px;
1104
+ color: var(--accent);
1105
+ display: flex;
1106
+ align-items: center;
1107
+ gap: 6px;
1108
+ }
1109
+
1110
+ .code-block-language::before {
1111
+ content: '';
1112
+ width: 8px;
1113
+ height: 8px;
1114
+ border-radius: 50%;
1115
+ background: var(--accent);
1116
+ display: inline-block;
1117
  }
1118
 
1119
  .copy-code-btn {
1120
  display: flex;
1121
  align-items: center;
1122
+ gap: 6px;
1123
+ padding: 6px 12px;
1124
  background: var(--card);
1125
  border: 1px solid var(--border);
1126
+ border-radius: 8px;
1127
  color: var(--text-secondary);
1128
  font-size: 11px;
1129
+ font-weight: 500;
1130
  cursor: pointer;
1131
+ transition: all 0.3s ease;
1132
+ position: relative;
1133
+ overflow: hidden;
1134
+ }
1135
+
1136
+ .copy-code-btn::before {
1137
+ content: '';
1138
+ position: absolute;
1139
+ top: 0;
1140
+ left: -100%;
1141
+ width: 100%;
1142
+ height: 100%;
1143
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
1144
+ transition: left 0.5s ease;
1145
  }
1146
 
1147
  .copy-code-btn:hover {
1148
  background: var(--card-hover);
1149
+ border-color: var(--accent);
1150
  color: var(--text);
1151
+ transform: translateY(-1px);
1152
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
1153
+ }
1154
+
1155
+ .copy-code-btn:hover::before {
1156
+ left: 100%;
1157
  }
1158
 
1159
  .copy-code-btn.copied {
1160
  background: var(--success);
1161
  color: white;
1162
  border-color: var(--success);
1163
+ transform: scale(1.05);
1164
  }
1165
 
1166
  .copy-code-btn svg {
1167
+ width: 14px;
1168
+ height: 14px;
1169
+ transition: transform 0.2s ease;
1170
+ }
1171
+
1172
+ .copy-code-btn:hover svg {
1173
+ transform: scale(1.1);
1174
  }
1175
 
1176
  .code-block-content {
1177
+ background: linear-gradient(135deg, #1a1a1a 0%, #1e1e1e 100%);
1178
+ color: #e6e6e6;
1179
+ padding: 20px;
1180
  overflow-x: auto;
1181
+ font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
1182
  font-size: 14px;
1183
+ line-height: 1.6;
1184
+ position: relative;
1185
+ }
1186
+
1187
+ .code-block-content::before {
1188
+ content: '';
1189
+ position: absolute;
1190
+ top: 0;
1191
+ left: 0;
1192
+ right: 0;
1193
+ height: 1px;
1194
+ background: linear-gradient(90deg, transparent, var(--accent), transparent);
1195
+ }
1196
+
1197
+ /* Enhanced syntax highlighting for code blocks */
1198
+ .code-block-content .hljs {
1199
+ background: transparent !important;
1200
+ color: inherit !important;
1201
+ }
1202
+
1203
+ .code-block-content .hljs-keyword {
1204
+ color: #ff7b72;
1205
+ font-weight: 600;
1206
+ }
1207
+
1208
+ .code-block-content .hljs-string {
1209
+ color: #a5d6ff;
1210
+ }
1211
+
1212
+ .code-block-content .hljs-comment {
1213
+ color: #8b949e;
1214
+ font-style: italic;
1215
+ }
1216
+
1217
+ .code-block-content .hljs-number {
1218
+ color: #79c0ff;
1219
+ }
1220
+
1221
+ .code-block-content .hljs-function {
1222
+ color: #d2a8ff;
1223
+ }
1224
+
1225
+ .code-block-content .hljs-variable {
1226
+ color: #ffa657;
1227
+ }
1228
+
1229
+ /* Scrollbar styling for code blocks */
1230
+ .code-block-content::-webkit-scrollbar {
1231
+ height: 8px;
1232
+ }
1233
+
1234
+ .code-block-content::-webkit-scrollbar-track {
1235
+ background: #2d2d2d;
1236
+ border-radius: 4px;
1237
+ }
1238
+
1239
+ .code-block-content::-webkit-scrollbar-thumb {
1240
+ background: var(--accent);
1241
+ border-radius: 4px;
1242
+ }
1243
+
1244
+ .code-block-content::-webkit-scrollbar-thumb:hover {
1245
+ background: var(--accent-hover);
1246
  }
1247
 
1248
  /* Download PDF button */
utils/api/router.py CHANGED
@@ -94,25 +94,39 @@ async def generate_answer_with_model(selection: Dict[str, Any], system_prompt: s
94
  model = selection["model"]
95
 
96
  if provider == "gemini":
97
- key = gemini_rotator.get_key() or ""
98
- url = f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent?key={key}"
99
- payload = {
100
- "contents": [
101
- {"role": "user", "parts": [{"text": f"{system_prompt}\n\n{user_prompt}"}]}
102
- ],
103
- "generationConfig": {"temperature": 0.2}
104
- }
105
- headers = {"Content-Type": "application/json"}
106
- data = await robust_post_json(url, headers, payload, gemini_rotator)
107
  try:
 
 
 
 
 
 
 
 
 
 
 
108
  content = data["candidates"][0]["content"]["parts"][0]["text"]
109
  if not content or content.strip() == "":
110
  logger.warning(f"Empty content from Gemini model: {data}")
111
- return "I received an empty response from the model."
112
  return content
113
  except Exception as e:
114
- logger.warning(f"Unexpected Gemini response: {data}, error: {e}")
115
- return "I couldn't parse the model response."
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
  elif provider == "nvidia":
118
  # Many NVIDIA endpoints are OpenAI-compatible. Adjust if using a different path.
 
94
  model = selection["model"]
95
 
96
  if provider == "gemini":
97
+ # Try Gemini first
 
 
 
 
 
 
 
 
 
98
  try:
99
+ key = gemini_rotator.get_key() or ""
100
+ url = f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent?key={key}"
101
+ payload = {
102
+ "contents": [
103
+ {"role": "user", "parts": [{"text": f"{system_prompt}\n\n{user_prompt}"}]}
104
+ ],
105
+ "generationConfig": {"temperature": 0.2}
106
+ }
107
+ headers = {"Content-Type": "application/json"}
108
+ data = await robust_post_json(url, headers, payload, gemini_rotator)
109
+
110
  content = data["candidates"][0]["content"]["parts"][0]["text"]
111
  if not content or content.strip() == "":
112
  logger.warning(f"Empty content from Gemini model: {data}")
113
+ raise Exception("Empty content from Gemini")
114
  return content
115
  except Exception as e:
116
+ logger.warning(f"Gemini model {model} failed: {e}. Attempting fallback...")
117
+
118
+ # Fallback logic: GEMINI_PRO/MED → NVIDIA_LARGE, GEMINI_SMALL → NVIDIA_SMALL
119
+ if model in [GEMINI_PRO, GEMINI_MED]:
120
+ logger.info(f"Falling back from {model} to NVIDIA_LARGE")
121
+ fallback_selection = {"provider": "nvidia_large", "model": NVIDIA_LARGE}
122
+ return await generate_answer_with_model(fallback_selection, system_prompt, user_prompt, gemini_rotator, nvidia_rotator)
123
+ elif model == GEMINI_SMALL:
124
+ logger.info(f"Falling back from {model} to NVIDIA_SMALL")
125
+ fallback_selection = {"provider": "nvidia", "model": NVIDIA_SMALL}
126
+ return await generate_answer_with_model(fallback_selection, system_prompt, user_prompt, gemini_rotator, nvidia_rotator)
127
+ else:
128
+ logger.error(f"No fallback defined for Gemini model: {model}")
129
+ return "I couldn't parse the model response."
130
 
131
  elif provider == "nvidia":
132
  # Many NVIDIA endpoints are OpenAI-compatible. Adjust if using a different path.