chatbot
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
// import path from "path";
|
||||
|
||||
import compression from "compression";
|
||||
import cookieParser from "cookie-parser";
|
||||
import cors from "cors";
|
||||
@@ -142,6 +144,11 @@ class App {
|
||||
*/
|
||||
app.use(cors(appConfig.cors));
|
||||
|
||||
/**
|
||||
* serve static files from project root (for test files)
|
||||
*/
|
||||
app.use(express.static(process.cwd()));
|
||||
|
||||
/**
|
||||
* config passport
|
||||
*/
|
||||
|
||||
@@ -16,7 +16,7 @@ export class LLMService {
|
||||
constructor(@inject(IOCTYPES.ChatbotDataContextService) private dataContextService: DataContextService) {
|
||||
this.logger = new Logger("LLMService");
|
||||
this.config = {
|
||||
model: process.env.OPENAI_BASE_URL || CHATBOT_CONSTANTS.DEFAULT_MODEL,
|
||||
model: process.env.OPENAI_MODEL || CHATBOT_CONSTANTS.DEFAULT_MODEL,
|
||||
temperature: Number(process.env.OPENAI_TEMPERATURE || CHATBOT_CONSTANTS.DEFAULT_TEMPERATURE),
|
||||
maxTokens: Number(process.env.OPENAI_MAX_TOKENS || CHATBOT_CONSTANTS.DEFAULT_MAX_TOKENS),
|
||||
topP: Number(process.env.OPENAI_TOP_P || "0.95"),
|
||||
@@ -66,8 +66,7 @@ export class LLMService {
|
||||
});
|
||||
|
||||
const botMessage =
|
||||
completion.choices[0]?.message?.content ||
|
||||
"متأسفم، نمیتوانم پاسخی تولید کنم. لطفاً سوال خود را دوباره مطرح کنید. 🤖";
|
||||
completion.choices[0]?.message?.content || "متأسفم، نمیتوانم پاسخی تولید کنم. لطفاً سوال خود را دوباره مطرح کنید. 🤖";
|
||||
|
||||
// Calculate token usage from OpenAI response
|
||||
const tokensUsed = (completion.usage?.total_tokens || 0) + this.estimateTokens(systemInstruction);
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Chatbot Socket.IO Test</title>
|
||||
<script src="https://cdn.socket.io/4.8.1/socket.io.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 50px auto;
|
||||
padding: 20px;
|
||||
}
|
||||
.container {
|
||||
border: 1px solid #ddd;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
button {
|
||||
padding: 10px 20px;
|
||||
margin: 5px;
|
||||
cursor: pointer;
|
||||
background: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
}
|
||||
button:hover {
|
||||
background: #0056b3;
|
||||
}
|
||||
button:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
#log {
|
||||
background: #f5f5f5;
|
||||
padding: 10px;
|
||||
height: 400px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #ddd;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
.log-entry {
|
||||
margin: 5px 0;
|
||||
padding: 5px;
|
||||
}
|
||||
.log-success { color: green; }
|
||||
.log-error { color: red; }
|
||||
.log-info { color: blue; }
|
||||
input {
|
||||
padding: 8px;
|
||||
margin: 5px;
|
||||
width: 300px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Chatbot Socket.IO Test Client</h1>
|
||||
|
||||
<div>
|
||||
<label>Server URL:</label><br>
|
||||
<input type="text" id="serverUrl" value="http://localhost:4000" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Token (optional, for authenticated connection):</label><br>
|
||||
<input type="text" id="token" placeholder="Leave empty for anonymous connection" />
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<button id="connectBtn" onclick="connect()">Connect</button>
|
||||
<button id="disconnectBtn" onclick="disconnect()" disabled>Disconnect</button>
|
||||
<button onclick="createSession()" id="createSessionBtn" disabled>Create Session</button>
|
||||
<button onclick="clearLog()">Clear Log</button>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<label>Session ID:</label><br>
|
||||
<input type="text" id="sessionId" placeholder="Will be set after creating session" readonly />
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<label>Message:</label><br>
|
||||
<input type="text" id="messageInput" placeholder="Type your message here" />
|
||||
<button onclick="sendMessage()" id="sendMessageBtn" disabled>Send Message</button>
|
||||
<button onclick="sendMessageStream()" id="sendStreamBtn" disabled>Send (Stream)</button>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<h3>Event Log:</h3>
|
||||
<div id="log"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let socket = null;
|
||||
let currentSessionId = null;
|
||||
|
||||
function log(message, type = 'info') {
|
||||
const logDiv = document.getElementById('log');
|
||||
const entry = document.createElement('div');
|
||||
entry.className = `log-entry log-${type}`;
|
||||
entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
|
||||
logDiv.appendChild(entry);
|
||||
logDiv.scrollTop = logDiv.scrollHeight;
|
||||
}
|
||||
|
||||
function clearLog() {
|
||||
document.getElementById('log').innerHTML = '';
|
||||
}
|
||||
|
||||
function connect() {
|
||||
const serverUrl = document.getElementById('serverUrl').value;
|
||||
const token = document.getElementById('token').value;
|
||||
|
||||
const options = {
|
||||
path: '/ws-chatbot',
|
||||
transports: ['websocket'],
|
||||
};
|
||||
|
||||
if (token) {
|
||||
options.query = { token: token };
|
||||
}
|
||||
|
||||
log(`Connecting to ${serverUrl}...`, 'info');
|
||||
socket = io(serverUrl, options);
|
||||
|
||||
socket.on('connect', () => {
|
||||
log('✅ Connected! Socket ID: ' + socket.id, 'success');
|
||||
document.getElementById('connectBtn').disabled = true;
|
||||
document.getElementById('disconnectBtn').disabled = false;
|
||||
document.getElementById('createSessionBtn').disabled = false;
|
||||
});
|
||||
|
||||
socket.on('authenticated', (data) => {
|
||||
log('✅ Authenticated: ' + JSON.stringify(data), 'success');
|
||||
});
|
||||
|
||||
socket.on('unauthorized', (data) => {
|
||||
log('❌ Unauthorized: ' + JSON.stringify(data), 'error');
|
||||
});
|
||||
|
||||
socket.on('session_created', (data) => {
|
||||
log('✅ Session created: ' + JSON.stringify(data, null, 2), 'success');
|
||||
if (data.data && data.data.id) {
|
||||
currentSessionId = data.data.id;
|
||||
document.getElementById('sessionId').value = currentSessionId;
|
||||
document.getElementById('sendMessageBtn').disabled = false;
|
||||
document.getElementById('sendStreamBtn').disabled = false;
|
||||
// Auto-join the session
|
||||
socket.emit('join_chat', currentSessionId);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('chat_joined', (data) => {
|
||||
log('✅ Joined chat: ' + JSON.stringify(data, null, 2), 'success');
|
||||
});
|
||||
|
||||
socket.on('message_received', (data) => {
|
||||
log('📨 Message received: ' + JSON.stringify(data, null, 2), 'info');
|
||||
});
|
||||
|
||||
socket.on('bot_response_start', (data) => {
|
||||
log('🤖 Bot response started...', 'info');
|
||||
});
|
||||
|
||||
socket.on('bot_response_chunk', (data) => {
|
||||
if (data.data && data.data.chunk) {
|
||||
process.stdout = {
|
||||
write: (text) => log('🤖 ' + text, 'info')
|
||||
};
|
||||
// Append chunk to log
|
||||
const logDiv = document.getElementById('log');
|
||||
const lastEntry = logDiv.lastElementChild;
|
||||
if (lastEntry && lastEntry.textContent.includes('🤖')) {
|
||||
lastEntry.textContent += data.data.chunk;
|
||||
} else {
|
||||
log('🤖 ' + data.data.chunk, 'info');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('bot_response_end', (data) => {
|
||||
log('✅ Bot response completed: ' + JSON.stringify(data, null, 2), 'success');
|
||||
});
|
||||
|
||||
socket.on('bot_response', (data) => {
|
||||
log('🤖 Bot response: ' + JSON.stringify(data, null, 2), 'info');
|
||||
});
|
||||
|
||||
socket.on('error', (data) => {
|
||||
log('❌ Error: ' + JSON.stringify(data, null, 2), 'error');
|
||||
});
|
||||
|
||||
socket.on('session_error', (data) => {
|
||||
log('❌ Session error: ' + JSON.stringify(data, null, 2), 'error');
|
||||
});
|
||||
|
||||
socket.on('message_error', (data) => {
|
||||
log('❌ Message error: ' + JSON.stringify(data, null, 2), 'error');
|
||||
});
|
||||
|
||||
socket.on('disconnect', (reason) => {
|
||||
log('❌ Disconnected: ' + reason, 'error');
|
||||
document.getElementById('connectBtn').disabled = false;
|
||||
document.getElementById('disconnectBtn').disabled = true;
|
||||
document.getElementById('createSessionBtn').disabled = true;
|
||||
document.getElementById('sendMessageBtn').disabled = true;
|
||||
document.getElementById('sendStreamBtn').disabled = true;
|
||||
});
|
||||
|
||||
socket.on('connect_error', (error) => {
|
||||
log('❌ Connection error: ' + error.message, 'error');
|
||||
});
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
if (socket) {
|
||||
socket.disconnect();
|
||||
socket = null;
|
||||
currentSessionId = null;
|
||||
document.getElementById('sessionId').value = '';
|
||||
}
|
||||
}
|
||||
|
||||
function createSession() {
|
||||
if (socket && socket.connected) {
|
||||
log('📤 Creating session...', 'info');
|
||||
socket.emit('create_session');
|
||||
} else {
|
||||
log('❌ Not connected!', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function sendMessage() {
|
||||
const message = document.getElementById('messageInput').value;
|
||||
if (!socket || !socket.connected) {
|
||||
log('❌ Not connected!', 'error');
|
||||
return;
|
||||
}
|
||||
if (!currentSessionId) {
|
||||
log('❌ No session ID! Create a session first.', 'error');
|
||||
return;
|
||||
}
|
||||
if (!message) {
|
||||
log('❌ Message is empty!', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
log('📤 Sending message: ' + message, 'info');
|
||||
socket.emit('send_message', {
|
||||
sessionId: currentSessionId,
|
||||
content: message
|
||||
});
|
||||
document.getElementById('messageInput').value = '';
|
||||
}
|
||||
|
||||
function sendMessageStream() {
|
||||
const message = document.getElementById('messageInput').value;
|
||||
if (!socket || !socket.connected) {
|
||||
log('❌ Not connected!', 'error');
|
||||
return;
|
||||
}
|
||||
if (!currentSessionId) {
|
||||
log('❌ No session ID! Create a session first.', 'error');
|
||||
return;
|
||||
}
|
||||
if (!message) {
|
||||
log('❌ Message is empty!', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
log('📤 Sending message (stream): ' + message, 'info');
|
||||
socket.emit('send_message_stream', {
|
||||
sessionId: currentSessionId,
|
||||
content: message
|
||||
});
|
||||
document.getElementById('messageInput').value = '';
|
||||
}
|
||||
|
||||
// Allow Enter key to send message
|
||||
document.getElementById('messageInput').addEventListener('keypress', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
sendMessage();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// Test script for ChatbotGateway Socket.IO connection
|
||||
// Run with: node test-chatbot-socket.js
|
||||
|
||||
const io = require("socket.io-client");
|
||||
|
||||
// Connect to the chatbot gateway
|
||||
// The path option matches the path configured in ChatbotGateway
|
||||
const socket = io("http://localhost:4000", {
|
||||
path: "/ws-chatbot",
|
||||
transports: ["websocket"],
|
||||
// Optional: Add token for authenticated connection
|
||||
// query: {
|
||||
// token: "your-jwt-token-here"
|
||||
// }
|
||||
});
|
||||
|
||||
socket.on("connect", () => {
|
||||
console.log("✅ Connected to ChatbotGateway!");
|
||||
console.log("Socket ID:", socket.id);
|
||||
|
||||
// Test: Create a session
|
||||
console.log("\n📤 Creating session...");
|
||||
socket.emit("create_session");
|
||||
});
|
||||
|
||||
socket.on("authenticated", (data) => {
|
||||
console.log("✅ Authenticated:", data);
|
||||
});
|
||||
|
||||
socket.on("unauthorized", (data) => {
|
||||
console.log("❌ Unauthorized:", data);
|
||||
});
|
||||
|
||||
socket.on("session_created", (data) => {
|
||||
console.log("✅ Session created:", JSON.stringify(data, null, 2));
|
||||
|
||||
// Test: Join the session
|
||||
if (data.data && data.data.id) {
|
||||
console.log("\n📤 Joining session:", data.data.id);
|
||||
socket.emit("join_chat", data.data.id);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("chat_joined", (data) => {
|
||||
console.log("✅ Joined chat:", JSON.stringify(data, null, 2));
|
||||
|
||||
// Test: Send a message
|
||||
if (data.data && data.data.id) {
|
||||
console.log("\n📤 Sending test message...");
|
||||
socket.emit("send_message", {
|
||||
sessionId: data.data.id,
|
||||
content: "Hello, chatbot!",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("message_received", (data) => {
|
||||
console.log("📨 Message received:", JSON.stringify(data, null, 2));
|
||||
});
|
||||
|
||||
socket.on("bot_response_start", (data) => {
|
||||
console.log("🤖 Bot response started:", JSON.stringify(data, null, 2));
|
||||
});
|
||||
|
||||
socket.on("bot_response_chunk", (data) => {
|
||||
process.stdout.write(data.data?.chunk || "");
|
||||
});
|
||||
|
||||
socket.on("bot_response_end", (data) => {
|
||||
console.log("\n✅ Bot response completed:", JSON.stringify(data, null, 2));
|
||||
});
|
||||
|
||||
socket.on("bot_response", (data) => {
|
||||
console.log("🤖 Bot response:", JSON.stringify(data, null, 2));
|
||||
});
|
||||
|
||||
socket.on("error", (data) => {
|
||||
console.log("❌ Error:", JSON.stringify(data, null, 2));
|
||||
});
|
||||
|
||||
socket.on("session_error", (data) => {
|
||||
console.log("❌ Session error:", JSON.stringify(data, null, 2));
|
||||
});
|
||||
|
||||
socket.on("message_error", (data) => {
|
||||
console.log("❌ Message error:", JSON.stringify(data, null, 2));
|
||||
});
|
||||
|
||||
socket.on("disconnect", (reason) => {
|
||||
console.log("❌ Disconnected:", reason);
|
||||
});
|
||||
|
||||
socket.on("connect_error", (error) => {
|
||||
console.log("❌ Connection error:", error.message);
|
||||
});
|
||||
|
||||
// Keep the script running
|
||||
process.stdin.resume();
|
||||
|
||||
Reference in New Issue
Block a user