diff --git a/src/python/AgentHubAPI/AgentHubAPI.pyproj b/src/python/AgentHubAPI/AgentHubAPI.pyproj index 3ed49d3792..94eb97e7fc 100644 --- a/src/python/AgentHubAPI/AgentHubAPI.pyproj +++ b/src/python/AgentHubAPI/AgentHubAPI.pyproj @@ -4,7 +4,7 @@ 2.0 865a944e-76c4-4da9-b367-6d1cab66abcc . - app/main.py + run.py ..\PythonSDK . Standard Python launcher @@ -34,12 +34,12 @@ + - diff --git a/src/python/AgentHubAPI/app/dependencies.py b/src/python/AgentHubAPI/app/dependencies.py index 56a07bb4e6..7d5ff1a00f 100644 --- a/src/python/AgentHubAPI/app/dependencies.py +++ b/src/python/AgentHubAPI/app/dependencies.py @@ -2,6 +2,7 @@ Provides dependencies for API calls. """ import logging +import time from typing import Annotated from fastapi import Depends, HTTPException from fastapi.security import APIKeyHeader @@ -18,17 +19,20 @@ def get_config() -> Configuration: Configuration Returns the application configuration settings. """ - return __config or Configuration() + global __config -def validate_api_key_header(config: Annotated[Configuration, Depends()], - x_api_key: str = Depends(APIKeyHeader(name='X-API-Key'))): + start = time.time() + __config = __config or Configuration() + end = time.time() + print(f'Time to load config: {end-start}') + return __config + +def validate_api_key_header(x_api_key: str = Depends(APIKeyHeader(name='X-API-Key'))): """ Validates that the X-API-Key value in the request header matches the key expected for this API. Parameters ---------- - app_config : Configuration - Used for retrieving application configuration settings. x_api_key : str The X-API-Key value in the request header. @@ -37,8 +41,7 @@ def validate_api_key_header(config: Annotated[Configuration, Depends()], Returns True of the X-API-Key value from the request header matches the expected value. Otherwise, returns False. """ - - result = x_api_key == config.get_value('FoundationaLLM:APIs:AgentHubAPI:APIKey') + result = x_api_key == get_config().get_value('FoundationaLLM:APIs:AgentHubAPI:APIKey') if not result: logging.error('Invalid API key. You must provide a valid API key in the X-API-KEY header.') @@ -47,7 +50,7 @@ def validate_api_key_header(config: Annotated[Configuration, Depends()], detail = 'Invalid API key. You must provide a valid API key in the X-API-KEY header.' ) -def handle_exception(exception: Exception): +def handle_exception(exception: Exception, status_code: int = 500): """ Handles an exception that occurred while processing a request. @@ -58,6 +61,6 @@ def handle_exception(exception: Exception): """ logging.error(exception, stack_info=True, exc_info=True) raise HTTPException( - status_code = 500, + status_code = status_code, detail = str(exception) ) from exception diff --git a/src/python/AgentHubAPI/app/main.py b/src/python/AgentHubAPI/app/main.py index 157dfdcbe0..fac71d4857 100644 --- a/src/python/AgentHubAPI/app/main.py +++ b/src/python/AgentHubAPI/app/main.py @@ -2,7 +2,6 @@ Main entry-point for the FoundationaLLM AgentHubAPI. Runs web server exposing the API. """ -import uvicorn from fastapi import FastAPI from app.dependencies import get_config from app.routers import resolve, status, list_agents @@ -17,10 +16,8 @@ app = FastAPI( title='FoundationaLLM AgentHubAPI', summary='API for retrieving Agent metadata', - description= - """The FoundationaLLM AgentHubAPI is a wrapper around - AgentHub functionality contained in the - foundationallm.core Python SDK.""", + description="""The FoundationaLLM AgentHubAPI is a wrapper around AgentHub + functionality contained in the foundationallm Python SDK.""", version='1.0.0', contact={ 'name':'Solliance, Inc.', @@ -52,7 +49,3 @@ async def root(): Returns a JSON object containing a message and value. """ return { 'message': 'FoundationaLLM AgentHubAPI' } - -if __name__ == '__main__': - uvicorn.run('app.main:app', host='0.0.0.0', port=8742, - reload=True, forwarded_allow_ips='*', proxy_headers=True) diff --git a/src/python/AgentHubAPI/app/routers/list_agents.py b/src/python/AgentHubAPI/app/routers/list_agents.py index 4429b2dd8d..5a18f66c54 100644 --- a/src/python/AgentHubAPI/app/routers/list_agents.py +++ b/src/python/AgentHubAPI/app/routers/list_agents.py @@ -2,7 +2,7 @@ The API endpoint for listing available agents. """ from typing import List -from fastapi import APIRouter, Depends +from fastapi import APIRouter, Depends, Request from foundationallm.hubs.agent import AgentHub from app.dependencies import validate_api_key_header, handle_exception @@ -15,9 +15,14 @@ ) @router.get('') -async def list_agents() -> List: +async def list_agents(request: Request) -> List: """ Retrieves a list of available agents. + + Parameters + ---------- + request : Request + The underlying HTTP request. Returns ------- @@ -25,6 +30,6 @@ async def list_agents() -> List: Returns a list of metadata objects for all available agents. """ try: - return AgentHub().list() + return AgentHub(config=request.app.extra['config']).list() except Exception as e: handle_exception(e) diff --git a/src/python/AgentHubAPI/app/routers/resolve.py b/src/python/AgentHubAPI/app/routers/resolve.py index 6938a6047c..e4c4b5dc54 100644 --- a/src/python/AgentHubAPI/app/routers/resolve.py +++ b/src/python/AgentHubAPI/app/routers/resolve.py @@ -6,7 +6,7 @@ from foundationallm.config import Context from foundationallm.hubs.agent import AgentHub, AgentHubRequest, AgentHubResponse from foundationallm.models import AgentHint -from app.dependencies import validate_api_key_header, handle_exception +from app.dependencies import handle_exception, validate_api_key_header router = APIRouter( prefix='/resolve', diff --git a/src/python/AgentHubAPI/run.py b/src/python/AgentHubAPI/run.py new file mode 100644 index 0000000000..ff02b728de --- /dev/null +++ b/src/python/AgentHubAPI/run.py @@ -0,0 +1,11 @@ +import uvicorn + +if __name__ == '__main__': + uvicorn.run( + 'app.main:app', + host='0.0.0.0', + port=8742, + reload=True, + forwarded_allow_ips='*', + proxy_headers=True + ) diff --git a/src/python/AgentHubAPI/startup.sh b/src/python/AgentHubAPI/startup.sh deleted file mode 100644 index f9c45a8039..0000000000 --- a/src/python/AgentHubAPI/startup.sh +++ /dev/null @@ -1 +0,0 @@ -gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app \ No newline at end of file diff --git a/src/python/DataSourceHubAPI/DataSourceHubAPI.pyproj b/src/python/DataSourceHubAPI/DataSourceHubAPI.pyproj index 7056e6b904..8db0f2f9b4 100644 --- a/src/python/DataSourceHubAPI/DataSourceHubAPI.pyproj +++ b/src/python/DataSourceHubAPI/DataSourceHubAPI.pyproj @@ -6,7 +6,7 @@ 637b74c9-aeb1-4b1a-8e92-20ac35d111eb . {1b580a1a-fdb3-4b32-83e1-6407eb2722e6};{349c5851-65df-11da-9384-00065b846f21};{888888a0-9f3d-457c-b088-3a5042f75d52} - app/main.py + run.py ..\PythonSDK . Standard Python launcher @@ -36,12 +36,12 @@ + - diff --git a/src/python/DataSourceHubAPI/app/dependencies.py b/src/python/DataSourceHubAPI/app/dependencies.py index e4393d75ce..cbf0accfde 100644 --- a/src/python/DataSourceHubAPI/app/dependencies.py +++ b/src/python/DataSourceHubAPI/app/dependencies.py @@ -2,6 +2,7 @@ Provides dependencies for API calls. """ import logging +import time from typing import Annotated from fastapi import Depends, HTTPException from fastapi.security import APIKeyHeader @@ -18,17 +19,20 @@ def get_config() -> Configuration: Configuration Returns the application configuration settings. """ - return __config or Configuration() + global __config -def validate_api_key_header(config: Annotated[Configuration, Depends()], - x_api_key: str = Depends(APIKeyHeader(name='X-API-Key'))): + start = time.time() + __config = __config or Configuration() + end = time.time() + print(f'Time to load config: {end-start}') + return __config + +def validate_api_key_header(x_api_key: str = Depends(APIKeyHeader(name='X-API-Key'))): """ Validates that the X-API-Key value in the request header matches the key expected for this API. Parameters ---------- - app_config : Configuration - Used for retrieving application configuration settings. x_api_key : str The X-API-Key value in the request header. @@ -38,7 +42,7 @@ def validate_api_key_header(config: Annotated[Configuration, Depends()], Otherwise, returns False. """ - result = x_api_key == config.get_value('FoundationaLLM:APIs:DataSourceHubAPI:APIKey') + result = x_api_key == get_config().get_value('FoundationaLLM:APIs:DataSourceHubAPI:APIKey') if not result: logging.error('Invalid API key. You must provide a valid API key in the X-API-KEY header.') @@ -46,3 +50,18 @@ def validate_api_key_header(config: Annotated[Configuration, Depends()], status_code = 401, detail = 'Invalid API key. You must provide a valid API key in the X-API-KEY header.' ) + +def handle_exception(exception: Exception, status_code: int = 500): + """ + Handles an exception that occurred while processing a request. + + Parameters + ---------- + exception : Exception + The exception that occurred. + """ + logging.error(exception, stack_info=True, exc_info=True) + raise HTTPException( + status_code = status_code, + detail = str(exception) + ) from exception diff --git a/src/python/DataSourceHubAPI/app/main.py b/src/python/DataSourceHubAPI/app/main.py index 18038a2d0d..a500333976 100644 --- a/src/python/DataSourceHubAPI/app/main.py +++ b/src/python/DataSourceHubAPI/app/main.py @@ -2,7 +2,6 @@ Main entry-point for the FoundationaLLM DataSourceHubAPI. Runs web server exposing the API. """ -import uvicorn from fastapi import FastAPI from app.dependencies import get_config from app.routers import resolve, status @@ -18,7 +17,7 @@ title='FoundationaLLM DataSourceHubAPI', summary='API for retrieving DataSource metadata', description="""The FoundationaLLM DataSourceHubAPI is a wrapper around DataSourceHub - functionality contained in the foundationallm.core Python SDK.""", + functionality contained in the foundationallm Python SDK.""", version='1.0.0', contact={ 'name':'Solliance, Inc.', @@ -49,7 +48,3 @@ async def root(): Returns a JSON object containing a message and value. """ return { 'message': 'FoundationaLLM DataSourceHubAPI' } - -if __name__ == '__main__': - uvicorn.run('main:app', host='0.0.0.0', port=8842, - reload=True, forwarded_allow_ips='*', proxy_headers=True) diff --git a/src/python/DataSourceHubAPI/app/routers/resolve.py b/src/python/DataSourceHubAPI/app/routers/resolve.py index 25941610bb..236e7c1ee8 100644 --- a/src/python/DataSourceHubAPI/app/routers/resolve.py +++ b/src/python/DataSourceHubAPI/app/routers/resolve.py @@ -1,14 +1,16 @@ """ The API endpoint for returning the requested data source metadata. """ -import logging from typing import Optional -from fastapi import APIRouter, Depends, HTTPException, Header, Request +from fastapi import APIRouter, Depends, Header, Request from foundationallm.config import Context from foundationallm.models import AgentHint -from foundationallm.hubs.data_source import (DataSourceHubRequest, - DataSourceHubResponse, DataSourceHub) -from app.dependencies import validate_api_key_header +from foundationallm.hubs.data_source import ( + DataSourceHubRequest, + DataSourceHubResponse, + DataSourceHub +) +from app.dependencies import handle_exception, validate_api_key_header router = APIRouter( prefix='/resolve', @@ -49,8 +51,4 @@ async def resolve( return DataSourceHub(config=request.app.extra['config']).resolve(request=datasource_request, user_context=context, hint=agent_hint) return DataSourceHub(config=request.app.extra['config']).resolve(request=datasource_request, user_context=context) except Exception as e: - logging.error(e, stack_info=True, exc_info=True) - raise HTTPException( - status_code = 500, - detail = str(e) - ) from e + handle_exception(e) diff --git a/src/python/DataSourceHubAPI/run.py b/src/python/DataSourceHubAPI/run.py new file mode 100644 index 0000000000..979e4bdbbf --- /dev/null +++ b/src/python/DataSourceHubAPI/run.py @@ -0,0 +1,11 @@ +import uvicorn + +if __name__ == '__main__': + uvicorn.run( + 'app.main:app', + host='0.0.0.0', + port=8842, + reload=True, + forwarded_allow_ips='*', + proxy_headers=True + ) diff --git a/src/python/DataSourceHubAPI/startup.sh b/src/python/DataSourceHubAPI/startup.sh deleted file mode 100644 index f9c45a8039..0000000000 --- a/src/python/DataSourceHubAPI/startup.sh +++ /dev/null @@ -1 +0,0 @@ -gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app \ No newline at end of file diff --git a/src/python/GatekeeperIntegrationAPI/GatekeeperIntegrationAPI.pyproj b/src/python/GatekeeperIntegrationAPI/GatekeeperIntegrationAPI.pyproj index 9d5e859203..0418a3dac1 100644 --- a/src/python/GatekeeperIntegrationAPI/GatekeeperIntegrationAPI.pyproj +++ b/src/python/GatekeeperIntegrationAPI/GatekeeperIntegrationAPI.pyproj @@ -5,7 +5,7 @@ f74cbb5a-97b9-4f68-8077-8bab49c841dc - app/main.py + run.py ..\IntegrationSDK . . @@ -31,6 +31,7 @@ + @@ -40,7 +41,6 @@ - diff --git a/src/python/GatekeeperIntegrationAPI/app/dependencies.py b/src/python/GatekeeperIntegrationAPI/app/dependencies.py index f3f65d4b99..f509f4056b 100644 --- a/src/python/GatekeeperIntegrationAPI/app/dependencies.py +++ b/src/python/GatekeeperIntegrationAPI/app/dependencies.py @@ -2,6 +2,7 @@ Provides dependencies for API calls. """ import logging +import time from typing import Annotated from fastapi import Depends, HTTPException from fastapi.security import APIKeyHeader @@ -18,17 +19,20 @@ def get_config() -> Configuration: Configuration Returns the application configuration settings. """ - return __config or Configuration() + global __config -def validate_api_key_header(config: Annotated[Configuration, Depends()], - x_api_key: str = Depends(APIKeyHeader(name='X-API-Key'))): + start = time.time() + __config = __config or Configuration() + end = time.time() + print(f'Time to load config: {end-start}') + return __config + +def validate_api_key_header(x_api_key: str = Depends(APIKeyHeader(name='X-API-Key'))): """ Validates that the X-API-Key value in the request header matches the key expected for this API. Parameters ---------- - app_config : Configuration - Used for retrieving application configuration settings. x_api_key : str The X-API-Key value in the request header. @@ -38,7 +42,7 @@ def validate_api_key_header(config: Annotated[Configuration, Depends()], Otherwise, returns False. """ - result = x_api_key == config.get_value('FoundationaLLM:APIs:GatekeeperIntegrationAPI:APIKey') + result = x_api_key == get_config().get_value('FoundationaLLM:APIs:GatekeeperIntegrationAPI:APIKey') if not result: logging.error('Invalid API key. You must provide a valid API key in the X-API-KEY header.') @@ -47,7 +51,7 @@ def validate_api_key_header(config: Annotated[Configuration, Depends()], detail = 'Invalid API key. You must provide a valid API key in the X-API-KEY header.' ) -def handle_exception(exception: Exception): +def handle_exception(exception: Exception, status_code: int = 500): """ Handles an exception that occurred while processing a request. @@ -58,6 +62,6 @@ def handle_exception(exception: Exception): """ logging.error(exception, stack_info=True, exc_info=True) raise HTTPException( - status_code = 500, + status_code = status_code, detail = str(exception) ) from exception diff --git a/src/python/GatekeeperIntegrationAPI/app/main.py b/src/python/GatekeeperIntegrationAPI/app/main.py index a42e697002..b375ecd842 100644 --- a/src/python/GatekeeperIntegrationAPI/app/main.py +++ b/src/python/GatekeeperIntegrationAPI/app/main.py @@ -2,7 +2,6 @@ Main entry-point for the FoundationaLLM DataSourceHubAPI. Runs web server exposing the API. """ -import uvicorn from fastapi import FastAPI from app.dependencies import get_config from app.routers import analyze, status @@ -42,7 +41,3 @@ async def root(): Returns a JSON object containing a message and value. """ return { 'message': 'FoundationaLLM GatekeeperIntegrationAPI' } - -if __name__ == '__main__': - uvicorn.run('main:app', host='0.0.0.0', port=8042, reload=True, - forwarded_allow_ips='*', proxy_headers=True) diff --git a/src/python/GatekeeperIntegrationAPI/run.py b/src/python/GatekeeperIntegrationAPI/run.py new file mode 100644 index 0000000000..6370201c38 --- /dev/null +++ b/src/python/GatekeeperIntegrationAPI/run.py @@ -0,0 +1,11 @@ +import uvicorn + +if __name__ == '__main__': + uvicorn.run( + 'app.main:app', + host='0.0.0.0', + port=8042, + reload=True, + forwarded_allow_ips='*', + proxy_headers=True + ) diff --git a/src/python/GatekeeperIntegrationAPI/startup.sh b/src/python/GatekeeperIntegrationAPI/startup.sh deleted file mode 100644 index f9c45a8039..0000000000 --- a/src/python/GatekeeperIntegrationAPI/startup.sh +++ /dev/null @@ -1 +0,0 @@ -gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app \ No newline at end of file diff --git a/src/python/LangChainAPI/LangChainAPI.pyproj b/src/python/LangChainAPI/LangChainAPI.pyproj index 61b5ab667a..e77658fa8b 100644 --- a/src/python/LangChainAPI/LangChainAPI.pyproj +++ b/src/python/LangChainAPI/LangChainAPI.pyproj @@ -7,7 +7,7 @@ {1b580a1a-fdb3-4b32-83e1-6407eb2722e6};{349c5851-65df-11da-9384-00065b846f21};{888888a0-9f3d-457c-b088-3a5042f75d52} - app/main.py + run.py ..\PythonSDK . Standard Python launcher @@ -37,7 +37,6 @@ - @@ -46,6 +45,7 @@ + diff --git a/src/python/LangChainAPI/app/dependencies.py b/src/python/LangChainAPI/app/dependencies.py index 76b445a2ff..be070b8926 100644 --- a/src/python/LangChainAPI/app/dependencies.py +++ b/src/python/LangChainAPI/app/dependencies.py @@ -2,6 +2,7 @@ Provides dependencies for API calls. """ import logging +import time from typing import Annotated from fastapi import Depends, HTTPException from fastapi.security import APIKeyHeader @@ -18,17 +19,20 @@ def get_config() -> Configuration: Configuration Returns the application configuration settings. """ - return __config or Configuration() + global __config -async def validate_api_key_header(config: Annotated[Configuration, Depends()], - x_api_key: str = Depends(APIKeyHeader(name='X-API-Key'))) -> bool: + start = time.time() + __config = __config or Configuration() + end = time.time() + print(f'Time to load config: {end-start}') + return __config + +async def validate_api_key_header(x_api_key: str = Depends(APIKeyHeader(name='X-API-Key'))) -> bool: """ Validates that the X-API-Key value in the request header matches the key expected for this API. Parameters ---------- - app_config : Configuration - Used for retrieving application configuration settings. x_api_key : str The X-API-Key value in the request header. @@ -38,7 +42,7 @@ async def validate_api_key_header(config: Annotated[Configuration, Depends()], Otherwise, returns False. """ - result = x_api_key == config.get_value('FoundationaLLM:LangChainAPI:Key') + result = x_api_key == get_config().get_value('FoundationaLLM:LangChainAPI:Key') if not result: logging.error('Invalid API key. You must provide a valid API key in the X-API-KEY header.') @@ -46,3 +50,18 @@ async def validate_api_key_header(config: Annotated[Configuration, Depends()], status_code = 401, detail = 'Invalid API key. You must provide a valid API key in the X-API-KEY header.' ) + +def handle_exception(exception: Exception, status_code: int = 500): + """ + Handles an exception that occurred while processing a request. + + Parameters + ---------- + exception : Exception + The exception that occurred. + """ + logging.error(exception, stack_info=True, exc_info=True) + raise HTTPException( + status_code = status_code, + detail = str(exception) + ) from exception diff --git a/src/python/LangChainAPI/app/main.py b/src/python/LangChainAPI/app/main.py index 80388d3caf..016fdc4000 100644 --- a/src/python/LangChainAPI/app/main.py +++ b/src/python/LangChainAPI/app/main.py @@ -2,7 +2,6 @@ Main entry-point for the FoundationaLLM LangChainAPI. Runs web server exposing the API. """ -import uvicorn from fastapi import FastAPI from app.dependencies import get_config from app.routers import orchestration, status @@ -49,7 +48,3 @@ async def root(): Returns a JSON object containing a message and value. """ return { 'message': 'FoundationaLLM LangChainAPI' } - -if __name__ == '__main__': - uvicorn.run('app.main:app', host='0.0.0.0', port=8765, reload=True, - forwarded_allow_ips='*', proxy_headers=True) diff --git a/src/python/LangChainAPI/app/routers/orchestration.py b/src/python/LangChainAPI/app/routers/orchestration.py index fc90c490bf..8d49cde54a 100644 --- a/src/python/LangChainAPI/app/routers/orchestration.py +++ b/src/python/LangChainAPI/app/routers/orchestration.py @@ -1,13 +1,12 @@ """ The API endpoint for returning the completion from the LLM for the specified user prompt. """ -import logging from typing import Optional -from fastapi import APIRouter, Depends, Header, HTTPException, Request +from fastapi import APIRouter, Depends, Header, Request from foundationallm.config import Context from foundationallm.models.orchestration import CompletionRequest, CompletionResponse from foundationallm.langchain.orchestration import OrchestrationManager -from app.dependencies import get_config, validate_api_key_header +from app.dependencies import handle_exception, validate_api_key_header # Initialize API routing router = APIRouter( @@ -32,6 +31,8 @@ async def get_completion( and generate a completion. request : Request The underlying HTTP request. + x_user_identity : str + The optional X-USER-IDENTITY header value. Returns ------- @@ -44,8 +45,4 @@ async def get_completion( context=Context(user_identity=x_user_identity)) return orchestration_manager.run(completion_request.user_prompt) except Exception as e: - logging.error(e, stack_info=True, exc_info=True) - raise HTTPException( - status_code = 500, - detail = str(e) - ) from e + handle_exception(e) diff --git a/src/python/LangChainAPI/run.py b/src/python/LangChainAPI/run.py new file mode 100644 index 0000000000..1db72d4e7c --- /dev/null +++ b/src/python/LangChainAPI/run.py @@ -0,0 +1,11 @@ +import uvicorn + +if __name__ == '__main__': + uvicorn.run( + 'app.main:app', + host='0.0.0.0', + port=8765, + reload=True, + forwarded_allow_ips='*', + proxy_headers=True + ) diff --git a/src/python/LangChainAPI/startup.sh b/src/python/LangChainAPI/startup.sh deleted file mode 100644 index 8dc12093c7..0000000000 --- a/src/python/LangChainAPI/startup.sh +++ /dev/null @@ -1 +0,0 @@ -gunicorn -w 4 -k uvicorn.workers.UvicornWorker app.main:app \ No newline at end of file diff --git a/src/python/PromptHubAPI/PromptHubAPI.pyproj b/src/python/PromptHubAPI/PromptHubAPI.pyproj index 4c05075405..d340e8ada7 100644 --- a/src/python/PromptHubAPI/PromptHubAPI.pyproj +++ b/src/python/PromptHubAPI/PromptHubAPI.pyproj @@ -4,7 +4,7 @@ 2.0 5d5fc907-72ad-4026-aa8d-db6ba578ae0d . - app/main.py + run.py ..\PythonSDK . Standard Python launcher @@ -33,12 +33,12 @@ + - diff --git a/src/python/PromptHubAPI/app/dependencies.py b/src/python/PromptHubAPI/app/dependencies.py index 61be4b0972..cdef71ef15 100644 --- a/src/python/PromptHubAPI/app/dependencies.py +++ b/src/python/PromptHubAPI/app/dependencies.py @@ -2,6 +2,7 @@ Provides dependencies for API calls. """ import logging +import time from typing import Annotated from fastapi import Depends, HTTPException from fastapi.security import APIKeyHeader @@ -18,17 +19,20 @@ def get_config() -> Configuration: Configuration Returns the application configuration settings. """ - return __config or Configuration() + global __config -def validate_api_key_header(config: Annotated[Configuration, Depends()], - x_api_key: str = Depends(APIKeyHeader(name='X-API-Key'))): + start = time.time() + __config = __config or Configuration() + end = time.time() + print(f'Time to load config: {end-start}') + return __config + +def validate_api_key_header(x_api_key: str = Depends(APIKeyHeader(name='X-API-Key'))): """ Validates that the X-API-Key value in the request header matches the key expected for this API. Parameters ---------- - app_config : Configuration - Used for retrieving application configuration settings. x_api_key : str The X-API-Key value in the request header. @@ -38,7 +42,7 @@ def validate_api_key_header(config: Annotated[Configuration, Depends()], Otherwise, returns False. """ - result = x_api_key == config.get_value('FoundationaLLM:APIs:PromptHubAPI:APIKey') + result = x_api_key == get_config().get_value('FoundationaLLM:APIs:PromptHubAPI:APIKey') if not result: logging.error('Invalid API key. You must provide a valid API key in the X-API-KEY header.') @@ -46,3 +50,18 @@ def validate_api_key_header(config: Annotated[Configuration, Depends()], status_code = 401, detail = 'Invalid API key. You must provide a valid API key in the X-API-KEY header.' ) + +def handle_exception(exception: Exception, status_code: int = 500): + """ + Handles an exception that occurred while processing a request. + + Parameters + ---------- + exception : Exception + The exception that occurred. + """ + logging.error(exception, stack_info=True, exc_info=True) + raise HTTPException( + status_code = status_code, + detail = str(exception) + ) from exception diff --git a/src/python/PromptHubAPI/app/main.py b/src/python/PromptHubAPI/app/main.py index 2767ec4b44..46799d0766 100644 --- a/src/python/PromptHubAPI/app/main.py +++ b/src/python/PromptHubAPI/app/main.py @@ -2,7 +2,6 @@ Main entry-point for the FoundationaLLM PromptHubAPI. Runs web server exposing the API. """ -import uvicorn from fastapi import FastAPI from app.dependencies import get_config from app.routers import resolve, status @@ -17,9 +16,8 @@ app = FastAPI( title='FoundationaLLM PromptHubAPI', summary='API for retrieving Prompt metadata', - description="""The FoundationaLLM PromptHubAPI is a wrapper around - PromptHub functionality contained in the - foundationallm.core Python SDK.""", + description="""The FoundationaLLM PromptHubAPI is a wrapper around PromptHub + functionality contained in the foundationallm.core Python SDK.""", version='1.0.0', contact={ 'name':'Solliance, Inc.', @@ -50,7 +48,3 @@ async def root(): Returns a JSON object containing a message and value. """ return { 'message': 'FoundationaLLM PromptHubAPI' } - -if __name__ == '__main__': - uvicorn.run('main:app', host='0.0.0.0', port=8642, - reload=True, forwarded_allow_ips='*', proxy_headers=True) diff --git a/src/python/PromptHubAPI/app/routers/resolve.py b/src/python/PromptHubAPI/app/routers/resolve.py index 0d3bb6b352..0275341c90 100644 --- a/src/python/PromptHubAPI/app/routers/resolve.py +++ b/src/python/PromptHubAPI/app/routers/resolve.py @@ -1,13 +1,12 @@ """ The API endpoint for returning the appropriate agent prompt for the specified user prompt. """ -import logging from typing import Optional -from fastapi import APIRouter, Depends, HTTPException, Header, Request +from fastapi import APIRouter, Depends, Header, Request from foundationallm.config import Context from foundationallm.models import AgentHint from foundationallm.hubs.prompt import PromptHubRequest, PromptHubResponse, PromptHub -from app.dependencies import validate_api_key_header +from app.dependencies import handle_exception, validate_api_key_header router = APIRouter( prefix='/resolve', @@ -49,8 +48,4 @@ async def resolve( return PromptHub(config=request.app.extra['config']).resolve(request=prompt_request, user_context=context, hint=agent_hint) return PromptHub(config=request.app.extra['config']).resolve(prompt_request, user_context=context) except Exception as e: - logging.error(e, stack_info=True, exc_info=True) - raise HTTPException( - status_code = 500, - detail = str(e) - ) from e + handle_exception(e) diff --git a/src/python/PromptHubAPI/run.py b/src/python/PromptHubAPI/run.py new file mode 100644 index 0000000000..b130dd70e1 --- /dev/null +++ b/src/python/PromptHubAPI/run.py @@ -0,0 +1,11 @@ +import uvicorn + +if __name__ == '__main__': + uvicorn.run( + 'app.main:app', + host='0.0.0.0', + port=8642, + reload=True, + forwarded_allow_ips='*', + proxy_headers=True + ) diff --git a/src/python/PromptHubAPI/startup.sh b/src/python/PromptHubAPI/startup.sh deleted file mode 100644 index f9c45a8039..0000000000 --- a/src/python/PromptHubAPI/startup.sh +++ /dev/null @@ -1 +0,0 @@ -gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app \ No newline at end of file diff --git a/src/python/PythonSDK/foundationallm/models/metadata/data_source.py b/src/python/PythonSDK/foundationallm/models/metadata/data_source.py index 1e42e12441..6ef9ce5116 100644 --- a/src/python/PythonSDK/foundationallm/models/metadata/data_source.py +++ b/src/python/PythonSDK/foundationallm/models/metadata/data_source.py @@ -11,7 +11,8 @@ class DataSource(MetadataBase): configuration: Union[ CSVConfiguration, SQLDatabaseConfiguration, + CXOConfiguration, BlobStorageConfiguration, - SearchServiceConfiguration, - CXOConfiguration] + SearchServiceConfiguration + ] data_description: Optional[str] = None