File size: 3,717 Bytes
7f611c5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# Context Builder

The context builder turns program state into LLM prompts. It is called once per iteration and returns `{"system": ..., "user": ...}`.

For most tasks you do not need to touch this. Just set the system prompt in `config.yaml`:

```yaml
prompt:
  system_message: |-
    You are an expert at optimizing load balancing algorithms.
```

Only write a custom builder if your algorithm has search-state data (tree path, island ID, rejection history) that the LLM should see.

---

## Structure

```
context_builder/
  base.py              ContextBuilder ABC (one method: build_prompt)
  utils.py             TemplateManager (loads .txt templates from directories)
  human_feedback.py    File-based human feedback injection
  default/
    builder.py         DefaultContextBuilder (handles diff / rewrite / image / prompt modes)
    templates/         .txt prompt templates
  evox/
    builder.py         EvoxContextBuilder (extends Default, adds LLM-generated summaries)
    templates/         .txt templates (override default ones with the same filename)
```

Each builder owns its own `TemplateManager`. Later directories passed to `TemplateManager` override earlier ones on filename conflicts.

---

## Default templates

| File | Role | When used |
|------|------|-----------|
| `system_message.txt` | system | Default system prompt (overridden by config) |
| `diff_user_message.txt` | user | Diff-based generation (default mode) |
| `full_rewrite_user_message.txt` | user | Full rewrite mode |
| `full_rewrite_prompt_opt_user_message.txt` | user | Prompt optimization tasks |
| `image_user_message.txt` | user | Image generation mode |
| `evaluator_system_message.txt` | system | LLM judge (only with llm_as_judge) |
| `evaluator_user_message.txt` | user | LLM judge user message |

---

## Writing a custom builder

The most common pattern is extending `DefaultContextBuilder` and injecting extra guidance via the `{search_guidance}` placeholder. The default templates already include this slot; an empty string makes it disappear cleanly.

```python
from pathlib import Path
from skydiscover.context_builder.default import DefaultContextBuilder
from skydiscover.context_builder.utils import TemplateManager

class MyContextBuilder(DefaultContextBuilder):

    def __init__(self, config):
        super().__init__(config)
        # load your templates on top of the defaults
        default_templates = str(Path(__file__).parent.parent / "default" / "templates")
        my_templates = str(Path(__file__).parent / "templates")
        self.template_manager = TemplateManager(default_templates, my_templates)

    def build_prompt(self, current_program, context=None, **kwargs):
        context = context or {}
        # format whatever the manager put into the context dict
        guidance = self._format_guidance(context.get("my_key"))
        return super().build_prompt(current_program, context, search_guidance=guidance, **kwargs)

    def _format_guidance(self, data):
        if not data:
            return ""
        return f"## CONTEXT\n{data}"
```

The manager populates `context["my_key"]` before calling `build_prompt()`, and sets the builder in its `__init__`:

```python
self.context_builder = MyContextBuilder(self.config)
```

Example to copy: `adaevolve/builder.py` (adds evaluator feedback, paradigm guidance, and sibling context).

---

## Registration

To make a builder available via config instead of hardcoding it in a manager, add it to `_init_context_builder()` in `search/default_discovery_controller.py`:

```python
elif template == "my_builder":
    self.context_builder = MyContextBuilder(self.config)
```

Then activate with:

```yaml
prompt:
  template: my_builder
```