ChatBot / index.html
JarWithWater's picture
Upload 23 files
586b1c8 verified
Raw History Blame Contribute Delete
10.7 kB
<!DOCTYPE html>
<html lang="ru" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HBB Chat</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css" id="hljs-theme">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="app">
<!-- ===== Боковая панель ===== -->
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<div class="logo">
<img src="icons/assistant.png" class="icon" alt=""> HBB Chat
</div>
</div>
<div class="search-box">
<input type="text" id="search-input" placeholder="Поиск по чатам..." oninput="filterChats()">
</div>
<button class="new-chat-btn" onclick="createNewChat()">
<img src="icons/new-chat.png" class="icon" alt=""> Новый чат
</button>
<div class="chat-list" id="chat-list"></div>
<div class="sidebar-footer">
<span><span class="status-dot" id="status-dot"></span><span id="status-text">Проверка...</span></span>
<a class="settings-link" onclick="openSettings()">
<img src="icons/settings.png" class="icon" alt=""> Настройки
</a>
</div>
</aside>
<!-- ===== Основная область ===== -->
<main class="main">
<div class="topbar">
<button class="toggle-btn" onclick="toggleSidebar()" title="Свернуть/развернуть">
<img src="icons/menu.png" class="icon" alt="">
</button>
<div class="current-title" id="current-title" ondblclick="renameCurrentChat()">Новый чат</div>
<div class="spacer"></div>
<div class="token-info" id="token-info"></div>
<button class="theme-btn" onclick="toggleTheme()" title="Тема">
<img src="icons/theme-dark.png" class="icon" alt="">
</button>
</div>
<div class="chat-area" id="chat-area">
<div class="welcome" id="welcome">
<div class="title">
<img src="icons/assistant.png" class="icon" alt=""> Привет! Чем помочь сегодня?
</div>
<div class="subtitle">Напишите сообщение, прикрепите файл или картинку.</div>
</div>
<div class="chat-inner" id="chat-inner"></div>
</div>
<div class="input-wrap">
<div class="input-box">
<div class="attachments-preview" id="attachments-preview"></div>
<textarea id="user-input" placeholder="Напишите сообщение... (Ctrl+Enter — отправить)" rows="1"></textarea>
<div class="input-actions">
<div class="left">
<button class="icon-btn" id="attach-btn" title="Прикрепить файл">
<img src="icons/attach.png" class="icon" alt="">
</button>
</div>
<button class="send-btn" id="send-btn" title="Отправить">
<img src="icons/send.png" class="icon" alt="">
</button>
</div>
</div>
</div>
</main>
</div>
<!-- ===== Настройки ===== -->
<div class="settings-overlay" id="settings-overlay">
<div class="settings-panel">
<h3>Настройки <button onclick="closeSettings()"><img src="icons/close.png" class="icon" alt=""></button></h3>
<div class="field">
<label>Бэкенд</label>
<select id="backend-select">
<option value="llamacpp">llama.cpp (OpenAI API)</option>
<option value="ollama">Ollama</option>
</select>
</div>
<div class="field">
<label>API Endpoint</label>
<input type="text" id="api-url" value="http://localhost:8080">
</div>
<div class="field">
<label>Имя пользователя</label>
<input type="text" id="user-name" value="Вы" maxlength="32">
</div>
<div class="field">
<label>Имя ассистента</label>
<input type="text" id="assistant-name" value="Ассистент" maxlength="32">
</div>
<div class="field">
<label>Аватар пользователя</label>
<input type="text" id="user-avatar" value="user" maxlength="32">
<div class="hint">Имя файла в icons/ без .png</div>
</div>
<div class="field">
<label>Аватар ассистента</label>
<input type="text" id="assistant-avatar" value="assistant" maxlength="32">
<div class="hint">Имя файла в icons/ без .png</div>
</div>
<div class="field">
<label>Профиль ассистента</label>
<select id="persona-select">
<option value="none">Ничего</option>
<option value="enthusiastic">Восторженный помощник</option>
<option value="coder">Помощник по программированию</option>
<option value="explainer">Разжёвывающий помощник</option>
<option value="sarcastic">Саркастичный помощник</option>
<option value="teacher">Терпеливый учитель</option>
</select>
</div>
<div class="field">
<label>Системный промпт</label>
<textarea id="system-prompt" placeholder="Ты — полезный ассистент..."></textarea>
</div>
<div class="divider"></div>
<div class="field">
<label>Temperature <span id="temp-val">0.8</span></label>
<input type="range" id="temp" min="0" max="2" step="0.05" value="0.8">
</div>
<div class="field">
<label>Top P <span id="topp-val">0.9</span></label>
<input type="range" id="topp" min="0" max="1" step="0.05" value="0.9">
</div>
<div class="field">
<label>Top K <span id="topk-val">40</span></label>
<input type="range" id="topk" min="1" max="100" step="1" value="40">
</div>
<div class="field">
<label>Repeat Penalty <span id="rep-val">1.1</span></label>
<input type="range" id="reppen" min="0.5" max="2" step="0.05" value="1.1">
</div>
<div class="field">
<label>Max tokens <span id="np-val">512</span></label>
<input type="range" id="numpredict" min="32" max="4096" step="32" value="512">
</div>
<div class="field">
<label>Context (n_ctx) <span id="ctx-val">4096</span></label>
<input type="range" id="numctx" min="512" max="32768" step="512" value="4096">
</div>
<div class="field">
<label>Image min tokens</label>
<input type="number" id="img-min-tokens" value="256" min="64" max="2048" step="64">
</div>
<div class="divider"></div>
<h4 style="margin: 0 0 10px 0; font-size: 0.85rem;">Предлагаемые запросы</h4>
<div class="field">
<label>
<input type="checkbox" id="suggest-enabled" style="width:auto;margin-right:6px;" checked>
Включить генерацию предложений
</label>
</div>
<div class="field">
<label>Модель для предложений</label>
<input type="text" id="suggest-model" value="gemma-3-1b-it">
</div>
<div class="field">
<label>Endpoint для предложений</label>
<input type="text" id="suggest-api-url" value="http://localhost:8080">
</div>
<div class="field">
<label>Кол-во предложений <span id="suggest-count-val">3</span></label>
<input type="range" id="suggest-count" min="1" max="5" step="1" value="3">
</div>
<div class="divider"></div>
<div class="field">
<label>Макс. сторона картинки, px</label>
<input type="number" id="img-max-side" value="1280" min="256" max="4096" step="64">
</div>
<div class="field">
<label>Качество JPEG <span id="img-q-val">0.85</span></label>
<input type="range" id="img-quality" min="0.3" max="1" step="0.05" value="0.85">
</div>
<button class="btn-primary" onclick="saveSettings()">Сохранить</button>
<div class="btn-row">
<button class="btn-secondary" onclick="exportChats()">
<img src="icons/export.png" class="icon" alt=""> Экспорт
</button>
<button class="btn-secondary" onclick="importChats()">
<img src="icons/import.png" class="icon" alt=""> Импорт
</button>
</div>
<button class="btn-secondary" onclick="resetSettings()">Сбросить всё</button>
</div>
</div>
<div class="lightbox" id="lightbox" onclick="closeLightbox()">
<img id="lightbox-img" alt="">
</div>
<!-- ===== Атрибуция Icons8 ===== -->
<div style="
position: fixed;
bottom: 2px;
right: 4px;
font-size: 6px;
color: var(--text-dim);
opacity: 0.4;
z-index: 9999;
pointer-events: auto;
font-family: sans-serif;
line-height: 1;
">
Icons by <a href="https://icons8.ru" target="_blank" style="color: inherit; text-decoration: none;">icons8.ru</a>
</div>
<!-- ===== Библиотеки ===== -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.0/marked.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.9/purify.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<!-- ===== Основной скрипт ===== -->
<script src="script.js"></script>
</body>
</html>