Compare commits
No commits in common. "a7dfbe2ebdf46542d95ca421b1bea68be240a409" and "9750ba524ad0c92409ef6d236345848b091ef66c" have entirely different histories.
a7dfbe2ebd
...
9750ba524a
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1 @@
|
|||||||
/.env.server
|
/.env.server
|
||||||
/nginx.conf
|
|
||||||
|
35
client/chat.html
Normal file
35
client/chat.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<!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;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
/* height: 100vh;*/
|
height: 100vh;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background-color: #e9ecef;
|
background-color: #e9ecef;
|
||||||
}
|
}
|
||||||
@ -89,7 +89,6 @@ button:hover {
|
|||||||
|
|
||||||
/* Header Layout */
|
/* Header Layout */
|
||||||
.header {
|
.header {
|
||||||
z-index: 10;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -150,7 +149,6 @@ main {
|
|||||||
|
|
||||||
/* Benutzerliste Styling */
|
/* Benutzerliste Styling */
|
||||||
.user-list {
|
.user-list {
|
||||||
margin-top: 6rem;
|
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
background-color: #f8f9fa;
|
background-color: #f8f9fa;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@ -171,9 +169,10 @@ main {
|
|||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Chat Interface Styles
|
/* Chat Interface Styles */
|
||||||
.chat-container {
|
.chat-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
max-width: 600px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -182,7 +181,7 @@ main {
|
|||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
.chat-box {
|
.chat-box {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@ -251,10 +250,8 @@ main {
|
|||||||
|
|
||||||
/* Haupt-Container für Layout mit Seitenleiste */
|
/* Haupt-Container für Layout mit Seitenleiste */
|
||||||
.main-container {
|
.main-container {
|
||||||
height: 90vh;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
transform: translate(0px, 6rem);
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Linke Seitenleiste */
|
/* Linke Seitenleiste */
|
||||||
@ -291,7 +288,6 @@ main {
|
|||||||
|
|
||||||
/* Chatbereich Styles (wie oben beschrieben) */
|
/* Chatbereich Styles (wie oben beschrieben) */
|
||||||
.chat-container {
|
.chat-container {
|
||||||
width: 100%;
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -311,7 +307,6 @@ main {
|
|||||||
#chatBox {
|
#chatBox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#sendButton {
|
#sendButton {
|
||||||
@ -371,4 +366,3 @@ main {
|
|||||||
background-color: #27ae60;
|
background-color: #27ae60;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
let chatCount = 0; // Zähler für Chat-Sessions
|
let chatCount = 0; // Zähler für Chat-Sessions
|
||||||
let currentChatId = null; // Aktuell angezeigte Chat-ID
|
let currentChatId = null; // Aktuell angezeigte Chat-ID
|
||||||
let useMarkdown = true;
|
|
||||||
|
|
||||||
document.getElementById('newChatButton').addEventListener('click', () => {
|
document.getElementById('newChatButton').addEventListener('click', () => {
|
||||||
createNewChat();
|
createNewChat();
|
||||||
@ -14,14 +13,7 @@ document.getElementById('sendButton').addEventListener('click', () => {
|
|||||||
if (messageText !== '' && currentChatId !== null) { // Stelle sicher, dass eine Chat-ID vorhanden ist
|
if (messageText !== '' && currentChatId !== null) { // Stelle sicher, dass eine Chat-ID vorhanden ist
|
||||||
const messageElement = document.createElement('div');
|
const messageElement = document.createElement('div');
|
||||||
messageElement.classList.add('chat-message', 'user');
|
messageElement.classList.add('chat-message', 'user');
|
||||||
//messageElement.innerText = messageText;
|
messageElement.innerText = messageText;
|
||||||
|
|
||||||
if (useMarkdown) {
|
|
||||||
messageElement.innerHTML = renderMarkdown(messageText);
|
|
||||||
} else {
|
|
||||||
messageElement.innerText = messageText;
|
|
||||||
}
|
|
||||||
|
|
||||||
chatBox.prepend(messageElement);
|
chatBox.prepend(messageElement);
|
||||||
|
|
||||||
// Nachricht speichern
|
// Nachricht speichern
|
||||||
@ -45,31 +37,21 @@ function createNewChat() {
|
|||||||
loadChatHistory(currentChatId); // Lade den neuen Chat
|
loadChatHistory(currentChatId); // Lade den neuen Chat
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveMessage(chatId, message) {
|
function saveMessage(chatId, message) {
|
||||||
const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || [];
|
const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || [];
|
||||||
chatHistory.push({ role: "user", content: message });
|
chatHistory.push({ user: "user", text: message });
|
||||||
localStorage.setItem(`chatHistory-${chatId}`, JSON.stringify(chatHistory));
|
localStorage.setItem(`chatHistory-${chatId}`, JSON.stringify(chatHistory));
|
||||||
|
|
||||||
// Aktualisiere den Button-Text in der Sidebar
|
// Aktualisiere den Button-Text in der Sidebar
|
||||||
updateChatSessionButton(chatId);
|
updateChatSessionButton(chatId, message);
|
||||||
|
|
||||||
// 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) {
|
function updateChatSessionButton(chatId, message) {
|
||||||
const button = document.getElementById(`chatSession-${chatId}`);
|
const button = document.getElementById(`chatSession-${chatId}`);
|
||||||
if (button) {
|
if (button) {
|
||||||
const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || [];
|
const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || [];
|
||||||
// Hole die erste Nachricht oder lasse es leer, wenn keine vorhanden ist
|
// Hole die erste Nachricht oder lasse es leer, wenn keine vorhanden ist
|
||||||
const chatName = chatHistory.length > 0 ? chatHistory[0].content.slice(0, 10) : ''; // Nimm die ersten 10 Zeichen der ersten Nachricht
|
const chatName = chatHistory.length > 0 ? chatHistory[0].text.slice(0, 10) : ''; // Nimm die ersten 10 Zeichen der ersten Nachricht
|
||||||
button.innerText = chatName + "..." || `Chat ${chatId + 1}`; // Falls leer, setze auf "Chat x"
|
button.innerText = chatName + "..." || `Chat ${chatId + 1}`; // Falls leer, setze auf "Chat x"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,8 +105,8 @@ function loadChatHistory(chatId) {
|
|||||||
const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || [];
|
const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || [];
|
||||||
chatHistory.forEach(entry => {
|
chatHistory.forEach(entry => {
|
||||||
const messageElement = document.createElement('div');
|
const messageElement = document.createElement('div');
|
||||||
messageElement.classList.add('chat-message', entry.role);
|
messageElement.classList.add('chat-message', entry.user);
|
||||||
messageElement.innerText = entry.content;
|
messageElement.innerText = entry.text;
|
||||||
chatBox.prepend(messageElement);
|
chatBox.prepend(messageElement);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -145,11 +127,7 @@ function loadAllChatSessions() {
|
|||||||
chatCount = Math.max(chatCount, chatId + 1); // Chat-Zähler aktualisieren
|
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
|
// Lade den neuesten Chat-Verlauf
|
||||||
if (chatCount > 0) {
|
if (chatCount > 0) {
|
||||||
loadChatHistory(chatCount - 1);
|
loadChatHistory(chatCount - 1);
|
||||||
@ -168,10 +146,6 @@ const chatInput = document.getElementById('chatInput');
|
|||||||
// Event-Listener für das Senden der Nachricht und das Erstellen eines Zeilenumbruchs
|
// Event-Listener für das Senden der Nachricht und das Erstellen eines Zeilenumbruchs
|
||||||
chatInput.addEventListener('keydown', (event) => {
|
chatInput.addEventListener('keydown', (event) => {
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
if (currentChatId == null){
|
|
||||||
createNewChat();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prüfen, ob die Shift-Taste nicht gedrückt wird
|
// Prüfen, ob die Shift-Taste nicht gedrückt wird
|
||||||
if (!event.shiftKey) {
|
if (!event.shiftKey) {
|
||||||
event.preventDefault(); // Verhindert das Standardverhalten (Absenden des Formulars)
|
event.preventDefault(); // Verhindert das Standardverhalten (Absenden des Formulars)
|
||||||
@ -198,118 +172,3 @@ 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,42 +9,23 @@
|
|||||||
<body>
|
<body>
|
||||||
|
|
||||||
<!-- Header für Benutzer-Info und Buttons -->
|
<!-- Header für Benutzer-Info und Buttons -->
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<h1 class="header-welcome">Ein simples Chat-Interface mit Fokus auf die Privatsphäre.</h1>
|
<h1 class="header-welcome">Willkommen auf Ihrer persönlichen Seite!</h1>
|
||||||
|
|
||||||
<div class="header-user-info">
|
<div class="header-user-info">
|
||||||
<p><strong>Benutzername:</strong> <span id="username">Gast</span></p>
|
<p><strong>Benutzername:</strong> <span id="username">Gast</span></p>
|
||||||
<p><strong>Admin:</strong> <span id="isAdmin">Nein</span></p>
|
<p><strong>Admin:</strong> <span id="isAdmin">Nein</span></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="header-buttons">
|
||||||
|
<button id="adminPermissionsBtn" class="header-btn" style="display: none;">Admin-Einstellungen</button>
|
||||||
|
<button id="logoutBtn" class="header-btn">Abmelden</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
<div class="header-buttons">
|
|
||||||
<button id="adminPermissionsBtn" class="header-btn" style="display: none;">Admin-Einstellungen</button>
|
|
||||||
<button id="logoutBtn" class="header-btn">Abmelden</button>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<!-- Freier Platz für zukünftige Features -->
|
<!-- Freier Platz für zukünftige Features -->
|
||||||
<div class="main-container">
|
<main></main>
|
||||||
<!-- 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>
|
<script src="js/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -14,24 +14,6 @@ server {
|
|||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
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
|
# Anfragen für andere statische Dateien (HTML, CSS, JS, Bilder) im Root-Verzeichnis suchen
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.html; # Bei nicht gefundenen Dateien auf index.html zurückgreifen
|
try_files $uri $uri/ /index.html; # Bei nicht gefundenen Dateien auf index.html zurückgreifen
|
Loading…
Reference in New Issue
Block a user