Perplexica/src/websocket/messageHandler.ts

110 lines
3.1 KiB
TypeScript
Raw Normal View History

import { EventEmitter, WebSocket } from 'ws';
2024-04-09 16:21:05 +05:30
import { BaseMessage, AIMessage, HumanMessage } from '@langchain/core/messages';
import handleWebSearch from '../agents/webSearchAgent';
2024-04-13 12:11:47 +05:30
import handleAcademicSearch from '../agents/academicSearchAgent';
import handleWritingAssistant from '../agents/writingAssistant';
import handleWolframAlphaSearch from '../agents/wolframAlphaSearchAgent';
import handleYoutubeSearch from '../agents/youtubeSearchAgent';
import handleRedditSearch from '../agents/redditSearchAgent';
2024-04-20 09:32:19 +05:30
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
import type { Embeddings } from '@langchain/core/embeddings';
2024-04-30 12:18:18 +05:30
import logger from '../utils/logger';
2024-04-09 16:21:05 +05:30
type Message = {
type: string;
content: string;
copilot: boolean;
2024-04-13 12:11:47 +05:30
focusMode: string;
2024-04-09 16:21:05 +05:30
history: Array<[string, string]>;
};
const searchHandlers = {
webSearch: handleWebSearch,
academicSearch: handleAcademicSearch,
writingAssistant: handleWritingAssistant,
wolframAlphaSearch: handleWolframAlphaSearch,
youtubeSearch: handleYoutubeSearch,
redditSearch: handleRedditSearch,
};
const handleEmitterEvents = (
emitter: EventEmitter,
ws: WebSocket,
id: string,
) => {
emitter.on('data', (data) => {
const parsedData = JSON.parse(data);
if (parsedData.type === 'response') {
ws.send(
JSON.stringify({
type: 'message',
data: parsedData.data,
messageId: id,
}),
);
} else if (parsedData.type === 'sources') {
ws.send(
JSON.stringify({
type: 'sources',
data: parsedData.data,
messageId: id,
}),
);
}
});
emitter.on('end', () => {
ws.send(JSON.stringify({ type: 'messageEnd', messageId: id }));
});
emitter.on('error', (data) => {
const parsedData = JSON.parse(data);
ws.send(JSON.stringify({ type: 'error', data: parsedData.data }));
});
};
2024-04-20 09:32:19 +05:30
export const handleMessage = async (
message: string,
ws: WebSocket,
llm: BaseChatModel,
embeddings: Embeddings,
) => {
2024-04-09 16:21:05 +05:30
try {
const parsedMessage = JSON.parse(message) as Message;
const id = Math.random().toString(36).substring(7);
if (!parsedMessage.content)
return ws.send(
JSON.stringify({ type: 'error', data: 'Invalid message format' }),
);
const history: BaseMessage[] = parsedMessage.history.map((msg) => {
if (msg[0] === 'human') {
return new HumanMessage({
content: msg[1],
});
} else {
return new AIMessage({
content: msg[1],
});
}
});
if (parsedMessage.type === 'message') {
const handler = searchHandlers[parsedMessage.focusMode];
if (handler) {
2024-04-20 09:32:19 +05:30
const emitter = handler(
parsedMessage.content,
history,
llm,
embeddings,
);
handleEmitterEvents(emitter, ws, id);
} else {
ws.send(JSON.stringify({ type: 'error', data: 'Invalid focus mode' }));
2024-04-09 16:21:05 +05:30
}
}
2024-04-30 12:18:18 +05:30
} catch (err) {
2024-04-09 16:21:05 +05:30
ws.send(JSON.stringify({ type: 'error', data: 'Invalid message format' }));
2024-04-30 12:18:18 +05:30
logger.error(`Failed to handle message: ${err}`);
2024-04-09 16:21:05 +05:30
}
};