Compare commits
10 Commits
9750ba524a
...
a7dfbe2ebd
Author | SHA1 | Date | |
---|---|---|---|
a7dfbe2ebd | |||
4d2e5332d8 | |||
192070333c | |||
cd00e28fd7 | |||
08b5b62442 | |||
78c854439a | |||
0b8028635a | |||
9679e5efaf | |||
226e9133ed | |||
dc80804241 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
/.env.server
|
||||
/nginx.conf
|
||||
|
@ -1,35 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Chat Interface</title>
|
||||
<link rel="stylesheet" href="css/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="main-container">
|
||||
<!-- Linke Seitenleiste für Chat-Sessions -->
|
||||
<div class="sidebar" id="chatSidebar">
|
||||
<h3>Gespeicherte Chats</h3>
|
||||
<button id="newChatButton">Neuer Chat</button>
|
||||
<div id="chatList"></div>
|
||||
</div>
|
||||
|
||||
<!-- Chatbereich -->
|
||||
<div class="chat-container">
|
||||
|
||||
|
||||
<div class="chat-box" id="chatBox">
|
||||
<!-- Nachrichten werden hier angezeigt -->
|
||||
</div>
|
||||
<div class="chat-input-container">
|
||||
<textarea id="chatInput" class="chat-input" placeholder="Schreibe eine Nachricht..."></textarea>
|
||||
<button id="sendButton" class="chat-send-button">Senden</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="js/chat.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -4,7 +4,7 @@ body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
/* height: 100vh;*/
|
||||
margin: 0;
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
@ -89,6 +89,7 @@ button:hover {
|
||||
|
||||
/* Header Layout */
|
||||
.header {
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
@ -149,6 +150,7 @@ main {
|
||||
|
||||
/* Benutzerliste Styling */
|
||||
.user-list {
|
||||
margin-top: 6rem;
|
||||
padding: 20px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
@ -169,10 +171,9 @@ main {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/* Chat Interface Styles */
|
||||
/* Chat Interface Styles
|
||||
.chat-container {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -181,7 +182,7 @@ main {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}*/
|
||||
|
||||
.chat-box {
|
||||
flex: 1;
|
||||
@ -250,8 +251,10 @@ main {
|
||||
|
||||
/* Haupt-Container für Layout mit Seitenleiste */
|
||||
.main-container {
|
||||
height: 90vh;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
transform: translate(0px, 6rem);
|
||||
}
|
||||
|
||||
/* Linke Seitenleiste */
|
||||
@ -288,6 +291,7 @@ main {
|
||||
|
||||
/* Chatbereich Styles (wie oben beschrieben) */
|
||||
.chat-container {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -307,6 +311,7 @@ main {
|
||||
#chatBox {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#sendButton {
|
||||
@ -366,3 +371,4 @@ main {
|
||||
background-color: #27ae60;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
let chatCount = 0; // Zähler für Chat-Sessions
|
||||
let currentChatId = null; // Aktuell angezeigte Chat-ID
|
||||
let useMarkdown = true;
|
||||
|
||||
document.getElementById('newChatButton').addEventListener('click', () => {
|
||||
createNewChat();
|
||||
@ -13,7 +14,14 @@ document.getElementById('sendButton').addEventListener('click', () => {
|
||||
if (messageText !== '' && currentChatId !== null) { // Stelle sicher, dass eine Chat-ID vorhanden ist
|
||||
const messageElement = document.createElement('div');
|
||||
messageElement.classList.add('chat-message', 'user');
|
||||
//messageElement.innerText = messageText;
|
||||
|
||||
if (useMarkdown) {
|
||||
messageElement.innerHTML = renderMarkdown(messageText);
|
||||
} else {
|
||||
messageElement.innerText = messageText;
|
||||
}
|
||||
|
||||
chatBox.prepend(messageElement);
|
||||
|
||||
// Nachricht speichern
|
||||
@ -37,21 +45,31 @@ function createNewChat() {
|
||||
loadChatHistory(currentChatId); // Lade den neuen Chat
|
||||
}
|
||||
|
||||
function saveMessage(chatId, message) {
|
||||
async function saveMessage(chatId, message) {
|
||||
const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || [];
|
||||
chatHistory.push({ user: "user", text: message });
|
||||
chatHistory.push({ role: "user", content: message });
|
||||
localStorage.setItem(`chatHistory-${chatId}`, JSON.stringify(chatHistory));
|
||||
|
||||
// Aktualisiere den Button-Text in der Sidebar
|
||||
updateChatSessionButton(chatId, message);
|
||||
updateChatSessionButton(chatId);
|
||||
|
||||
// Sende die Nachricht an den Chatbot
|
||||
const userMessage = getLastUserMessage();
|
||||
if (userMessage) {
|
||||
let a = await stream_api_open_ai(userMessage);
|
||||
console.log("Komplette Nachricht: " + a)
|
||||
const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || [];
|
||||
chatHistory.push({ role: "assistant", content: a });
|
||||
localStorage.setItem(`chatHistory-${chatId}`, JSON.stringify(chatHistory));
|
||||
}
|
||||
}
|
||||
|
||||
function updateChatSessionButton(chatId, message) {
|
||||
function updateChatSessionButton(chatId) {
|
||||
const button = document.getElementById(`chatSession-${chatId}`);
|
||||
if (button) {
|
||||
const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || [];
|
||||
// Hole die erste Nachricht oder lasse es leer, wenn keine vorhanden ist
|
||||
const chatName = chatHistory.length > 0 ? chatHistory[0].text.slice(0, 10) : ''; // Nimm die ersten 10 Zeichen der ersten Nachricht
|
||||
const chatName = chatHistory.length > 0 ? chatHistory[0].content.slice(0, 10) : ''; // Nimm die ersten 10 Zeichen der ersten Nachricht
|
||||
button.innerText = chatName + "..." || `Chat ${chatId + 1}`; // Falls leer, setze auf "Chat x"
|
||||
}
|
||||
}
|
||||
@ -105,8 +123,8 @@ function loadChatHistory(chatId) {
|
||||
const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || [];
|
||||
chatHistory.forEach(entry => {
|
||||
const messageElement = document.createElement('div');
|
||||
messageElement.classList.add('chat-message', entry.user);
|
||||
messageElement.innerText = entry.text;
|
||||
messageElement.classList.add('chat-message', entry.role);
|
||||
messageElement.innerText = entry.content;
|
||||
chatBox.prepend(messageElement);
|
||||
});
|
||||
}
|
||||
@ -127,7 +145,11 @@ function loadAllChatSessions() {
|
||||
chatCount = Math.max(chatCount, chatId + 1); // Chat-Zähler aktualisieren
|
||||
}
|
||||
});
|
||||
console.log(chatCount)
|
||||
|
||||
for (let i = 0; i < chatCount; i++) {// Aktualisiere die Namen an der Seite
|
||||
updateChatSessionButton(i);
|
||||
}
|
||||
// Lade den neuesten Chat-Verlauf
|
||||
if (chatCount > 0) {
|
||||
loadChatHistory(chatCount - 1);
|
||||
@ -146,6 +168,10 @@ const chatInput = document.getElementById('chatInput');
|
||||
// Event-Listener für das Senden der Nachricht und das Erstellen eines Zeilenumbruchs
|
||||
chatInput.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Enter') {
|
||||
if (currentChatId == null){
|
||||
createNewChat();
|
||||
}
|
||||
|
||||
// Prüfen, ob die Shift-Taste nicht gedrückt wird
|
||||
if (!event.shiftKey) {
|
||||
event.preventDefault(); // Verhindert das Standardverhalten (Absenden des Formulars)
|
||||
@ -172,3 +198,118 @@ chatInput.addEventListener('keydown', (event) => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* OpenAI zeug */
|
||||
|
||||
async function getModels() {
|
||||
|
||||
try {
|
||||
const response = await fetch(`http://localhost:8015/v1/models`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': `Bearer YOUR_API_KEY`,
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const models = await response.json();
|
||||
return models.data[0].id
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fetching models:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function getAllCurrentChatMessages() {
|
||||
const cookieData = JSON.parse(localStorage.getItem(`chatHistory-${currentChatId}`)) || [];
|
||||
return cookieData
|
||||
}
|
||||
|
||||
|
||||
function getLastUserMessage() {
|
||||
// Lade die Cookie-Daten (ersetze dies durch den tatsächlichen Weg zur Cookie-Datenstruktur)
|
||||
const cookieData = JSON.parse(localStorage.getItem(`chatHistory-${currentChatId}`)) || [];
|
||||
|
||||
|
||||
// Filter nur die User-Nachrichten heraus
|
||||
const userMessages = cookieData.filter(message => message.role === "user");
|
||||
|
||||
// Falls es User-Nachrichten gibt, die letzte davon zurückgeben
|
||||
if (userMessages.length > 0) {
|
||||
return userMessages[userMessages.length - 1].content;
|
||||
}
|
||||
|
||||
return ''; // Rückgabe eines leeren Strings, falls keine Nachricht gefunden wird
|
||||
}
|
||||
|
||||
function renderMarkdown(content) {
|
||||
return marked.parse(content);
|
||||
}
|
||||
|
||||
async function stream_api_open_ai(userMessage) {
|
||||
// Neues div-Element für die Antwort des Chatbots erstellen
|
||||
const chatBox = document.getElementById('chatBox');
|
||||
const botMessageDiv = document.createElement('div');
|
||||
botMessageDiv.className = 'chat-message bot';
|
||||
chatBox.prepend(botMessageDiv);
|
||||
|
||||
const response = await fetch('http://localhost:8015/v1/chat/completions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer YOUR_API_KEY`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: await getModels(),
|
||||
messages: [
|
||||
{ role: 'system', content: 'You are a knowledgeable assistant.' },
|
||||
...getAllCurrentChatMessages()
|
||||
],
|
||||
stream: true,
|
||||
temperature: 0.3
|
||||
})
|
||||
});
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder('utf-8');
|
||||
|
||||
let result = '';
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
const chunk = decoder.decode(value, { stream: true });
|
||||
const lines = chunk.split('\n');
|
||||
|
||||
for (const line of lines) {
|
||||
if (line && line.includes('data: ')) {
|
||||
const jsonStr = line.replace('data: ', '').trim();
|
||||
|
||||
if (jsonStr === '[DONE]'){
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
const json = JSON.parse(jsonStr);
|
||||
if (json.choices[0].delta.content) {
|
||||
const token = json.choices[0].delta.content;
|
||||
result += token;
|
||||
|
||||
if (useMarkdown) {
|
||||
botMessageDiv.innerHTML = renderMarkdown(result);
|
||||
} else {
|
||||
botMessageDiv.textContent = result;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error parsing JSON:', error, 'Received:', jsonStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -9,8 +9,8 @@
|
||||
<body>
|
||||
|
||||
<!-- Header für Benutzer-Info und Buttons -->
|
||||
<header class="header">
|
||||
<h1 class="header-welcome">Willkommen auf Ihrer persönlichen Seite!</h1>
|
||||
<header class="header">
|
||||
<h1 class="header-welcome">Ein simples Chat-Interface mit Fokus auf die Privatsphäre.</h1>
|
||||
|
||||
<div class="header-user-info">
|
||||
<p><strong>Benutzername:</strong> <span id="username">Gast</span></p>
|
||||
@ -21,11 +21,30 @@
|
||||
<button id="adminPermissionsBtn" class="header-btn" style="display: none;">Admin-Einstellungen</button>
|
||||
<button id="logoutBtn" class="header-btn">Abmelden</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
</header>
|
||||
<!-- Freier Platz für zukünftige Features -->
|
||||
<main></main>
|
||||
<div class="main-container">
|
||||
<!-- Linke Seitenleiste für Chat-Sessions -->
|
||||
<div class="sidebar" id="chatSidebar">
|
||||
<h3>Gespeicherte Chats</h3>
|
||||
<button id="newChatButton">Neuer Chat</button>
|
||||
<div id="chatList"></div>
|
||||
</div>
|
||||
|
||||
<!-- Chatbereich -->
|
||||
|
||||
<div class="chat-container">
|
||||
<div class="chat-box" id="chatBox">
|
||||
<!-- Nachrichten werden hier angezeigt -->
|
||||
</div>
|
||||
<div class="chat-input-container">
|
||||
<textarea id="chatInput" class="chat-input" placeholder="Schreibe eine Nachricht..."></textarea>
|
||||
<button id="sendButton" class="chat-send-button">Senden</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||
<script src="js/chat.js"></script>
|
||||
<script src="js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -14,6 +14,24 @@ server {
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Weiterleitung für v1/models
|
||||
location /v1/models {
|
||||
proxy_pass http://ip:port/v1/models;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Weiterleitung für v1/chat/completions
|
||||
location /v1/chat/completions {
|
||||
proxy_pass http://ip:port/v1/chat/completions;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Anfragen für andere statische Dateien (HTML, CSS, JS, Bilder) im Root-Verzeichnis suchen
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html; # Bei nicht gefundenen Dateien auf index.html zurückgreifen
|
Loading…
Reference in New Issue
Block a user