> ## Documentation Index
> Fetch the complete documentation index at: https://www.krea.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 训练自定义风格

> 使用你自己的数据集训练自定义图像风格，并生成一致的输出，同时了解在数据筛选、打标签和迭代方面的最佳实践。

export const HeroHeader = ({image, video, title, description}) => {
  return <div className="relative aspect-[2/1] h-[30vh] w-full rounded-lg overflow-hidden mb-8">
      {}
      {video && <video autoPlay muted loop playsInline className="absolute top-0 left-0 w-full h-full object-cover hidden md:block m-0" style={{
    zIndex: 1,
    objectPosition: "20% 20%"
  }}>
          <source src={video} type="video/webm" />
        </video>}

      {}
      <img src={image} alt="" className={`absolute top-0 left-0 m-0 w-full h-full object-cover ${video ? "md:hidden" : "block"}`} style={{
    zIndex: 1,
    objectPosition: "20% 20%"
  }} />

      {}
      <div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/30 to-black/10 flex flex-col justify-end p-8 dark:hidden" style={{
    zIndex: 2
  }}>
        <h1 className="text-4xl font-bold text-white m-0 drop-shadow-[0_2px_4px_rgba(0,0,0,0.5)]">
          {title}
        </h1>
        <p className="text-lg text-white/95 mt-2 drop-shadow-[0_1px_2px_rgba(0,0,0,0.5)]">
          {description}
        </p>
      </div>

      {}
      <div className="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-black/20 hidden dark:flex flex-col justify-end p-8" style={{
    zIndex: 2
  }}>
        <h1 className="text-4xl font-bold text-white m-0 drop-shadow-[0_2px_4px_rgba(0,0,0,0.5)]">
          {title}
        </h1>
        <p className="text-lg text-white/95 mt-2 drop-shadow-[0_1px_2px_rgba(0,0,0,0.5)]">
          {description}
        </p>
      </div>
    </div>;
};

<HeroHeader image="https://s.krea.ai/docs-lora.webp" title="Train a Custom Style (LoRA)" description="Train a custom style using your own images to generate AI art with consistent visual aesthetics." />

## 概述

LoRA（Low-Rank Adaptation，低秩适配）是一种微调技术，用一小组示例图像教会 AI 模型一种新的视觉风格。它通过向已有模型注入新的"风格权重"来实现，训练既快又高效。

本指南将带你完成完整的工作流：

<Steps>
  <Step title="准备训练图像" icon="images">
    挑选并上传能代表你所需风格的高质量图像
  </Step>

  <Step title="提交训练任务" icon="play">
    使用你的图像 URL 和配置向 `/styles/train` 发送 POST 请求
  </Step>

  <Step title="监控进度" icon="clock">
    使用返回的 `job_id` 跟踪训练任务状态
  </Step>

  <Step title="使用你的风格生成图像" icon="sparkles">
    将训练好的风格应用于图像生成
  </Step>
</Steps>

***

## 准备训练图像

### 筛选你的数据集

训练图像的质量直接影响结果。不同的训练类型有不同的要求：

| 类型            | 适用场景       | 建议           |
| ------------- | ---------- | ------------ |
| **Style**     | 艺术风格、视觉美学  | 在不同主题间保持风格一致 |
| **Character** | 人物形象、一致的角色 | 姿势、表情、光照多样   |
| **Object**    | 特定物品、产品    | 多角度，物体一致     |

### 需要多少张图像？

质量远比数量重要。少量优秀的图像会胜过大量平庸的图像。

| 数据集大小         | 指导建议            |
| ------------- | --------------- |
| **5 张图像**     | 最低可用。适合简单、一致的风格 |
| **10-30 张图像** | 推荐。质量和覆盖度的最佳平衡  |
| **50+ 张图像**   | 收益递减，除非风格差异很大   |

<Warning>
  **质量 > 数量**

  15 张高质量图像会比 50 张低质量图像产出更好的结果。优先考虑：

  * 高分辨率（最少 1024x1024）
  * 所有图像的风格保持一致
  * 没有水印、文字覆盖或压缩伪影
  * 主题多样但风格保持一致
</Warning>

