Custom Optimizer Prompts

Customize the internal prompts used by optimizers

The Opik Optimizer uses a PromptLibrary system that lets you customize the internal prompts used by each optimizer. This is useful when you need to:

  • Add domain-specific constraints (legal, medical, coding standards)
  • Inject safety or compliance requirements
  • Adjust output formatting or style
  • Experiment with different reasoning approaches

Quick Start

Every optimizer accepts a prompt_overrides parameter:

1from opik_optimizer import MetaPromptOptimizer
2
3# Simple dict override
4optimizer = MetaPromptOptimizer(
5 model="gpt-4o",
6 prompt_overrides={"reasoning_system": "Be concise. Focus on clarity."}
7)

How It Works

Each optimizer defines its own DEFAULT_PROMPTS dictionary with keys specific to that algorithm. The PromptLibrary:

  1. Stores the default prompts
  2. Applies your overrides (dict or callable)
  3. Validates that override keys exist (catches typos early)
  4. Provides get_prompt() for runtime access

Override Methods

Best when you know exactly which prompt to replace with a static string:

1from opik_optimizer import EvolutionaryOptimizer
2
3optimizer = EvolutionaryOptimizer(
4 model="gpt-4o",
5 prompt_overrides={
6 "synonyms_system_prompt": "Return exactly ONE synonym. No explanation.",
7 "infer_style_system_prompt": "Analyze the writing style briefly.",
8 }
9)

Best when you need to modify existing prompts, apply conditional logic, or update multiple prompts:

1from opik_optimizer import MetaPromptOptimizer
2from opik_optimizer.utils.prompt_library import PromptLibrary
3
4def customize_prompts(prompts: PromptLibrary) -> None:
5 # List available keys
6 print("Available keys:", prompts.keys())
7
8 # Prepend a constraint to the reasoning prompt
9 original = prompts.get("reasoning_system")
10 prompts.set("reasoning_system", "Always respond in English.\n\n" + original)
11
12 # Append format instructions to another prompt
13 if "candidate_generation" in prompts.keys():
14 prompts.set(
15 "candidate_generation",
16 prompts.get("candidate_generation") + "\n\nUse markdown formatting."
17 )
18
19optimizer = MetaPromptOptimizer(
20 model="gpt-4o",
21 prompt_overrides=customize_prompts
22)

Discovering Available Keys

Each optimizer has different prompt keys. Use list_prompts() to discover them:

1from opik_optimizer import MetaPromptOptimizer
2
3optimizer = MetaPromptOptimizer(model="gpt-4o")
4print("Available prompt keys:")
5for key in optimizer.list_prompts():
6 print(f" - {key}")

Common Keys by Optimizer

OptimizerKey Examples
MetaPromptOptimizerreasoning_system, candidate_generation, synthesis, pattern_extraction_system
EvolutionaryOptimizerinfer_style_system_prompt, synonyms_system_prompt, semantic_mutation_system_prompt_template
FewShotBayesianOptimizerexample_placeholder, system_prompt_template
HierarchicalReflectiveOptimizerbatch_analysis_prompt, synthesis_prompt, improve_prompt_template

Reading Prompts at Runtime

After creating an optimizer, you can inspect the current prompts:

1optimizer = MetaPromptOptimizer(
2 model="gpt-4o",
3 prompt_overrides={"reasoning_system": "Custom prompt here..."}
4)
5
6# Get the current (possibly overridden) prompt
7current = optimizer.get_prompt("reasoning_system")
8print(current)
9
10# Get the original default (before any overrides)
11default = optimizer.prompts.get_default("reasoning_system")
12print(default)

Template Variables

Some prompts contain placeholders that get filled at runtime using Python’s {variable} format. When overriding prompts with placeholders, keep the same placeholders:

1# Original: "Generate {num_prompts} variations of the prompt."
2# Your override should keep {num_prompts}:
3prompt_overrides = {
4 "candidate_generation": "Be creative. Generate {num_prompts} diverse variations."
5}

Use Cases

1def add_legal_constraints(prompts: PromptLibrary) -> None:
2 for key in prompts.keys():
3 original = prompts.get(key)
4 prompts.set(key,
5 "LEGAL CONTEXT: Do not reference specific case law.\n\n" + original
6 )
7
8optimizer = MetaPromptOptimizer(
9 model="gpt-4o",
10 prompt_overrides=add_legal_constraints
11)
1optimizer = EvolutionaryOptimizer(
2 model="gpt-4o",
3 prompt_overrides={
4 "infer_style_system_prompt": """
5Analyze writing style. Return a JSON object with:
6{
7 "tone": "formal|casual|technical",
8 "complexity": "simple|moderate|complex",
9 "key_patterns": ["list", "of", "patterns"]
10}
11"""
12 }
13)
1def add_safety_layer(prompts: PromptLibrary) -> None:
2 safety_prefix = """
3SAFETY REQUIREMENTS:
4- Never generate harmful or offensive content
5- Avoid personal identifiable information
6- Flag uncertain responses
7
8"""
9 for key in prompts.keys():
10 if "system" in key.lower():
11 prompts.set(key, safety_prefix + prompts.get(key))
12
13optimizer = MetaPromptOptimizer(
14 model="gpt-4o",
15 prompt_overrides=add_safety_layer
16)

Error Handling

The PromptLibrary validates keys to catch typos early:

1# This will raise KeyError - "reasoing_system" is misspelled
2optimizer = MetaPromptOptimizer(
3 model="gpt-4o",
4 prompt_overrides={"reasoing_system": "Oops, typo!"} # KeyError!
5)
6
7# Error message shows available keys:
8# KeyError: "Unknown prompt keys: ['reasoing_system'].
9# Available: ['candidate_generation', 'reasoning_system', ...]"

Best Practices

Tips for effective prompt customization:

  1. List keys first – Always use list_prompts() to see available keys before overriding
  2. Keep placeholders – If a prompt has {variables}, keep them in your override
  3. Test incrementally – Override one prompt at a time to isolate effects
  4. Use callable for complex logic – Dict is simpler, but callable is more powerful
  5. Don’t break JSON – Some prompts expect JSON output; maintain that structure

Full Example

1from opik_optimizer import MetaPromptOptimizer
2from opik_optimizer.utils.prompt_library import PromptLibrary
3
4def my_customizations(prompts: PromptLibrary) -> None:
5 """Customize prompts for a code generation task."""
6
7 # 1. Add coding focus to reasoning
8 prompts.set(
9 "reasoning_system",
10 "You are an expert code prompt engineer.\n\n" + prompts.get("reasoning_system")
11 )
12
13 # 2. Enforce Python-specific patterns
14 prompts.set(
15 "candidate_generation",
16 prompts.get("candidate_generation") + """
17
18ADDITIONAL REQUIREMENTS:
19- Prompts should encourage well-documented code
20- Prefer type hints and docstrings
21- Emphasize error handling and edge cases
22"""
23 )
24
25# Create optimizer with customizations
26optimizer = MetaPromptOptimizer(
27 model="gpt-4o",
28 prompt_overrides=my_customizations
29)
30
31# Verify customizations applied
32print("Customized reasoning prompt:")
33print(optimizer.get_prompt("reasoning_system")[:200] + "...")