Spaces:
Runtime error
Runtime error
<html lang="ru"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>Улучшенный Хакерский Веб Интерфейс</title> | |
<style> | |
body { | |
background-color: #1e1e1e; | |
color: #ffffff; | |
font-family: 'Courier New', Courier, monospace; | |
margin: 0; | |
padding: 20px; | |
} | |
h1 { | |
color: #ff4d4d; | |
} | |
#input-container { | |
margin-bottom: 20px; | |
} | |
input, textarea { | |
width: 100%; | |
padding: 10px; | |
margin-bottom: 10px; | |
background-color: #333; | |
color: #fff; | |
border: none; | |
border-radius: 5px; | |
box-sizing: border-box; | |
} | |
button { | |
padding: 10px 20px; | |
background-color: #ff4d4d; | |
color: #fff; | |
border: none; | |
border-radius: 5px; | |
cursor: pointer; | |
} | |
button:hover { | |
background-color: #cc3333; | |
} | |
#loading-indicator { | |
display: none; | |
color: #ffcc00; | |
font-weight: bold; | |
margin-bottom: 10px; | |
} | |
#response-container, #final-answer { | |
margin-top: 20px; | |
white-space: pre-wrap; | |
} | |
.step { | |
border-bottom: 1px solid #555; | |
padding: 10px 0; | |
} | |
.step:last-child { | |
border-bottom: none; | |
} | |
.step-title { | |
font-weight: bold; | |
color: #ffcc00; | |
} | |
.error { | |
color: #ff4d4d; | |
font-weight: bold; | |
margin-top: 20px; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Улучшенный Хакерский Веб Интерфейс</h1> | |
<div id="input-container"> | |
<input type="text" id="api-endpoint" placeholder="Введите URL API (например, https://your-api.com/chat)" value="https://api.example.com/chat/completions" /> | |
<input type="text" id="api-key" placeholder="Введите ключ API (если требуется)" /> | |
<textarea id="prompt" placeholder="Введите запрос..." rows="4"></textarea> | |
<textarea id="context" placeholder="Введите контекст (необязательно)..." rows="2"></textarea> | |
<button id="start-btn">Запустить генерацию</button> | |
<div id="loading-indicator">Загрузка...</div> | |
</div> | |
<div id="response-container"></div> | |
<div id="final-answer"></div> | |
<script> | |
// Конфигурация | |
const CONFIG = { | |
DEFAULT_MAX_TOKENS: 6000, | |
FINAL_MAX_TOKENS: 6000, | |
RETRY_DELAY: 1000, // в мс | |
MAX_RETRIES: 3, | |
MODELS: { | |
intermediate: "qwen-2.5-32b", | |
final: "deepseek-r1-distill-llama-70b" | |
}, | |
TEMPERATURE: 0.5 | |
}; | |
// Асинхронная функция задержки | |
const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); | |
// Функция валидации ввода | |
function validateInputs() { | |
const apiEndpoint = document.getElementById("api-endpoint").value.trim(); | |
const prompt = document.getElementById("prompt").value.trim(); | |
if (!apiEndpoint) { | |
throw new Error("Введите URL API!"); | |
} | |
if (!prompt) { | |
throw new Error("Введите запрос!"); | |
} | |
return { apiEndpoint, prompt }; | |
} | |
// Парсинг JSON-ответа с валидацией ключей | |
function parseJsonResponse(rawResponse) { | |
try { | |
const parsed = JSON.parse(rawResponse); | |
const requiredKeys = ["title", "content", "next_action"]; | |
for (const key of requiredKeys) { | |
if (!(key in parsed)) { | |
throw new Error(`Отсутствует ключ "${key}"`); | |
} | |
} | |
return parsed; | |
} catch (e) { | |
throw new Error(`Invalid JSON: ${e.message}, content: ${rawResponse}`); | |
} | |
} | |
// Функция вызова API с повторными попытками и улучшенной обработкой ошибок | |
async function makeApiCall(messages, maxTokens, isFinalAnswer = false) { | |
const apiEndpoint = document.getElementById("api-endpoint").value.trim() || "https://api.example.com/chat/completions"; | |
const model = isFinalAnswer ? CONFIG.MODELS.final : CONFIG.MODELS.intermediate; | |
const responseType = isFinalAnswer ? "text" : "json_object"; | |
let attempt = 0; | |
let lastError = null; | |
while (attempt < CONFIG.MAX_RETRIES) { | |
try { | |
const response = await fetch(apiEndpoint, { | |
method: "POST", | |
headers: { | |
"Content-Type": "application/json", | |
"Authorization": document.getElementById("api-key").value.trim() || "" | |
}, | |
body: JSON.stringify({ | |
model: model, | |
messages: messages, | |
max_tokens: maxTokens, | |
temperature: CONFIG.TEMPERATURE, | |
response_format: { type: responseType } | |
}) | |
}); | |
if (!response.ok) { | |
const errorText = await response.text(); | |
throw new Error(`Ошибка API: ${response.status} ${response.statusText}. Подробности: ${errorText}`); | |
} | |
const data = await response.json(); | |
const messageContent = data.choices[0].message.content; | |
if (isFinalAnswer) { | |
return messageContent; | |
} else { | |
return parseJsonResponse(messageContent); | |
} | |
} catch (error) { | |
lastError = error; | |
console.error(`Попытка ${attempt + 1} не удалась:`, error); | |
attempt++; | |
if (attempt < CONFIG.MAX_RETRIES) { | |
await delay(CONFIG.RETRY_DELAY); | |
} | |
} | |
} | |
if (isFinalAnswer) { | |
return `Error: Не удалось получить финальный ответ за ${CONFIG.MAX_RETRIES} попыток. Ошибка: ${lastError.message}`; | |
} else { | |
return { | |
title: "Error", | |
content: `Не удалось сгенерировать шаг за ${CONFIG.MAX_RETRIES} попыток. Ошибка: ${lastError.message}`, | |
next_action: "final_answer" | |
}; | |
} | |
} | |
// Генерация цепочки рассуждений с отображением шагов | |
async function generateResponse(prompt, context) { | |
const responseContainer = document.getElementById("response-container"); | |
const finalAnswerContainer = document.getElementById("final-answer"); | |
responseContainer.innerHTML = ""; | |
finalAnswerContainer.innerHTML = ""; | |
const systemMessage = `Вы – интеллектуальный помощник, эксперт по разработке на Python, который анализирует и объясняет свои рассуждения шаг за шагом на русском языке. | |
Формат ответа: строгий JSON без дополнительного текста. | |
Обязательные ключи: | |
"title": краткое название шага, | |
"content": описание действий, | |
"next_action": "continue" или "final_answer". | |
Пример: | |
{"title": "Анализ задачи", "content": "Выделение ключевых элементов...", "next_action": "continue"} | |
Дополнительные требования: используйте русский язык и избегайте Unicode-кодировок (например, пишите "Привет", а не "\\u041f\\u0440\\u0438...")`; | |
const userContent = context ? `Я хотел бы узнать про autogen. Контекст: ${context}. ${prompt}` : prompt; | |
const messages = [ | |
{ role: "system", content: systemMessage }, | |
{ role: "user", content: userContent }, | |
{ role: "assistant", content: "Спасибо! Начинаю анализ..." } | |
]; | |
let stepCount = 1; | |
let totalThinkingTime = 0; | |
while (stepCount <= 25) { | |
document.getElementById("loading-indicator").style.display = "block"; | |
const stepStart = performance.now(); | |
const stepData = await makeApiCall(messages, CONFIG.DEFAULT_MAX_TOKENS); | |
const elapsed = (performance.now() - stepStart) / 1000; | |
totalThinkingTime += elapsed; | |
document.getElementById("loading-indicator").style.display = "none"; | |
const stepDiv = document.createElement("div"); | |
stepDiv.className = "step"; | |
stepDiv.innerHTML = `<div class="step-title">Step ${stepCount}: ${stepData.title}</div> | |
<div>${stepData.content}</div> | |
<div>(Время: ${elapsed.toFixed(2)} сек)</div>`; | |
responseContainer.appendChild(stepDiv); | |
messages.push({ role: "assistant", content: JSON.stringify(stepData, null, 2) }); | |
if (stepData.next_action === "final_answer") break; | |
stepCount++; | |
} | |
messages.push({ | |
role: "user", | |
content: "Предоставьте окончательный ответ без формата JSON, сохранив исходное форматирование из подсказки." | |
}); | |
document.getElementById("loading-indicator").style.display = "block"; | |
const finalStart = performance.now(); | |
const finalAnswer = await makeApiCall(messages, CONFIG.FINAL_MAX_TOKENS, true); | |
const finalElapsed = (performance.now() - finalStart) / 1000; | |
totalThinkingTime += finalElapsed; | |
document.getElementById("loading-indicator").style.display = "none"; | |
const finalDiv = document.createElement("div"); | |
finalDiv.innerHTML = `<div class="step-title">Final Answer</div> | |
<div>${finalAnswer}</div> | |
<div>(Время: ${finalElapsed.toFixed(2)} сек)</div> | |
<div>Общее время обработки: ${totalThinkingTime.toFixed(2)} сек</div>`; | |
finalAnswerContainer.appendChild(finalDiv); | |
} | |
// Обработчик события запуска | |
document.getElementById("start-btn").addEventListener("click", () => { | |
try { | |
const { apiEndpoint, prompt } = validateInputs(); | |
generateResponse(prompt, document.getElementById("context").value.trim()).catch(error => { | |
document.getElementById("response-container").innerHTML = `<div class="error">Ошибка: ${error.message}</div>`; | |
}); | |
} catch (e) { | |
alert(e.message); | |
} | |
}); | |
</script> | |
</body> | |
</html> | |