You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch Serve自定义Handler无推理输出及日志不打印问题求助

PyTorch Serve自定义Handler无输出且日志不打印的排查与修复

核心问题总结

你的Handler代码存在方法参数不匹配、语法错误、类型转换错误三大类问题,同时日志未打印可能是初始化失败或未查看Worker进程日志导致的。以下是具体问题和修复方案:


1. 初始化阶段日志未打印:存在变量名笔误

get_enhancement_model方法里的loadnet是未定义的变量,实际应为ldnet,这会直接导致初始化失败,Worker进程启动异常,但主日志不会显示Worker的错误,需要查看Worker日志文件(路径通常是logs/W-9000-facex_1.0.log)。

修复代码:

def get_enhancement_model(self, device):
    gan = GAN(device)
    ldnet = torch.load(MODEL_PATH_RET)
    name = 'params_ema' if 'params_ema' in ldnet else 'params'
    gan.load_state_dict(ldnet[name], strict=True)  # 修正为ldnet
    gan.eval()
    gan = gan.to(device)
    return gan

2. 推理方法参数不符合TorchServe规范

TorchServe的BaseHandler默认执行流程是:handle() → preprocess() → inference() → postprocess(),但你的方法参数完全不符合规范:

  • preprocess接收的是请求数据列表(比如[request1, request2]),不是单个image
  • inference接收的是preprocess返回的张量,不是PIL Image

修复preprocess(先补全缺失的io导入):

import io  # 新增导入

def preprocess(self, data):
    logger.info("\n\n\n Inside preprocess Function")
    logger.info("Type of received data = %s", type(data))
    # 取第一个请求的内容,兼容data/body两种格式
    request_data = data[0].get("data") or data[0].get("body")
    if isinstance(request_data, bytes):
        image = Image.open(io.BytesIO(request_data))
    else:
        image = Image.open(io.BytesIO(request_data))
    
    # 转换为模型需要的张量格式(适配你的GAN输入要求)
    image_np = np.array(image)
    image_tensor = torch.from_numpy(image_np.transpose(2, 0, 1)).float().unsqueeze(0).to(self.device)
    logger.info("Preprocessing complete.")
    return image_tensor

修复inference:

def inference(self, input_tensor):
    logger.info("\n\n\n Inside Inference Function")
    logger.info("Type of received tensor = %s", type(input_tensor))
    output_tensor = self.pi(input_tensor)
    output_image = self.postprocess(output_tensor)
    logger.info("Type of Output = %s", type(output_image))
    return output_image

3. 推理逻辑中的语法错误

poi方法存在两处明显语法问题:

  • alc()调用未传参数(原函数需传入人脸关键点等必要参数)
  • self.fc_enh(torch.from_numpy(cropped_face)缺少闭合括号

修复示例:

def poi(self, input_tensor: torch.Tensor):
    img_np = input_tensor.squeeze(0).detach().cpu().numpy().transpose(1, 2, 0)
    face_landmarks, _ = self.fc_h.get_face_landmarks(img_np)
    restored_img = img_np.copy()  # 初始化原始图像,避免为空
    for face_landmark in face_landmarks:
        # 传入必要参数给alc(根据你的fb.py逻辑补全)
        cropped_face, inverse_affine = alc(face_landmark, img_np)
        # 补全括号并转换为模型适配的张量格式
        cropped_tensor = torch.from_numpy(cropped_face).float().unsqueeze(0).to(self.device)
        restored_face = self.fc_enh(cropped_tensor)
        restored_face = restored_face.squeeze(0).detach().cpu().numpy().transpose(1, 2, 0)
        restored_img = pfb(img_np, restored_face, inverse_affine=inverse_affine)

    return torch.from_numpy(restored_img.transpose(2, 0, 1)).unsqueeze(0).to(self.device), [], []

4. Postprocess返回格式不符合要求

你的postprocess返回PIL Image,但TorchServe无法直接序列化PIL Image返回给客户端,需要转换为字节流。

修复postprocess:

def postprocess(self, output: torch.Tensor) -> bytes:
    output_np = output.squeeze(0).detach().cpu().numpy().transpose(1, 2, 0)
    output_np = np.clip(output_np, 0, 255).astype(np.uint8)
    output_image = Image.fromarray(output_np)
    # 转换为字节流返回
    img_byte_arr = io.BytesIO()
    output_image.save(img_byte_arr, format='JPEG')
    img_byte_arr.seek(0)
    # 同时保存到本地(可选)
    output_image.save("processed_output.jpg")
    return img_byte_arr.getvalue()

5. 日志查看建议

主日志ts_log.log仅记录服务器启动信息,Worker进程的错误和自定义日志会写入Worker日志文件(路径:logs/W-<端口>-<模型名>_<版本>.log),比如你的场景对应logs/W-9000-facex_1.0.log,排查时必须查看该文件。


6. 重新打包与启动

修复代码后,重新生成.mar文件(注意添加fb.py到额外文件):

torch-model-archiver --model-name facex --version 1.0 --handler handler.py --serialized-file model.pth --extra-files landmarks.dat,GANModel.py,LD.py,Utils.py,fb.py

重启服务器:

torchserve --stop
torchserve --ncs --start --model-store model_store --ts-config config.properties --models facex.mar

内容的提问来源于stack exchange,提问作者Muhammad Danial Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 10:38:09