Generate prompts for Kling, Runway, and Veo simultaneously — then compare them side by side
Day 19 of 80
A script called prompt_compare.py that:
prompts.json libraryYesterday, your API call code sat directly in the script. Today you wrap it in a function — a named block of code you can call multiple times with different arguments.
Instead of copy-pasting the API call three times (once for Kling, once for Runway, once for Veo), you write it once as generate_prompt(shot, platform) and call it in a loop. If you ever need to change the system prompt or the model, you change it in one place — not three.
This is a preview of Week 5's main topic. Don't worry about mastering functions today — just see how they make repetitive work disappear.
You'll use results = {} as a "collection box" — loop through the platforms, generate a prompt for each one, and store it: results[platform] = generated_text. At the end of the loop, results is a dictionary mapping platform names to their generated prompts. Then you loop through it again to display everything.
This separation — first collect, then display — is a clean pattern you'll use constantly. Don't mix collecting and printing in the same loop.
Create prompt_compare.py in the same folder as your other scripts.
import anthropic
import json
from dotenv import load_dotenv
load_dotenv()
client = anthropic.Anthropic()
PLATFORMS = ["Kling", "Runway", "Veo"]
def generate_prompt(shot, platform):
"""Call Claude to generate an AI video prompt for the given platform."""
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=300,
system="You are an expert AI video prompt engineer who writes concise, "
"production-ready prompts for AI video generation platforms.",
messages=[{
"role": "user",
"content": f"""Write a production-ready {platform} prompt for this shot:
{shot}
Requirements:
- Include camera movement, lighting, mood, and style details
- Match {platform}'s prompt style and strengths
- Keep it under 100 words
- Return ONLY the prompt text, nothing else"""
}]
)
return message.content[0].text
def generate_prompt(shot, platform): — defines the function. shot and platform are parameters (inputs).return message.content[0].text — the function gives back the generated text to whoever called it. Without return, the result would be lost.generate_prompt("wide aerial shot", "Kling") anywhere and get a generated prompt back. No copy-paste needed.
print("=== DVP Multi-Platform Comparison ===\n")
shot = input("Describe your shot: ")
print()
results = {}
for platform in PLATFORMS:
print(f"Generating {platform}...")
try:
results[platform] = generate_prompt(shot, platform)
except Exception as e:
results[platform] = f"[Error: {e}]"
results = {} starts as an empty dictionary — the collection box.for loop runs three times, once per platform. Each iteration calls generate_prompt() and stores the result: results["Kling"] = "...", results["Runway"] = "...", etc.except Exception as e catches any error for this platform and stores an error message in results instead of crashing the whole script. In production you'd be more specific (catching anthropic.APIError), but for a learning project this broad catch keeps things running. Note the tradeoff.results has all three prompts (or error messages) ready to display.
print("\n" + "=" * 50)
print("COMPARISON RESULTS")
print("=" * 50)
for platform, prompt in results.items():
print(f"\n[{platform}]")
print(prompt)
print("-" * 40)
results.items() gives you both the key and value in each iteration — platform is the key ("Kling"), prompt is the value (the generated text). "=" * 50 creates a separator line 50 characters wide — string multiplication. Clean, no imports needed.
print("\nWhich to save? (all / none / comma-separated list like: kling,veo)")
choice = input("Save: ").strip().lower()
if choice == "none" or choice == "":
print("Nothing saved.")
else:
if choice == "all":
to_save = [p.lower() for p in PLATFORMS]
else:
to_save = [c.strip().lower() for c in choice.split(",")]
try:
with open("prompts.json", "r") as f:
prompts = json.load(f)
except FileNotFoundError:
prompts = []
saved_count = 0
for platform, prompt in results.items():
if platform.lower() in to_save:
prompts.append({
"platform": platform,
"shot": shot,
"prompt": prompt
})
saved_count += 1
with open("prompts.json", "w") as f:
json.dump(prompts, f, indent=2)
print(f"Saved {saved_count} prompts. Library now has {len(prompts)} total.")
[c.strip().lower() for c in choice.split(",")] is a list comprehension that splits "kling, veo" on commas, strips whitespace from each piece, and converts to lowercase — all in one line. This gives you ["kling", "veo"] regardless of how the user typed it. Then you compare platform.lower() in to_save to decide what to save.
$ python prompt_compare.py
=== DVP Multi-Platform Comparison ===
Describe your shot: handheld tracking shot following a golfer walking to the green
Generating Kling...
Generating Runway...
Generating Veo...
==================================================
COMPARISON RESULTS
==================================================
[Kling]
Handheld tracking shot follows a golfer walking purposefully toward the green.
Warm afternoon sun creates long shadows across manicured turf. Shallow focus,
slight camera shake, intimate and focused energy. Cinematic 4K.
----------------------------------------
[Runway]
Documentary-style tracking shot. Camera follows golfer at eye level, slight
handheld movement. Golden hour lighting, rich greens and warm tones. Focused
and deliberate movement. Photorealistic, 4K, cinematic.
----------------------------------------
[Veo]
Smooth handheld tracking shot behind golfer approaching putting green. Late
afternoon light, vivid green grass, realistic textures. Camera slightly shakes
with footsteps. Naturalistic color grading, cinematic feel.
----------------------------------------
Which to save? (all / none / comma-separated list like: kling,veo)
Save: kling,runway
Saved 2 prompts. Library now has 5 total.
Notice how each platform generates slightly different vocabulary and emphasis. This is intentional — Claude knows each platform has different strengths. Kling tends toward cinematic language; Runway toward documentary realism; Veo toward naturalistic detail. This comparison is genuinely useful when you're choosing a platform for a specific shot.
prompt_compare.py runs and generates all three platformsgenerate_prompt(shot, platform) does and why it's a functionWeek 4 Review and Milestone. You'll consolidate everything — APIs, the Claude SDK, token-aware prompt engineering, and error handling. Then a vocabulary test and self-check to lock it all in before Week 5.