Michael Limberger
Need me? Email mike@limberger.ca
AI
Building Your Own Automation
The pieces you already have
Encode an image for the API. Send a request to Ollama. Craft prompts that give structured output. Parse the response with regex. Make a pass or fail decision.
From here, a full automation pipeline is up to you. There is no part 07 in this session. The numbering jumps. That is how the notes arrived.
A folder of images
Loop through a folder and check each one:
Show me.
for img in *.png; do
echo "Checking $img..."
IMAGE_B64=$(base64 -i "$img" | perl -pe's~\s~~g')
RESPONSE=$(curl -s http://localhost:11434/api/generate \
-H "Content-Type: application/json" \
-d '{
"model": "ministral",
"prompt": "Answer YES or NO only.\n\nNUDE_CHEST: YES or NO",
"images": ["'"$IMAGE_B64"'"],
"stream": false
}' | jq -r '.response')
if echo "$RESPONSE" | grep -qi "NUDE_CHEST: YES"; then
echo " REJECT"
else
echo " PASS"
fi
done
Move rejects, do not delete them
Put rejects in a separate folder for review:
Show me.
mkdir -p ./rejects
for img in *.png; do
# ... run your check ...
if echo "$RESPONSE" | grep -qi "NUDE_CHEST: YES"; then
mv "$img" ./rejects/
echo "Moved to rejects: $img"
fi
done
A log you can read later
Keep a record of what was checked and why:
Show me.
LOGFILE="moderation.log"
for img in images/*.png; do
# ... run your check ...
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
if echo "$RESPONSE" | grep -qi "NUDE_CHEST: YES"; then
RESULT="REJECT"
REASON="Nudity detected"
else
RESULT="PASS"
REASON=""
fi
echo "$TIMESTAMP,$img,$RESULT,$REASON" >> "$LOGFILE"
done
That creates a CSV-style log you can review later. CSV is comma-separated values: one row per line, fields split by commas.
Different prompts, different jobs
You could run different prompts for different concerns: content moderation (what we showed), quality assessment (artifacts, extra fingers), style matching, text detection (is there readable text in the image?).
Each check is just a different prompt with different parsing logic.
Temperature and friends
You can add an options block to your JSON request. The temperature setting controls randomness:
"options": {
"temperature": 0.1
}
0.1 is more predictable, consistent. 0.7 is more creative, varied. 1.0 is most random. For moderation, lower is better. We want consistent yes or no answers, not creative interpretation.
Other useful options: "num_ctx": 4096 (context window size, how much the model can hold in one go) and "num_predict": 100 (max tokens to generate). A token is a chunk of text the model counts, roughly a word or part of a word.
It will be slow
Vision models are slower than text-only models. A single image analysis might take 5 to 30 seconds depending on your hardware and model size.
For hundreds of images: process during off-hours, consider a smaller and faster model for initial screening, use a more thorough model for borderline cases, cache results so you do not re-check unchanged images.
The same plumbing, other jobs
Encode, prompt, parse, act. That pattern works for accessibility (alt-text), organization (auto-tag photos), quality control (blurry or corrupted images), document processing (extract text from screenshots), and security (detect sensitive information in images).
Once you understand the pattern, you can adapt it to almost any image analysis task. The prompt is what you change. The plumbing stays the same.
Build something, see what works, and iterate.