enotkrutoy commited on
Commit
6510699
·
verified ·
1 Parent(s): 860cb43

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +258 -42
templates/index.html CHANGED
@@ -1,49 +1,265 @@
1
  <!DOCTYPE html>
2
  <html lang="ru">
3
  <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Чат с моделью Hugging Face</title>
7
- <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  </head>
9
  <body>
10
- <div class="container mt-5">
11
- <h1>Чат с моделью Hugging Face</h1>
12
- <div id="chat" class="mb-3">
13
- <!-- Сообщения будут добавляться сюда -->
14
- </div>
15
- <div class="input-group mb-3">
16
- <input type="text" id="user-input" class="form-control" placeholder="Напишите сообщение...">
17
- <button class="btn btn-primary" onclick="sendMessage()">Отправить</button>
18
- </div>
19
- </div>
20
-
21
- <script>
22
- async function sendMessage() {
23
- const userInput = document.getElementById('user-input').value;
24
- const chatDiv = document.getElementById('chat');
25
-
26
- // Добавляем сообщение пользователя
27
- chatDiv.innerHTML += `<div class="alert alert-primary" role="alert">${userInput}</div>`;
28
-
29
- // Отправляем сообщение на сервер
30
- const response = await fetch('/chat', {
31
- method: 'POST',
32
- headers: {
33
- 'Content-Type': 'application/json'
34
- },
35
- body: JSON.stringify({ message: userInput })
36
- });
37
-
38
- const data = await response.json();
39
- const reply = data.reply;
40
-
41
- // Добавляем ответ модели
42
- chatDiv.innerHTML += `<div class="alert alert-secondary" role="alert">${reply}</div>`;
43
-
44
- // Очищаем поле ввода
45
- document.getElementById('user-input').value = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  }
47
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  </body>
49
- </html>
 
1
  <!DOCTYPE html>
2
  <html lang="ru">
3
  <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Улучшенный Хакерский Веб Интерфейс</title>
7
+ <style>
8
+ body {
9
+ background-color: #1e1e1e;
10
+ color: #ffffff;
11
+ font-family: 'Courier New', Courier, monospace;
12
+ margin: 0;
13
+ padding: 20px;
14
+ }
15
+ h1 {
16
+ color: #ff4d4d;
17
+ }
18
+ #input-container {
19
+ margin-bottom: 20px;
20
+ }
21
+ input, textarea {
22
+ width: 100%;
23
+ padding: 10px;
24
+ margin-bottom: 10px;
25
+ background-color: #333;
26
+ color: #fff;
27
+ border: none;
28
+ border-radius: 5px;
29
+ box-sizing: border-box;
30
+ }
31
+ button {
32
+ padding: 10px 20px;
33
+ background-color: #ff4d4d;
34
+ color: #fff;
35
+ border: none;
36
+ border-radius: 5px;
37
+ cursor: pointer;
38
+ }
39
+ button:hover {
40
+ background-color: #cc3333;
41
+ }
42
+ #loading-indicator {
43
+ display: none;
44
+ color: #ffcc00;
45
+ font-weight: bold;
46
+ margin-bottom: 10px;
47
+ }
48
+ #response-container, #final-answer {
49
+ margin-top: 20px;
50
+ white-space: pre-wrap;
51
+ }
52
+ .step {
53
+ border-bottom: 1px solid #555;
54
+ padding: 10px 0;
55
+ }
56
+ .step:last-child {
57
+ border-bottom: none;
58
+ }
59
+ .step-title {
60
+ font-weight: bold;
61
+ color: #ffcc00;
62
+ }
63
+ .error {
64
+ color: #ff4d4d;
65
+ font-weight: bold;
66
+ margin-top: 20px;
67
+ }
68
+ </style>
69
  </head>
70
  <body>
