diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..90e7e65 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,54 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..b14c225 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..3a65488 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/py.iml b/.idea/py.iml new file mode 100644 index 0000000..5a0e028 --- /dev/null +++ b/.idea/py.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 2169bb7..4e60cd4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,6 +20,6 @@ RUN pip install --no-cache-dir -r requirements.txt -i https://mirrors.aliyun.com COPY predict_with_excel.py . COPY degree3/ ./degree3/ -EXPOSE 8000 +EXPOSE 8001 -CMD ["uvicorn", "predict_with_excel:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file +CMD ["uvicorn", "predict_with_excel:app", "--host", "0.0.0.0", "--port", "8001"] \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 8b82a18..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# gc_worktime - diff --git a/direct_test.py b/direct_test.py new file mode 100644 index 0000000..549a586 --- /dev/null +++ b/direct_test.py @@ -0,0 +1,51 @@ +import pandas as pd +import numpy as np +from pathlib import Path +import joblib + +# 直接测试模型加载功能 +print("=== Direct Model Loading Test ===") + +# 设置模型文件夹路径 +model_folder = Path("./degree3") +print(f"Model folder path: {model_folder}") +print(f"Model folder exists: {model_folder.exists()}") + +# 加载EV17.5相关的模型 +try: + # 加载EV17.5_立焊模型 + ev175_vertical_model_path = model_folder / "EV17.5_立焊.xlsx_model_degree3.pkl" + print(f"EV17.5_立焊 model path: {ev175_vertical_model_path}") + print(f"EV17.5_立焊 model exists: {ev175_vertical_model_path.exists()}") + + if ev175_vertical_model_path.exists(): + ev175_vertical_model = joblib.load(ev175_vertical_model_path) + print(f"EV17.5_立焊 model loaded successfully!") + + # 测试模型预测 + test_thickness = np.array([[9.0]]) + prediction = ev175_vertical_model.predict(test_thickness) + print(f"EV17.5_立焊 prediction for thickness 9.0mm: {prediction}") + else: + print(f"EV17.5_立焊 model file not found!") + + # 加载EV17.5_横焊模型 + ev175_horizontal_model_path = model_folder / "EV17.5_横焊.xlsx_model_degree3.pkl" + print(f"\nEV17.5_横焊 model path: {ev175_horizontal_model_path}") + print(f"EV17.5_横焊 model exists: {ev175_horizontal_model_path.exists()}") + + if ev175_horizontal_model_path.exists(): + ev175_horizontal_model = joblib.load(ev175_horizontal_model_path) + print(f"EV17.5_横焊 model loaded successfully!") + + # 测试模型预测 + test_thickness = np.array([[9.0]]) + prediction = ev175_horizontal_model.predict(test_thickness) + print(f"EV17.5_横焊 prediction for thickness 9.0mm: {prediction}") + else: + print(f"EV17.5_横焊 model file not found!") + +except Exception as e: + print(f"Error during model loading or prediction: {e}") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 585a0a4..61ff106 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,8 +3,9 @@ services: welding-app: build: . + container_name: welding-app ports: - - "8000:8000" + - "8001:8001" # volumes: # - ./degree3:/app/degree3 # - ./data:/app/data diff --git a/predict_with_excel.py b/predict_with_excel.py index 7c73cc8..de3c3e7 100644 --- a/predict_with_excel.py +++ b/predict_with_excel.py @@ -123,7 +123,8 @@ def split_by_plus(s: str) -> list[str]: # %% import joblib -folder_path = Path("./degree3") +# 使用绝对路径来确保模型文件能够被正确找到 +folder_path = Path(__file__).parent / "degree3" def load_all_models(): @@ -131,14 +132,10 @@ def load_all_models(): 加载所有模型到 model_list """ global model_list - # 清空列表以确保重新加载(尽管有启动时加载一次的逻辑) - # model_list = [] - # ^^^ 注释掉这行,因为 FastAPI 的 on_event("startup") 应该只执行一次。 - # 如果在开发中需要热重载模型,可以取消注释或提供专门的重载端点。 - - if model_list: # 如果已经加载过,则不再重复加载 (主要由 startup_event 控制) - print(f"[MODEL_LOADER] Models already loaded. Count: {len(model_list)}") - return + # 清空列表以确保重新加载 + model_list = [] + + print(f"[MODEL_LOADER] Attempting to load models...") print( f"[MODEL_LOADER] Attempting to load models. Initial model_list length: {len(model_list)}" @@ -187,26 +184,15 @@ def load_all_models(): for file_path_obj in files_found: if file_path_obj.is_file(): try: - model_name_parts = file_path_obj.name.split(".xlsx") - if len(model_name_parts) > 1: - model_name = model_name_parts[0] - else: - model_name_base = file_path_obj.stem - if model_name_base.endswith("_model_degree3"): - model_name = model_name_base[: -len("_model_degree3")] - elif model_name_base.endswith( - "3" - ): # 兼容 *3.pkl 但不含 .xlsx 的情况 - model_name = model_name_base[: -len("3")].rstrip( - "." - ) # 移除可能的尾部'.' (来自.pkl) - if model_name.endswith("_model_degree"): # 进一步处理 - model_name = model_name[: -len("_model_degree")] - else: - model_name = model_name_base - print( - f"[MODEL_LOADER] WARNING: Filename {file_path_obj.name} does not contain '.xlsx' as expected for name splitting. Using '{model_name}' as model name based on stem." - ) + filename = file_path_obj.name + # 移除文件扩展名 .pkl + model_name = filename[:-4] + # 移除 _model_degree3 后缀 + if model_name.endswith("_model_degree3"): + model_name = model_name[:-14] + # 移除 .xlsx 后缀(如果存在) + if ".xlsx" in model_name: + model_name = model_name.split(".xlsx")[0] loaded_model = joblib.load(file_path_obj) temp_model_list.append( @@ -237,6 +223,12 @@ def load_all_models(): def get_welding_coefficient(row): coefficient = 0.0 global model_list + + # 添加调试日志,查看model_list的长度和内容 + print(f"[DEBUG] model_list length: {len(model_list)}") + loaded_model_names = [model["name"] for model in model_list] + print(f"[DEBUG] Loaded models: {loaded_model_names}") + model_map = {model["name"]: model for model in model_list} lenth = row.长度_m welding_type = row.坡口代码 @@ -275,26 +267,33 @@ def get_welding_coefficient(row): # 如果已经是系数形式,直接累加 coefficient += float(item.replace("min/m", "").strip()) else: - model_name = f"{item}_{welding_position}" - selected_model_info = model_map.get(model_name) - if selected_model_info is None: - raise KeyError(f"模型 '{model_name}' 未加载") - model = selected_model_info["model"] - range_str = MODEL_RANGES.get(model_name, "0-Infinity") - min_val_str, max_val_str = range_str.split("-") - min_val = float(min_val_str) - max_val = None if max_val_str == "Infinity" else float(max_val_str) - if thickness_value < min_val or ( - max_val is not None and thickness_value > max_val - ): - print( - f"⚠️ 警告: 厚度 {thickness_value}mm 超出模型 '{model_name}' 的适用范围 ({range_str} mm)。" - ) - coefficient = float('nan') - break - else: - prediction = float(model.predict(thickness_array)[0]) - coefficient += prediction + model_name = f"{item}_{welding_position}" + selected_model_info = model_map.get(model_name) + if selected_model_info is None: + print(f"⚠️ 处理坡口代码模型不存在: {model_name}, 错误: 模型未加载") + coefficient = float('nan') + break + model = selected_model_info["model"] + range_str = MODEL_RANGES.get(model_name, "0-Infinity") + min_val_str, max_val_str = range_str.split("-") + min_val = float(min_val_str) + max_val = None if max_val_str == "Infinity" else float(max_val_str) + if thickness_value < min_val or ( + max_val is not None and thickness_value > max_val + ): + print( + f"⚠️ 警告: 厚度 {thickness_value}mm 超出模型 '{model_name}' 的适用范围 ({range_str} mm)。" + ) + coefficient = float('nan') + break + else: + try: + prediction = float(model.predict(thickness_array)[0]) + coefficient += prediction + except Exception as e: + print(f"⚠️ 模型预测失败: {model_name}, 错误: {e}") + coefficient = float('nan') + break except Exception as e: coefficient = float('nan') print( @@ -391,6 +390,9 @@ def process_excel( 当 sheet_name 为 None 时,处理工作簿内所有工作表并返回 {sheet_name: DataFrame}。 """ + + # 在每次预测之前重新加载模型,确保模型能够被正确加载 + load_all_models() path_like, excel_bytes = _prepare_excel_source(excel_source) @@ -426,6 +428,21 @@ def startup_event(): load_all_models() +@app.get("/models", summary="获取已加载的模型列表") +def get_models(): + """ + 获取已加载的模型列表,用于调试和检查模型加载状态 + """ + global model_list + return { + "total_models": len(model_list), + "models": [{ + "name": model["name"], + "filename": model["filename"] + } for model in model_list] + } + + def _sanitize_sheet_name(name: Union[str, int], existing: set[str]) -> str: base = str(name) if str(name).strip() else "Sheet" base = base[:31] @@ -520,7 +537,36 @@ async def predict( def main(): + print("[TEST] Script started...") + + # 检查degree3文件夹是否存在 + print(f"[TEST] Current file path: {__file__}") + print(f"[TEST] Folder path: {folder_path}") + print(f"[TEST] Folder exists: {folder_path.exists()}") + print(f"[TEST] Folder is directory: {folder_path.is_dir()}") + + # 列出degree3文件夹中的文件 + if folder_path.exists() and folder_path.is_dir(): + files = list(folder_path.glob("*3.pkl")) + print(f"[TEST] Number of model files found: {len(files)}") + for file in files[:10]: # 显示前10个文件 + print(f"[TEST] Found model file: {file.name}") + + # 加载模型 load_all_models() + + # 添加调试信息,显示加载的模型名称 + print(f"[DEBUG] Total models loaded: {len(model_list)}") + for model in model_list: + print(f"[DEBUG] Loaded model: {model['name']} from {model['filename']}") + + # 检查是否包含CV17.5相关的模型 + cv175_models = [model['name'] for model in model_list if 'CV17.5' in model['name']] + print(f"[DEBUG] CV17.5 models found: {cv175_models}") + + # 检查是否包含平焊相关的模型 + pinghan_models = [model['name'] for model in model_list if '平焊' in model['name']] + print(f"[DEBUG] 平焊 models found: {pinghan_models}") # result_obj = process_excel(source_excel_path, sheet_name=0) # output_file_path = source_excel_path.parent.joinpath( # source_excel_path.stem + "_预测结果.xlsx" diff --git a/test_model_load.py b/test_model_load.py new file mode 100644 index 0000000..fbb5128 --- /dev/null +++ b/test_model_load.py @@ -0,0 +1,34 @@ +import os +import sys +from pathlib import Path + +# 添加当前目录到Python路径 +sys.path.append(str(Path(__file__).parent)) + +# 导入需要的模块 +from predict_with_excel import load_all_models, model_list + +# 测试模型加载 +print("[TEST] Starting model loading test...") +print(f"[TEST] Current working directory: {os.getcwd()}") + +# 加载模型 +load_all_models() + +# 显示加载的模型信息 +print(f"[TEST] Total models loaded: {len(model_list)}") +if model_list: + print("[TEST] Loaded models:") + for model in model_list: + print(f" - {model['name']}") +else: + print("[TEST] No models were loaded!") + +# 检查EV17.5相关的模型 +ev175_models = [model for model in model_list if 'EV17.5' in model['name']] +print(f"[TEST] EV17.5 models found: {len(ev175_models)}") +if ev175_models: + for model in ev175_models: + print(f" - {model['name']}") +else: + print("[TEST] No EV17.5 models found!") \ No newline at end of file