Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions backend/src/services/vector.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ async function createMemory({vectors, metadata, messageId}){
}])
}

async function queryMemory({queryVector, limit=5, metadata}){
async function queryMemory({ queryVector, limit, metadata }) {
const data = await llmIndex.query({
vector:queryVector,
topK:limit,
filter:metadata? {metadata} :undefined
})
vector: queryVector,
topK: limit,
filter: metadata ? metadata : undefined,
includeMetadata: true,

});

return data.matches;
}


module.exports = {createMemory, queryMemory}
234 changes: 157 additions & 77 deletions backend/src/sockets/socket.server.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,38 @@
const { Server } = require('socket.io')
const cookie = require('cookie')
const userModel = require('../models/user.model')
const jwt = require('jsonwebtoken')
const { generateResponse, generateVector } = require('../services/ai.service')
const messageModel = require('../models/messege.model')
const { createMemory, queryMemory } = require('../services/vector.service')
const { Server } = require("socket.io");
const cookie = require("cookie");
const userModel = require("../models/user.model");
const jwt = require("jsonwebtoken");
const { generateResponse, generateVector } = require("../services/ai.service");
const messageModel = require("../models/messege.model");
const { createMemory, queryMemory } = require("../services/vector.service");
const initSocketServer = (httpServer) => {
const io = new Server(httpServer, {})

// middleware
io.use(async (socket, next) => {
const cookies = cookie.parse(socket.handshake.headers?.cookie || "")
// console.log(cookies)
if (!cookies.token) {
next(new Error('unauthorized : token not found'))
}
try {
const decoded = jwt.verify(cookies.token, process.env.JWT_SECRET);
const user = await userModel.findById(
decoded.id
)
socket.user = user;
next()
} catch (error) {
// console.log('error')
next(new Error('Invalid token' + error))
}
})


io.on('connection', (socket) => {
// console.log('a user connected')
// console.log('user connected', socket.id, socket.user)

socket.on('user-message', async (messagePayload) => {
// user message vectors
// console.log(vectors)



const io = new Server(httpServer, {});

// middleware
io.use(async (socket, next) => {
const cookies = cookie.parse(socket.handshake.headers?.cookie || "");
// console.log(cookies)
if (!cookies.token) {
next(new Error("unauthorized : token not found"));
}
try {
const decoded = jwt.verify(cookies.token, process.env.JWT_SECRET);
const user = await userModel.findById(decoded.id);
socket.user = user;
next();
} catch (error) {
// console.log('error')
next(new Error("Invalid token" + error));
}
});

io.on("connection", (socket) => {
socket.on("user-message", async (messagePayload) => {
// user message vectors

/*


// mongo model
const userMessage = await messageModel.create({
user: socket.user._id,
Expand All @@ -49,46 +43,132 @@ const initSocketServer = (httpServer) => {

// vector memory
const vectors = await generateVector(messagePayload.content);
await createMemory({
vectors, messageId: userMessage._id, metadata: {
user: socket.user._id,
chatId: messagePayload.chatId,
message:messagePayload.content
}
})
// STM
const chatHistory = await messageModel.find({ chatId: messagePayload.chatId })
const STM = chatHistory.map((item) => {
return {
role: item.role,
parts: [{ text: item.content }]
}
})//.slice(-4)
const response = await generateResponse(STM)

// mongo model
const responseMessage = await messageModel.create({
user: socket.user._id,
chatId: messagePayload.chatId,
content: response,
role: "model"
})
// response vectors
const responseVectors = await generateVector(response)
// console.log(vectors)
*/

const [userMessage, vectors] = await Promise.all([
(messageModel.create({
user: socket.user._id,
chatId: messagePayload.chatId,
content: messagePayload.content,
role: "user",
})),
// vector memory
(generateVector(messagePayload.content)),
]);
/*
// pinecone query
const pineconeData = await queryMemory({
queryVector: vectors,
limit: 5,
metadata: {
user: socket.user._id,
},
});
*/
/*
// console.log(pineconeData)
await createMemory({
vectors,
messageId: userMessage._id,
metadata: {
user: socket.user._id,
chatId: messagePayload.chatId,
message: messagePayload.content,
},
});

// STM
const chatHistory = (
await messageModel
.find({ chatId: messagePayload.chatId })
.sort({ createdAt: -1 })
.limit(8)
.lean()
).reverse();

*/

const [_,pineconeData, chatHistory] = await Promise.all([
(createMemory({
vectors,
messageId: userMessage._id,
metadata: {
user: socket.user._id,
chatId: messagePayload.chatId,
message: messagePayload.content,
},
})),
queryMemory({
queryVector: vectors,
limit: 5,
metadata: {
user: socket.user._id,
},
}),
(
(
await messageModel
.find({ chatId: messagePayload.chatId })
.sort({ createdAt: -1 })
.limit(8)
.lean()
).reverse()
)
])

// console.log(chatHistory)

const stm = chatHistory.map((item) => {
return {
role: item.role,
parts: [{ text: item.content }],
};
}); //.slice(-4)

const ltm = [
{
role: "user",
parts: [
{
text: `You are an assistant with long-term memory. Here are relevant memories about the user: ${pineconeData
.map((item) => `- ${item.metadata.message}`)
.join("\n")}`,
},
],
},
];
console.log(pineconeData);
// console.log("ltm:-",ltm, "stm:-", stm)
const response = await generateResponse([...ltm, ...stm]);

// response vector memory
await createMemory({vectors:responseVectors, messageId:responseMessage._id, metadata:{
chatId:messagePayload.chatId,
user:socket.user._id,
message:response
}})
socket.emit('ai-response', { chatId: messagePayload.chatId, response })
})
})
// mongo model
const responseMessage = await messageModel.create({
user: socket.user._id,
chatId: messagePayload.chatId,
content: response,
role: "model",
});


socket.emit("ai-response", { chatId: messagePayload.chatId, response });

}
// response vectors
const responseVectors = await generateVector(response);
// console.log(responseVectors)

// response vector memory
await createMemory({
vectors: responseVectors,
messageId: responseMessage._id,
metadata: {
chatId: messagePayload.chatId,
user: socket.user._id,
message: response,
},
});
});
});
};

module.exports = initSocketServer;
module.exports = initSocketServer;
24 changes: 24 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
12 changes: 12 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# React + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## Expanding the ESLint configuration

If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.
29 changes: 29 additions & 0 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import { defineConfig, globalIgnores } from 'eslint/config'

export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{js,jsx}'],
extends: [
js.configs.recommended,
reactHooks.configs['recommended-latest'],
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
rules: {
'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
},
},
])
13 changes: 13 additions & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
Loading