Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🍎 Fruit Ripeness Classifier — LLM Prompt Package

A structured, production-ready prompt package for classifying fresh produce images using a vision-capable large language model. Designed for warehouse intake pipelines where a single image arrives per item and a single routing label must be returned.


Overview

This repository contains a complete, ready-to-deploy prompt package for automated fruit ripeness classification. Given a single image, the classifier returns exactly one of four labels:

Label Meaning
Ripe Fruit is fresh and at optimal maturity for delivery
Unripe Fruit is biologically immature; not ready for delivery
Other Not classifiable as fresh fruit — damaged, processed, ambiguous, non-fruit, or poor image quality
Error Technical image failure — black frame, white frame, corrupted file

The system is intentionally minimal: one image in, one label out. No explanations, no confidence scores, no follow-up questions.


Use Case

This prompt package is designed for produce quality triage at intake stations. Images are captured one at a time from a camera on a sorting line. The classifier automates the initial label so that:

  • Ripe items can be routed directly to available inventory
  • Unripe items can be held or rerouted
  • Other items are flagged for human review
  • Error labels indicate a camera or transmission fault requiring technical attention

The goal is to reduce manual review burden while keeping humans in the loop for genuine edge cases.


Repository Structure

fruit-ripeness-classifier/
│
├── README.md                        ← You are here
│
├── prompt_package/
│   ├── system_prompt.txt            ← Core system prompt (role, rules, decision flowchart)
│   ├── class_definitions.yaml       ← Per-label definitions and visual indicators
│   ├── edge_case_policy.yaml        ← Handling rules for ambiguous scenarios
│   └── few_shot_examples.txt        ← Input/output examples for in-context learning
│
├── sample_data/
│   ├── ripe/                        ← Example images labeled Ripe
│   ├── unripe/                      ← Example images labeled Unripe
│   └── other/                       ← Example images labeled Other
│
└── docs/
    └── prompt_design_notes.md       ← Design rationale and known limitations

Prompt Package

The prompt is composed of four modular files that work together:

system_prompt.txt

The core instruction set. Defines the model's role as a classification engine, enumerates the four allowed output labels, establishes global rules (no explanations, no invented labels, conservative defaults), and provides a step-by-step decision flowchart. This is the file you pass as the system parameter in your API call.

class_definitions.yaml

Detailed definitions for each label class. Each entry includes:

  • A plain-language definition
  • Visual indicators the model should look for
  • Explicit exclusions to prevent misclassification

edge_case_policy.yaml

A policy table for scenarios that fall outside clean classification: motion blur, partial visibility, multiple fruits, mixed ripeness, exotic varieties, processed produce, artificial fruit, and more. Each case has a defined policy so the model has deterministic guidance rather than guessing.

few_shot_examples.txt

A small set of labeled input/output pairs. These are appended to the prompt (or passed as early conversation turns) to anchor the model's output format and reinforce label usage before it sees the real image.


How to Use

Basic API Call (Anthropic)

import anthropic
import base64

client = anthropic.Anthropic()

# Load prompt components
with open("prompt_package/system_prompt.txt") as f:
    system_prompt = f.read()

# Load your image
with open("sample_data/ripe/banana_ripe.jpg", "rb") as f:
    image_data = base64.standard_b64encode(f.read()).decode("utf-8")

response = client.messages.create(
    model="claude-opus-4-5",   # or any vision-capable model
    max_tokens=10,
    system=system_prompt,
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/jpeg",
                        "data": image_data,
                    },
                }
            ],
        }
    ],
)

label = response.content[0].text.strip()
print(label)  # → "Ripe", "Unripe", "Other", or "Error"

Basic API Call (OpenAI)

from openai import OpenAI
import base64

client = OpenAI()

with open("prompt_package/system_prompt.txt") as f:
    system_prompt = f.read()

with open("sample_data/ripe/banana_ripe.jpg", "rb") as f:
    image_data = base64.b64encode(f.read()).decode("utf-8")

response = client.chat.completions.create(
    model="gpt-4o",
    max_tokens=10,
    messages=[
        {"role": "system", "content": system_prompt},
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {"url": f"data:image/jpeg;base64,{image_data}"},
                }
            ],
        },
    ],
)

label = response.choices[0].message.content.strip()
print(label)

Including Few-Shot Examples

To use the few-shot examples, prepend them to the user message or inject them as early conversation turns before the image. The few_shot_examples.txt file is formatted as INPUT DESCRIPTION / OUTPUT pairs and can be adapted to either pattern.


Output Contract

The model is instructed to return exactly one word with no additional text:

Ripe
Unripe
Other
Error

Downstream systems can treat the response as a simple string match. No parsing, no JSON decoding required.


Design Principles

Minimal output surface. A single-word response eliminates parsing complexity and reduces the chance of the model embedding reasoning or hedging language in the output.

Conservative defaults. When evidence is ambiguous, the prompt defaults to Other (flag for human review) rather than guessing between Ripe and Unripe. At the boundary between the two, the model defaults to Unripe (Rule 5 — Conservative Boundary Rule).

Variety-aware classification. The prompt explicitly instructs the model not to rely on color alone. Green-ripe varieties (Granny Smith apple, lime, certain mango and banana cultivars) are handled through the Variety Awareness rule.

Botanical, not culinary. Ripeness is defined botanically. A green mango used in a chutney is still Unripe. A tomato is treated as a fruit.

Modular prompt architecture. The four-file structure separates concerns: the system prompt handles role and rules, the class definitions handle semantics, the edge case policy handles ambiguity, and the few-shot examples handle format anchoring. Each file can be updated independently.


Model Compatibility

This prompt package is designed to be model-agnostic. It has been written for use with any vision-capable LLM that accepts a system prompt and an image input. Tested prompt structures are compatible with:

  • Anthropic Claude (claude-3-5-sonnet, claude-opus-4, etc.)
  • OpenAI GPT-4o
  • Google Gemini 1.5 Pro / 2.0 Flash

Performance may vary across models, particularly on edge cases involving exotic fruit varieties or borderline ripeness. Evaluation across providers is recommended before production deployment.


Known Limitations

  • The classifier operates on visual information only. It cannot detect internal defects, taste, smell, or firmness that isn't visible in the image.
  • Exotic or rare fruit varieties with non-standard ripeness color signatures are intentionally handled conservatively — the model will return Other when ripeness evidence is unclear for an unfamiliar variety.
  • Camera angle and lighting at the intake station significantly affect accuracy. Consistent, well-lit, close-up photography of a single fruit produces the most reliable results.
  • The system is designed for one fruit per image. Multi-fruit images with unclear dominance return Other.

See docs/prompt_design_notes.md for extended discussion of design decisions and tradeoffs.


License

MIT License. See LICENSE for details.

About

A structured, production-ready prompt package for classifying fresh produce images using a vision-capable large language model. Designed for warehouse intake pipelines where a single image arrives per item and a single routing label must be returned.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors