Skip to main content
Lesson 12 of 20 · API Tools: Search, Files, and Code Interpreter

Process data: CSV, Excel, images

Lesson 12 of 20 Updated November 2, 2026 Developer
On this page
  1. Process data: CSV, Excel, images
  2. Processing CSV files
  3. Processing Excel files
  4. Processing images
  5. Pattern: Complete ETL pipeline
  6. Supported formats
  7. Key takeaways

Updated November 2, 2026 based on OpenAI documentation: the Code Interpreter tool requires a container parameter (added to all examples), input text parts use the type input_text, and web search uses the web_search tool (web_search_preview is now a legacy tool without domain filters). Generated files are retrieved using the fichiers_generes and telecharger functions from Lesson 10. Files attached to a message are uploaded with the user_data usage, which OpenAI recommends for model inputs (File inputs). Sources: Code Interpreter · Web search.

Process data: CSV, Excel, images

Code Interpreter changes the nature of what you ask the model to do. Without it, you get a description of what needs to be done; with it, the model writes Python code, executes it in a sandbox, checks the result, and corrects its own code if it makes a mistake. For a data file, the difference is decisive: no one can guess the structure of a CSV without opening it, and that is exactly what code execution allows.

The reasoning in this lesson applies to the three formats that follow. You upload the file, describe the expected result in natural language, and retrieve either an analysis or a new file. What separates good usage from bad comes down to the precision of your instruction: “analyze this file” produces a generic summary, while a numbered request like the ones below produces a result you can use as is.

Processing CSV files

Exploratory analysis

Always start here, even when you think you know the file. A CSV exported from a business tool holds surprises the specification doesn’t mention: a numeric column stored as text because of a decimal separator, dates in three different formats, or a total row slipped into the middle of the data. The five points requested below—dimensions, types, missing values, statistics, and a preview—are the minimum before any transformation because they determine what you can ask for next.

from openai import OpenAI

client = OpenAI()

with open("clients_2025.csv", "rb") as f:
    fichier = client.files.create(file=f, purpose="user_data")

response = client.responses.create(
    model="gpt-5.6-terra",
    input=[{
        "role": "user",
        "content": [
            {"type": "input_text", "text": (
                "Analyze this CSV file: "
                "1. Number of rows and columns "
                "2. Data types for each column "
                "3. Missing values per column "
                "4. Descriptive statistics for numeric columns "
                "5. The first 5 rows"
            )},
            {"type": "input_file", "file_id": fichier.id}
        ]
    }],
    tools=[{"type": "code_interpreter", "container": {"type": "auto"}}]
)

print(response.output_text)

Cleaning and transformation

Cleaning is the step where decisions matter, and where you must make them explicitly rather than leaving them to the model. Filling missing values with the median for numbers and the mode for categories is a defensible choice, but it is a choice: on a revenue column where a third of the values are missing, it creates an artificially narrow distribution that will skew any subsequent analysis. State the rule in your prompt, as shown below, and you will know what was done; stay vague, and you will have to reopen the file to find out.

response = client.responses.create(
    model="gpt-5.6-terra",
    input=[{
        "role": "user",
        "content": [
            {"type": "input_text", "text": (
                "Clean this CSV: "
                "- Remove duplicates "
                "- Fill missing values (median for numbers, "
                "  mode for categories) "
                "- Normalize city names (title case) "
                "- Convert dates to ISO format "
                "- Export the result as a cleaned CSV"
            )},
            {"type": "input_file", "file_id": fichier.id}
        ]
    }],
    tools=[{"type": "code_interpreter", "container": {"type": "auto"}}]
)

# Retrieve the cleaned file
for ann in fichiers_generes(response):
    telecharger(client, ann, "clients_nettoye.csv")

Processing Excel files

Code Interpreter handles Excel files natively thanks to openpyxl. Two differences from CSV deserve your attention. First, a workbook contains multiple sheets, and a prompt that doesn’t specify one will make the model work on whichever one it picks first; so start by asking for a list of sheets, as in the example. Second, Excel contains formulas, merged cells, and decorative header rows—elements that look like data but aren’t, and that the model must know to ignore because you told it to.

with open("budget_2026.xlsx", "rb") as f:
    fichier_excel = client.files.create(file=f, purpose="user_data")

response = client.responses.create(
    model="gpt-5.6-terra",
    input=[{
        "role": "user",
        "content": [
            {"type": "input_text", "text": (
                "This Excel file contains multiple sheets. "
                "1. List all available sheets "
                "2. For each sheet, provide a summary of the content "
                "3. Create a pivot table: total expenses "
                "   by department and by quarter "
                "4. Export the result to a new Excel file"
            )},
            {"type": "input_file", "file_id": fichier_excel.id}
        ]
    }],
    tools=[{"type": "code_interpreter", "container": {"type": "auto"}}]
)

Merging multiple files

Merging is the case where code execution pulls furthest ahead of manual processing: four quarters mean four files whose columns have almost the same names and almost the same order. That “almost” is the problem, and it is precisely what a program detects while copy-pasting masks it. Ask for a summary sheet in addition to the merged data: it serves as a control, since a total that doesn’t match the sum of the four files immediately reveals a misaligned column.

