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

Fastapi impl #25

Merged
merged 12 commits into from
Sep 22, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@
- `python deploy_code.py`
- `python deploy_workflow.py`
- `python main.py`

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Settings:
PROJECT_NAME: str = "Simple RAG as FastAPI Application"


settings = Settings()
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from fastapi import APIRouter, Depends
from models.payload import Payload
from self_correction_core import SelfCorrectingRAG


self_correcting_rag = SelfCorrectingRAG(input_dir='data', show_progress=True, no_of_retries=3)

router = APIRouter(prefix="/api/v1/rag", tags=["rag"])


@router.post(path='/query')
def fetch_response(payload: Payload):
response = self_correcting_rag.query_with_source_query_engine(query=payload.query)
return response
110 changes: 110 additions & 0 deletions bootstraprag/templates/llamaindex/rag_with_self_correction/apis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
from fastapi import FastAPI, Request
from fastapi.openapi.utils import get_openapi
from api_routes.apis import router
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
import logging
import time

logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
)
logger = logging.getLogger(__name__)
allowed_origins = [
"*"
]

app = FastAPI(
title="My FastAPI Application",
description="This is a FastAPI implementation for RAG application with Swagger UI configurations.",
version="1.0.0",
docs_url="/documentation",
redoc_url="/redoc",
openapi_url="/openapi.json",
contact={
"name": "M K Pavan Kumar",
"linkedin": "https://www.linkedin.com",
},
license_info={
"name": "MIT License",
"url": "https://opensource.org/licenses/MIT",
},
terms_of_service="https://www.yourwebsite.com/terms/",
)
app.add_middleware(
CORSMiddleware,
allow_origins=allowed_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(router)


# Custom OpenAPI schema generation (optional)
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="RAG APIs",
version="1.0.0",
description="This is a custom OpenAPI schema with additional metadata.",
routes=app.routes,
tags=[
{
"name": "rag",
"description": "Operations for RAG query.",
}
],
)
# Modify openapi_schema as needed
app.openapi_schema = openapi_schema
return app.openapi_schema


app.openapi = custom_openapi


@app.middleware("http")
async def log_requests(request: Request, call_next):
try:
logger.info(f"Incoming request: {request.method} {request.url}")
response = await call_next(request)
logger.info(f"Response status: {response.status_code}")
return response
except Exception as e:
logger.exception(f"Error processing request: {e}")
raise e


# Request Timing Middleware
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
logger.info(f"Processed in {process_time:.4f} seconds")
return response


# Logging Middleware
@app.middleware("http")
async def log_requests(request: Request, call_next):
logger.info(f"Incoming request: {request.method} {request.url}")
response = await call_next(request)
logger.info(f"Response status: {response.status_code}")
return response


if __name__ == "__main__":
uvicorn.run(
"apis:app",
host="127.0.0.1",
port=8000,
reload=True,
log_level="info",
workers=1,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pydantic import BaseModel


class Payload(BaseModel):
query: str
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@
- query_with_retry_query_engine(query=user_query)
- query_with_source_query_engine(query=user_query)
- query_with_guideline_query_engine(query=user_query)

### How to expose RAG as API
- run `python apis.py`
- verify the swagger redoc and documentation as below
- open browser and hit `http://localhost:8000/redoc`
- open browser and hit `http://localhost:8000/documentation`
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Settings:
PROJECT_NAME: str = "Simple RAG as FastAPI Application"


settings = Settings()
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from fastapi import APIRouter, Depends
from models.payload import Payload
from self_correction_core import SelfCorrectingRAG


self_correcting_rag = SelfCorrectingRAG(input_dir='data', show_progress=True, no_of_retries=3)

router = APIRouter(prefix="/api/v1/rag", tags=["rag"])


@router.post(path='/query')
def fetch_response(payload: Payload):
response = self_correcting_rag.query_with_source_query_engine(query=payload.query)
return response
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
from fastapi import FastAPI, Request
from fastapi.openapi.utils import get_openapi
from api_routes.apis import router
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
import logging
import time

logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
)
logger = logging.getLogger(__name__)
allowed_origins = [
"*"
]

app = FastAPI(
title="My FastAPI Application",
description="This is a FastAPI implementation for RAG application with Swagger UI configurations.",
version="1.0.0",
docs_url="/documentation",
redoc_url="/redoc",
openapi_url="/openapi.json",
contact={
"name": "M K Pavan Kumar",
"linkedin": "https://www.linkedin.com",
},
license_info={
"name": "MIT License",
"url": "https://opensource.org/licenses/MIT",
},
terms_of_service="https://www.yourwebsite.com/terms/",
)
app.add_middleware(
CORSMiddleware,
allow_origins=allowed_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(router)


# Custom OpenAPI schema generation (optional)
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="RAG APIs",
version="1.0.0",
description="This is a custom OpenAPI schema with additional metadata.",
routes=app.routes,
tags=[
{
"name": "rag",
"description": "Operations for RAG query.",
}
],
)
# Modify openapi_schema as needed
app.openapi_schema = openapi_schema
return app.openapi_schema


app.openapi = custom_openapi


@app.middleware("http")
async def log_requests(request: Request, call_next):
try:
logger.info(f"Incoming request: {request.method} {request.url}")
response = await call_next(request)
logger.info(f"Response status: {response.status_code}")
return response
except Exception as e:
logger.exception(f"Error processing request: {e}")
raise e


# Request Timing Middleware
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
logger.info(f"Processed in {process_time:.4f} seconds")
return response


# Logging Middleware
@app.middleware("http")
async def log_requests(request: Request, call_next):
logger.info(f"Incoming request: {request.method} {request.url}")
response = await call_next(request)
logger.info(f"Response status: {response.status_code}")
return response


if __name__ == "__main__":
uvicorn.run(
"apis:app",
host="127.0.0.1",
port=8000,
reload=True,
log_level="info",
workers=1,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pydantic import BaseModel


class Payload(BaseModel):
query: str
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,10 @@
- query_with_source_query_engine(query=user_query)
- query_with_guideline_query_engine(query=user_query)

- This code is enabled with Observability powered by `Arize Phoenix`.
- This code is enabled with Observability powered by `Arize Phoenix`.

### How to expose RAG as API
- run `python apis.py`
- verify the swagger redoc and documentation as below
- open browser and hit `http://localhost:8000/redoc`
- open browser and hit `http://localhost:8000/documentation`
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Settings:
PROJECT_NAME: str = "Simple RAG as FastAPI Application"


settings = Settings()
Empty file.
12 changes: 12 additions & 0 deletions bootstraprag/templates/llamaindex/simple_rag/api_routes/apis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from fastapi import APIRouter, Depends
from models.payload import Payload
from simple_rag import SimpleRAG

router = APIRouter(prefix="/api/v1/rag", tags=["rag"])
simpleRAG = SimpleRAG(input_dir='data', show_progress=True)


@router.post(path='/query')
def fetch_response(payload: Payload):
response = simpleRAG.do_rag(user_query=payload.query)
return response
Loading
Loading