<Info>
  **示例数据集**

  * **人物训练**：一位人物在不同姿势、表情和光照条件下的照片。避免图像中出现其他人。
  * **风格训练**：一组风格一致的艺术作品集。例如，[The Metropolitan Museum of Art Ukiyo-E Dataset](https://www.kaggle.com/datasets/kengoichiki/the-metropolitan-museum-of-art-ukiyoe-dataset) 提供了适合训练艺术风格的日本浮世绘。
</Info>

### 上传图像

训练之前，先上传图像获取托管 URL。使用 `/assets` 端点：

<CodeGroup>
  ```python Python theme={null}
  import requests
  import os
  from dotenv import load_dotenv
  import mimetypes

  load_dotenv()

  API_BASE = "https://api.krea.ai"
  API_TOKEN = os.getenv("API_TOKEN")

  image_dir = "training_images"
  uploaded_urls = []

  for filename in os.listdir(image_dir):
      if filename.lower().endswith(('.jpg', '.jpeg', '.png', '.webp')):
          filepath = os.path.join(image_dir, filename)
          mime_type, _ = mimetypes.guess_type(filepath)

          with open(filepath, 'rb') as f:
              response = requests.post(
                  f"{API_BASE}/assets",
                  headers={"Authorization": f"Bearer {API_TOKEN}"},
                  files={"file": (filename, f, mime_type)},
                  data={"description": f"Training image: {filename}"}
              )

          if response.ok:
              data = response.json()
              uploaded_urls.append(data["image_url"])
              print(f"Uploaded: {filename}")
          else:
              print(f"Failed: {filename}")

  print(f"\nUploaded {len(uploaded_urls)} images")
  ```

  ```bash cURL theme={null}
  # Upload a single image
  curl -X POST https://api.krea.ai/assets \
    -H "Authorization: Bearer YOUR_API_TOKEN" \
    -F "file=@/path/to/image.jpg" \
    -F "description=Training image"

  # Response: {"id": "...", "image_url": "https://..."}
  ```
</CodeGroup>

<Tip>
  保存返回的 `image_url` 值——你将把这些值传递给训练端点。
</Tip>

***

## 训练你的风格

### 基础训练示例

提交你的图像 URL 开始训练：

<CodeGroup>
  ```python Python theme={null}
  import requests
  import os
  from dotenv import load_dotenv

  load_dotenv()

  API_BASE = "https://api.krea.ai"
  API_TOKEN = os.getenv("API_TOKEN")

  # Training URLs from the upload step
  urls = [
      "https://krea.ai/assets/img1.jpg",
      "https://krea.ai/assets/img2.jpg",
      "https://krea.ai/assets/img3.jpg",
      # ... more images
  ]

  response = requests.post(
      f"{API_BASE}/styles/train",
      headers={
          "Authorization": f"Bearer {API_TOKEN}",
          "Content-Type": "application/json"
      },
      json={
          "name": "Ukiyo-E Style",
          "urls": urls,
          "model": "flux_dev",
          "type": "Style",
          "max_train_steps": 500
      }
  )

  response.raise_for_status()
  job = response.json()
  print(f"Training started! Job ID: {job['job_id']}")
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.krea.ai/styles/train \
    -H "Authorization: Bearer YOUR_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Ukiyo-E Style",
      "urls": [
        "https://krea.ai/assets/img1.jpg",
        "https://krea.ai/assets/img2.jpg",
        "https://krea.ai/assets/img3.jpg"
      ],
      "model": "flux_dev",
      "type": "Style",
      "max_train_steps": 500
    }'
  ```
</CodeGroup>

### 训练类型

`type` 参数会为你的使用场景设置针对性的智能默认值：

| 类型          | 最适合        |
| ----------- | ---------- |
| `Style`     | 艺术风格、视觉美学  |
| `Character` | 人物形象、一致的角色 |
| `Object`    | 特定物品、产品    |
| `Default`   | 通用训练       |

### 参数

#### 必需参数

<ParamField path="name" type="string" required>
  你的自定义风格的描述性名称。

  **示例：** `"Ukiyo-E Style"`、`"Product Photos"`
</ParamField>

<ParamField path="urls" type="array" required>
  用于训练的图像 URL 数组。加入更多图像可获得更好的结果。
</ParamField>

#### 可选参数

<ParamField path="model" type="string" default="flux_dev">
  用于训练的基础模型：

  **图像模型：**

  * `flux_dev` - 高质量、通用
  * `flux_schnell` - BFL 的实时模型
  * `qwen` - 阿里巴巴的模型
  * `z-image` - 阿里巴巴的高效图像模型
  * `wan22` - 仅图像生成

  **视频模型：**

  * `wan` - 阿里巴巴的视频模型
</ParamField>

<ParamField path="type" type="string" default="Default">
  训练类别：`Style`、`Object`、`Character` 或 `Default`
</ParamField>

<ParamField path="trigger_word" type="string">
  用于在提示词中激活此风格的自定义单词。未指定时使用风格名称。

  <Tip>选择不会出现在常见提示词中的独特触发词。多词触发词使用下划线：`ukiyo_style`</Tip>
</ParamField>

<Accordion title="高级参数" icon="sliders">
  <ParamField path="learning_rate" type="number">
    控制训练强度。更高的值训练更快，但可能过拟合。

    **推荐范围：** 0.0001 - 0.001
  </ParamField>

  <ParamField path="max_train_steps" type="integer">
    最大训练迭代次数。范围：1-2000
  </ParamField>

  <ParamField path="batch_size" type="integer">
    同时处理的图像数量。较大的批次训练更快，但占用更多内存。
  </ParamField>
</Accordion>

### 调整高级参数

先使用 `type` 字段所设置的默认值——它们适用于大多数情况。只有在遇到特定问题时才需要调整：

<AccordionGroup>
  <Accordion title="Learning Rate" icon="gauge">
    控制模型对训练图像的适应程度。

    | 值                    | 何时使用            |
    | -------------------- | --------------- |
    | **0.0001**（较低）       | 过拟合问题、复杂风格、小数据集 |
    | **0.0003**（默认）       | 大多数场景           |
    | **0.0005-0.001**（较高） | 更快的训练           |

    **需要调整的信号：**

    * 输出看起来与训练图像一模一样 → 降低学习率
    * 训练后风格影响很弱 → 稍微提高学习率
  </Accordion>

  <Accordion title="训练步数" icon="shoe-prints">
    模型在你的图像上训练多久。

    | 数据集大小     | 推荐步数       |
    | --------- | ---------- |
    | 5-10 张图像  | 300-500 步  |
    | 15-30 张图像 | 500-800 步  |
    | 50+ 张图像   | 800-1500 步 |

    **需要调整的信号：**

    * 输出过于僵硬，忽略提示词 → 减少步数
    * 风格影响很弱 → 增加步数
    * 生成的图像看起来完全和训练数据一样 → 减少步数（过拟合）
  </Accordion>
</AccordionGroup>

<Tip>
  **迭代式调优**

  如果你的第一次训练没有产生想要的结果：

  1. 先调整 `max_train_steps`（最常见的修正）
  2. 如果单独调整步数无效，再尝试 `learning_rate`
</Tip>

### 响应格式

```json theme={null}
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "queued",
  "created_at": "2024-01-15T10:30:00Z"
}
```

***

## 监控训练进度

训练通常需要 5-15 分钟。轮询 Jobs API 检查状态：

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time
  import os
  from dotenv import load_dotenv

  load_dotenv()

  API_BASE = "https://api.krea.ai"
  API_TOKEN = os.getenv("API_TOKEN")
  job_id = "your-job-id"

  while True:
      response = requests.get(
          f"{API_BASE}/jobs/{job_id}",
          headers={"Authorization": f"Bearer {API_TOKEN}"}
      )
      job = response.json()
      status = job["status"]

      print(f"Status: {status}")

      if status == "completed":
          style_id = job["result"]["style_id"]
          print(f"Training complete! Style ID: {style_id}")
          break
      elif status in ["failed", "cancelled"]:
          print(f"Training {status}")
          break

      time.sleep(30)
  ```

  ```bash cURL theme={null}
  # Check job status (repeat until completed)
  curl -X GET https://api.krea.ai/jobs/YOUR_JOB_ID \
    -H "Authorization: Bearer YOUR_API_TOKEN"
  ```
</CodeGroup>

<Accordion title="任务状态值" icon="diagram-project">
  训练任务会经历以下状态：

  1. **queued** - 在队列中等待
  2. **processing** - 正在训练
  3. **completed** - 训练成功完成
  4. **failed** - 训练遇到错误
  5. **cancelled** - 任务被手动取消
</Accordion>

***

## 使用你训练好的风格

训练完成后，通过 `styles` 参数将你的风格应用于图像生成：

<Warning>
  **应用与 API 之间的风格所有权**

  API 和 Krea 网页应用在你的工作区中作为不同的用户身份运行。风格对创建者而言是私有的，因此：

  * **在应用中训练的风格** 通过 API 无法访问，除非共享
  * **通过 API 训练的风格** 在应用中无法访问，除非共享

  要将风格共享给你的工作区（双向都可以）：

  ```bash theme={null}
  curl -X POST https://api.krea.ai/styles/YOUR_STYLE_ID/share/workspace \
    -H "Authorization: Bearer YOUR_API_TOKEN"
  ```
</Warning>

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time
  import os
  from dotenv import load_dotenv

  load_dotenv()

  API_BASE = "https://api.krea.ai"
  API_TOKEN = os.getenv("API_TOKEN")
  STYLE_ID = "w29t6pvy0"

  response = requests.post(
      f"{API_BASE}/generate/image/krea/krea-2/medium",
      headers={
          "Authorization": f"Bearer {API_TOKEN}",
          "Content-Type": "application/json"
      },
      json={
          "prompt": "An abstract, colorful, surreal composition of symmetry and balance. Swirling colors, imagery of trees and coalescing patterns converge. The lantern of light and death. It is as if the world was at once dark, and yet again lit.",
          "aspect_ratio": "1:1",
          "resolution": "1K",
          "styles": [
              {
                  "id": STYLE_ID,
                  "strength": 0.95
              }
          ]
      }
  )

  job = response.json()
  job_id = job["job_id"]
  print(f"Generation started! Job ID: {job_id}")

  # Poll for completion
  while True:
      check = requests.get(
          f"{API_BASE}/jobs/{job_id}",
          headers={"Authorization": f"Bearer {API_TOKEN}"}
      )
      status_data = check.json()

      if status_data["status"] == "completed":
          image_url = status_data["result"]["urls"][0]
          print(f"Image ready: {image_url}")
          break
      elif status_data["status"] == "failed":
          print("Generation failed")
          break

      time.sleep(2)
  ```

  ```bash cURL theme={null}
  # Generate with style
  curl -X POST https://api.krea.ai/generate/image/krea/krea-2/medium \
    -H "Authorization: Bearer YOUR_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "prompt": "An abstract, colorful, surreal composition of symmetry and balance. Swirling colors, imagery of trees and coalescing patterns converge. The lantern of light and death. It is as if the world was at once dark, and yet again lit.",
      "aspect_ratio": "1:1",
      "resolution": "1K",
      "styles": [
        {
          "id": "w29t6pvy0",
          "strength": 0.95
        }
      ]
    }'

  # Then poll /jobs/{job_id} for the result
  ```
</CodeGroup>

### 风格强度

`strength` 参数（0.0-1.0）控制你的风格被应用的强度：

| 强度       | 效果                   |
| -------- | -------------------- |
| 0.5-0.7  | 微妙的影响，保留提示词灵活性       |
| 0.8-0.9  | 强烈的风格应用，推荐起点         |
| 0.95-1.0 | 最大程度贴合风格，可能降低提示词响应能力 |

<Tip>
  从 `0.8` 强度开始，然后根据结果调整。较低的值提供更多创作自由；较高的值则强制更严格的风格贴合。
</Tip>

### 组合多种风格

通过将多种风格添加到 `styles` 数组来应用多种风格：

```python theme={null}
"styles": [
    {"id": "style-id-1", "strength": 0.6},
    {"id": "style-id-2", "strength": 0.4}
]
```

***

## 最佳实践

<AccordionGroup>
  <Accordion title="图像选择" icon="images">
    * 尽可能使用足够多的高质量图像以获得最佳结果
    * 确保所有训练图像的风格保持一致
    * 主题保持多样性但风格保持一致
    * 避免水印、文字覆盖或伪影
    * 使用至少 1024x1024 分辨率的图像
  </Accordion>

  <Accordion title="训练配置" icon="sliders">
    * 使用 `type` 字段以默认参数开始
    * 对于风格：500-1000 步通常足够
    * 较低的学习率（0.0001-0.0003）可防止过拟合
    * 如果风格不够强，则增加步数
    * 如果输出过于僵硬，则减少步数
  </Accordion>

  <Accordion title="触发词" icon="wand-magic-sparkles">
    * 如果你打算组合多种风格，使用相同的触发词
    * 当你使用某个风格时，触发词会自动注入到提示词中
    * 避免常见词语，它们会出现在常规提示词里
    * 多词触发词使用下划线：`my_custom_style`
  </Accordion>
</AccordionGroup>