71
+ <h1>Улучшенный Хакерский Веб Интерфейс</h1>
72
+ <div id="input-container">
73
+ <input type="text" id="api-endpoint" placeholder="Введите URL API (например, https://your-api.com/chat)" value="https://api.example.com/chat/completions" />
74
+ <input type="text" id="api-key" placeholder="Введите ключ API (если требуется)" />
75
+ <textarea id="prompt" placeholder="Введите запрос..." rows="4"></textarea>
76
+ <textarea id="context" placeholder="Введите контекст (необязательно)..." rows="2"></textarea>
77
+ <button id="start-btn">Запустить генерацию</button>
78
+ <div id="loading-indicator">Загрузка...</div>
79
+ </div>
80
+ <div id="response-container"></div>
81
+ <div id="final-answer"></div>
82
+
83
+ <script>
84
+ // Конфигурация
85
+ const CONFIG = {
86
+ DEFAULT_MAX_TOKENS: 6000,
87
+ FINAL_MAX_TOKENS: 6000,
88
+ RETRY_DELAY: 1000, // в мс
89
+ MAX_RETRIES: 3,
90
+ MODELS: {
91
+ intermediate: "qwen-2.5-32b",
92
+ final: "deepseek-r1-distill-llama-70b"
93
+ },
94
+ TEMPERATURE: 0.5
95
+ };
96
+
97
+ // Асинхронная функция задержки
98
+ const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
99
+
100
+ // Функция валидации ввода
101
+ function validateInputs() {
102
+ const apiEndpoint = document.getElementById("api-endpoint").value.trim();
103
+ const prompt = document.getElementById("prompt").value.trim();
104
+ if (!apiEndpoint) {
105
+ throw new Error("Введите URL API!");
106
+ }
107
+ if (!prompt) {
108
+ throw new Error("Введите запрос!");
109
+ }
110
+ return { apiEndpoint, prompt };
111
+ }
112
+
113
+ // Парсинг JSON-ответа с валидацией ключей
114
+ function parseJsonResponse(rawResponse) {
115
+ try {
116
+ const parsed = JSON.parse(rawResponse);
117
+ const requiredKeys = ["title", "content", "next_action"];
118
+ for (const key of requiredKeys) {
119
+ if (!(key in parsed)) {
120
+ throw new Error(`Отсутствует ключ "${key}"`);
121
+ }
122
+ }
123
+ return parsed;
124
+ } catch (e) {
125
+ throw new Error(`Invalid JSON: ${e.message}, content: ${rawResponse}`);
126
+ }
127
+ }
128
+
129
+ // Функция вызова API с повторными попытками и улучшенной обработкой ошибок
130
+ async function makeApiCall(messages, maxTokens, isFinalAnswer = false) {
131
+ const apiEndpoint = document.getElementById("api-endpoint").value.trim() || "https://api.example.com/chat/completions";
132
+ const model = isFinalAnswer ? CONFIG.MODELS.final : CONFIG.MODELS.intermediate;
133
+ const responseType = isFinalAnswer ? "text" : "json_object";
134
+ let attempt = 0;
135
+ let lastError = null;
136
+
137
+ while (attempt < CONFIG.MAX_RETRIES) {
138
+ try {
139
+ const response = await fetch(apiEndpoint, {
140
+ method: "POST",
141
+ headers: {
142
+ "Content-Type": "application/json",
143
+ "Authorization": document.getElementById("api-key").value.trim() || ""
144
+ },
145
+ body: JSON.stringify({
146
+ model: model,
147
+ messages: messages,
148
+ max_tokens: maxTokens,
149
+ temperature: CONFIG.TEMPERATURE,
150
+ response_format: { type: responseType }
151
+ })
152
+ });
153
+
154
+ if (!response.ok) {
155
+ const errorText = await response.text();
156
+ throw new Error(`Ошибка API: ${response.status} ${response.statusText}. Подробности: ${errorText}`);
157
+ }
158
+ const data = await response.json();
159
+ const messageContent = data.choices[0].message.content;
160
+
161
+ if (isFinalAnswer) {
162
+ return messageContent;
163
+ } else {
164
+ return parseJsonResponse(messageContent);
165
+ }
166
+ } catch (error) {
167
+ lastError = error;
168
+ console.error(`Попытка ${attempt + 1} не удалась:`, error);
169
+ attempt++;
170
+ if (attempt < CONFIG.MAX_RETRIES) {
171
+ await delay(CONFIG.RETRY_DELAY);
172
+ }
173
  }
174
+ }
175
+ if (isFinalAnswer) {
176
+ return `Error: Не удалось получить финальный ответ за ${CONFIG.MAX_RETRIES} попыток. Ошибка: ${lastError.message}`;
177
+ } else {
178
+ return {
179
+ title: "Error",
180
+ content: `Не удалось сгенерировать шаг за ${CONFIG.MAX_RETRIES} попыток. Ошибка: ${lastError.message}`,
181
+ next_action: "final_answer"
182
+ };
183
+ }
184
+ }
185
+
186
+ // Генерация цепочки рассуждений с отображением шагов
187
+ async function generateResponse(prompt, context) {
188
+ const responseContainer = document.getElementById("response-container");
189
+ const finalAnswerContainer = document.getElementById("final-answer");
190
+ responseContainer.innerHTML = "";
191
+ finalAnswerContainer.innerHTML = "";
192
+
193
+ const systemMessage = `Вы – интеллектуальный помощник, эксперт по разработке на Python, который анализирует и объясняет свои рассуждения шаг за шагом на русском языке.
194
+ Формат ответа: строгий JSON без дополнительного текста.
195
+ Обязательные ключи:
196
+ "title": краткое название шага,
197
+ "content": описание действий,
198
+ "next_action": "continue" или "final_answer".
199
+ Пример:
200
+ {"title": "Анализ задачи", "content": "Выделение ключевых элементов...", "next_action": "continue"}
201
+ Дополнительные требования: используйте русский язык и избегайте Unicode-кодировок (например, пишите "Привет", а не "\\u041f\\u0440\\u0438...")`;
202
+
203
+ const userContent = context ? `Я хотел бы узнать про autogen. Контекст: ${context}. ${prompt}` : prompt;
204
+ const messages = [
205
+ { role: "system", content: systemMessage },
206
+ { role: "user", content: userContent },
207
+ { role: "assistant", content: "Спасибо! Начинаю анализ..." }
208
+ ];
209
+
210
+ let stepCount = 1;
211
+ let totalThinkingTime = 0;
212
+
213
+ while (stepCount <= 25) {
214
+ document.getElementById("loading-indicator").style.display = "block";
215
+ const stepStart = performance.now();
216
+ const stepData = await makeApiCall(messages, CONFIG.DEFAULT_MAX_TOKENS);
217
+ const elapsed = (performance.now() - stepStart) / 1000;
218
+ totalThinkingTime += elapsed;
219
+ document.getElementById("loading-indicator").style.display = "none";
220
+
221
+ const stepDiv = document.createElement("div");
222
+ stepDiv.className = "step";
223
+ stepDiv.innerHTML = `<div class="step-title">Step ${stepCount}: ${stepData.title}</div>
224
+ <div>${stepData.content}</div>
225
+ <div>(Время: ${elapsed.toFixed(2)} сек)</div>`;
226
+ responseContainer.appendChild(stepDiv);
227
+
228
+ messages.push({ role: "assistant", content: JSON.stringify(stepData, null, 2) });
229
+ if (stepData.next_action === "final_answer") break;
230
+ stepCount++;
231
+ }
232
+
233
+ messages.push({
234
+ role: "user",
235
+ content: "Предоставьте окончательный ответ без формата JSON, сохранив исходное форматирование из подсказки."
236
+ });
237
+ document.getElementById("loading-indicator").style.display = "block";
238
+ const finalStart = performance.now();
239
+ const finalAnswer = await makeApiCall(messages, CONFIG.FINAL_MAX_TOKENS, true);
240
+ const finalElapsed = (performance.now() - finalStart) / 1000;
241
+ totalThinkingTime += finalElapsed;
242
+ document.getElementById("loading-indicator").style.display = "none";
243
+
244
+ const finalDiv = document.createElement("div");
245
+ finalDiv.innerHTML = `<div class="step-title">Final Answer</div>
246
+ <div>${finalAnswer}</div>
247
+ <div>(Время: ${finalElapsed.toFixed(2)} сек)</div>
248
+ <div>Общее время обработки: ${totalThinkingTime.toFixed(2)} сек</div>`;
249
+ finalAnswerContainer.appendChild(finalDiv);
250
+ }
251
+
252
+ // Обработчик события запуска
253
+ document.getElementById("start-btn").addEventListener("click", () => {
254
+ try {
255
+ const { apiEndpoint, prompt } = validateInputs();
256
+ generateResponse(prompt, document.getElementById("context").value.trim()).catch(error => {
257
+ document.getElementById("response-container").innerHTML = `<div class="error">Ошибка: ${error.message}</div>`;
258
+ });
259
+ } catch (e) {
260
+ alert(e.message);
261
+ }
262
+ });
263
+ </script>
264
  </body>
265
+ </html>