diff --git a/app/routes/cost_and_duration_calculation.py b/app/routes/cost_and_duration_calculation.py index a1c6f56..de0541b 100644 --- a/app/routes/cost_and_duration_calculation.py +++ b/app/routes/cost_and_duration_calculation.py @@ -2,11 +2,23 @@ from util.s3util import S3Util from config.config import get_config from util.date_time_utils import DateTimeUtils +import pandas as pd +import os configs = get_config() S3_BUCKET = configs.s3_bucket -bedrock_price_df = S3Util().read_csv_from_s3(configs.bedrock_limit_csv_path, S3_BUCKET, as_dataframe=True) +try: + bedrock_price_df = S3Util().read_csv_from_s3(configs.bedrock_limit_csv_path, S3_BUCKET, as_dataframe=True) +except Exception: + # Local/dev fallback to avoid hard dependency on S3 during startup + local_csv_path = os.path.join(os.getcwd(), "bedrock_limits.csv") + if os.path.exists(local_csv_path): + bedrock_price_df = pd.read_csv(local_csv_path) + else: + bedrock_price_df = pd.DataFrame([ + {"model": "amazon.titan-embed-text-v2:0", "Region": "us-east-1", "input_price": 0.0, "output_price": 0.0} + ]) from app.price_calculator import estimate_opensearch_price, estimate_sagemaker_price, estimate_embedding_model_bedrock_price, estimate_retrieval_model_bedrock_price from app.configuration_validation import read_gt_data, count_characters_in_file diff --git a/app/routes/expert_eval.py b/app/routes/expert_eval.py index 8926bbc..7650a1b 100644 --- a/app/routes/expert_eval.py +++ b/app/routes/expert_eval.py @@ -25,6 +25,8 @@ from flotorch_core.embedding.titanv1_embedding import TitanV1Embedding from flotorch_core.embedding.cohere_embedding import CohereEmbedding from flotorch_core.embedding.bge_large_embedding import BGELargeEmbedding, BGEM3Embedding, GTEQwen2Embedding +import pandas as pd +import os # Flotorch-core config env_config_provider = EnvConfigProvider() @@ -36,7 +38,17 @@ logger = logging.getLogger(__name__) router = APIRouter() -bedrock_price_df = S3Util().read_csv_from_s3(configs.bedrock_limit_csv_path, S3_BUCKET, as_dataframe=True) +try: + bedrock_price_df = S3Util().read_csv_from_s3(configs.bedrock_limit_csv_path, S3_BUCKET, as_dataframe=True) +except Exception: + # Local/dev fallback to avoid hard dependency on S3 during startup + local_csv_path = os.path.join(os.getcwd(), "bedrock_limits.csv") + if os.path.exists(local_csv_path): + bedrock_price_df = pd.read_csv(local_csv_path) + else: + bedrock_price_df = pd.DataFrame([ + {"model": "amazon.titan-embed-text-v2:0", "Region": "us-east-1", "input_price": 0.0, "output_price": 0.0} + ]) class ExperimentQuery(BaseModel): experiment_ids: List[str] diff --git a/app/routes/uploads.py b/app/routes/uploads.py index 247cfb7..a6d8544 100644 --- a/app/routes/uploads.py +++ b/app/routes/uploads.py @@ -12,7 +12,7 @@ logger = logging.getLogger(__name__) router = APIRouter() -class PresignedurlRequestKB(BaseModel): +class PresignedurlRequestKB(BaseModel): unique_id: str files: List[str] diff --git a/bedrock_limits.csv b/bedrock_limits.csv new file mode 100644 index 0000000..8f6c760 --- /dev/null +++ b/bedrock_limits.csv @@ -0,0 +1,2 @@ +model,Region,input_price,output_price +amazon.titan-embed-text-v2:0,us-east-1,0.0001,0.0002 \ No newline at end of file diff --git a/cors.json b/cors.json new file mode 100644 index 0000000..56c5768 --- /dev/null +++ b/cors.json @@ -0,0 +1 @@ +{"CORSRules":[{"AllowedOrigins":["http://localhost:3000"],"AllowedMethods":["PUT","GET","HEAD"],"AllowedHeaders":["*"],"ExposeHeaders":["ETag"],"MaxAgeSeconds":3000}]} diff --git a/gt.json b/gt.json new file mode 100644 index 0000000..795e5e5 --- /dev/null +++ b/gt.json @@ -0,0 +1,4 @@ +[ + { "question": "What is FloTorch?", "answer": "A tool to run LLM RAG experiments." }, + { "question": "Which regions are supported?", "answer": "us-east-1 and us-west-2." } +] \ No newline at end of file diff --git a/poll.json b/poll.json new file mode 100644 index 0000000..b1ed703 --- /dev/null +++ b/poll.json @@ -0,0 +1 @@ +{"validation_status":null} \ No newline at end of file diff --git a/ui/app/components/File/Upload.vue b/ui/app/components/File/Upload.vue index f329936..5b12c04 100644 --- a/ui/app/components/File/Upload.vue +++ b/ui/app/components/File/Upload.vue @@ -67,7 +67,8 @@ onChange(async (files) => { try { await $fetch(props.data.presignedurl, { method: "PUT", - body: file + body: file, + headers: { "Content-Type": file.type || "application/json" } }) isUploading.value = false filepath.value = props.data.path diff --git a/util/pdf_utils.py b/util/pdf_utils.py index 38440a2..4856433 100644 --- a/util/pdf_utils.py +++ b/util/pdf_utils.py @@ -2,7 +2,7 @@ from PyPDF2 import PdfReader import logging from io import StringIO -import fitz +# Avoid importing PyMuPDF (fitz) at module import time to prevent DLL errors on Windows. logger = logging.getLogger() logger.setLevel(logging.INFO) @@ -22,22 +22,28 @@ def extract_text_from_pdf(file_path: str) -> str: raise def extract_text_from_pdf_pymudf(file_path: str) -> str: - """Extract text from a PDF file.""" + """Extract text from a PDF file using PyMuPDF if available; falls back to PyPDF2.""" try: - logger.info(f"Extracting text from PDF: {file_path}") + logger.info(f"Extracting text from PDF (PyMuPDF preferred): {file_path}") + try: + import fitz # local import to avoid DLL load at module import time + except Exception as imp_err: + logger.warning(f"PyMuPDF unavailable ({imp_err}); falling back to PyPDF2") + return extract_text_from_pdf(file_path) + doc = fitz.open(file_path) text_buffer = StringIO() for page in doc: page_text = page.get_text() or "" text_buffer.write(page_text) - logger.info("Text extraction from PDF successful.") + logger.info("Text extraction from PDF successful (PyMuPDF).") text = text_buffer.getvalue() text_buffer.close() return text except Exception as e: - logger.error(f"Failed to extract text from PDF: {e}") - raise + logger.error(f"Failed to extract text from PDF via PyMuPDF: {e}; using PyPDF2 fallback") + return extract_text_from_pdf(file_path) def process_pdf_from_folder(file_path: str) -> str: "Extract text from all files in a folder"