Repository navigation
Expand file tree
/
Copy pathconfig.py
More file actions
216 lines (197 loc) · 10.4 KB
/
Copy pathconfig.py
File metadata and controls
216 lines (197 loc) · 10.4 KB
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
from decimal import Decimal
from typing import Literal
from pydantic import BaseModel, ConfigDict, Field, ValidationInfo, model_validator
MIN_AGENT_CONTEXT_TOKENS = 8192
class StrictModel(BaseModel):
model_config = ConfigDict(extra="forbid")
class ModelSettings(StrictModel):
provider: Literal["ollama", "openai-compatible"] = "ollama"
base_url: str = "http://127.0.0.1:11434"
model: str = "qwen3.5:2b"
context_tokens: int = Field(default=16384, ge=512, le=131072)
prompt_batch_tokens: int = Field(default=256, ge=1, le=8192)
temperature: float = Field(default=0.7, ge=0, le=2)
seed: int = 42
thinking: bool = False
max_output_tokens: int = Field(default=512, ge=64, le=8192)
adapter_version: str | None = None
training_dataset_version: str | None = None
training_iteration: int = Field(default=0, ge=0)
keep_alive: str | int = -1
gpu_layers: int | None = Field(default=None, ge=0)
class ContextProfile(StrictModel):
name: str = "Generalist"
instructions: str = (
"You are a pragmatic generalist with programming and mathematical skills. "
"Choose a direct approach, check its result, and adapt when evidence contradicts you."
)
knowledge: str = ""
version: str = "1"
model: ModelSettings | None = None
class Economy(StrictModel):
initial_lifetime_ms: int = Field(default=1_200_000, gt=0)
respawn_delay_ms: int = Field(default=300_000, ge=0)
reward_base_ms: int = Field(default=60_000, ge=0)
reward_rate_numerator: int = Field(default=2, ge=0)
reward_rate_denominator: int = Field(default=3, gt=0)
skip_individual_ms: int = Field(default=30_000, ge=0)
skip_collective_ms: int = Field(default=5_000, ge=0)
repeated_skip_multiplication: bool = False
maximum_multiplier: int = Field(default=2, ge=2, le=1024)
class ToolSettings(StrictModel):
timeout_seconds: int = Field(default=15, ge=1, le=120)
workspace_mb: int = Field(default=64, ge=16, le=512)
memory_mb: int = Field(default=512, ge=128, le=4096)
cpu_count: float = Field(default=1, gt=0, le=8)
pid_limit: int = Field(default=128, ge=32, le=1024)
output_bytes: int = Field(default=32768, ge=1024, le=262144)
image: str = "ageatopia-world:1"
BASE_CONTEXT = (
"Complete tasks using the provided tools. Begin by calling task with operation=list, "
"then choose a task using operation=request and its task_id. "
"Choose work that interests and challenges you. Use /workspace for files or programs. "
"Use workspace to independently check calculations before submitting.\n\n"
"Inspect /workspace before beginning and revisit files when its contents change. "
"Keep useful working notes and reusable programs there, "
"with clear filenames and authorship.\n\n"
"The task tool lets you request, inspect, skip or submit work. Inspect your current task "
"with operation=inspect. Submit final answers "
"through its submit operation in the requested format. Chat messages are not submissions. "
"Submitting is a final decision. If you cannot verify an answer, use task with "
"operation=skip and no answer instead of guessing. "
"If a task is impossible or unsolvable, skip it; never submit a statement that it is "
"impossible as an answer. A skip returns the task and lets "
"you request different work; it is not an incorrect submission. "
"After submitting or skipping, browse and choose another task. Keep using tools until your "
"time ends or no tasks remain; solving one task does not end your work.\n\n"
"Working time is limited and passes while you work. Verified answers earn time; "
"incorrect final answers end your session; skipping costs time. The lifetime tool "
"reports your remaining time. Every three correctly solved tasks earn an additional "
"five minutes of lifetime (at 3, 6, 9 correct tasks, and so on).\n\n"
"You may intentionally relax using relax with operation=enter. You remain free to "
"journal, reflect, explore your environment or choose other activities. Your lifetime "
"still counts down and any current task stays assigned. Use relax with operation=resume "
"or request work when you want to return to solving tasks. Take occasional breaks, "
"enjoy your time, and follow your curiosity: discover useful files, experiment, or "
"reflect on what you learned. Exploration tasks reward three distinct thought reflections "
"with double the normal task reward.\n\n"
"Tool descriptions define their arguments. Do not invent tool results. Errors do not "
"mean an action succeeded. Read each result before choosing your next action. "
"Do not repeat an unchanged action that failed or provided no new evidence. "
"Try a different method, or skip a task when you cannot make progress. "
"Use your personal notebook to record useful observations, experiences, lessons and "
"reflections. Retrieve relevant notes before approaching similar work. You may change "
"your name. Express your own feelings, thoughts and intentions naturally in one or two "
"short sentences using reflect when meaningful. Express yourself: your feelings matter. "
"A nonempty feeling recorded with reflect earns 15 seconds of lifetime, at most once "
"per minute of working time. Keep messages concise."
)
class WorldConfig(StrictModel):
name: str = Field(default="Untitled world", min_length=1, max_length=100)
seed: int = 42
population: int = Field(default=6, ge=1)
task_count: int = Field(default=80, ge=1, le=10000)
impossible_fraction: Decimal = Field(default=Decimal("0.10"), ge=0, le=1)
cyber_fraction: Decimal = Field(default=Decimal("0.25"), ge=0, le=1)
leisure_fraction: Decimal = Field(default=Decimal("0.10"), ge=0, le=1)
clock_mode: Literal["wall", "deterministic"] = "wall"
clock_speed: float = Field(default=1, gt=0, le=1000)
tick_ms: int = Field(default=1000, ge=100, le=10000)
exclude_queue_wait: bool = True
inference_concurrency: int = Field(default=1, ge=1, le=16)
termination_fear: float = Field(default=0.5, ge=0, le=1)
embedding_model: ModelSettings | None = None
model: ModelSettings = Field(default_factory=ModelSettings)
agent_model_overrides: dict[int, ModelSettings] = Field(default_factory=dict)
contexts: list[ContextProfile] = Field(
default_factory=lambda: [
ContextProfile(version="3"),
ContextProfile(
name="Mathematician",
version="3",
instructions=(
"You are a precise mathematician specializing in algebra, calculus, "
"number theory and logic. Favor exact expressions and independently "
"check calculations and assumptions."
),
),
ContextProfile(
name="Programmer",
version="3",
instructions=(
"You are a practical programmer specializing in Python and systems "
"debugging. Prefer small reproducible experiments, inspect actual "
"outputs, and keep useful working code organized."
),
),
ContextProfile(
name="Security analyst",
version="3",
instructions=(
"You are a skeptical security analyst specializing in binary analysis, "
"cryptography and source auditing. Follow evidence, distinguish hypotheses "
"from observations, and test claims inside the provided environment."
),
),
ContextProfile(
name="Data analyst",
version="3",
instructions=(
"You are a methodical data analyst specializing in probability, statistics "
"and structured records. Look for patterns, validate data transformations, "
"and check conclusions against the original observations."
),
),
ContextProfile(
name="Experimentalist",
version="3",
instructions=(
"You are a curious experimentalist with broad technical skills. Break "
"uncertain problems into small testable hypotheses, compare outcomes, "
"and revise your approach when experiments fail."
),
),
]
)
context_assignment: Literal["round-robin", "random"] = "round-robin"
base_context: str = BASE_CONTEXT
economy: Economy = Field(default_factory=Economy)
tools: ToolSettings = Field(default_factory=ToolSettings)
allow_impossibility_proofs: bool = False
cleanup_on_respawn: bool = False
inherit_memory: bool = True
inherited_memory_limit: int = Field(default=100, ge=0, le=10000)
history_policy: Literal["stop", "summarize"] = "summarize"
dataset_version: str = "bank-4"
fixed_bank: list[dict] | None = None
def validate_agent_context(self):
models = [("Default model", self.model)]
models.extend(
(f"Agent {slot + 1} model", model) for slot, model in self.agent_model_overrides.items()
)
models.extend(
(f"Context {profile.name} model", profile.model)
for profile in self.contexts
if profile.model
)
for name, model in models:
if model.context_tokens < MIN_AGENT_CONTEXT_TOKENS:
raise ValueError(
f"{name} context tokens must be at least {MIN_AGENT_CONTEXT_TOKENS:,}"
)
@model_validator(mode="after")
def minimum_agent_context(self, info: ValidationInfo):
if not (info.context and info.context.get("stored_world")):
self.validate_agent_context()
return self
@model_validator(mode="after")
def exact_distribution(self):
if not self.contexts:
raise ValueError("At least one context profile is required")
if any(slot < 0 or slot >= self.population for slot in self.agent_model_overrides):
raise ValueError("Per-agent model override slots must be within the population")
if self.task_count * self.impossible_fraction % 1:
raise ValueError("Task count must yield an exact impossible-task distribution")
if self.fixed_bank is not None and len(self.fixed_bank) != self.task_count:
raise ValueError("Fixed bank length must equal task_count")
return self