diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..5c1e710 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,76 @@ +version: '3.8' + +services: + backend: + build: ./src/backend # search for docker file here + ports: + - "8000:8000" + environment: + # - POSTGRES_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} + - MONGODB_URL=mongodb://mongodb:27017 + - REDIS_URL=redis://redis:6379 + - CHROMADB_URL=http://chromadb:8000 + - CHROMADB_PATH=/chroma/chroma + - OPENAI_API_KEY=${OPENAI_API_KEY} + - HUGGINGFACE_API_KEY=${HUGGINGFACE_API_KEY} + - GOOGLE_MAPS_API_KEY=${GOOGLE_MAPS_API_KEY} + - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} + - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} + - AWS_REGION=${AWS_REGION} + - S3_BUCKET_NAME=${S3_BUCKET_NAME} + - POSTGRES_HOST=postgres + - POSTGRES_PORT=5432 + - POSTGRES_DB=${POSTGRES_DB} + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - ENV=DEV + - CONFIG_PATH=/app/app/utils/config.yaml + - LOGGING_CONFIG_PATH=/app/app/utils/logging_config.yaml + depends_on: + - postgres + - mongodb + - redis + - chromadb + volumes: + - ./src/backend:/app + - chroma_data:/chroma/chroma + + frontend: + build: + context: ./src/frontend # search for docker file here + args: + - REACT_APP_API_URL=${REACT_APP_API_URL} + ports: + - "80:80" + environment: + - REACT_APP_API_URL=${REACT_APP_API_URL} + + postgres: + image: postgres:13 + environment: + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + volumes: + - ./dump.sql:/docker-entrypoint-initdb.d/dump.sql # initialize db with existing pg data + - postgres_data:/var/lib/postgresql/data + + mongodb: + image: mongo:5.0 + volumes: + - mongodb_data:/data/db + + chromadb: + image: chromadb/chroma + ports: + - "8080:8000" + volumes: + - chroma_data:/chroma/chroma + + redis: + image: redis:6 + +volumes: + postgres_data: + mongodb_data: + chroma_data: \ No newline at end of file diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 67a9c44..0000000 --- a/requirements.txt +++ /dev/null @@ -1,312 +0,0 @@ -aiobotocore==2.13.0 -aiohttp==3.9.5 -aioitertools==0.11.0 -aioredis==2.0.1 -aiosignal==1.3.1 -altair==5.2.0 -annotated-types==0.6.0 -anyio==4.1.0 -appnope==0.1.3 -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 -arrow==1.3.0 -asgiref==3.7.2 -asttokens==2.4.1 -async-lru==2.0.4 -async-timeout==4.0.3 -asyncpg==0.29.0 -attrs==23.2.0 -Babel==2.13.1 -backoff==2.2.1 -bcrypt==4.0.1 -beautifulsoup4==4.12.3 -black==24.3.0 -bleach==6.1.0 -blinker==1.7.0 -blis==0.7.11 -boto3==1.34.113 -botocore==1.34.106 -bs4==0.0.2 -build==1.1.1 -cachetools==5.3.3 -catalogue==2.0.10 -certifi==2023.11.17 -cffi==1.16.0 -cfgv==3.4.0 -charset-normalizer==3.3.2 -chroma-hnswlib==0.7.3 -chromadb==0.4.24 -click==8.1.7 -cloudpathlib==0.16.0 -coloredlogs==15.0.1 -comm==0.2.0 -confection==0.1.4 -contourpy==1.2.0 -cryptography==42.0.5 -cycler==0.12.1 -cymem==2.0.8 -dataclasses-json==0.6.4 -datasets==2.15.0 -debugpy==1.8.0 -decorator==5.1.1 -defusedxml==0.7.1 -Deprecated==1.2.14 -dill==0.3.7 -dirtyjson==1.0.8 -diskcache==5.6.3 -distlib==0.3.8 -distro==1.9.0 -dnspython==2.6.1 -ecdsa==0.19.0 -exceptiongroup==1.2.0 -executing==2.0.1 -fastai==2.7.13 -fastapi==0.110.0 -fastbook==0.0.29 -fastcore==1.5.29 -fastdownload==0.0.7 -fastjsonschema==2.19.0 -fastprogress==1.0.3 -filelock==3.13.1 -flatbuffers==24.3.7 -fonttools==4.46.0 -fqdn==1.5.1 -frozenlist==1.4.0 -fsspec==2024.5.0 -gitdb==4.0.11 -GitPython==3.1.42 -google-auth==2.28.2 -googleapis-common-protos==1.63.0 -gptcache==0.1.43 -graphviz==0.20.1 -greenlet==3.0.3 -grpcio==1.62.1 -guidance==0.1.10 -h11==0.14.0 -httpcore==1.0.4 -httptools==0.6.1 -httpx==0.27.0 -huggingface-hub==0.19.4 -humanfriendly==10.0 -identify==2.5.35 -idna==3.6 -importlib-metadata==6.11.0 -importlib_resources==6.1.3 -iniconfig==2.0.0 -install==1.3.5 -ipykernel==6.27.1 -ipython==8.18.1 -ipython-genutils==0.2.0 -ipywidgets==7.8.1 -isoduration==20.11.0 -isort==5.13.2 -jedi==0.19.1 -Jinja2==3.1.2 -jmespath==1.0.1 -joblib==1.3.2 -json5==0.9.14 -jsonpointer==2.4 -jsonschema==4.20.0 -jsonschema-specifications==2023.11.2 -jupyter-events==0.9.0 -jupyter-lsp==2.2.1 -jupyter_client==8.6.0 -jupyter_core==5.5.0 -jupyter_server==2.12.1 -jupyter_server_terminals==0.4.4 -jupyterlab==4.0.9 -jupyterlab-widgets==1.1.7 -jupyterlab_pygments==0.3.0 -jupyterlab_server==2.25.2 -kiwisolver==1.4.5 -kubernetes==29.0.0 -langcodes==3.3.0 -llama-index==0.10.18 -llama-index-agent-openai==0.1.5 -llama-index-cli==0.1.8 -llama-index-core==0.10.39.post1 -llama-index-embeddings-huggingface==0.2.0 -llama-index-embeddings-openai==0.1.6 -llama-index-indices-managed-llama-cloud==0.1.3 -llama-index-legacy==0.9.48 -llama-index-llms-openai==0.1.7 -llama-index-multi-modal-llms-openai==0.1.4 -llama-index-program-guidance==0.1.2 -llama-index-program-openai==0.1.4 -llama-index-question-gen-openai==0.1.3 -llama-index-readers-file==0.1.23 -llama-index-readers-llama-parse==0.1.3 -llama-index-readers-s3==0.1.8 -llama-index-vector-stores-chroma==0.1.6 -llama-parse==0.3.8 -llamaindex-py-client==0.1.19 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -marshmallow==3.21.1 -matplotlib==3.8.2 -matplotlib-inline==0.1.6 -mdurl==0.1.2 -mistune==3.0.2 -mmh3==4.1.0 -monotonic==1.6 -mpmath==1.3.0 -msal==1.27.0 -multidict==6.0.4 -multiprocess==0.70.15 -murmurhash==1.0.10 -mypy-extensions==1.0.0 -nbclient==0.9.0 -nbconvert==7.12.0 -nbformat==5.9.2 -nest-asyncio==1.5.8 -networkx==3.2.1 -nltk==3.8.1 -nodeenv==1.8.0 -notebook==7.0.6 -notebook_shim==0.2.3 -numpy==1.26.2 -oauthlib==3.2.2 -onnxruntime==1.16.3 -openai==1.13.3 -opentelemetry-api==1.23.0 -opentelemetry-exporter-otlp-proto-common==1.23.0 -opentelemetry-exporter-otlp-proto-grpc==1.23.0 -opentelemetry-instrumentation==0.44b0 -opentelemetry-instrumentation-asgi==0.44b0 -opentelemetry-instrumentation-fastapi==0.44b0 -opentelemetry-proto==1.23.0 -opentelemetry-sdk==1.23.0 -opentelemetry-semantic-conventions==0.44b0 -opentelemetry-util-http==0.44b0 -ordered-set==4.1.0 -orjson==3.9.15 -outcome==1.3.0.post0 -overrides==7.4.0 -packaging==23.2 -pandas==2.1.3 -pandocfilters==1.5.0 -parso==0.8.3 -passlib==1.7.4 -pathspec==0.12.1 -pexpect==4.9.0 -Pillow==10.1.0 -platformdirs==4.1.0 -pluggy==1.5.0 -posthog==3.5.0 -pre-commit==3.6.2 -preshed==3.0.9 -prometheus-client==0.19.0 -prompt-toolkit==3.0.41 -protobuf==4.25.3 -psutil==5.9.6 -psycopg2-binary==2.9.9 -ptyprocess==0.7.0 -pulsar-client==3.4.0 -pure-eval==0.2.2 -pyarrow==14.0.1 -pyarrow-hotfix==0.6 -pyasn1==0.5.1 -pyasn1-modules==0.3.0 -pycparser==2.21 -pydantic==2.5.2 -pydantic_core==2.14.5 -pydeck==0.8.1b0 -pydot==2.0.0 -pyformlang==1.0.7 -Pygments==2.17.2 -PyJWT==2.8.0 -pymongo==4.6.3 -PyMuPDF==1.23.26 -PyMuPDFb==1.23.22 -pyparsing==3.1.1 -pypdf==4.1.0 -PyPDF2==3.0.1 -PyPika==0.48.9 -pyproject_hooks==1.0.0 -PySocks==1.7.1 -pyspark==3.2.0 -pytest==8.2.0 -python-dateutil==2.8.2 -python-dotenv==1.0.1 -python-jose==3.3.0 -python-json-logger==2.0.7 -python-multipart==0.0.9 -pytz==2023.3.post1 -PyYAML==6.0.1 -pyzmq==25.1.2 -referencing==0.31.1 -regex==2023.10.3 -requests==2.31.0 -requests-oauthlib==1.4.0 -rfc3339-validator==0.1.4 -rfc3986-validator==0.1.1 -rich==13.7.1 -rpds-py==0.13.2 -rsa==4.9 -s3fs==2024.5.0 -s3transfer==0.10.1 -safetensors==0.4.1 -scikit-learn==1.3.2 -scipy==1.11.4 -selenium==4.19.0 -Send2Trash==1.8.2 -sentence-transformers==2.6.1 -sentencepiece==0.1.99 -six==1.16.0 -smart-open==6.4.0 -smmap==5.0.1 -sniffio==1.3.0 -sortedcontainers==2.4.0 -soupsieve==2.5 -spacy==3.7.2 -spacy-legacy==3.0.12 -spacy-loggers==1.0.5 -SQLAlchemy==2.0.28 -srsly==2.4.8 -stack-data==0.6.3 -starlette==0.36.3 -streamlit==1.32.1 -striprtf==0.0.26 -sympy==1.12 -tenacity==8.2.3 -terminado==0.18.0 -thinc==8.2.1 -threadpoolctl==3.2.0 -tiktoken==0.6.0 -tinycss2==1.2.1 -tokenizers==0.15.0 -toml==0.10.2 -tomli==2.0.1 -toolz==0.12.1 -torch==2.1.1 -torchvision==0.16.1 -tornado==6.4 -tqdm==4.66.1 -traitlets==5.14.0 -transformers==4.35.2 -trio==0.25.0 -trio-websocket==0.11.1 -typer==0.9.0 -types-python-dateutil==2.8.19.14 -typing-inspect==0.9.0 -typing_extensions==4.10.0 -tzdata==2023.3 -uri-template==1.3.0 -urllib3==2.1.0 -uvicorn==0.28.0 -uvloop==0.19.0 -virtualenv==20.25.1 -wasabi==1.1.2 -watchfiles==0.21.0 -wcwidth==0.2.12 -weasel==0.3.4 -webcolors==1.13 -webencodings==0.5.1 -websocket-client==1.7.0 -websockets==12.0 -widgetsnbextension==3.6.6 -wrapt==1.16.0 -wsproto==1.2.0 -xxhash==3.4.1 -yarl==1.9.4 -zipp==3.17.0 diff --git a/src/backend/Dockerfile b/src/backend/Dockerfile new file mode 100644 index 0000000..a1aea8f --- /dev/null +++ b/src/backend/Dockerfile @@ -0,0 +1,8 @@ +FROM python:3.10 +WORKDIR /app +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt +COPY . . +RUN echo "Directory structure:" && ls -R +RUN find / -name main.py +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file diff --git a/src/backend/app/api_v1/endpoints/appointments.py b/src/backend/app/api_v1/endpoints/appointments.py index ba40cf6..6ff9b2e 100644 --- a/src/backend/app/api_v1/endpoints/appointments.py +++ b/src/backend/app/api_v1/endpoints/appointments.py @@ -9,16 +9,7 @@ import aioredis import boto3 from dotenv import load_dotenv -from fastapi import ( - APIRouter, - BackgroundTasks, - Depends, - File, - Header, - HTTPException, - Request, - UploadFile, -) +from fastapi import APIRouter, BackgroundTasks, File, Header, HTTPException, UploadFile from fastapi.responses import JSONResponse from llama_index.core import SimpleDirectoryReader, download_loader from openai import AsyncOpenAI, OpenAI @@ -26,8 +17,6 @@ from pydantic import BaseModel, Field from pymongo import MongoClient -from ....models.open_ai import prompts as oai_prompts -from ....models.open_ai.utils import OAIRequest, a_send_rqt from ...db.nosql_db import get_provider_by_npi, get_provider_id, upsert_provider from ...db.relational_db import ( create_connection, @@ -37,6 +26,8 @@ ) from ...db.vector_db import load_documents from ...deps import get_current_user +from ...models.open_ai import prompts as oai_prompts +from ...models.open_ai.utils import OAIRequest, a_send_rqt from ...pydantic_models.pyd_models import ( AppointmentMeta, ApptRqt, @@ -45,7 +36,7 @@ Summary, specialties, ) -from ...utils.utils import create_hash_id, get_locations +from ...utils.utils import create_hash_id load_dotenv() @@ -55,7 +46,8 @@ AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY") AWS_REGION = os.getenv("AWS_REGION") S3_BUCKET_NAME = os.getenv("S3_BUCKET_NAME") - +REDIS_URL = os.getenv("REDIS_URL", "redis://localhost") +MONGODB_URL = os.getenv("MONGODB_URL", "mongodb://localhost:27017") METADATA_PARAMS = [ "user_id", @@ -63,13 +55,15 @@ "filename", "appointment_date", ] -locations = get_locations() + client = AsyncOpenAI() -redis = aioredis.from_url(locations["redis"]) -mongo_db_client = MongoClient(locations["mongo_db"]) +redis = aioredis.from_url(REDIS_URL) +mongo_db_client = MongoClient(MONGODB_URL) + db = mongo_db_client["wilson_ai"] provider_collection = db.providers conn = create_connection() + s3_client = boto3.client( "s3", aws_access_key_id=AWS_ACCESS_KEY_ID, @@ -233,6 +227,7 @@ async def analyze_appointment(appt_rqt: ApptRqt, background_tasks: BackgroundTas context = loader.load_data() text = " ".join([doc.text for doc in context]) + # check if response in redis cache first cache_key = create_hash_id(text, {"filename": appt_rqt.data_location}) encoded_info = await get_cached_data(cache_key) info = json.loads(encoded_info) if encoded_info else None @@ -317,7 +312,7 @@ async def get_appointments(user_id: int): client = AsyncOpenAI() - context = SimpleDirectoryReader("/Users/nickocorriveau/dev/wilson/data").load_data() + context = SimpleDirectoryReader("../data").load_data() appt = AppointmentAnalysis(client, context) logger.info("Starting timer") diff --git a/src/backend/app/api_v1/endpoints/chat_w_data.py b/src/backend/app/api_v1/endpoints/chat_w_data.py index ab07be4..5cca4f5 100644 --- a/src/backend/app/api_v1/endpoints/chat_w_data.py +++ b/src/backend/app/api_v1/endpoints/chat_w_data.py @@ -2,21 +2,20 @@ import logging import chromadb -from fastapi import APIRouter, Depends, File, Header, HTTPException, UploadFile +from fastapi import APIRouter, File, Header, HTTPException, UploadFile from openai import AsyncOpenAI from pydantic import BaseModel, Field from PyPDF2 import PdfReader -from ....models.open_ai.utils import OAIRequest, a_send_rqt from ...db.vector_db import ( COLLECTION, DB_PATH, EMBED_MODEL, - build_index, get_context, structure_context, ) from ...deps import get_current_user +from ...models.open_ai.utils import OAIRequest, a_send_rqt logger = logging.getLogger(__name__) diff --git a/src/backend/app/api_v1/endpoints/follow_ups.py b/src/backend/app/api_v1/endpoints/follow_ups.py index 3585b2a..53e2350 100644 --- a/src/backend/app/api_v1/endpoints/follow_ups.py +++ b/src/backend/app/api_v1/endpoints/follow_ups.py @@ -1,6 +1,6 @@ import asyncio import logging -import sys +import os from pprint import pprint from typing import Any, Dict @@ -11,15 +11,15 @@ from pymongo import MongoClient from pymongo.collection import Collection -from ....models.open_ai.utils import OAIRequest, a_send_rqt from ...db.nosql_db import get_relevant_providers from ...deps import get_current_user +from ...models.open_ai.utils import OAIRequest, a_send_rqt from ...pydantic_models.pyd_models import FollowUpRqt, TaskSpecialty, specialties -from ...utils.utils import get_locations from .appointments import FollowUps logger = logging.getLogger(__name__) +MONGODB_URL = os.getenv("MONGODB_URL", "mongodb://localhost:27017") SYSTEM_MSG = """ You are an expert medical assistant and are helping us match physician follow up tasks @@ -92,9 +92,8 @@ async def get_followup_suggestions( router = APIRouter(dependencies=[Depends(get_current_user)]) -locations = get_locations() client = AsyncOpenAI() -mongo_db_client = MongoClient("mongodb://localhost:27017/") +mongo_db_client = MongoClient(MONGODB_URL) db = mongo_db_client["wilson_ai"] provider_collection = db.providers @@ -111,7 +110,7 @@ async def get_follow_ups(followup_rqt: FollowUpRqt): if __name__ == "__main__": client = AsyncOpenAI() - client_db = MongoClient("mongodb://localhost:27017/") + client_db = MongoClient(MONGODB_URL) db = client_db["wilson_ai"] collection = db.providers diff --git a/src/backend/app/api_v1/endpoints/prescriptions.py b/src/backend/app/api_v1/endpoints/prescriptions.py index e70c8fb..24527cf 100644 --- a/src/backend/app/api_v1/endpoints/prescriptions.py +++ b/src/backend/app/api_v1/endpoints/prescriptions.py @@ -1,4 +1,5 @@ import logging +import os from pprint import pprint from typing import List @@ -15,10 +16,11 @@ set_prescription_status, ) from ...pydantic_models.pyd_models import PrescriptionRequest, PrescriptionResponse -from ...utils.utils import get_locations logger = logging.getLogger(__name__) +MONGODB_URL = os.getenv("MONGODB_URL", "mongodb://localhost:27017") + def get_prescriptions( user_id: int, conn: connection, collection: Collection @@ -41,8 +43,7 @@ def get_prescriptions( # dependencies=[Depends(get_current_user)] router = APIRouter() -locations = get_locations() -mongo_db_client = MongoClient(locations["mongo_db"]) +mongo_db_client = MongoClient(MONGODB_URL) db = mongo_db_client["wilson_ai"] conn = create_connection() provider_collection = db.providers @@ -63,7 +64,7 @@ async def set_status(prescription_id: int, rqt: PrescriptionRequest): if __name__ == "__main__": - client_db = MongoClient("mongodb://localhost:27017/") + client_db = MongoClient(MONGODB_URL) db = client_db["wilson_ai"] collection = db.providers conn = create_connection() diff --git a/src/backend/app/db/relational_db.py b/src/backend/app/db/relational_db.py index 9b7fef7..fbd2740 100644 --- a/src/backend/app/db/relational_db.py +++ b/src/backend/app/db/relational_db.py @@ -15,8 +15,12 @@ GOOGE_MAPS_API = "https://maps.googleapis.com/maps/api/geocode/json" logger = logging.getLogger(__name__) -password = os.getenv("POSTGRES_PASSWORD") api_key = os.getenv("GOOGLE_MAPS_API_KEY") +pg_user = os.getenv("POSTGRES_USER", "postgres") +pg_db = os.getenv("POSTGRES_DB", "postgres") +pg_pw = os.getenv("POSTGRES_PASSWORD") +pg_port = os.getenv("POSTGRES_PORT", "5432") +pg_host = os.getenv("POSTGRES_HOST", "localhost") def geocode_address(street, city, state, zip_code): @@ -246,19 +250,19 @@ def geocode_address(street, city, state, zip_code): """ pg_params = { - "dbname": "postgres", - "user": "postgres", - "password": password, - "host": "localhost", - "port": "5432", + "dbname": pg_db, + "user": pg_user, + "password": pg_pw, + "host": pg_host, + "port": pg_port, } async_pg_params = { - "database": "postgres", - "user": "postgres", - "password": password, - "host": "localhost", - "port": "5432", + "database": pg_db, + "user": pg_user, + "password": pg_pw, + "host": pg_host, + "port": pg_port, } diff --git a/src/backend/app/db/vector_db.py b/src/backend/app/db/vector_db.py index d65f2d6..d5e859d 100644 --- a/src/backend/app/db/vector_db.py +++ b/src/backend/app/db/vector_db.py @@ -15,7 +15,6 @@ from llama_index.core.indices.vector_store.base import VectorStoreIndex from llama_index.core.schema import Document from llama_index.core.vector_stores import MetadataFilter, MetadataFilters -from llama_index.vector_stores.chroma import ChromaVectorStore from ..utils.utils import create_hash_id @@ -23,8 +22,9 @@ os.environ["TOKENIZERS_PARALLELISM"] = "false" + +DB_PATH = os.getenv("CHROMADB_PATH", "./chroma_db") COLLECTION = "appointment_oai" -DB_PATH = "/Users/nickocorriveau/dev/wilson/chroma_db" HF_EMBED_MODEL = "BAAI/bge-base-en-v1.5" CHAT_W_DATA_SYS_MSG = """You are a word class medical physician who is also an expert in Q&A and you will assist in analyzing this patient's medical records @@ -101,15 +101,15 @@ def structure_context(context: Dict[str, Any]) -> str: return "\n".join(df["formatted_row"].to_list()) -def build_index(embed_model: Any) -> VectorStoreIndex: - db = chromadb.PersistentClient(path=DB_PATH) - chroma_collection = db.get_or_create_collection(COLLECTION) - vector_store = ChromaVectorStore(chroma_collection=chroma_collection) - index = VectorStoreIndex.from_vector_store( - vector_store, - embed_model=embed_model, - ) - return index +# def build_index(embed_model: Any) -> VectorStoreIndex: +# db = chromadb.PersistentClient(path=DB_PATH) +# chroma_collection = db.get_or_create_collection(COLLECTION) +# vector_store = ChromaVectorStore(chroma_collection=chroma_collection) +# index = VectorStoreIndex.from_vector_store( +# vector_store, +# embed_model=embed_model, +# ) +# return index def query_documents(query: str, user_id: int, index: VectorStoreIndex) -> Response: @@ -135,9 +135,9 @@ def query_documents(query: str, user_id: int, index: VectorStoreIndex) -> Respon client = AsyncOpenAI() _logger.info("Loading documents...") - context = SimpleDirectoryReader("../data").load_data() + context = SimpleDirectoryReader("./data").load_data() - db = chromadb.PersistentClient(path=DB_PATH) + db = chromadb.PersistentClient(path="./chroma_db") chroma_collection = db.get_or_create_collection( COLLECTION, embedding_function=EMBED_MODEL ) diff --git a/src/backend/app/main.py b/src/backend/app/main.py index 0e178ef..7193fe1 100644 --- a/src/backend/app/main.py +++ b/src/backend/app/main.py @@ -1,4 +1,5 @@ import logging +import os import yaml from dotenv import load_dotenv @@ -9,7 +10,12 @@ load_dotenv() -with open("src/backend/app/utils/logging_config.yaml", "r") as config_file: +config_path = os.getenv( + "LOGGING_CONFIG_PATH", "src/backend/app/utils/logging_config.yaml" +) + + +with open(config_path, "r") as config_file: logging_config = yaml.safe_load(config_file) logging.config.dictConfig(logging_config) diff --git a/src/backend/models/__init__.py b/src/backend/app/models/__init__.py similarity index 100% rename from src/backend/models/__init__.py rename to src/backend/app/models/__init__.py diff --git a/src/backend/models/open_ai/__init__.py b/src/backend/app/models/open_ai/__init__.py similarity index 100% rename from src/backend/models/open_ai/__init__.py rename to src/backend/app/models/open_ai/__init__.py diff --git a/src/backend/models/open_ai/prompts.py b/src/backend/app/models/open_ai/prompts.py similarity index 100% rename from src/backend/models/open_ai/prompts.py rename to src/backend/app/models/open_ai/prompts.py diff --git a/src/backend/models/open_ai/utils.py b/src/backend/app/models/open_ai/utils.py similarity index 100% rename from src/backend/models/open_ai/utils.py rename to src/backend/app/models/open_ai/utils.py diff --git a/src/backend/app/utils/utils.py b/src/backend/app/utils/utils.py index 5f62ec7..9619e3f 100644 --- a/src/backend/app/utils/utils.py +++ b/src/backend/app/utils/utils.py @@ -9,7 +9,7 @@ load_dotenv() -CONFIG_PATH = "src/backend/app/utils/config.yaml" +config_path = os.getenv("CONFIG_PATH", "src/backend/app/utils/config.yaml") class Env(Enum): @@ -31,7 +31,7 @@ def read_config(env: Env) -> Dict[str, Any]: """Read the configuration file.""" if env not in Env: raise ValueError(f"Invalid environment: {env}. Expected one of: {list(Env)}") - with open(CONFIG_PATH, "r") as config_file: + with open(config_path, "r") as config_file: config = yaml.safe_load(config_file) return config[env.value] diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt new file mode 100644 index 0000000..ef5d1b4 --- /dev/null +++ b/src/backend/requirements.txt @@ -0,0 +1,19 @@ +aioredis==2.0.1 +asyncpg==0.29.0 +boto3==1.34.113 +chromadb==0.5.5 +fastapi==0.111.1 +llama_index==0.10.56 +openai==1.36.1 +pandas==2.2.2 +passlib==1.7.4 +psycopg2_binary==2.9.9 +pydantic==2.8.2 +pymongo==4.6.3 +PyPDF2==3.0.1 +python-dotenv==1.0.1 +python_jose==3.3.0 +PyYAML==6.0.1 +PyYAML==6.0.1 +Requests==2.32.3 +selenium==4.23.0 diff --git a/src/frontend/Dockerfile b/src/frontend/Dockerfile new file mode 100644 index 0000000..957e163 --- /dev/null +++ b/src/frontend/Dockerfile @@ -0,0 +1,13 @@ +FROM node:18.7 as build +WORKDIR /app +COPY package*.json ./ +RUN npm install +COPY . . +ARG REACT_APP_API_URL +ENV REACT_APP_API_URL=$REACT_APP_API_URL +RUN npm run build + +FROM nginx:alpine +COPY --from=build /app/build /usr/share/nginx/html +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file