HemanthSai7 commited on
Commit
2ecc792
Β·
1 Parent(s): 5267759

Separated the backend and frontend

Browse files
.devcontainer/devcontainer.json DELETED
@@ -1,33 +0,0 @@
1
- {
2
- "name": "Python 3",
3
- // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
4
- "image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
5
- "customizations": {
6
- "codespaces": {
7
- "openFiles": [
8
- "README.md",
9
- "frontend/🏑_Home.py"
10
- ]
11
- },
12
- "vscode": {
13
- "settings": {},
14
- "extensions": [
15
- "ms-python.python",
16
- "ms-python.vscode-pylance"
17
- ]
18
- }
19
- },
20
- "updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y <packages.txt; [ -f requirements.txt ] && pip3 install --user -r requirements.txt; pip3 install --user streamlit; echo 'βœ… Packages installed and Requirements met'",
21
- "postAttachCommand": {
22
- "server": "streamlit run frontend/🏑_Home.py --server.enableCORS false --server.enableXsrfProtection false"
23
- },
24
- "portsAttributes": {
25
- "8501": {
26
- "label": "Application",
27
- "onAutoForward": "openPreview"
28
- }
29
- },
30
- "forwardPorts": [
31
- 8501
32
- ]
33
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
TechdocsAPI/.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
TechdocsAPI/Dockerfile ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11
2
+
3
+ WORKDIR /backend
4
+
5
+ COPY ./requirements.txt /backend/requirements.txt
6
+
7
+ RUN pip install --no-cache-dir --upgrade -r /backend/requirements.txt
8
+
9
+ COPY . .
10
+
11
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
TechdocsAPI/README.md ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: TechdocsAPI
3
+ emoji: 🐒
4
+ colorFrom: green
5
+ colorTo: green
6
+ sdk: docker
7
+ pinned: false
8
+ ---
9
+
10
+ # Techdocs: A code documentation generator
11
+
12
+ ## Introduction
13
+
14
+ **Code Documentation Generation** is a tool that generates documentation for your code. It is a simple tool that can be used by anyone who wants to generate documentation for their code. It leverages the power of **OpenAI GPT-3, Huggingface Transformers, Langchain and Clarifai** to generate documentation for your code.
15
+
16
+ To use the application, you need to provide your code as input. The tool will analyze your code and generate documentation for it. The documentation will include comments, descriptions, parameters, return values, examples, and more.
17
+
18
+ It is a useful tool for developers who want to document their code without spending too much time and effort. It can help you improve the readability, maintainability, and quality of your code. It can also help you share your code with others more easily.
19
+
20
+ ## Installation
21
+ > Download zip or Clone the repository and run the following command in the terminal to install the required packages.
22
+
23
+ > We recommend using a virtual environment for the installation.
24
+
25
+ ```bash
26
+ $ git clone https://github.com/HemanthSai7/Techdocs
27
+ $ cd Techdocs
28
+ $ pip install -r requirements.txt
29
+ $ -- Run backend
30
+ $ uvicorn app:app --reload
31
+ ```
32
+
33
+ ## Tech Stack Used
34
+ ![Python](https://img.shields.io/badge/python-3670A0?style=for-the-badge&logo=python&logoColor=ffdd54)
35
+ ![Azure](https://img.shields.io/badge/azure_SQL-%230072C6.svg?style=for-the-badge&logo=microsoftazure&logoColor=white)
36
+ ![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=for-the-badge&logo=fastapi)
37
+ ![Vercel](https://img.shields.io/badge/vercel-%23000000.svg?style=for-the-badge&logo=vercel&logoColor=white)
38
+ ![JWT](https://img.shields.io/badge/JWT-black?style=for-the-badge&logo=JSON%20web%20tokens)
39
+ ![GitHub Actions](https://img.shields.io/badge/github%20actions-%232671E5.svg?style=for-the-badge&logo=githubactions&logoColor=white)
40
+ ![Streamlit](https://img.shields.io/badge/Streamlit-EA6566?style=for-the-badge&logo=streamlit&logoColor=white)
41
+ ![Langchain](https://img.shields.io/badge/Langchain-F70A8D?style=for-the-badge&logo=langchain&logoColor=white)
42
+ ![Clarifai](https://img.shields.io/badge/Clarifai-FFA500?style=for-the-badge&logo=clarifai&logoColor=white)
43
+
44
+ ## Team Members
45
+ | Name | Github |
46
+ | --- | --- |
47
+ | Mayuresh Agashe | [Mayuresh Agashe](https://github.com/mayureshagashe2105) |
48
+ | Hemanth Sai Garladinne | [Hemanth Sai Garladinne](https://github.com/HemanthSai7) |
TechdocsAPI/app.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from backend import app
TechdocsAPI/backend/__init__.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import mysql.connector
2
+ from mysql.connector import errorcode
3
+
4
+ from fastapi import FastAPI, status
5
+ from fastapi.exceptions import HTTPException
6
+
7
+ from backend.utils import DBConnection
8
+ from backend.core.ConfigEnv import config
9
+
10
+ from langchain.llms import Clarifai
11
+ from langchain.chains import LLMChain
12
+ from langchain.prompts import PromptTemplate
13
+
14
+ app = FastAPI(title="Techdocs",
15
+ version="V0.0.1",
16
+ description="API for automatic code documentation generation!"
17
+ )
18
+
19
+ from backend import router
20
+
21
+ try:
22
+ dbconnection = DBConnection()
23
+ test_conn = DBConnection.get_client().get_server_info()
24
+
25
+ # send prompt wizardcoderLM-70b-instruct-GGUF model
26
+ with open("backend/utils/prompt.txt",'r') as f:
27
+ prompt = f.read()
28
+
29
+ prompt = PromptTemplate(template=prompt, input_variables=['instruction'])
30
+
31
+ llm = Clarifai(
32
+ pat = config.CLARIFAI_PAT,
33
+ user_id = config.USER_ID,
34
+ app_id = config.APP_ID,
35
+ model_id = config.MODEL_ID,
36
+ model_version_id=config.MODEL_VERSION_ID,
37
+ )
38
+
39
+ llmchain = LLMChain(
40
+ prompt=prompt,
41
+ llm=llm
42
+ )
43
+ app.state.llmchain = llmchain
44
+
45
+
46
+ except mysql.connector.Error as err:
47
+ raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(err))
48
+
49
+
TechdocsAPI/backend/core/ConfigEnv.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Config class for handling env variables.
2
+ """
3
+ from functools import lru_cache
4
+
5
+ from pydantic import BaseSettings
6
+
7
+
8
+ class Settings(BaseSettings):
9
+ HOSTNAME: str
10
+ DATABASE: str
11
+ UID: str
12
+ PASSWORD: str
13
+ ALGORITHM:str
14
+ JWT_SECRET_KEY:str
15
+ JWT_REFRESH_SECRET_KEY:str
16
+ # OPENAI_KEY:str
17
+ APP_ID:str
18
+ USER_ID:str
19
+ MODEL_ID:str
20
+ CLARIFAI_PAT:str
21
+ MODEL_VERSION_ID:str
22
+
23
+ class Config:
24
+ env_file = ".env"
25
+
26
+
27
+ @lru_cache()
28
+ def get_settings():
29
+ return Settings()
30
+
31
+
32
+ config = get_settings()
TechdocsAPI/backend/core/ExceptionHandlers.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from backend import app
2
+ from .Exceptions import *
3
+
4
+ from fastapi.responses import JSONResponse
5
+ from fastapi.requests import Request
6
+ from fastapi import status
7
+
8
+
9
+
10
+ @app.exception_handler(ExistingUserException)
11
+ async def handle_existing_user_found(request: Request, exec: ExistingUserException):
12
+ return JSONResponse(status_code=status.HTTP_226_IM_USED,
13
+ content=repr(exec)
14
+ )
15
+
16
+
17
+ @app.exception_handler(InvalidCredentialsException)
18
+ async def handle_login_failed(request: Request, exec: InvalidCredentialsException):
19
+ return JSONResponse(status_code=status.HTTP_403_FORBIDDEN,
20
+ content=repr(exec)
21
+ )
22
+
23
+ @app.exception_handler(InfoNotFoundException)
24
+ async def handle_info_not_found(request: Request, exec: InfoNotFoundException):
25
+ return JSONResponse(status_code=status.HTTP_401_UNAUTHORIZED,
26
+ content=repr(exec)
27
+ )
TechdocsAPI/backend/core/Exceptions.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+ from backend.models import GeneralResponse, TokenSchema
4
+
5
+
6
+ class InvalidCredentialsException(Exception):
7
+ def __init__(self, token_result: GeneralResponse):
8
+ self.token_result = token_result
9
+ self.set_statuses()
10
+ super(InvalidCredentialsException, self).__init__()
11
+
12
+ def set_statuses(self):
13
+ self.token_result.status = 'login_failed'
14
+
15
+ def __repr__(self):
16
+ return json.dumps(self.token_result)
17
+
18
+ class ExistingUserException(Exception):
19
+ def __init__(self, response_result: GeneralResponse):
20
+ self.response_result = response_result
21
+ self.set_statuses()
22
+ super(ExistingUserException, self).__init__()
23
+
24
+ def set_statuses(self):
25
+ self.response_result.status = f'failed'
26
+ self.response_result.message.append(f'user with this AADHAR Number already has an account')
27
+ self.response_result.message[0] = 'authenticated'
28
+
29
+ def __repr__(self):
30
+ return json.dumps(self.response_result)
31
+
32
+ class InfoNotFoundException(Exception):
33
+ def __init__(self, response_result: GeneralResponse, message: str):
34
+ self.response_result = response_result
35
+ self.message = message
36
+ self.set_statuses()
37
+ super(InfoNotFoundException, self).__init__(message)
38
+
39
+ def set_statuses(self):
40
+ self.response_result['status'] = 'abort'
41
+ self.response_result['message'][0] = 'authenticated'
42
+ self.response_result['message'].append(self.message)
43
+
44
+ def __repr__(self):
45
+ return json.dumps(self.response_result)
TechdocsAPI/backend/core/__init__.py ADDED
File without changes
TechdocsAPI/backend/models/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from .auth import *
2
+ from .generic import *
3
+ from .inference import *
TechdocsAPI/backend/models/auth.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel, Field, EmailStr
2
+ from typing import Union, List, Tuple
3
+
4
+ from .generic import Base
5
+
6
+
7
+ class TokenSchema(Base):
8
+ access_token: str
9
+ refresh_token: str
10
+
11
+
12
+ class UserAuth(Base):
13
+ username: str = Field(..., description="username")
14
+ password: str = Field(..., min_length=5, max_length=24, description="user password")
15
+ email: EmailStr
16
+
17
+
18
+ class User(Base):
19
+ username: str
20
+ email: EmailStr
21
+
22
+ class TokenPayload(Base):
23
+ sub: str = None
24
+ exp: int = None
25
+
26
+
27
+ class LoginCreds(Base):
28
+ username: str
29
+ password: str
30
+
31
+ class APIKey(Base):
32
+ api_key: str
TechdocsAPI/backend/models/generic.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import List
3
+
4
+
5
+ class Base(BaseModel):
6
+ @classmethod
7
+ def get_instance(cls, **kwargs):
8
+ return cls(**kwargs)
9
+
10
+
11
+ class GeneralResponse(Base):
12
+ status:str
13
+ message: List[str]
14
+ data:dict
TechdocsAPI/backend/models/inference.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import List
3
+ from .generic import Base
4
+
5
+ class Inference(Base):
6
+ docstr:str
TechdocsAPI/backend/router.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import Request, Depends, UploadFile
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+
4
+ from backend import app
5
+ from backend.utils import DBConnection
6
+ from backend.models import *
7
+ from backend.services.auth import *
8
+
9
+
10
+ app.add_middleware(
11
+ CORSMiddleware,
12
+ allow_origins=["*"],
13
+ allow_credentials=True,
14
+ allow_methods=["*"],
15
+ allow_headers=["*"],
16
+ )
17
+
18
+ @app.get("/api/response_check", tags=["Resource Server"])
19
+ def api_response_check():
20
+ response_result = GeneralResponse.get_instance(data={},
21
+ status="not_allowed",
22
+ message=["Not authenticated"]
23
+ )
24
+
25
+ try:
26
+ db_msg = ""
27
+ if DBConnection.is_connected():
28
+ db_msg = "Connection Successful to db!"
29
+ else:
30
+ db_msg = "Connection failed to db"
31
+
32
+ response_result.message.append(db_msg)
33
+
34
+ except Exception as e:
35
+ print("Exception :", e)
36
+
37
+ return response_result
38
+
39
+ @app.post("/auth/signup", summary="Creates new user account", response_model=GeneralResponse, tags=["Auth Server"])
40
+ async def signup(response: UserAuth):
41
+ response_result = GeneralResponse.get_instance(data={},
42
+ status="not_allowed",
43
+ message=["Not authenticated"]
44
+ )
45
+ ops_signup(response_result, response)
46
+
47
+ return response_result
48
+
49
+ @app.post("/auth/login", summary="Logs in user", response_model=TokenSchema, tags=["Auth Server"])
50
+ async def login(response:LoginCreds):
51
+ return ops_login(response)
52
+
53
+ @app.put("/auth/regenerate_api_key",summary="Forget Password",response_model=APIKey,tags=["Auth Server"],dependencies=[Depends(JWTBearer())])
54
+ async def regenerate_api_key(access_token: str = Depends(JWTBearer())):
55
+ user_sub=Auth.get_user_credentials(access_token)
56
+
57
+ return ops_regenerate_api_key(user_sub)
58
+
59
+ @app.post("/api/inference", summary="Inference", response_model=Inference, tags=["Resource Server"], dependencies=[Depends(JWTBearer())])
60
+ async def inference(code_block:str, api_key: str,access_token:str=Depends(JWTBearer())):
61
+ user_sub=Auth.get_user_credentials(access_token)
62
+
63
+ print("after res")
64
+
65
+ return ops_inference(code_block,api_key,user_sub)
TechdocsAPI/backend/services/__init__.py ADDED
File without changes
TechdocsAPI/backend/services/auth/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ from .ops import *
2
+ from .utils.JWTBearer import *
TechdocsAPI/backend/services/auth/ops.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .utils.auth_funcs import *
2
+ from .utils.JWTBearer import *
3
+ from backend.models import *
4
+ from backend.services.db.utils.DBQueries import DBQueries
5
+ from backend.core.Exceptions import *
6
+ from backend import app
7
+
8
+ # import openai
9
+ # from transformers import RobertaTokenizer, T5ForConditionalGeneration
10
+
11
+ def ops_signup(response_result: GeneralResponse, data: UserAuth):
12
+ """Wrapper method to handle signup process.
13
+
14
+ Args:
15
+ response_result: FrontendResponseModel. A TypedDict to return the
16
+ response captured from the API to the frontend.
17
+ data: UserAuth. New user's prospective credentials from the frontend
18
+ to create their account.
19
+
20
+ Raises:
21
+ ExistingUserException: If account with entered AADHAR Number already exists.
22
+ """
23
+ # querying database to check if user already exist
24
+ user = DBQueries.fetch_data_from_database('auth', ['username', 'email'], f"username='{data.username}' OR email='{data.email}'")
25
+ if len(list(user)) != 0:
26
+ # user with the entered credentials already exists
27
+ raise ExistingUserException(response_result)
28
+
29
+ DBQueries.insert_to_database('auth', (data.username, Auth.get_password_hash(data.password), data.email),
30
+ ['username', 'password', 'email'])
31
+
32
+ response_result.status = 'success'
33
+ response_result.message = [f'User created successfully']
34
+
35
+ def ops_login(data:LoginCreds):
36
+ """Wrapper method to handle login process.
37
+
38
+ Args:
39
+ data: LoginCreds. User's credentials from the frontend to login to their account.
40
+
41
+ Returns:
42
+ TokenSchema. A Pydantic BaseModel to return the JWT tokens to the frontend.
43
+
44
+ Raises:
45
+ InvalidCredentialsException: If account with entered credentials does not exist.
46
+ """
47
+ # querying database to check if user already exist
48
+ response_result = GeneralResponse.get_instance(data={},
49
+ status="not_allowed",
50
+ message=["Not authenticated"]
51
+ )
52
+ user = DBQueries.fetch_data_from_database('auth', ['username', 'password'], f"username='{data.username}'")
53
+ user = list(user)
54
+ if len(user) == 0:
55
+ # user with the entered credentials does not exist
56
+ raise InvalidCredentialsException(response_result)
57
+ user = user[0]
58
+ if not Auth.verify_password(data.password, user[1]) and Auth.verify_username(data.username, user[0]):
59
+ # password is incorrect
60
+ raise InvalidCredentialsException(response_result)
61
+
62
+ # password is correct
63
+ return TokenSchema(access_token=Auth.create_access_token(data.username),
64
+ refresh_token=Auth.create_refresh_token(data.username),
65
+ )
66
+
67
+ def ops_regenerate_api_key(username:str) -> APIKey:
68
+
69
+ user_API_entry = DBQueries.fetch_data_from_database('api_key', 'apikey', f"username='{username}'")
70
+ user_API_entry = list(user_API_entry)
71
+ apikey = None
72
+
73
+ if len(user_API_entry) != 0:
74
+ apikey = APIKey(api_key=Auth.generate_api_key(username))
75
+ DBQueries.update_data_in_database('api_key','apikey',f"username='{username}'", apikey.api_key)
76
+
77
+ else:
78
+ apikey = Auth.generate_api_key(username)
79
+ DBQueries.insert_to_database('api_key', (username, apikey), ['username', 'apikey'])
80
+ apikey = APIKey(api_key=apikey)
81
+
82
+ return apikey
83
+
84
+
85
+
86
+ def ops_inference(source_code:str,api_key:str,username:str):
87
+ response_result = GeneralResponse.get_instance(data={},
88
+ status="not_allowed",
89
+ message=["Not authenticated"]
90
+ )
91
+
92
+ user=DBQueries.fetch_data_from_database('api_key', ['apikey'], f"username='{username}'")
93
+ if len(list(user)) == 0:
94
+ # user with the entered credentials does not exist
95
+ raise InfoNotFoundException(response_result,"User not found")
96
+ elif list(user)[0][0]!=api_key:
97
+ raise InvalidCredentialsException(response_result)
98
+
99
+ def generate_docstring(source_code_message: str):
100
+
101
+
102
+ llm_response = app.state.llmchain.run({"instruction": source_code_message})
103
+
104
+ docstring = Inference(docstr=llm_response)
105
+
106
+
107
+ return docstring
108
+
109
+ return generate_docstring(source_code)
TechdocsAPI/backend/services/auth/utils/JWTBearer.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Custom Authentication & Authorization bearer to authenticate and authorize
2
+ users based on the following factors:
3
+ 1. username
4
+ 2.password
5
+ 3.email
6
+
7
+ This utility class validates generated JWTs and grants scoped access to users
8
+ according to their roles.
9
+ """
10
+ from backend.core.ConfigEnv import config
11
+ from backend.models import TokenPayload
12
+
13
+ from datetime import datetime
14
+
15
+ from fastapi import Request, HTTPException
16
+ from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
17
+ from pydantic import ValidationError
18
+ from jose import jwt
19
+
20
+
21
+ class JWTBearer(HTTPBearer):
22
+ """Custom bearer to validate access tokens.
23
+
24
+ Args:
25
+ auto_error: bool = True. Internal param to allow auto error detection.
26
+
27
+ Raises:
28
+ HHTTPException(403): If authentication scheme is not `Bearer`.
29
+ HTTPException(403): If the access token is invalid or expired.
30
+ HTTPException(403): If authorization code is invalid.
31
+ """
32
+ def __init__(self, auto_error: bool = True):
33
+ super(JWTBearer, self).__init__(auto_error=auto_error)
34
+
35
+ async def __call__(self, request: Request) -> str:
36
+ credentials: HTTPAuthorizationCredentials = await super(JWTBearer, self).__call__(request)
37
+ if credentials:
38
+ if not credentials.scheme == "Bearer":
39
+ raise HTTPException(status_code=403, detail="Invalid authentication scheme.")
40
+ else:
41
+ is_valid = JWTBearer.token_validation(credentials.credentials)
42
+ if not is_valid:
43
+ raise HTTPException(status_code=403, detail="Invalid token or expired token.")
44
+ return credentials.credentials
45
+ else:
46
+ raise HTTPException(status_code=403, detail="Invalid authorization code.")
47
+
48
+ @staticmethod
49
+ def token_validation(token: str) -> bool:
50
+ """Decodes JWTs to check their validity by inspecting expiry and
51
+ authorization code.
52
+
53
+ Args:
54
+ token: str. Authenticated `access_token` of the user.
55
+
56
+ Returns:
57
+ bool value to indicate validity of the access tokens.
58
+
59
+ Raises:
60
+ jwt.JWTError: If decode fails.
61
+ ValidationError: If JWTs are not in RFC 7519 standard.
62
+ """
63
+ try:
64
+ payload = jwt.decode(
65
+ token, config.JWT_SECRET_KEY, algorithms=[config.ALGORITHM]
66
+ )
67
+ token_data = TokenPayload(**payload)
68
+
69
+ if datetime.fromtimestamp(token_data.exp) < datetime.now():
70
+ return False
71
+
72
+ except(jwt.JWTError, ValidationError):
73
+ return False
74
+
75
+ return True
TechdocsAPI/backend/services/auth/utils/auth_funcs.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Utility class to leverage encryption, verification of entered credentials
2
+ and generation of JWT access tokens.
3
+ """
4
+ from datetime import datetime, timedelta
5
+ from typing import Union, Any
6
+ import secrets
7
+
8
+ from jose import jwt
9
+ from passlib.context import CryptContext
10
+ from pydantic import ValidationError
11
+
12
+ from fastapi.exceptions import HTTPException
13
+
14
+ from backend.core.ConfigEnv import config
15
+ from backend.core.Exceptions import *
16
+ from backend.models import TokenPayload, TokenSchema
17
+
18
+
19
+
20
+ ACCESS_TOKEN_EXPIRE_MINUTES = 30 # 30 minutes
21
+ REFRESH_TOKEN_EXPIRE_MINUTES = 60 * 24 * 3 # 3 days
22
+
23
+
24
+ class Auth:
25
+ """Utility class to perform - 1.encryption via `bcrypt` scheme.
26
+ 2.password hashing 3.verification of credentials and generating
27
+ access tokens.
28
+
29
+ Attrs:
30
+ pwd_context: CryptContext. Helper for hashing & verifying passwords
31
+ using `bcrypt` algorithm.
32
+ """
33
+ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
34
+
35
+
36
+
37
+ @classmethod
38
+ def get_password_hash(cls,password: str) -> str:
39
+ """Encrypts the entered password.
40
+
41
+ Args:
42
+ password: str. Entered password.
43
+
44
+ Returns:
45
+ returns hashed(encrypted) password string.
46
+ """
47
+ return cls.pwd_context.hash(password)
48
+
49
+ @classmethod
50
+ def verify_password(cls, plain_password: str, hashed_password: str) -> bool:
51
+ """Validates if the entered password matches the actual password.
52
+
53
+ Args:
54
+ plain_password: str. Entered password by user.
55
+ hashed_password: str. hashed password from the database.
56
+
57
+ Returns:
58
+ bool value indicating whether the passwords match or not.
59
+ """
60
+ return cls.pwd_context.verify(plain_password, hashed_password)
61
+
62
+ @staticmethod
63
+ def verify_username(entered_username: str, db_username: str) -> bool:
64
+ """Validates if the entered username matches the actual username.
65
+
66
+ Args:
67
+ entered_username: str. Entered `username` by user.
68
+ db_username: str. username from the database.
69
+
70
+ Returns:
71
+ bool value indicating whether the village names match or not.
72
+ """
73
+ return entered_username == db_username
74
+
75
+ @staticmethod
76
+ def create_access_token(subject: Union[str, Any], expires_delta: int = None) -> str:
77
+ """Creates JWT access token.
78
+
79
+ Args:
80
+ subject: Union[Any, str]. Hash_key to generate access token from.
81
+ expires_delta: int = None. Expiry time for the JWT.
82
+
83
+ Returns:
84
+ encoded_jwt: str. Encoded JWT token from the subject of interest.
85
+ """
86
+ if expires_delta is not None:
87
+ expires_delta = datetime.utcnow() + expires_delta
88
+ else:
89
+ expires_delta = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
90
+
91
+ to_encode = {"exp": expires_delta, "sub": str(subject)}
92
+ encoded_jwt = jwt.encode(to_encode, config.JWT_SECRET_KEY, config.ALGORITHM)
93
+ return encoded_jwt
94
+
95
+ @staticmethod
96
+ def create_refresh_token(subject: Union[str, Any], expires_delta: int = None) -> str:
97
+ """Creates JWT refresh access token.
98
+
99
+ Args:
100
+ subject: Union[Any, str]. Hash_key to generate access token from.
101
+ expires_delta: int = None. Expiry time for the JWT.
102
+
103
+ Returns:
104
+ encoded_jwt: str. Encoded JWT token from the subject of interest.
105
+ """
106
+ if expires_delta is not None:
107
+ expires_delta = datetime.utcnow() + expires_delta
108
+ else:
109
+ expires_delta = datetime.utcnow() + timedelta(minutes=REFRESH_TOKEN_EXPIRE_MINUTES)
110
+
111
+ to_encode = {"exp": expires_delta, "sub": str(subject)}
112
+ encoded_jwt = jwt.encode(to_encode, config.JWT_REFRESH_SECRET_KEY, config.ALGORITHM)
113
+ return encoded_jwt
114
+
115
+ @staticmethod
116
+ def generate_access_tokens_from_refresh_tokens(token: str) -> TokenSchema:
117
+ """Generates a new pair of tokens by implementing rotating
118
+ refresh_access_tokens.
119
+
120
+ Args:
121
+ token: str. Current valid refresh access token.
122
+
123
+ Returns:
124
+ tokens: TokenSchema. New tokens with new validity.
125
+
126
+ Raises:
127
+ LoginFailedException: If the current refresh access token is
128
+ invalid.
129
+ """
130
+ tokens = TokenSchema.get_instance(
131
+ access_token= "",
132
+ refresh_token= "",
133
+ )
134
+ try:
135
+ payload = jwt.decode(
136
+ token, config.JWT_REFRESH_SECRET_KEY, algorithms=[config.ALGORITHM]
137
+ )
138
+ token_data = TokenPayload(**payload)
139
+ if datetime.fromtimestamp(token_data.exp)< datetime.now():
140
+ raise HTTPException(status_code=403, detail="Invalid token or expired token.")
141
+ except (jwt.JWTError, ValidationError):
142
+ raise InvalidCredentialsException(tokens)
143
+ tokens['access_token'] = Auth.create_access_token(token_data.sub)
144
+ tokens['refresh_token'] = Auth.create_refresh_token(token_data.sub)
145
+ tokens['status'] = 'login successful'
146
+ tokens['role'] = token_data.sub.split("_")[1]
147
+ return tokens
148
+
149
+ @classmethod
150
+ def generate_api_key(cls, username: str):
151
+ return cls.get_password_hash(username + secrets.token_urlsafe(25 - len(username)))
152
+
153
+ @classmethod
154
+ def get_user_credentials(cls,access_token:str):
155
+ response_result = GeneralResponse.get_instance(data={},
156
+ status="not_allowed",
157
+ message=["Not authenticated"]
158
+ )
159
+ try:
160
+ payload = jwt.decode(
161
+ access_token, config.JWT_SECRET_KEY, algorithms=[config.ALGORITHM]
162
+ )
163
+ token_data = TokenPayload(**payload)
164
+ return token_data.sub
165
+ except (jwt.JWTError, ValidationError):
166
+ raise InvalidCredentialsException(response_result)
167
+
168
+ @classmethod
169
+ def verify_apikey(cls,user_api_key:str,true_api_key:str):
170
+ return user_api_key == true_api_key
171
+
TechdocsAPI/backend/services/db/__init__.py ADDED
File without changes
TechdocsAPI/backend/services/db/utils/DBQueries.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # fix ObjectId & FastApi conflict
2
+ import pydantic
3
+ from bson.objectid import ObjectId
4
+ pydantic.json.ENCODERS_BY_TYPE[ObjectId]=str
5
+
6
+ from typing import Union, Tuple, List
7
+
8
+ from backend.utils import DBConnection
9
+ from backend.core.Exceptions import *
10
+
11
+
12
+ class DBQueries:
13
+ @classmethod
14
+ def insert_to_database(cls, table_name:str, data:Union[Tuple, List[Tuple]], cols:List[str]=None):
15
+ con = DBConnection.get_client()
16
+ cursor = con.cursor()
17
+ QUERY = ('INSERT INTO {table_name} '
18
+ f'({",".join(cols)}) '
19
+ 'VALUES '
20
+ ).format(table_name=table_name)
21
+ print(data)
22
+ if isinstance(data, list):
23
+ QUERY+="("+",".join(["%s" for _ in range(len(data[0]))])+")"
24
+ cursor.executemany(QUERY, data)
25
+ else:
26
+ QUERY+="("+",".join(["%s" for _ in range(len(data))])+")"
27
+ cursor.execute(QUERY, data)
28
+ con.commit()
29
+
30
+ @classmethod
31
+ def fetch_data_from_database(cls,table_name:str,cols_to_fetch:Union[str, List[str]], where_clause:str=None):
32
+ con = DBConnection.get_client()
33
+ cursor = con.cursor()
34
+ if isinstance(cols_to_fetch, str):
35
+ cols_to_fetch = [cols_to_fetch]
36
+ cols_to_fetch = ", ".join(cols_to_fetch)
37
+ QUERY = ('SELECT {cols} FROM {table_name}').format(cols=cols_to_fetch, table_name=table_name)
38
+ if where_clause:
39
+ QUERY = QUERY + " WHERE " + where_clause
40
+ cursor.execute(QUERY)
41
+ return cursor.fetchall()
42
+
43
+ @classmethod
44
+ def update_data_in_database(cls, table_name:str, cols_to_update:Union[str, List[str]], where_clause:str=None, new_values:Union[str, List[str]]=None):
45
+ con = DBConnection.get_client()
46
+ cursor = con.cursor()
47
+ if isinstance(cols_to_update, str):
48
+ cols_to_update = cols_to_update + "=%s"
49
+ else:
50
+ cols_to_update = "=%s, ".join(cols_to_update)
51
+
52
+ if isinstance(new_values, str):
53
+ new_values = [new_values]
54
+
55
+ QUERY = ('UPDATE {table_name} SET {cols}').format(table_name=table_name, cols=cols_to_update)
56
+ if where_clause:
57
+ QUERY = QUERY + " WHERE " + where_clause
58
+ cursor.execute(QUERY, new_values)
59
+ con.commit()
60
+ return True
61
+
62
+
63
+
64
+
65
+
66
+
TechdocsAPI/backend/utils/DBConnection.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ Import Important Packages"""
2
+ import mysql.connector
3
+
4
+ from backend.core.ConfigEnv import config
5
+
6
+
7
+ class DBConnection:
8
+ """DBConnection Class. It ensures only one instance of the class is
9
+ created and it is accessible from everywhere. It is used in the
10
+ design of logging classes, Configuration classes where we need to have
11
+ only one instance of the class. There is no need to create multiple
12
+ instances of each operation across all components of application.
13
+
14
+ Raises:
15
+ Exception: It raises an exception if the client instance is not created.
16
+ """
17
+ __client = None #This is the client variable that is used to connect to the database
18
+ _flag = False
19
+ def __init__(self):
20
+ """This is the constructor of the class. It is used to create the client
21
+ variable. It also checks if the client instance is already created.
22
+ If the client instance is already created, then it does not create a
23
+ new client instance.
24
+ """
25
+ if DBConnection.__client is not None:
26
+ raise Exception("This class is a singleton!")
27
+ else:
28
+ creds={
29
+ 'host':config.HOSTNAME,
30
+ 'user':config.UID,
31
+ 'password':config.PASSWORD,
32
+ 'database':config.DATABASE
33
+ }
34
+ DBConnection.__client = mysql.connector.connect(**creds)
35
+ DBConnection._flag = True
36
+
37
+ @staticmethod # A static method is a method that is called without creating an instance of the class.
38
+ def get_client():
39
+ """The get_client() function is used to get the client instance.
40
+
41
+ Returns:
42
+ DBConnection.__client: It returns the client instance.
43
+ """
44
+ return DBConnection.__client
45
+
46
+ @classmethod
47
+ def is_connected(cls)->bool:
48
+ """property to get the database connection flag.
49
+ Returns:
50
+ DBConnection._flag: bool. Connection status to the DB.
51
+ """
52
+ return cls._flag
53
+
54
+
55
+
56
+
57
+
TechdocsAPI/backend/utils/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .DBConnection import DBConnection
TechdocsAPI/backend/utils/prompt.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You are an AI Coding Assitant and your task is to generate an elaborate, high quality docstring for the query function given by the user. A docstring consists of the following sections:
2
+ 1. Description: Is the description of what the function does.
3
+ 2. Arguments:
4
+ 1. Argument Name: Description of the argument and its type.
5
+ 3. Returns: Description of the return value of the function if any.
6
+ 4. Raises: Description of the errors that can be raised by the function if any.
7
+
8
+ Instruction: {instruction}
9
+
10
+ Your task is to generate a docstring for the above query.
11
+ Response:
TechdocsAPI/backend/utils/scopes.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from typing import Callable
2
+
3
+ from backend.models import User
TechdocsAPI/requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ fastapi==0.99.1
2
+ uvicorn
3
+ requests
4
+ pydantic==1.10.12
5
+ python-jose[cryptography]
6
+ passlib[bcrypt]
7
+ mysql-connector-python
8
+ pydantic[email]
9
+ langchain
10
+ clarifai
Login.py β†’ frontend/Login.py RENAMED
@@ -6,7 +6,7 @@ import streamlit as st
6
 
7
  def auth_page():
8
 
9
- base_url = 'https://hemanthsai7-techdocsapi.hf.space'
10
 
11
 
12
  headers={"accept":"application/json"}
 
6
 
7
  def auth_page():
8
 
9
+ base_url = 'http://localhost:8000'
10
 
11
 
12
  headers={"accept":"application/json"}
{pages β†’ frontend/pages}/Code.py RENAMED
@@ -28,7 +28,7 @@ with st.sidebar:
28
  if st.button("Generate API KEY"):
29
  with st.spinner("Generating API Key..."):
30
  try:
31
- base_url = "https://hemanthsai7-techdocsapi.hf.space"
32
  headers={"accept":"application/json", "Authorization": f"Bearer {st.session_state.access_token}"}
33
  response = requests.put(url=base_url + "/auth/regenerate_api_key", headers=headers, data=json.dumps({"username":st.session_state.username}))
34
  if (response.status_code!=200):
@@ -48,7 +48,7 @@ with st.sidebar:
48
 
49
 
50
  def code_page():
51
- base_url = 'https://hemanthsai7-techdocsapi.hf.space'
52
 
53
  def query_post(url, headers, data=None, params=None):
54
  response = requests.post(url, data=data, headers=headers, params=params)
 
28
  if st.button("Generate API KEY"):
29
  with st.spinner("Generating API Key..."):
30
  try:
31
+ base_url = "http://localhost:8000"
32
  headers={"accept":"application/json", "Authorization": f"Bearer {st.session_state.access_token}"}
33
  response = requests.put(url=base_url + "/auth/regenerate_api_key", headers=headers, data=json.dumps({"username":st.session_state.username}))
34
  if (response.status_code!=200):
 
48
 
49
 
50
  def code_page():
51
+ base_url = 'http://localhost:8000'
52
 
53
  def query_post(url, headers, data=None, params=None):
54
  response = requests.post(url, data=data, headers=headers, params=params)
requirements.txt β†’ frontend/requirements.txt RENAMED
File without changes
🏑_Home.py β†’ frontend/🏑_Home.py RENAMED
@@ -7,7 +7,7 @@ import base64
7
 
8
  # image2=Image.open('assets/logo2.png')
9
  st.set_page_config(
10
- page_title="DocGup-tea",
11
  layout="wide",
12
  page_icon="🏑",
13
  initial_sidebar_state="expanded",
 
7
 
8
  # image2=Image.open('assets/logo2.png')
9
  st.set_page_config(
10
+ page_title="Techdocs",
11
  layout="wide",
12
  page_icon="🏑",
13
  initial_sidebar_state="expanded",