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

Replicate训练完成后无法调用Ostris Flux LoRA训练版本生成AI头像的问题求助

Replicate训练完成后无法调用Ostris Flux LoRA训练版本生成AI头像的问题求助

我正在开发一个AI头像生成的SaaS产品,目前卡在了Replicate模型训练后的生成环节,实在有点搞不懂哪里出问题了。

我的预期流程是这样的:用户上传5-10张自拍照并点击开始 → 图片被发送到Replicate的Ostris Flux LoRA模型进行训练 → 训练完成后生成训练版本模型 → 用这个训练好的版本生成专业商务风格的头像 → 最后把生成的图片提取出来展示给用户下载。

现在的问题是,前面的步骤(上传图片、触发训练、训练完成生成版本)都没问题,但训练完成后,完全没法触发后续用训练版本生成图片的流程,根本没有生成任何图片。

我贴一下相关的后端代码片段,大家帮我看看哪里可能出问题了:

首先是检查训练状态并触发生成的接口:

app.post('/api/photoshoots/:id/check-training', isAuthenticated, async (req: any, res) => {
  try {
    const userId = req.user.claims.sub;
    const photoshootId = parseInt(req.params.id);
    const photoshoot = await storage.getPhotoshoot(photoshootId);

    if (!photoshoot || photoshoot.userId !== userId) {
      return res.status(404).json({ message: "Photoshoot not found" });
    }

    if (!photoshoot.replicateTrainingId) {
      return res.status(400).json({ message: "No training found for this photoshoot" });
    }

    // 检查训练状态
    const training = await replicate.trainings.get(photoshoot.replicateTrainingId);
    console.log(`Training ${photoshoot.replicateTrainingId} status: ${training.status}`);

    if (training.status === 'succeeded') {
      // 从输入照片中获取模型名称
      const inputPhotos = photoshoot.inputPhotos as any;
      const modelName = inputPhotos?.modelName;

      if (modelName) {
        const replicateUsername = process.env.REPLICATE_USERNAME;
        const destinationModel = `${replicateUsername}/${modelName}`;
        console.log(`Training completed, starting generation for ${destinationModel}`);

        // 启动生成流程
        processTrainingCompletion(photoshootId, photoshoot.replicateTrainingId, destinationModel);
        res.json({ status: 'training_complete', message: 'Training completed, starting generation process', trainingStatus: training.status });
      } else {
        res.status(500).json({ message: "Model name not found in photoshoot data" });
      }
    } else if (training.status === 'failed') {
      await storage.updatePhotoshoot(photoshootId, { status: 'failed' });
      res.json({ status: 'failed', message: 'Training failed', trainingStatus: training.status });
    } else {
      res.json({ status: 'training', message: 'Training still in progress', trainingStatus: training.status });
    }
  } catch (error) {
    console.error("Error checking training status:", error);
    res.status(500).json({ message: "Failed to check training status" });
  }
});

然后是上传图片并触发训练的接口:

app.post('/api/photoshoots/:id/upload', isAuthenticated, upload.array('photos', 30), async (req: any, res) => {
  console.log('=== Upload endpoint called ===');
  const userId = req.user?.claims?.sub;
  const photoshootId = parseInt(req.params.id);
  const files = req.files as Express.Multer.File[];

  console.log('Initial request data:', { userId, photoshootId, hasUser: !!req.user, hasFiles: !!files, filesCount: files ? files.length : 0, replicateToken: !!process.env.REPLICATE_API_TOKEN, stripeKey: !!process.env.STRIPE_SECRET_KEY });

  try {
    console.log('Upload request received:', { userId, photoshootId, filesCount: files ? files.length : 0, hasFiles: !!files, requestFiles: req.files, requestBody: Object.keys(req.body || {}), });

    if (!files || files.length < 10) {
      console.log(`Upload rejected: ${files ? files.length : 0} files, need at least 10`);
      return res.status(400).json({ message: `Please upload at least 10 photos. Received: ${files ? files.length : 0}` });
    }

    // 获取photoshoot并验证所有权
    const photoshoot = await storage.getPhotoshoot(photoshootId);
    if (!photoshoot || photoshoot.userId !== userId) {
      return res.status(404).json({ message: "Photoshoot not found" });
    }

    // 创建包含所有上传图片的zip文件
    console.log('Creating zip file from uploaded images...');
    const zip = new JSZip();

    // 将每个图片文件添加到zip
    files.forEach((file, index) => {
      const extension = file.originalname.split('.').pop() || 'jpg';
      const filename = `training_image_${index + 1}.${extension}`;
      console.log(`Adding file ${filename}, size: ${file.buffer.length} bytes`);
      zip.file(filename, file.buffer);
    });

    // 生成base64格式的zip文件
    console.log('Generating zip file...');
    // 原代码此处未完成,但上传到训练的流程是正常执行的
  } catch (error) {
    console.error("Upload error:", error);
    res.status(500).json({ message: "Upload failed" });
  }
});

我现在的疑问点主要有这些:

  • processTrainingCompletion函数里是不是有什么逻辑没处理对?比如调用训练版本生成图片的参数不符合Ostris Flux LoRA的要求?
  • 有没有可能训练完成后,我没有正确从Replicate的训练结果中获取到可用的模型版本ID,导致没法发起生成请求?
  • 是不是权限问题?比如我的Replicate API Token有没有权限调用训练后的私有模型版本?

有没有大佬遇到过类似的问题,或者能帮我分析下哪里可能出问题了?


内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 09:32:57