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
|
/.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;
|
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,6 +89,7 @@ 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;
|
||||||
@ -149,6 +150,7 @@ 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;
|
||||||
@ -169,10 +171,9 @@ 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;
|
||||||
@ -181,7 +182,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;
|
||||||
@ -250,8 +251,10 @@ 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;
|
||||||
height: 100vh;
|
transform: translate(0px, 6rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Linke Seitenleiste */
|
/* Linke Seitenleiste */
|
||||||
@ -288,6 +291,7 @@ 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;
|
||||||
@ -307,6 +311,7 @@ main {
|
|||||||
#chatBox {
|
#chatBox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sendButton {
|
#sendButton {
|
||||||
@ -366,3 +371,4 @@ main {
|
|||||||
background-color: #27ae60;
|
background-color: #27ae60;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
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();
|
||||||
@ -13,7 +14,14 @@ 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;
|
||||||
|
|
||||||
|
if (useMarkdown) {
|
||||||
|
messageElement.innerHTML = renderMarkdown(messageText);
|
||||||
|
} else {
|
||||||
messageElement.innerText = messageText;
|
messageElement.innerText = messageText;
|
||||||
|
}
|
||||||
|
|
||||||
chatBox.prepend(messageElement);
|
chatBox.prepend(messageElement);
|
||||||
|
|
||||||
// Nachricht speichern
|
// Nachricht speichern
|
||||||
@ -37,21 +45,31 @@ function createNewChat() {
|
|||||||
loadChatHistory(currentChatId); // Lade den neuen Chat
|
loadChatHistory(currentChatId); // Lade den neuen Chat
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveMessage(chatId, message) {
|
async function saveMessage(chatId, message) {
|
||||||
const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || [];
|
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));
|
localStorage.setItem(`chatHistory-${chatId}`, JSON.stringify(chatHistory));
|
||||||
|
|
||||||
// Aktualisiere den Button-Text in der Sidebar
|
// 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}`);
|
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].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"
|
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}`)) || [];
|
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.user);
|
messageElement.classList.add('chat-message', entry.role);
|
||||||
messageElement.innerText = entry.text;
|
messageElement.innerText = entry.content;
|
||||||
chatBox.prepend(messageElement);
|
chatBox.prepend(messageElement);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -127,7 +145,11 @@ 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);
|
||||||
@ -146,6 +168,10 @@ 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)
|
||||||
@ -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>
|
<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">Willkommen auf Ihrer persönlichen Seite!</h1>
|
<h1 class="header-welcome">Ein simples Chat-Interface mit Fokus auf die Privatsphäre.</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>
|
||||||
@ -21,11 +21,30 @@
|
|||||||
<button id="adminPermissionsBtn" class="header-btn" style="display: none;">Admin-Einstellungen</button>
|
<button id="adminPermissionsBtn" class="header-btn" style="display: none;">Admin-Einstellungen</button>
|
||||||
<button id="logoutBtn" class="header-btn">Abmelden</button>
|
<button id="logoutBtn" class="header-btn">Abmelden</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<!-- Freier Platz für zukünftige Features -->
|
<!-- 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>
|
<script src="js/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -14,6 +14,24 @@ 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