Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update #19

Open
wants to merge 9 commits into
base: starter
Choose a base branch
from
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
File renamed without changes.
51 changes: 49 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,50 @@
# Lama Dev AI Chat Bot App Starter Setup
# Lama Dev - AI Chatbot

This template provides a minimal setup to get React 19 working in Vite with HMR and some ESLint rules.
Lama Dev is an AI-powered chatbot application built using React, Node.js, and MongoDB. It allows users to engage in real-time conversations and ask any question, leveraging the Google Gemini API for intelligent responses.

## Features

- **AI-Powered Conversations:** Users can ask questions and receive AI-generated responses using the Google Gemini API.

- **User Authentication:** Secure login and registration using JWT-based authentication.

- **Chat History:** Stores user conversations for easy access and continuity.

- **Real-Time Communication:** WebSocket integration for instant messaging.

- **Scalable Backend:** Node.js and Express.js ensure efficient request handling and performance optimization.

- **Database Management:** MongoDB stores chat data securely.

## Technologies Used

Frontend: React.js, Tailwind CSS

Backend: Node.js, Express.js

Database: MongoDB

APIs: Google Gemini API, JWT Authentication

Real-Time Communication: WebSockets

### API Endpoints

- POST /api/auth/register - Register a new user

- POST /api/auth/login - Authenticate user

- GET /api/chat/history - Fetch user chat history

- POST /api/chat/send - Send a user query and receive AI response

## Contributing

Contributions are welcome! Please fork the repository and submit a pull request with your proposed changes.

## Screenshots
<span>
<img src="https://github.com/kartikpachori/My-Ai/blob/starter/assets/Pick1.png" width="100%" height="250%">
<img src="https://github.com/kartikpachori/My-Ai/blob/starter/assets/Pick2.png" width="100%" height="250%">
<img src="https://github.com/kartikpachori/My-Ai/blob/starter/assets/Pick3.png" width="100%" height="250%">
</span>
Binary file added assets/Pick1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/Pick2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/Pick3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions backend/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
IMAGE_KIT_ENDPOINT=https://ik.imagekit.io/fhfbjxkr0
IMAGE_KIT_PUBLIC_KEY=public_Vf3TxCowJ3PoNhPtxA6sW3caRqw=
IMAGE_KIT_PRIVATE_KEY=private_cC+DYZpwj1ahsupedteN38CsIdE=

CLIENT_URL = http://localhost:5173
MONGO = mongodb+srv://kartikeypachori1610:[email protected]/aichat?retryWrites=true&w=majority&appName=LamaDev

CLERK_PUBLISHABLE_KEY=pk_test_c3RlYWR5LW1vbmtleS00My5jbGVyay5hY2NvdW50cy5kZXYk
CLERK_SECRET_KEY=sk_test_HrZ9UciTatw1DqT21VQqhInKfueo0OvSKjEq6I70BK
168 changes: 168 additions & 0 deletions backend/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import express from "express";
import ImageKit from "imagekit";
import cors from "cors";
import mongoose from "mongoose";
import Chat from "./models/chat.js";
import UserChats from "./models/userChats.js";
import { ClerkExpressRequireAuth } from "@clerk/clerk-sdk-node";

const port = process.env.PORT || 3000;
const app = express();

app.use(
cors({
origin: process.env.CLIENT_URL,
credentials: true,
})
);

app.use(express.json());

const connect = async () => {
try {
await mongoose.connect(process.env.MONGO);
console.log("Connected to MongoDB");
} catch (err) {
console.log(err);
}
};

const imagekit = new ImageKit({
urlEndpoint: process.env.IMAGE_KIT_ENDPOINT,
publicKey: process.env.IMAGE_KIT_PUBLIC_KEY,
privateKey: process.env.IMAGE_KIT_PRIVATE_KEY,
});

app.get("/api/upload", (req, res) => {
const result = imagekit.getAuthenticationParameters();
res.send(result);
});

// app.get("/api/test", ClerkExpressRequireAuth(), (req, res) => {
// const userId = req.auth.userId;
// console.log(userId)
// res.send("Success!")
// })

