Skip to content

Commit

Permalink
feat(microservices): split into 4 quivr to better handle long services (
Browse files Browse the repository at this point in the history
QuivrHQ#972)

* feat(verbose): removed

* feat(microservices): split quivr into micro services

* test(main): fixed
  • Loading branch information
StanGirard authored Aug 18, 2023
1 parent ad7ac15 commit 7281fd9
Show file tree
Hide file tree
Showing 7 changed files with 359 additions and 17 deletions.
68 changes: 68 additions & 0 deletions backend/core/chat_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import os
if __name__ == "__main__":
# import needed here when running main.py to debug backend
# you will need to run pip install python-dotenv
from dotenv import load_dotenv
load_dotenv()
import sentry_sdk
from fastapi import FastAPI, HTTPException, Request, status
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from logger import get_logger
from middlewares.cors import add_cors_middleware
from routes.misc_routes import misc_router
from routes.chat_routes import chat_router

logger = get_logger(__name__)

sentry_dsn = os.getenv("SENTRY_DSN")
if sentry_dsn:
sentry_sdk.init(
dsn=sentry_dsn,
traces_sample_rate=1.0,
)

app = FastAPI()

add_cors_middleware(app)



app.include_router(chat_router)
app.include_router(misc_router)



@app.exception_handler(HTTPException)
async def http_exception_handler(_, exc):
return JSONResponse(
status_code=exc.status_code,
content={"detail": exc.detail},
)


# log more details about validation errors (422)
def handle_request_validation_error(app: FastAPI):
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(
request: Request, exc: RequestValidationError
):
exc_str = f"{exc}".replace("\n", " ").replace(" ", " ")
logger.error(request, exc_str)
content = {
"status_code": status.HTTP_422_UNPROCESSABLE_ENTITY,
"message": exc_str,
"data": None,
}
return JSONResponse(
content=content, status_code=status.HTTP_422_UNPROCESSABLE_ENTITY
)


handle_request_validation_error(app)

if __name__ == "__main__":
# run main.py to debug backend
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=5050)

68 changes: 68 additions & 0 deletions backend/core/crawl_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import os
if __name__ == "__main__":
# import needed here when running main.py to debug backend
# you will need to run pip install python-dotenv
from dotenv import load_dotenv
load_dotenv()
import sentry_sdk
from fastapi import FastAPI, HTTPException, Request, status
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from logger import get_logger
from middlewares.cors import add_cors_middleware
from routes.misc_routes import misc_router
from routes.crawl_routes import crawl_router

logger = get_logger(__name__)

sentry_dsn = os.getenv("SENTRY_DSN")
if sentry_dsn:
sentry_sdk.init(
dsn=sentry_dsn,
traces_sample_rate=1.0,
)

app = FastAPI()

add_cors_middleware(app)



app.include_router(crawl_router)
app.include_router(misc_router)



@app.exception_handler(HTTPException)
async def http_exception_handler(_, exc):
return JSONResponse(
status_code=exc.status_code,
content={"detail": exc.detail},
)


# log more details about validation errors (422)
def handle_request_validation_error(app: FastAPI):
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(
request: Request, exc: RequestValidationError
):
exc_str = f"{exc}".replace("\n", " ").replace(" ", " ")
logger.error(request, exc_str)
content = {
"status_code": status.HTTP_422_UNPROCESSABLE_ENTITY,
"message": exc_str,
"data": None,
}
return JSONResponse(
content=content, status_code=status.HTTP_422_UNPROCESSABLE_ENTITY
)


handle_request_validation_error(app)

if __name__ == "__main__":
# run main.py to debug backend
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=5050)

6 changes: 3 additions & 3 deletions backend/core/llm/qa_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def _create_llm(
temperature=temperature,
model=model,
streaming=streaming,
verbose=True,
verbose=False,
callbacks=callbacks,
openai_api_key=self.openai_api_key,
) # pyright: ignore reportPrivateUsage=none
Expand Down Expand Up @@ -135,7 +135,7 @@ def generate_answer(
question_generator=LLMChain(
llm=self._create_llm(model=self.model), prompt=CONDENSE_QUESTION_PROMPT
),
verbose=True,
verbose=False,
)

model_response = qa(
Expand Down Expand Up @@ -208,7 +208,7 @@ async def generate_stream(
question_generator=LLMChain(
llm=self._create_llm(model=self.model), prompt=CONDENSE_QUESTION_PROMPT
),
verbose=True,
verbose=False,
)

transformed_history = format_chat_history(history)
Expand Down
4 changes: 2 additions & 2 deletions backend/core/routes/chat_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from llm.openai import OpenAIBrainPicking
from models.brains import Brain
from models.brain_entity import BrainEntity
from models.chat import Chat, ChatHistory
from models.chat import Chat
from models.chats import ChatQuestion
from models.databases.supabase.supabase import SupabaseDB
from models.settings import LLMSettings, get_supabase_db
Expand Down Expand Up @@ -62,7 +62,7 @@ def check_user_limit(
):
if user.user_openai_api_key is None:
date = time.strftime("%Y%m%d")
max_requests_number = int(os.getenv("MAX_REQUESTS_NUMBER", 1000))
max_requests_number = int(os.getenv("MAX_REQUESTS_NUMBER", 1))

user.increment_user_request_count(date)
if int(user.requests_count) >= int(max_requests_number):
Expand Down
74 changes: 74 additions & 0 deletions backend/core/upload_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import os
if __name__ == "__main__":
# import needed here when running main.py to debug backend
# you will need to run pip install python-dotenv
from dotenv import load_dotenv
load_dotenv()
import sentry_sdk
import pypandoc
from fastapi import FastAPI, HTTPException, Request, status
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from logger import get_logger
from middlewares.cors import add_cors_middleware
from routes.misc_routes import misc_router
from routes.upload_routes import upload_router

logger = get_logger(__name__)

sentry_dsn = os.getenv("SENTRY_DSN")
if sentry_dsn:
sentry_sdk.init(
dsn=sentry_dsn,
traces_sample_rate=1.0,
)

app = FastAPI()

@app.on_event("startup")
async def startup_event():
if not os.path.exists(pypandoc.get_pandoc_path()):
pypandoc.download_pandoc()

add_cors_middleware(app)



app.include_router(upload_router)
app.include_router(misc_router)



@app.exception_handler(HTTPException)
async def http_exception_handler(_, exc):
return JSONResponse(
status_code=exc.status_code,
content={"detail": exc.detail},
)


# log more details about validation errors (422)
def handle_request_validation_error(app: FastAPI):
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(
request: Request, exc: RequestValidationError
):
exc_str = f"{exc}".replace("\n", " ").replace(" ", " ")
logger.error(request, exc_str)
content = {
"status_code": status.HTTP_422_UNPROCESSABLE_ENTITY,
"message": exc_str,
"data": None,
}
return JSONResponse(
content=content, status_code=status.HTTP_422_UNPROCESSABLE_ENTITY
)


handle_request_validation_error(app)

if __name__ == "__main__":
# run main.py to debug backend
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=5050)

80 changes: 72 additions & 8 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
version: "3"
version: '3'

services:
traefik:
image: traefik:v2.10
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:5050"
ports:
- "5050:5050"
- "8080:8080" # For the Traefik dashboard (optional)
volumes:
- /var/run/docker.sock:/var/run/docker.sock

frontend:
env_file:
- ./frontend/.env
Expand All @@ -9,22 +22,73 @@ services:
dockerfile: Dockerfile.dev
container_name: web
restart: always
volumes:
- ./frontend/:/app
- /app/node_modules
- /app/.next
ports:
- 3000:3000

backend-core:
env_file:
- ./backend/core/.env
build:
context: backend/core
dockerfile: Dockerfile
container_name: backend-core
command: uvicorn main:app --host 0.0.0.0 --port 5050
restart: always
volumes:
- ./backend/core/:/code/
- ~/.config/gcloud:/root/.config/gcloud
ports:
- 5050:5050
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend-core.rule=PathPrefix(`/`)"
- "traefik.http.routers.backend-core.entrypoints=web"
- "traefik.http.services.backend-core.loadbalancer.server.port=5050"

backend-chat:
env_file:
- ./backend/core/.env
build:
context: backend/core
dockerfile: Dockerfile
container_name: backend-chat
command: uvicorn chat_service:app --host 0.0.0.0 --port 5050
restart: always
volumes:
- ./backend/core/:/code/
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend-chat.rule=PathPrefix(`/chat`)"
- "traefik.http.routers.backend-chat.entrypoints=web"
- "traefik.http.services.backend-chat.loadbalancer.server.port=5050"

backend-crawl:
env_file:
- ./backend/core/.env
build:
context: backend/core
dockerfile: Dockerfile
container_name: backend-crawl
command: uvicorn crawl_service:app --host 0.0.0.0 --port 5050
restart: always
volumes:
- ./backend/core/:/code/
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend-crawl.rule=PathPrefix(`/crawl`)"
- "traefik.http.routers.backend-crawl.entrypoints=web"
- "traefik.http.services.backend-crawl.loadbalancer.server.port=5050"

backend-upload:
env_file:
- ./backend/core/.env
build:
context: backend/core
dockerfile: Dockerfile
container_name: backend-upload
command: uvicorn upload_service:app --host 0.0.0.0 --port 5050
restart: always
volumes:
- ./backend/core/:/code/
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend-upload.rule=PathPrefix(`/upload`)"
- "traefik.http.routers.backend-upload.entrypoints=web"
- "traefik.http.services.backend-upload.loadbalancer.server.port=5050"
Loading

0 comments on commit 7281fd9

Please sign in to comment.