Spaces:
Runtime error
Runtime error
Soham
commited on
Commit
·
6648464
1
Parent(s):
e90709b
created folder strucutre
Browse files- .gitignore +3 -0
- Dockerfile +14 -0
- ai_model/callAiModel.py +48 -0
- ai_model/callGeminiModel.py +27 -0
- config/database.py +13 -0
- main.py +14 -0
- requirements.txt +11 -0
- routes/route.py +259 -0
- schema/model.py +42 -0
- utils/auth.py +40 -0
- utils/download_mongodb_logs.py +51 -0
- utils/email_validator.py +37 -0
.gitignore
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.venv
|
| 2 |
+
.env
|
| 3 |
+
__pycache__/
|
Dockerfile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# read the doc: https://huggingface.co/docs/hub/spaces-sdks-docker
|
| 2 |
+
# you will also find guides on how best to write your Dockerfile
|
| 3 |
+
|
| 4 |
+
FROM python:3.9
|
| 5 |
+
|
| 6 |
+
WORKDIR /code
|
| 7 |
+
|
| 8 |
+
COPY ./requirements.txt /code/requirements.txt
|
| 9 |
+
|
| 10 |
+
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
|
| 11 |
+
|
| 12 |
+
COPY . .
|
| 13 |
+
|
| 14 |
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
|
ai_model/callAiModel.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain.chains import LLMChain
|
| 2 |
+
from langchain.memory import ConversationBufferMemory
|
| 3 |
+
from langchain.prompts import PromptTemplate
|
| 4 |
+
from langchain_huggingface import HuggingFaceEndpoint
|
| 5 |
+
|
| 6 |
+
# HuggingFace Endpoint Initialization
|
| 7 |
+
repo_id = "mistralai/Mixtral-8x7B-Instruct-v0.1"
|
| 8 |
+
llmModel = HuggingFaceEndpoint(
|
| 9 |
+
repo_id=repo_id,
|
| 10 |
+
max_new_tokens=512,
|
| 11 |
+
temperature=0.5,
|
| 12 |
+
huggingfacehub_api_token="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",
|
| 13 |
+
task="text-generation",
|
| 14 |
+
)
|
| 15 |
+
|
| 16 |
+
# Define the prompt template
|
| 17 |
+
prompt = PromptTemplate(
|
| 18 |
+
input_variables=["logs", "query"],
|
| 19 |
+
template=(
|
| 20 |
+
""" You are an expert log analyzer. Analyze the system logs provided below. Return only precise and concise answers to the questions asked, formatted clearly and without unnecessary elaboration.
|
| 21 |
+
Logs: {logs}
|
| 22 |
+
User's Query: Analyze the logs and answer the following question:{query}
|
| 23 |
+
Be concise and direct in your responses."""
|
| 24 |
+
),
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
# Memory setup
|
| 28 |
+
memory = ConversationBufferMemory(
|
| 29 |
+
input_key="query",
|
| 30 |
+
memory_key="history",
|
| 31 |
+
return_messages=False,
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
# Create the LLM chain with memory
|
| 35 |
+
conversation_chain = LLMChain(llm=llmModel, prompt=prompt, memory=memory)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def generate_ai_response(user_query,logs):
|
| 39 |
+
try:
|
| 40 |
+
# Run the conversation chain
|
| 41 |
+
response = conversation_chain.run({"logs": logs, "query": user_query})
|
| 42 |
+
return response
|
| 43 |
+
except Exception as e:
|
| 44 |
+
print(e)
|
| 45 |
+
return f"An error occurred: {e}"
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
# generate_ai_response ("who is prime minister of india")
|
ai_model/callGeminiModel.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import google.generativeai as genai
|
| 2 |
+
from langchain.prompts import PromptTemplate
|
| 3 |
+
|
| 4 |
+
# Configure Gemini
|
| 5 |
+
api_key = "AIzaSyCWj2sHInMricyC2frSg3uwUgsd_QOGkLA"
|
| 6 |
+
genai.configure(api_key=api_key)
|
| 7 |
+
model = genai.GenerativeModel(model_name="gemini-1.5-flash-latest")
|
| 8 |
+
|
| 9 |
+
# Define the Prompt Template
|
| 10 |
+
log_prompt = PromptTemplate(
|
| 11 |
+
input_variables=["logs", "query"],
|
| 12 |
+
template=(
|
| 13 |
+
"""You are an expert log analyzer. Analyze the system logs provided below.
|
| 14 |
+
Return only precise and concise answers to the questions asked, formatted clearly.
|
| 15 |
+
|
| 16 |
+
Logs: {logs}
|
| 17 |
+
User's Query: {query}
|
| 18 |
+
|
| 19 |
+
Be concise and direct in your responses."""
|
| 20 |
+
),
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def generate_ai_response(user_query, logs):
|
| 25 |
+
formatted_prompt = log_prompt.format(logs=logs, query=user_query)
|
| 26 |
+
response = model.generate_content([formatted_prompt])
|
| 27 |
+
return response.text
|
config/database.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pymongo
|
| 2 |
+
import gridfs
|
| 3 |
+
|
| 4 |
+
# database connection
|
| 5 |
+
client = pymongo.MongoClient(
|
| 6 |
+
"mongodb+srv://soham2000:soham2000@cluster0.lbu4i.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0",
|
| 7 |
+
ssl=True,
|
| 8 |
+
)
|
| 9 |
+
db = client["nodetest"]
|
| 10 |
+
user_collection = db["users"]
|
| 11 |
+
chat_collection = db["chats"]
|
| 12 |
+
log_collection = db["logs"]
|
| 13 |
+
fs = gridfs.GridFS(db) # Initialize GridFS bucket
|
main.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI
|
| 2 |
+
from routes.route import router
|
| 3 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 4 |
+
app = FastAPI()
|
| 5 |
+
|
| 6 |
+
app.add_middleware(
|
| 7 |
+
CORSMiddleware,
|
| 8 |
+
allow_origins=["*"], # Allow requests from any origin
|
| 9 |
+
allow_credentials=True,
|
| 10 |
+
allow_methods=["GET", "POST", "PUT", "DELETE"],
|
| 11 |
+
allow_headers=["Authorization", "Content-Type"],
|
| 12 |
+
)
|
| 13 |
+
|
| 14 |
+
app.include_router(router)
|
requirements.txt
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastapi==0.115.8
|
| 2 |
+
uvicorn==0.34.0
|
| 3 |
+
pydantic==2.10.6
|
| 4 |
+
pymongo==4.11
|
| 5 |
+
passlib[bcrypt]
|
| 6 |
+
python-jose[cryptography]
|
| 7 |
+
python-multipart==0.0.20
|
| 8 |
+
langchain==0.3.17
|
| 9 |
+
langchain-huggingface==0.1.2
|
| 10 |
+
google-generativeai==0.8.4
|
| 11 |
+
huggingface-hub==0.28.1
|
routes/route.py
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
from fastapi import APIRouter, Body, HTTPException, Depends
|
| 3 |
+
from ai_model.callGeminiModel import generate_ai_response
|
| 4 |
+
from config.database import user_collection, chat_collection, log_collection
|
| 5 |
+
from utils.auth import create_access_token, hash_password, verify_password, verify_token
|
| 6 |
+
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
| 7 |
+
from schema.model import (
|
| 8 |
+
ChatData,
|
| 9 |
+
DateRangeModel,
|
| 10 |
+
QueryModel,
|
| 11 |
+
UserIdModel,
|
| 12 |
+
UserRegister,
|
| 13 |
+
UserLogin,
|
| 14 |
+
)
|
| 15 |
+
from datetime import datetime, timedelta, timezone
|
| 16 |
+
from cryptography.fernet import Fernet
|
| 17 |
+
|
| 18 |
+
security_scheme = HTTPBearer()
|
| 19 |
+
router = APIRouter()
|
| 20 |
+
activation_tokens = {}
|
| 21 |
+
encryption_key = b"kFRvFTtpl6WDr0eceOteS5IAnv3ps0YtCavmUwllO0k="
|
| 22 |
+
cipher = Fernet(encryption_key)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
# -------------------------------------------User Collections-------------------------------------------
|
| 26 |
+
@router.post("/api/user/userLogin", tags=["user"])
|
| 27 |
+
async def user_login(userLogin: UserLogin):
|
| 28 |
+
collection = user_collection
|
| 29 |
+
user = collection.find_one({"userName": userLogin.userName})
|
| 30 |
+
if not user or not verify_password(userLogin.password, user.get("password", "")):
|
| 31 |
+
raise HTTPException(status_code=401, detail="Incorrect username or password")
|
| 32 |
+
user_data = {
|
| 33 |
+
"email": user.get("email"),
|
| 34 |
+
"username": user.get("userName"),
|
| 35 |
+
"id": str(user.get("_id")),
|
| 36 |
+
"role": user.get("role"),
|
| 37 |
+
}
|
| 38 |
+
token = create_access_token({"sub": userLogin.userName})
|
| 39 |
+
response_data = {
|
| 40 |
+
"access_token": token,
|
| 41 |
+
"token_type": "bearer",
|
| 42 |
+
"user_data": user_data,
|
| 43 |
+
}
|
| 44 |
+
return response_data
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
# User Registration Api
|
| 48 |
+
@router.post("/api/user/registerUser", tags=["user"])
|
| 49 |
+
async def create_user(user: UserRegister):
|
| 50 |
+
hashed_password = hash_password(user.password)
|
| 51 |
+
user_dict = user.dict()
|
| 52 |
+
user_dict["password"] = hashed_password
|
| 53 |
+
result = user_collection.insert_one(user_dict)
|
| 54 |
+
return {"message": "User created successfully", "userId": str(result.inserted_id)}
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
# Api to show the registered users list
|
| 58 |
+
@router.get(
|
| 59 |
+
"/api/user/getAllUsers", tags=["user"], dependencies=[Depends(security_scheme)]
|
| 60 |
+
)
|
| 61 |
+
async def get_all_user(token: HTTPAuthorizationCredentials = Depends(security_scheme)):
|
| 62 |
+
verify_token(token.credentials)
|
| 63 |
+
users = user_collection.find({})
|
| 64 |
+
user_list = []
|
| 65 |
+
for user in users:
|
| 66 |
+
user["_id"] = str(user["_id"]) # Convert ObjectId to string
|
| 67 |
+
user_list.append(user)
|
| 68 |
+
return user_list
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
# -------------------------------------------Model Collections-------------------------------------------
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
# Api to create new chat
|
| 75 |
+
@router.post(
|
| 76 |
+
"/api/model/callModel", tags=["model"], dependencies=[Depends(security_scheme)]
|
| 77 |
+
)
|
| 78 |
+
async def call_ai_model(
|
| 79 |
+
query: QueryModel,
|
| 80 |
+
token: HTTPAuthorizationCredentials = Depends(security_scheme),
|
| 81 |
+
):
|
| 82 |
+
verify_token(token.credentials)
|
| 83 |
+
answer = generate_ai_response(query.query, query.logs)
|
| 84 |
+
return {"answer": answer}
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
# Api to show the registered users list
|
| 88 |
+
@router.post(
|
| 89 |
+
"/api/model/getAllChatHistoryByTitleId",
|
| 90 |
+
tags=["model"],
|
| 91 |
+
dependencies=[Depends(security_scheme)],
|
| 92 |
+
)
|
| 93 |
+
async def get_all_chat_history(
|
| 94 |
+
titleUId: str = Body(...),
|
| 95 |
+
userID: str = Body(...),
|
| 96 |
+
token: HTTPAuthorizationCredentials = Depends(security_scheme),
|
| 97 |
+
):
|
| 98 |
+
verify_token(token.credentials)
|
| 99 |
+
if not titleUId or not userID:
|
| 100 |
+
raise HTTPException(
|
| 101 |
+
status_code=400, detail="Both titleUId and userID are required"
|
| 102 |
+
)
|
| 103 |
+
|
| 104 |
+
# Find matching document from MongoDB
|
| 105 |
+
result = chat_collection.find_one({"titleUId": titleUId, "userID": userID})
|
| 106 |
+
if not result:
|
| 107 |
+
raise HTTPException(status_code=404, detail="No chat history found")
|
| 108 |
+
|
| 109 |
+
# Convert ObjectId and prepare response
|
| 110 |
+
result["_id"] = str(result["_id"])
|
| 111 |
+
result.pop("_id", None) # Remove _id if not needed
|
| 112 |
+
|
| 113 |
+
# Ensure chat format consistency
|
| 114 |
+
result.setdefault("chat", [])
|
| 115 |
+
result["chat"] = [
|
| 116 |
+
{"question": entry.get("question", ""), "answer": entry.get("answer", "")}
|
| 117 |
+
for entry in result.get("chat", [])
|
| 118 |
+
]
|
| 119 |
+
|
| 120 |
+
return result
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
@router.post(
|
| 124 |
+
"/api/model/addUpdateChatHistory",
|
| 125 |
+
tags=["model"],
|
| 126 |
+
dependencies=[Depends(security_scheme)],
|
| 127 |
+
)
|
| 128 |
+
async def add_or_update_chat(
|
| 129 |
+
data: ChatData,
|
| 130 |
+
token: HTTPAuthorizationCredentials = Depends(security_scheme),
|
| 131 |
+
):
|
| 132 |
+
verify_token(token.credentials)
|
| 133 |
+
existing_entry = chat_collection.find_one(
|
| 134 |
+
{"userID": data.userID, "titleUId": data.titleUId}
|
| 135 |
+
)
|
| 136 |
+
|
| 137 |
+
if existing_entry:
|
| 138 |
+
# Extract existing chat questions to avoid duplication
|
| 139 |
+
existing_questions = {
|
| 140 |
+
entry["question"] for entry in existing_entry.get("chat", [])
|
| 141 |
+
}
|
| 142 |
+
new_entries = [
|
| 143 |
+
entry.dict()
|
| 144 |
+
for entry in data.chat
|
| 145 |
+
if entry.question not in existing_questions
|
| 146 |
+
]
|
| 147 |
+
|
| 148 |
+
if new_entries:
|
| 149 |
+
chat_collection.update_one(
|
| 150 |
+
{"_id": existing_entry["_id"]},
|
| 151 |
+
{"$push": {"chat": {"$each": new_entries}}},
|
| 152 |
+
)
|
| 153 |
+
return {"message": "Chat updated successfully."}
|
| 154 |
+
else:
|
| 155 |
+
return {"message": "No new chat entries to add."}
|
| 156 |
+
else:
|
| 157 |
+
# Insert new document
|
| 158 |
+
new_data = data.dict()
|
| 159 |
+
chat_collection.insert_one(new_data)
|
| 160 |
+
return {"message": "Chat added successfully."}
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
@router.post(
|
| 165 |
+
"/api/model/getAllTitleByUserId",
|
| 166 |
+
tags=["model"],
|
| 167 |
+
dependencies=[Depends(security_scheme)],
|
| 168 |
+
)
|
| 169 |
+
async def get_all_title(
|
| 170 |
+
data: UserIdModel,
|
| 171 |
+
token: HTTPAuthorizationCredentials = Depends(security_scheme),
|
| 172 |
+
):
|
| 173 |
+
verify_token(token.credentials)
|
| 174 |
+
chats = chat_collection.find({"userID": data.userID})
|
| 175 |
+
chatList = []
|
| 176 |
+
for chat in chats:
|
| 177 |
+
chatObj = {
|
| 178 |
+
"titleUId": chat["titleUId"],
|
| 179 |
+
"titleName": chat["titleName"],
|
| 180 |
+
} # Convert ObjectId to string
|
| 181 |
+
chatList.append(chatObj)
|
| 182 |
+
chatList.reverse()
|
| 183 |
+
return chatList
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
@router.post(
|
| 188 |
+
"/api/model/getAllLogsByDateRange",
|
| 189 |
+
tags=["model"],
|
| 190 |
+
dependencies=[Depends(security_scheme)],
|
| 191 |
+
)
|
| 192 |
+
async def get_logs_by_daterange(
|
| 193 |
+
data: DateRangeModel,
|
| 194 |
+
token: HTTPAuthorizationCredentials = Depends(security_scheme),
|
| 195 |
+
):
|
| 196 |
+
verify_token(token.credentials)
|
| 197 |
+
current_date = datetime.now(timezone.utc) # Ensure timezone awareness
|
| 198 |
+
|
| 199 |
+
# Determine start_date based on duration format
|
| 200 |
+
if " - " in data.duration: # Handle custom date range
|
| 201 |
+
try:
|
| 202 |
+
start_date_str, end_date_str = map(str.strip, data.duration.split(" - "))
|
| 203 |
+
start_date = datetime.fromisoformat(start_date_str)
|
| 204 |
+
end_date = datetime.fromisoformat(end_date_str)
|
| 205 |
+
except ValueError:
|
| 206 |
+
raise ValueError("Invalid date format. Use ISO 8601 format: YYYY-MM-DDTHH:MM:SS.ssssss+00:00 - YYYY-MM-DDTHH:MM:SS.ssssss+00:00")
|
| 207 |
+
else: # Handle predefined durations
|
| 208 |
+
if data.duration == "1 Day":
|
| 209 |
+
start_date = current_date - timedelta(days=1)
|
| 210 |
+
elif data.duration == "Current Week":
|
| 211 |
+
start_date = current_date - timedelta(weeks=1)
|
| 212 |
+
elif data.duration == "Last 2 Weeks":
|
| 213 |
+
start_date = current_date - timedelta(weeks=2)
|
| 214 |
+
else:
|
| 215 |
+
raise ValueError("Invalid duration selected")
|
| 216 |
+
end_date = current_date
|
| 217 |
+
|
| 218 |
+
# Ensure timestamps are in UTC
|
| 219 |
+
start_date = start_date.astimezone(timezone.utc)
|
| 220 |
+
end_date = end_date.astimezone(timezone.utc)
|
| 221 |
+
|
| 222 |
+
duration_str = f"{start_date.isoformat()} - {end_date.isoformat()}"
|
| 223 |
+
|
| 224 |
+
logs_list = []
|
| 225 |
+
for encrypted_record in log_collection.find():
|
| 226 |
+
encrypted_data = encrypted_record["encrypted_data"]
|
| 227 |
+
decrypted_data = cipher.decrypt(encrypted_data).decode()
|
| 228 |
+
log = json.loads(decrypted_data)
|
| 229 |
+
log_timestamp = datetime.fromisoformat(log["Timestamp"]).astimezone(timezone.utc)
|
| 230 |
+
|
| 231 |
+
if start_date <= log_timestamp <= end_date:
|
| 232 |
+
logs_list.append(log)
|
| 233 |
+
|
| 234 |
+
return {"duration": duration_str, "logList": logs_list}
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
@router.delete(
|
| 238 |
+
"/api/model/deleteChatHistoryByTitleId",
|
| 239 |
+
tags=["model"],
|
| 240 |
+
dependencies=[Depends(security_scheme)],
|
| 241 |
+
)
|
| 242 |
+
async def delete_chat_history(
|
| 243 |
+
titleUId: str = Body(...),
|
| 244 |
+
userID: str = Body(...),
|
| 245 |
+
token: HTTPAuthorizationCredentials = Depends(security_scheme),
|
| 246 |
+
):
|
| 247 |
+
verify_token(token.credentials)
|
| 248 |
+
if not titleUId or not userID:
|
| 249 |
+
raise HTTPException(
|
| 250 |
+
status_code=400, detail="Both titleUId and userID are required"
|
| 251 |
+
)
|
| 252 |
+
|
| 253 |
+
# Attempt to delete the document
|
| 254 |
+
delete_result = chat_collection.delete_one({"titleUId": titleUId, "userID": userID})
|
| 255 |
+
|
| 256 |
+
if delete_result.deleted_count == 0:
|
| 257 |
+
raise HTTPException(status_code=404, detail="No chat history found to delete")
|
| 258 |
+
|
| 259 |
+
return {"message": "Chat history deleted successfully"}
|
schema/model.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel
|
| 2 |
+
from typing import List
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
# user registration parameters
|
| 6 |
+
class UserRegister(BaseModel):
|
| 7 |
+
name: str
|
| 8 |
+
userName: str
|
| 9 |
+
email: str
|
| 10 |
+
password: str
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
# user login parameters
|
| 14 |
+
class UserLogin(BaseModel):
|
| 15 |
+
userName: str
|
| 16 |
+
password: str
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class ChatEntry(BaseModel):
|
| 20 |
+
question: str
|
| 21 |
+
answer: str
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class ChatData(BaseModel):
|
| 25 |
+
userID: str
|
| 26 |
+
titleName: str
|
| 27 |
+
titleUId: str
|
| 28 |
+
dateRange: str
|
| 29 |
+
chat: List[ChatEntry]
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class UserIdModel(BaseModel):
|
| 33 |
+
userID: str
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class QueryModel(BaseModel):
|
| 37 |
+
query: str
|
| 38 |
+
logs: str
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
class DateRangeModel(BaseModel):
|
| 42 |
+
duration: str
|
utils/auth.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import HTTPException, status
|
| 2 |
+
from fastapi.security import HTTPBearer
|
| 3 |
+
from datetime import datetime, timedelta
|
| 4 |
+
from jose import JWTError, jwt
|
| 5 |
+
import bcrypt
|
| 6 |
+
|
| 7 |
+
security = HTTPBearer()
|
| 8 |
+
|
| 9 |
+
# Secret key for JWT token
|
| 10 |
+
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
|
| 11 |
+
ALGORITHM = "HS256"
|
| 12 |
+
ACCESS_TOKEN_EXPIRE_MINUTES = 180
|
| 13 |
+
|
| 14 |
+
# Function to generate JWT token
|
| 15 |
+
def create_access_token(data: dict):
|
| 16 |
+
to_encode = data.copy()
|
| 17 |
+
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
| 18 |
+
to_encode.update({"exp": expire})
|
| 19 |
+
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
| 20 |
+
return encoded_jwt
|
| 21 |
+
|
| 22 |
+
# Function to hash a password
|
| 23 |
+
def hash_password(password: str) -> str:
|
| 24 |
+
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
|
| 25 |
+
return hashed_password
|
| 26 |
+
|
| 27 |
+
# Function to verify a password
|
| 28 |
+
def verify_password(plain_password: str, hashed_password: bytes) -> bool:
|
| 29 |
+
return bcrypt.checkpw(plain_password.encode('utf-8'), hashed_password)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def verify_token(token: str):
|
| 33 |
+
try:
|
| 34 |
+
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
| 35 |
+
return payload
|
| 36 |
+
except JWTError:
|
| 37 |
+
raise HTTPException(
|
| 38 |
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
| 39 |
+
detail="Invalid or expired token"
|
| 40 |
+
)
|
utils/download_mongodb_logs.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pymongo import MongoClient
|
| 2 |
+
from cryptography.fernet import Fernet
|
| 3 |
+
import json
|
| 4 |
+
from datetime import datetime, timedelta
|
| 5 |
+
|
| 6 |
+
# MongoDB connection string
|
| 7 |
+
connection_string = "mongodb+srv://soham2000:soham2000@cluster0.lbu4i.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0"
|
| 8 |
+
|
| 9 |
+
# Encryption key (generate this once and store securely)
|
| 10 |
+
encryption_key = b"kFRvFTtpl6WDr0eceOteS5IAnv3ps0YtCavmUwllO0k="
|
| 11 |
+
cipher = Fernet(encryption_key)
|
| 12 |
+
|
| 13 |
+
client = MongoClient(connection_string)
|
| 14 |
+
db = client["nodetest"]
|
| 15 |
+
collection = db["logs"]
|
| 16 |
+
logs_list = []
|
| 17 |
+
# Calculate the date range based on the selected duration
|
| 18 |
+
def download_logs(duration):
|
| 19 |
+
# Get the current date
|
| 20 |
+
current_date = datetime.now()
|
| 21 |
+
|
| 22 |
+
# Calculate the start and end date based on the selected duration
|
| 23 |
+
if duration == "1 day":
|
| 24 |
+
start_date = current_date - timedelta(days=1)
|
| 25 |
+
end_date = current_date
|
| 26 |
+
elif duration == "1 week":
|
| 27 |
+
start_date = current_date - timedelta(weeks=1)
|
| 28 |
+
end_date = current_date
|
| 29 |
+
elif duration == "2 weeks":
|
| 30 |
+
start_date = current_date - timedelta(weeks=2)
|
| 31 |
+
end_date = current_date
|
| 32 |
+
else:
|
| 33 |
+
raise ValueError("Invalid duration selected")
|
| 34 |
+
|
| 35 |
+
# Decrypt and filter logs based on the calculated date range
|
| 36 |
+
for encrypted_record in collection.find():
|
| 37 |
+
encrypted_data = encrypted_record["encrypted_data"]
|
| 38 |
+
decrypted_data = cipher.decrypt(encrypted_data).decode()
|
| 39 |
+
log = json.loads(decrypted_data)
|
| 40 |
+
|
| 41 |
+
# Parse the Timestamp field into a datetime object
|
| 42 |
+
log_timestamp = datetime.fromisoformat(log["Timestamp"])
|
| 43 |
+
|
| 44 |
+
# Check if the log falls within the specified date range
|
| 45 |
+
if start_date <= log_timestamp <= end_date:
|
| 46 |
+
logs_list.append(log)
|
| 47 |
+
|
| 48 |
+
return logs_list
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
download_logs("1 week")
|
utils/email_validator.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from email.mime.text import MIMEText
|
| 2 |
+
from email.mime.multipart import MIMEMultipart
|
| 3 |
+
import smtplib
|
| 4 |
+
|
| 5 |
+
# Function to send activation email with HTML content
|
| 6 |
+
def send_activation_email(email: str, activation_otp: int):
|
| 7 |
+
sender_email = "chandratresoham@gmail.com" # Update with your email address
|
| 8 |
+
sender_password = "wbuc okcv hzzn iwyx" # Update with your email password
|
| 9 |
+
# Update with your website URL
|
| 10 |
+
|
| 11 |
+
# HTML content for the email body
|
| 12 |
+
email_body = f"""
|
| 13 |
+
<html>
|
| 14 |
+
<body>
|
| 15 |
+
<p>
|
| 16 |
+
Hello,<br><br>
|
| 17 |
+
You have successfully registered to the system.<br><br>
|
| 18 |
+
Please enter below otp to verify your accout<br><br>
|
| 19 |
+
<p style="font-size:17px; font-weight:bold">{activation_otp}</p><br><br>
|
| 20 |
+
Thank you!<br>
|
| 21 |
+
</p>
|
| 22 |
+
</body>
|
| 23 |
+
</html>
|
| 24 |
+
"""
|
| 25 |
+
|
| 26 |
+
# Create MIMEText object with HTML content
|
| 27 |
+
message = MIMEMultipart("alternative")
|
| 28 |
+
message['From'] = sender_email
|
| 29 |
+
message['To'] = email
|
| 30 |
+
message['Subject'] = "Activate your account"
|
| 31 |
+
message.attach(MIMEText(email_body, 'html'))
|
| 32 |
+
|
| 33 |
+
# Connect to SMTP server and send email
|
| 34 |
+
with smtplib.SMTP('smtp.gmail.com', 587) as server: # Update with your SMTP server details
|
| 35 |
+
server.starttls()
|
| 36 |
+
server.login(sender_email, sender_password)
|
| 37 |
+
server.sendmail(sender_email, email, message.as_string())
|