This commit is contained in:
leehk 2025-04-07 16:35:34 +08:00
parent 1942039f3b
commit cdff0df5f5
15 changed files with 1288 additions and 5 deletions

View File

23
app/backend/Dockerfile Normal file
View File

@ -0,0 +1,23 @@
# pull official base image
FROM python:3.11-slim
# set working directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install system dependencies
RUN apt-get update \
&& apt-get -y install build-essential netcat-traditional gcc postgresql \
&& apt-get clean
# install python dependencies
RUN pip install --upgrade pip setuptools wheel -i https://pypi.tuna.tsinghua.edu.cn/simple
RUN pip install pipenv -i https://pypi.tuna.tsinghua.edu.cn/simple
COPY ./Pipfile .
RUN pipenv install --deploy --dev
# add app
COPY . .

23
app/backend/Pipfile Normal file
View File

@ -0,0 +1,23 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
fastapi = "*"
pydantic = "*"
uvicorn = "*"
pydantic-settings = "==2.1.0"
[dev-packages]
httpx = "==0.26.0"
pytest = "==7.4.4"
pytest-cov = "==4.1.0"
pytest-mock = "==3.10.0"
flake8 = "==7.0.0"
black = "==23.12.1"
isort = "==5.13.2"
ipykernel = "*"
[requires]
python_version = "3.11"

1090
app/backend/Pipfile.lock generated Normal file

File diff suppressed because it is too large Load Diff

15
app/backend/api/ping.py Normal file
View File

@ -0,0 +1,15 @@
from fastapi import APIRouter, Depends
from config import get_settings, Settings
router = APIRouter()
@router.get("/ping")
async def pong(settings: Settings = Depends(get_settings)):
return {
"ping": "pong!",
"environment": settings.environment,
"testing": settings.testing
}

10
app/backend/api/query.py Normal file
View File

@ -0,0 +1,10 @@
from typing import List
from fastapi import APIRouter
from models.adaptive_rag.router import RouteQuery
from models.adaptive_rag.grading import GradeAnswer, GradeDocuments, GradeHallucinations
router = APIRouter()
@router.post("/", response_model=SummaryResponseSchema, status_code=201)

18
app/backend/config.py Normal file
View File

@ -0,0 +1,18 @@
import logging
from functools import lru_cache
from pydantic_settings import BaseSettings
log = logging.getLogger("uvicorn")
class Settings(BaseSettings):
environment: str = "dev"
testing: bool = 0
@lru_cache()
def get_settings() -> BaseSettings:
log.info("Loading config settings from the environment...")
return Settings()

View File

@ -0,0 +1,24 @@
import logging
from fastapi import FastAPI, Depends
from config import get_settings, Settings
from api import ping, query
log = logging.getLogger("uvicorn")
def create_application() -> FastAPI:
application = FastAPI()
application.include_router(ping.router)
application.include_router(
query.router, prefix="/query", tags=["query"]
)
return application
app = create_application()

View File

@ -0,0 +1,23 @@
from pydantic import BaseModel, Field
class GradeDocuments(BaseModel):
"""Binary score for relevance check on retrieved documents."""
binary_score: str = Field(
description="Documents are relevant to the question, 'yes' or 'no'"
)
class GradeHallucinations(BaseModel):
"""Binary score for hallucination present in generation answer."""
binary_score: str = Field(
description="Answer is grounded in the facts, 'yes' or 'no'"
)
class GradeAnswer(BaseModel):
"""Binary score to assess answer addresses question."""
binary_score: str = Field(
description="Answer addresses the question, 'yes' or 'no'"
)

View File

@ -0,0 +1,5 @@
from pydantic import BaseModel
class final_answer(BaseModel):
"""Final answer to be returned to the user."""
answer: str

View File

@ -0,0 +1,11 @@
from typing import Literal
from pydantic import BaseModel, Field
class RouteQuery(BaseModel):
"""Route a user query to the most relevant datasource."""
datasource: Literal["vectorstore", "web_search"] = Field(
...,
description="Given a user question choose to route it to web search or a vectorstore.",
)

View File

View File

@ -0,0 +1,23 @@
import os
import pytest
from starlette.testclient import TestClient
import main
from config import get_settings, Settings
def get_settings_override():
return Settings(testing=1)
@pytest.fixture(scope="module")
def test_app():
# set up
main.app.dependency_overrides[get_settings] = get_settings_override
with TestClient(main.app) as test_client:
# testing
yield test_client
# tear down

View File

@ -0,0 +1,4 @@
def test_ping(test_app):
response = test_app.get("/ping")
assert response.status_code == 200
assert response.json() == {"environment": "dev", "ping": "pong!", "testing": True}

View File

@ -1,10 +1,24 @@
version: "3.9"
services:
streamlit:
build: ./streamlit
# streamlit:
# build: ./streamlit
# platform: linux/amd64
# ports:
# - "8501:8501"
# volumes:
# - ./llmops/src/rag_cot_evaluation/chroma_db:/app/llmops/src/rag_cot_evaluation/chroma_db
backend:
build:
context: ./backend
dockerfile: Dockerfile
platform: linux/amd64
ports:
- "8501:8501"
command: pipenv run uvicorn main:app --reload --workers 1 --host 0.0.0.0 --port 8000
volumes:
- ./llmops/src/rag_cot_evaluation/chroma_db:/app/llmops/src/rag_cot_evaluation/chroma_db
- ./backend:/usr/src/app
ports:
- "8004:8000"
environment:
- ENVIRONMENT=dev
- TESTING=0