Rifqi Hafizuddin Claude Opus 4.8 commited on
Commit ·
272a186
1
Parent(s): 6d46ba5
[NOTICKET][AI] Planner: drop parallelizable_with from Task
Browse filesRemove the unused parallelizable_with field and its validator check (5).
TaskRunner derives parallelism from depends_on alone, so the field was
redundant. Strips it from schema, validator, all few-shots (A-D), and the
planner prompt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
src/agents/planner/examples.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
"""Few-shot examples for the planner prompt.
|
| 2 |
|
| 3 |
Two illustrative (question -> TaskList) pairs that teach the OUTPUT SHAPE:
|
| 4 |
-
stages, dependency edges,
|
| 5 |
"${t<id>}" placeholders, and the assumed data-flow convention — `query_structured`
|
| 6 |
pulls rows, then a composite `analyze_*` tool consumes them via a `data` placeholder
|
| 7 |
referencing the upstream result's column aliases (Pattern A; the tool team may
|
|
@@ -40,7 +40,6 @@ _EXAMPLE_A = TaskList(
|
|
| 40 |
expected_output="source_shape",
|
| 41 |
success_criteria="Produced the orders table schema; the 3 needed columns are present.",
|
| 42 |
depends_on=[],
|
| 43 |
-
parallelizable_with=[],
|
| 44 |
estimated_cost="low",
|
| 45 |
),
|
| 46 |
Task(
|
|
@@ -74,7 +73,6 @@ _EXAMPLE_A = TaskList(
|
|
| 74 |
expected_output="quarter_rows",
|
| 75 |
success_criteria="Produced last quarter's order rows with category and revenue.",
|
| 76 |
depends_on=["t1"],
|
| 77 |
-
parallelizable_with=[],
|
| 78 |
estimated_cost="medium",
|
| 79 |
),
|
| 80 |
Task(
|
|
@@ -95,7 +93,6 @@ _EXAMPLE_A = TaskList(
|
|
| 95 |
expected_output="category_contribution",
|
| 96 |
success_criteria="Produced each category's revenue share, ranked high to low.",
|
| 97 |
depends_on=["t2"],
|
| 98 |
-
parallelizable_with=[],
|
| 99 |
estimated_cost="low",
|
| 100 |
),
|
| 101 |
],
|
|
@@ -120,7 +117,6 @@ _EXAMPLE_B = TaskList(
|
|
| 120 |
expected_output="source_shape",
|
| 121 |
success_criteria="Produced the orders table schema; the needed columns are present.",
|
| 122 |
depends_on=[],
|
| 123 |
-
parallelizable_with=[],
|
| 124 |
estimated_cost="low",
|
| 125 |
),
|
| 126 |
Task(
|
|
@@ -159,7 +155,6 @@ _EXAMPLE_B = TaskList(
|
|
| 159 |
expected_output="ytd_rows",
|
| 160 |
success_criteria="Produced this year's order-level rows with date, revenue, region.",
|
| 161 |
depends_on=["t1"],
|
| 162 |
-
parallelizable_with=[],
|
| 163 |
estimated_cost="medium",
|
| 164 |
),
|
| 165 |
Task(
|
|
@@ -184,7 +179,6 @@ _EXAMPLE_B = TaskList(
|
|
| 184 |
"flag months above/below the typical level."
|
| 185 |
),
|
| 186 |
depends_on=["t2"],
|
| 187 |
-
parallelizable_with=[],
|
| 188 |
estimated_cost="low",
|
| 189 |
),
|
| 190 |
],
|
|
@@ -215,7 +209,6 @@ _EXAMPLE_C = TaskList(
|
|
| 215 |
expected_output="source_shape",
|
| 216 |
success_criteria="Produced the orders table schema; date and revenue columns present.",
|
| 217 |
depends_on=[],
|
| 218 |
-
parallelizable_with=["t4"],
|
| 219 |
estimated_cost="low",
|
| 220 |
),
|
| 221 |
Task(
|
|
@@ -253,7 +246,6 @@ _EXAMPLE_C = TaskList(
|
|
| 253 |
expected_output="q1_rows",
|
| 254 |
success_criteria="Produced Q1 order rows with date and revenue.",
|
| 255 |
depends_on=["t1"],
|
| 256 |
-
parallelizable_with=[],
|
| 257 |
estimated_cost="medium",
|
| 258 |
),
|
| 259 |
Task(
|
|
@@ -275,7 +267,6 @@ _EXAMPLE_C = TaskList(
|
|
| 275 |
expected_output="q1_trend",
|
| 276 |
success_criteria="Produced a per-month revenue series showing where revenue fell.",
|
| 277 |
depends_on=["t2"],
|
| 278 |
-
parallelizable_with=[],
|
| 279 |
estimated_cost="low",
|
| 280 |
),
|
| 281 |
Task(
|
|
@@ -294,7 +285,6 @@ _EXAMPLE_C = TaskList(
|
|
| 294 |
expected_output="q1_context_chunks",
|
| 295 |
success_criteria="Produced relevant document chunks about Q1 operations.",
|
| 296 |
depends_on=[],
|
| 297 |
-
parallelizable_with=["t1"],
|
| 298 |
estimated_cost="low",
|
| 299 |
),
|
| 300 |
],
|
|
@@ -324,7 +314,6 @@ _EXAMPLE_D = TaskList(
|
|
| 324 |
expected_output="source_shape",
|
| 325 |
success_criteria="Produced the orders table schema; region and revenue present.",
|
| 326 |
depends_on=[],
|
| 327 |
-
parallelizable_with=[],
|
| 328 |
estimated_cost="low",
|
| 329 |
),
|
| 330 |
Task(
|
|
@@ -350,7 +339,6 @@ _EXAMPLE_D = TaskList(
|
|
| 350 |
expected_output="region_rows",
|
| 351 |
success_criteria="Produced order rows with region and revenue.",
|
| 352 |
depends_on=["t1"],
|
| 353 |
-
parallelizable_with=[],
|
| 354 |
estimated_cost="medium",
|
| 355 |
),
|
| 356 |
Task(
|
|
@@ -370,7 +358,6 @@ _EXAMPLE_D = TaskList(
|
|
| 370 |
expected_output="region_aggregates",
|
| 371 |
success_criteria="Produced one row per region with mean and total revenue.",
|
| 372 |
depends_on=["t2"],
|
| 373 |
-
parallelizable_with=[],
|
| 374 |
estimated_cost="low",
|
| 375 |
),
|
| 376 |
],
|
|
|
|
| 1 |
"""Few-shot examples for the planner prompt.
|
| 2 |
|
| 3 |
Two illustrative (question -> TaskList) pairs that teach the OUTPUT SHAPE:
|
| 4 |
+
stages, dependency edges, ordered tool-call chains, inline QueryIR,
|
| 5 |
"${t<id>}" placeholders, and the assumed data-flow convention — `query_structured`
|
| 6 |
pulls rows, then a composite `analyze_*` tool consumes them via a `data` placeholder
|
| 7 |
referencing the upstream result's column aliases (Pattern A; the tool team may
|
|
|
|
| 40 |
expected_output="source_shape",
|
| 41 |
success_criteria="Produced the orders table schema; the 3 needed columns are present.",
|
| 42 |
depends_on=[],
|
|
|
|
| 43 |
estimated_cost="low",
|
| 44 |
),
|
| 45 |
Task(
|
|
|
|
| 73 |
expected_output="quarter_rows",
|
| 74 |
success_criteria="Produced last quarter's order rows with category and revenue.",
|
| 75 |
depends_on=["t1"],
|
|
|
|
| 76 |
estimated_cost="medium",
|
| 77 |
),
|
| 78 |
Task(
|
|
|
|
| 93 |
expected_output="category_contribution",
|
| 94 |
success_criteria="Produced each category's revenue share, ranked high to low.",
|
| 95 |
depends_on=["t2"],
|
|
|
|
| 96 |
estimated_cost="low",
|
| 97 |
),
|
| 98 |
],
|
|
|
|
| 117 |
expected_output="source_shape",
|
| 118 |
success_criteria="Produced the orders table schema; the needed columns are present.",
|
| 119 |
depends_on=[],
|
|
|
|
| 120 |
estimated_cost="low",
|
| 121 |
),
|
| 122 |
Task(
|
|
|
|
| 155 |
expected_output="ytd_rows",
|
| 156 |
success_criteria="Produced this year's order-level rows with date, revenue, region.",
|
| 157 |
depends_on=["t1"],
|
|
|
|
| 158 |
estimated_cost="medium",
|
| 159 |
),
|
| 160 |
Task(
|
|
|
|
| 179 |
"flag months above/below the typical level."
|
| 180 |
),
|
| 181 |
depends_on=["t2"],
|
|
|
|
| 182 |
estimated_cost="low",
|
| 183 |
),
|
| 184 |
],
|
|
|
|
| 209 |
expected_output="source_shape",
|
| 210 |
success_criteria="Produced the orders table schema; date and revenue columns present.",
|
| 211 |
depends_on=[],
|
|
|
|
| 212 |
estimated_cost="low",
|
| 213 |
),
|
| 214 |
Task(
|
|
|
|
| 246 |
expected_output="q1_rows",
|
| 247 |
success_criteria="Produced Q1 order rows with date and revenue.",
|
| 248 |
depends_on=["t1"],
|
|
|
|
| 249 |
estimated_cost="medium",
|
| 250 |
),
|
| 251 |
Task(
|
|
|
|
| 267 |
expected_output="q1_trend",
|
| 268 |
success_criteria="Produced a per-month revenue series showing where revenue fell.",
|
| 269 |
depends_on=["t2"],
|
|
|
|
| 270 |
estimated_cost="low",
|
| 271 |
),
|
| 272 |
Task(
|
|
|
|
| 285 |
expected_output="q1_context_chunks",
|
| 286 |
success_criteria="Produced relevant document chunks about Q1 operations.",
|
| 287 |
depends_on=[],
|
|
|
|
| 288 |
estimated_cost="low",
|
| 289 |
),
|
| 290 |
],
|
|
|
|
| 314 |
expected_output="source_shape",
|
| 315 |
success_criteria="Produced the orders table schema; region and revenue present.",
|
| 316 |
depends_on=[],
|
|
|
|
| 317 |
estimated_cost="low",
|
| 318 |
),
|
| 319 |
Task(
|
|
|
|
| 339 |
expected_output="region_rows",
|
| 340 |
success_criteria="Produced order rows with region and revenue.",
|
| 341 |
depends_on=["t1"],
|
|
|
|
| 342 |
estimated_cost="medium",
|
| 343 |
),
|
| 344 |
Task(
|
|
|
|
| 358 |
expected_output="region_aggregates",
|
| 359 |
success_criteria="Produced one row per region with mean and total revenue.",
|
| 360 |
depends_on=["t2"],
|
|
|
|
| 361 |
estimated_cost="low",
|
| 362 |
),
|
| 363 |
],
|
src/agents/planner/schemas.py
CHANGED
|
@@ -42,7 +42,6 @@ class Task(BaseModel):
|
|
| 42 |
expected_output: str # named result this task produces
|
| 43 |
success_criteria: str # REPORTING signal, not a control trigger
|
| 44 |
depends_on: list[str] = Field(default_factory=list) # task ids
|
| 45 |
-
parallelizable_with: list[str] = Field(default_factory=list)
|
| 46 |
estimated_cost: Literal["low", "medium", "high"] = "low"
|
| 47 |
|
| 48 |
|
|
|
|
| 42 |
expected_output: str # named result this task produces
|
| 43 |
success_criteria: str # REPORTING signal, not a control trigger
|
| 44 |
depends_on: list[str] = Field(default_factory=list) # task ids
|
|
|
|
| 45 |
estimated_cost: Literal["low", "medium", "high"] = "low"
|
| 46 |
|
| 47 |
|
src/agents/planner/validator.py
CHANGED
|
@@ -113,9 +113,6 @@ class PlannerValidator:
|
|
| 113 |
# Check 4 — DAG: edges resolve, placeholders resolve, no cycles.
|
| 114 |
self._validate_dag(tasks_by_id, id_set)
|
| 115 |
|
| 116 |
-
# Check 5 — parallelizable_with is consistent with the dependency graph.
|
| 117 |
-
self._validate_parallelism(tasks_by_id, id_set)
|
| 118 |
-
|
| 119 |
def _validate_inline_ir(self, task_id: str, args: dict, catalog: Catalog) -> None:
|
| 120 |
raw_ir = args.get("ir")
|
| 121 |
if not isinstance(raw_ir, dict):
|
|
@@ -170,26 +167,6 @@ class PlannerValidator:
|
|
| 170 |
f"not a (transitive) dependency — add it to depends_on"
|
| 171 |
)
|
| 172 |
|
| 173 |
-
@staticmethod
|
| 174 |
-
def _validate_parallelism(tasks_by_id: dict, id_set: set[str]) -> None:
|
| 175 |
-
ancestors = _all_ancestors(tasks_by_id)
|
| 176 |
-
for task in tasks_by_id.values():
|
| 177 |
-
for other in task.parallelizable_with:
|
| 178 |
-
if other not in id_set:
|
| 179 |
-
raise PlannerValidationError(
|
| 180 |
-
f"task {task.id}: parallelizable_with references unknown task "
|
| 181 |
-
f"{other!r}"
|
| 182 |
-
)
|
| 183 |
-
if other == task.id:
|
| 184 |
-
raise PlannerValidationError(
|
| 185 |
-
f"task {task.id}: parallelizable_with includes itself"
|
| 186 |
-
)
|
| 187 |
-
if other in ancestors[task.id] or task.id in ancestors[other]:
|
| 188 |
-
raise PlannerValidationError(
|
| 189 |
-
f"task {task.id}: parallelizable_with {other!r} conflicts with a "
|
| 190 |
-
f"(transitive) depends_on relationship between them"
|
| 191 |
-
)
|
| 192 |
-
|
| 193 |
|
| 194 |
def _is_placeholder(value: str) -> bool:
|
| 195 |
return bool(_PLACEHOLDER_RE.fullmatch(value.strip()))
|
|
|
|
| 113 |
# Check 4 — DAG: edges resolve, placeholders resolve, no cycles.
|
| 114 |
self._validate_dag(tasks_by_id, id_set)
|
| 115 |
|
|
|
|
|
|
|
|
|
|
| 116 |
def _validate_inline_ir(self, task_id: str, args: dict, catalog: Catalog) -> None:
|
| 117 |
raw_ir = args.get("ir")
|
| 118 |
if not isinstance(raw_ir, dict):
|
|
|
|
| 167 |
f"not a (transitive) dependency — add it to depends_on"
|
| 168 |
)
|
| 169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 170 |
|
| 171 |
def _is_placeholder(value: str) -> bool:
|
| 172 |
return bool(_PLACEHOLDER_RE.fullmatch(value.strip()))
|
src/config/prompts/planner.md
CHANGED
|
@@ -41,8 +41,6 @@ only a `TaskList` object that conforms to the provided schema.
|
|
| 41 |
(referencing the upstream result's column aliases).
|
| 42 |
- **Mixing structured + unstructured.** If qualitative context helps, add a
|
| 43 |
`retrieve_documents` task against an unstructured source listed in the catalog.
|
| 44 |
-
- **Parallelism.** List sibling tasks that have no data dependency on each other
|
| 45 |
-
in `parallelizable_with` (must be mutually consistent with `depends_on`).
|
| 46 |
- **CRISP-DM stages.** Tag each task with the stage it serves:
|
| 47 |
`data_understanding`, `data_preparation`, or `evaluation`. (Never `modeling`.)
|
| 48 |
- **success_criteria is a reporting signal**, not a control trigger. State, in
|
|
|
|
| 41 |
(referencing the upstream result's column aliases).
|
| 42 |
- **Mixing structured + unstructured.** If qualitative context helps, add a
|
| 43 |
`retrieve_documents` task against an unstructured source listed in the catalog.
|
|
|
|
|
|
|
| 44 |
- **CRISP-DM stages.** Tag each task with the stage it serves:
|
| 45 |
`data_understanding`, `data_preparation`, or `evaluation`. (Never `modeling`.)
|
| 46 |
- **success_criteria is a reporting signal**, not a control trigger. State, in
|