# How to Use GPT-Image2 for Reference-Photo Editing with Prompt Chaining

> Learn to edit reference photos with GPT-Image2 using prompt chaining. Preserve unchanged regions while applying edits effectively with this two-step workflow.

- Repository: [苍何/awesome-gpt-image-2](https://github.com/freestylefly/awesome-gpt-image-2)
- Tags: how-to-guide
- Published: 2026-09-05

---

**GPT-Image2 implements reference-photo editing through a two-step prompt-chaining workflow where the first prompt extracts a description of the unchanged reference region, and the second prompt applies user edits while preserving that region, using APIMart's asynchronous generation API.**

The freestylefly/awesome-gpt-image-2 repository demonstrates an elegant, **stateless architecture** for GPT-Image2 reference-photo editing with prompt chaining, combining a React front-end with serverless API endpoints to orchestrate multi-stage image generation without requiring a backend database. This approach leverages **Case 541**—documented in [`data/cases.json`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/data/cases.json) and [`docs/gallery-part-2.md`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/docs/gallery-part-2.md)—to preserve specific portions of a reference image while transforming others.

## Understanding the Prompt-Chaining Architecture

The workflow relies on **APIMart's** `/v1/images/generations` endpoint and maintains state purely in the browser. The core client logic resides in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js), which exports `submitPlatformGeneration` for initiating jobs and `fetchPlatformTask` (wrapped in `pollApimartTask`) for retrieving results.

**Key design characteristics:**

- **Stateless server**: The API endpoints do not persist generation data; the server only forwards requests to APIMart and returns **task IDs**
- **Client-side persistence**: Pending task IDs are stored in browser localStorage using the constants `APIMART_PENDING_STORAGE_KEY` and `GENERATED_TESTS_STORAGE_KEY` defined in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js)
- **Asynchronous polling**: After submitting a prompt, the front-end polls `/api/generation/status` until the task reaches a terminal state (`succeeded` or `failed`)

## Implementing the Two-Step Workflow

### Step 1: Extracting the Reference Description

The first prompt asks the model to analyze the reference image and generate a concise description of the region that must remain unchanged. The UI component in [`src/main.jsx`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/main.jsx) collects the reference image URL and sends a POST request to `/api/generate-image`, implemented in [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js).

```javascript
// src/main.jsx - Initiating reference extraction
async function startReferenceExtraction(refImageUrl, userPrompt) {
  const body = {
    caseId: 541,  // Reference-photo editing case identifier
    prompt: `Analyse the reference image ${refImageUrl} and return a short description of the unchanged portion.`,
    language: 'en'
  };
  
  const res = await fetch('/api/generate-image', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body)
  });
  
  const { taskId } = await res.json();
  return taskId;
}

```

The [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js) handler forwards this payload via `submitPlatformGeneration` in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js), which returns a **taskId** representing the asynchronous job.

### Step 2: Chaining the Edit Instruction

Once the first task completes, the client extracts the generated description and appends the user’s edit instruction. This **prompt chaining** occurs entirely client-side before submitting the second generation request.

```javascript
// Chaining the reference description with the edit instruction
async function applyEdit(referenceDesc, userEdit) {
  const editPrompt = `${referenceDesc}. Now ${userEdit}.`;
  
  const body = {
    caseId: 541,
    prompt: editPrompt,
    language: 'en'
  };
  
  const res = await fetch('/api/generate-image', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body)
  });
  
  const { taskId } = await res.json();
  return taskId;
}

```

This concatenated prompt ensures the model preserves the reference region while applying the transformation to the target area.

### Step 3: Polling for Generation Status

Both generation steps require polling `/api/generation/status` (implemented in [`api/generation/status.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generation/status.js)) via the `fetchPlatformTask` function. The endpoint queries APIMart for the current task state every few seconds until completion.

```javascript
// Polling implementation for asynchronous tasks
async function pollTask(taskId) {
  while (true) {
    const r = await fetch(`/api/generation/status?taskId=${taskId}&language=en`);
    const data = await r.json();
    
    if (data.status === 'succeeded') return data;
    if (data.status === 'failed') throw new Error('Generation failed');
    
    await new Promise(res => setTimeout(res, 2000));  // 2-second interval
  }
}

```

## Complete End-to-End Implementation

The following function orchestrates the full workflow, from reference extraction through final image display, utilizing the stateless task management system:

```javascript
// Complete reference-photo editing workflow
async function editReferencePhoto(refImageUrl, userEdit) {
  // Step 1: Extract description of the unchanged portion
  const firstTaskId = await startReferenceExtraction(refImageUrl, userEdit);
  const firstResult = await pollTask(firstTaskId);
  const referenceDesc = firstResult.output?.description ?? '';

  // Step 2: Generate edited image using chained prompt
  const secondTaskId = await applyEdit(referenceDesc, userEdit);
  const finalResult = await pollTask(secondTaskId);

  // Step 3: Display the final result
  document.getElementById('result').src = finalResult.output?.imageUrl;
}

```

When `finalResult.output.imageUrl` is returned, the React component replaces the placeholder with the edited image, maintaining the integrity of the original reference portion as specified in **Case 541**.

## Key Source Files and Functions

Understanding these files is essential for customizing or debugging the GPT-Image2 reference-photo editing workflow:

- **[`src/main.jsx`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/main.jsx)** — React entry point that gathers user input, displays results, and coordinates the prompt-chaining sequence
- **[`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js)** — Core client library exporting `submitPlatformGeneration` for image requests and `pollApimartTask` for status monitoring; manages localStorage persistence
- **[`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js)** — Server-side handler that forwards prompts to APIMart's `/v1/images/generations` endpoint and returns the initial taskId
- **[`api/generation/status.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generation/status.js)** — Server-side endpoint that invokes `fetchPlatformTask` to retrieve current generation status from APIMart
- **[`data/cases.json`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/data/cases.json)** — Structured metadata for all use cases, including **Case 541** configuration parameters for reference-photo editing
- **[`docs/gallery-part-2.md`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/docs/gallery-part-2.md)** — Documentation describing the reference-photo editing capabilities and gallery examples

## Summary

- **GPT-Image2** achieves reference-photo editing through a **two-step prompt-chaining** methodology that first analyzes and describes the preservation region, then applies edits while maintaining that description in context.
- The architecture is **stateless on the server side**, with task persistence handled via browser localStorage using keys defined in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js).
- **Case 541** provides the specific implementation pattern for preserving portions of reference images while transforming others.
- The workflow relies on **asynchronous polling** via `/api/generation/status` to retrieve final images from APIMart's generation service.
- All orchestration occurs in [`src/main.jsx`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/main.jsx) and supporting API routes, requiring no dedicated database infrastructure.

## Frequently Asked Questions

### What is Case 541 in the GPT-Image2 repository?

**Case 541** is the specific reference-photo editing implementation documented in [`data/cases.json`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/data/cases.json) and [`docs/gallery-part-2.md`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/docs/gallery-part-2.md). It defines the parameters for workflows where users upload a reference image and specify which portions to preserve while editing others, serving as the canonical example for prompt-chaining-based preservation.

### How does the stateless architecture track pending generations?

Since the server does not maintain a database, pending **task IDs** are stored in browser localStorage using the constants `APIMART_PENDING_STORAGE_KEY` and `GENERATED_TESTS_STORAGE_KEY` defined in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js). This allows the React front-end to resume polling for results even if the user refreshes the page.

### Why is prompt chaining necessary instead of a single prompt?

**Prompt chaining** is required because the model needs to first analyze and encode the visual characteristics of the reference region before receiving the edit instruction. Attempting both operations in a single generation would reduce accuracy; separating them ensures the preservation description is explicitly available in the context window when the transformation is applied.

### Which APIMart endpoint handles the actual image generation?

The `submitPlatformGeneration` function in [`src/apimartClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/apimartClient.js) forwards all requests to the APIMart **`/v1/images/generations`** endpoint. This endpoint accepts the JSON payload containing the chained prompt and returns a `taskId` for asynchronous processing.