app.post("/api/chats", ClerkExpressRequireAuth(), async (req, res) => {
const userId = req.auth.userId;
const { text } = req.body;

try {
// CREATE A NEW CHAT
const newChat = new Chat({
userId: userId,
history: [{ role: "user", parts: [{ text }] }],
});

const savedChat = await newChat.save();

// CHECK IF THE USERCHATS EXISTS
const userChats = await UserChats.find({ userId: userId });

// IF DOESN'T EXIST CREATE A NEW ONE AND ADD THE CHAT IN THE CHATS ARRAY
if (!userChats.length) {
const newUserChats = new UserChats({
userId: userId,
chats: [
{
_id: savedChat._id,
title: text.substring(0, 40),
},
],
});

await newUserChats.save();
} else {
// IF EXISTS, PUSH THE CHAT TO THE EXISTING ARRAY
await UserChats.updateOne(
{ userId: userId },
{
$push: {
chats: {
_id: savedChat._id,
title: text.substring(0, 40),
},
},
}
);

res.status(201).send(newChat._id);
}
} catch (err) {
console.log(err);
res.status(500).send("Error creating chat!");
}
});

app.get("/api/userchats", ClerkExpressRequireAuth(), async (req, res) => {
const userId = req.auth.userId;

try {
const userChats = await UserChats.find({ userId });
if (!userChats.length) {
return res.status(404).send("No chats found for this user.");
}
res.status(200).send(userChats[0].chats);
} catch (err) {
console.log(err);
res.status(500).send("Error fetching userchats!");
}
});

app.get("/api/chats/:id", ClerkExpressRequireAuth(), async (req, res) => {
const userId = req.auth.userId;

try {
const chat = await Chat.findOne({ _id: req.params.id, userId });
if (!chat) {
return res.status(404).send("Chat not found!");
}
res.status(200).send(chat);
} catch (err) {
console.log(err);
res.status(500).send("Error fetching chat!");
}
});

app.put("/api/chats/:id", ClerkExpressRequireAuth(), async (req, res) => {
const userId = req.auth.userId;

const { question, answer, img } = req.body;

const newItems = [
...(question
? [{ role: "user", parts: [{ text: question }], ...(img && { img }) }]
: []),
{ role: "model", parts: [{ text: answer }] },
];

try {
const updatedChat = await Chat.updateOne(
{ _id: req.params.id, userId },
{
$push: {
history: {
$each: newItems,
},
},
}
);
res.status(200).send(updatedChat);
} catch (err) {
console.log(err);
res.status(500).send("Error adding conversation!");
}
});


app.use((err, req, res, next) => {
console.error(err.stack);
res.status(401).send("Unauthenticated!");
});


app.listen(port, () => {
connect();
console.log("Server running on 3000");
});
34 changes: 34 additions & 0 deletions backend/models/chat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import mongoose from "mongoose";

const chatSchema = new mongoose.Schema(
{
userId: {
type: String,
required: true,
},
history: [
{
role: {
type: String,
enum: ["user", "model"],
required: true,
},
parts: [
{
text: {
type: String,
required: true,
},
},
],
img: {
type: String,
required: false,
},
},
],
},
{ timestamps: true }
);

export default mongoose.models.chat || mongoose.model("chat", chatSchema);
30 changes: 30 additions & 0 deletions backend/models/userChats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import mongoose from "mongoose";

const userChatsSchema = new mongoose.Schema(
{
userId: {
type: String,
required: true,
},
chats: [
{
_id: {
type: String,
required: true,
},
title: {
type: String,
required: true,
},
createdAt: {
type: Date,
default: Date.now()
},
},
],
},
{ timestamps: true }
);

export default mongoose.models.userchats ||
mongoose.model("userchats", userChatsSchema);
16 changes: 16 additions & 0 deletions backend/node_modules/.bin/mime

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions backend/node_modules/.bin/mime.cmd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions backend/node_modules/.bin/mime.ps1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions backend/node_modules/.bin/nodemon

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading