chatbot
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
// import path from "path";
|
||||||
|
|
||||||
import compression from "compression";
|
import compression from "compression";
|
||||||
import cookieParser from "cookie-parser";
|
import cookieParser from "cookie-parser";
|
||||||
import cors from "cors";
|
import cors from "cors";
|
||||||
@@ -142,6 +144,11 @@ class App {
|
|||||||
*/
|
*/
|
||||||
app.use(cors(appConfig.cors));
|
app.use(cors(appConfig.cors));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* serve static files from project root (for test files)
|
||||||
|
*/
|
||||||
|
app.use(express.static(process.cwd()));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* config passport
|
* config passport
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export class LLMService {
|
|||||||
constructor(@inject(IOCTYPES.ChatbotDataContextService) private dataContextService: DataContextService) {
|
constructor(@inject(IOCTYPES.ChatbotDataContextService) private dataContextService: DataContextService) {
|
||||||
this.logger = new Logger("LLMService");
|
this.logger = new Logger("LLMService");
|
||||||
this.config = {
|
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),
|
temperature: Number(process.env.OPENAI_TEMPERATURE || CHATBOT_CONSTANTS.DEFAULT_TEMPERATURE),
|
||||||
maxTokens: Number(process.env.OPENAI_MAX_TOKENS || CHATBOT_CONSTANTS.DEFAULT_MAX_TOKENS),
|
maxTokens: Number(process.env.OPENAI_MAX_TOKENS || CHATBOT_CONSTANTS.DEFAULT_MAX_TOKENS),
|
||||||
topP: Number(process.env.OPENAI_TOP_P || "0.95"),
|
topP: Number(process.env.OPENAI_TOP_P || "0.95"),
|
||||||
@@ -66,8 +66,7 @@ export class LLMService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const botMessage =
|
const botMessage =
|
||||||
completion.choices[0]?.message?.content ||
|
completion.choices[0]?.message?.content || "متأسفم، نمیتوانم پاسخی تولید کنم. لطفاً سوال خود را دوباره مطرح کنید. 🤖";
|
||||||
"متأسفم، نمیتوانم پاسخی تولید کنم. لطفاً سوال خود را دوباره مطرح کنید. 🤖";
|
|
||||||
|
|
||||||
// Calculate token usage from OpenAI response
|
// Calculate token usage from OpenAI response
|
||||||
const tokensUsed = (completion.usage?.total_tokens || 0) + this.estimateTokens(systemInstruction);
|
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