# Upload multiple files
fichiers_ids = []
for nom in ["ventes_q1.xlsx", "ventes_q2.xlsx", "ventes_q3.xlsx", "ventes_q4.xlsx"]:
    with open(nom, "rb") as f:
        fichier = client.files.create(file=f, purpose="user_data")
        fichiers_ids.append(fichier.id)

content = [
    {"type": "input_text", "text": (
        "These 4 Excel files contain sales data by quarter. "
        "Merge them into a single file with: "
        "- A 'Data' sheet with all sales "
        "- A 'Summary' sheet with totals by quarter "
        "- A 'Trends' sheet with quarter-over-quarter variations"
    )}
]
for fid in fichiers_ids:
    content.append({"type": "input_file", "file_id": fid})

response = client.responses.create(
    model="gpt-5.6-terra",
    input=[{"role": "user", "content": content}],
    tools=[{"type": "code_interpreter", "container": {"type": "auto"}}]
)

Processing images

Code Interpreter manipulates images with Pillow, and you need to see clearly what that covers. This is image processing—resizing, converting, measuring, compositing—not visual understanding: to describe what a photo shows, the model’s vision capabilities are at work, not the sandbox. The two combine very well in a single call, with the model looking at the image while the code transforms it.

Analysis and transformation

with open("photo_produit.jpg", "rb") as f:
    fichier_image = client.files.create(file=f, purpose="user_data")

response = client.responses.create(
    model="gpt-5.6-terra",
    input=[{
        "role": "user",
        "content": [
            {"type": "input_text", "text": (
                "Analyze this image: "
                "1. Dimensions, format, file size "
                "2. Color histogram "
                "3. Create 3 versions: "
                "   - Thumbnail 200x200 "
                "   - Black and white version "
                "   - Version with contrast increased by 30%"
            )},
            {"type": "input_file", "file_id": fichier_image.id}
        ]
    }],
    tools=[{"type": "code_interpreter", "container": {"type": "auto"}}]
)

Batch processing

Batch processing shifts the question to cost and limits. Each uploaded image consumes storage and occupies the sandbox, whose space and lifespan are bounded: beyond a few dozen files, a local script with Pillow costs less and runs faster. Reserve batch processing for cases where the decision is hard to code—cropping that depends on content, a watermark to place where the image is most uniform—and keep mechanical transformations for your own machine.

# Upload multiple images
images_ids = []
for img_path in ["img1.png", "img2.png", "img3.png"]:
    with open(img_path, "rb") as f:
        fichier = client.files.create(file=f, purpose="user_data")
        images_ids.append(fichier.id)

content = [
    {"type": "input_text", "text": (
        "Resize all these images to 800x600 pixels, "
        "add a semi-transparent 'DRAFT' watermark, "
        "and compress as JPEG quality 85."
    )}
]
for fid in images_ids:
    content.append({"type": "input_file", "file_id": fid})

response = client.responses.create(
    model="gpt-5.6-terra",
    input=[{"role": "user", "content": content}],
    tools=[{"type": "code_interpreter", "container": {"type": "auto"}}]
)

Pattern: Complete ETL pipeline

def pipeline_etl(fichier_source: str, transformations: str) -> dict:
    """Extract-Transform-Load pipeline with Code Interpreter."""
    # Extract: upload source file
    with open(fichier_source, "rb") as f:
        fichier = client.files.create(file=f, purpose="user_data")

    # Transform: apply transformations
    response = client.responses.create(
        model="gpt-5.6-terra",
        input=[{
            "role": "user",
            "content": [
                {"type": "input_text", "text": transformations},
                {"type": "input_file", "file_id": fichier.id}
            ]
        }],
        tools=[{"type": "code_interpreter", "container": {"type": "auto"}}],
        instructions=(
            "Execute each transformation step by step. "
            "Display a summary after each step: "
            "number of rows before/after, modified columns. "
            "Export the final result as CSV and Excel."
        )
    )

    # Load: retrieve generated files
    fichiers_sortie = []
    for ann in fichiers_generes(response):
        telecharger(client, ann, ann.filename)
        fichiers_sortie.append(ann.filename)

    return {
        "rapport": response.output_text,
        "fichiers_generes": fichiers_sortie
    }

# Usage
resultat = pipeline_etl(
    "donnees_brutes.csv",
    "1. Remove empty columns "
    "2. Convert amounts from cents to euros "
    "3. Add a 'quarter' column based on the date "
    "4. Aggregate sales by quarter and category "
    "5. Calculate percentage variations"
)

Supported formats

FormatExtensionsReadWrite
CSV.csvYesYes
Excel.xlsx, .xlsYesYes
JSON.jsonYesYes
Images.png, .jpg, .gif, .bmpYesYes
Text.txt, .mdYesYes
PDF.pdfLimited readNo

Key takeaways

  • Upload files with purpose="user_data" and pass them via input_file
  • The model handles CSV, multi-sheet Excel, and images natively
  • Retrieve generated files from the container_file_citation annotations and download them via the containers API (Lesson 10)
  • For large files, request batch processing
  • Combine multiple files in a single call for merges and comparisons