datawhalechina/hello-agents · error · ValueError

Tool 'decompose' only accepts theorems with parameters!

Error message

Tool 'decompose' only accepts theorems with parameters!

What it means

decompose() uses _parse_theorem() to split the theorem into name and parameters, then requires parameters: goal decomposition works by substituting explicit parameters into the theorem's conclusion to build a new sub-goal, which is meaningless without a binding. Unlike apply(), decompose() raises ValueError (not Exception) when theorem_paras is None.

Source

Thrown at Co-creation-projects/BitSecret-GPSAgent/src/gps/symbolic_solver.py:1362

                fact_id, goal_ids = self._add_conclusion(theorem_gdl, replace, premise_ids[i], operation_id)
                all_goal_ids.update(goal_ids)

            self._check_goals(all_goal_ids)

            if len(all_goal_ids) == 0:
                return f"定理'{theorem_name}'执行成功,但没有推导出新的结论。"

            result = f"定理'{theorem_name}'执行成功,以下为问题的状态更新。\n"
            return result + self._get_update(old_fact_id, old_goal_id, old_goal_status)

    def decompose(self, theorem):
        old_fact_id = len(self.facts)
        old_goal_id = len(self.goals)
        old_goal_status = self.status_of_goal.copy()
        theorem_name, theorem_paras = self._parse_theorem(theorem)

        if theorem_paras is None:
            raise ValueError("Tool 'decompose' only accepts theorems with parameters!")

        theorem_gdl = self.parsed_gdl['Theorems'][theorem_name]
        replace = dict(zip(theorem_gdl['paras'], theorem_paras))
        predicate, instance = theorem_gdl['conclusion']  # generate conclusion
        if predicate == "Eq":
            instance = self._adjust_expr(replace_expr(instance, replace))
            if instance is None or len(instance.free_symbols) == 0:
                return f"使用定理'{theorem}'分解目标{_anti_parse_fact((predicate, instance))}失败,目标无需分解或非法。"
        else:
            instance = tuple(replace_paras(instance, replace))
        goal = _anti_parse_fact((predicate, instance))

        passed, result = self._pass_algebraic_constraints(theorem_gdl, replace)  # ac checks
        if not passed:
            return f"使用定理'{theorem}'分解目标{goal}失败," + result

        passed, result = self._pass_geometric_constraints(predicate, instance)  # ee checks
        if not passed:

View on GitHub (pinned to 606a07d341)

Solutions

  1. Call decompose with explicit parameters: solver.decompose('midline(A,B,C)').
  2. Remember parameters must be single uppercase letters and commas only, matching the GDL arity (errors 121/122 apply).
  3. If you only want to run a theorem forward, use apply() instead of decompose().

Example fix

# before
solver.decompose('pythagorean_theorem')

# after
solver.decompose('pythagorean_theorem(A,B,C)')
Defensive patterns

Strategy: validation

Validate before calling

def can_decompose(theorem):
    return '(' in theorem and any(c.isupper() for c in theorem.split('(', 1)[1])

Try / catch

try:
    solver.decompose(theorem)
except ValueError as e:
    if 'only accepts theorems with parameters' in str(e):
        theorem = f"{theorem.split('(')[0]}({','.join(points)})"  # bind and retry

Prevention

When it happens

Trigger: Calling solver.decompose('some_theorem') with no parenthesized parameter list — note that '()' or whitespace-only params also parse to an empty string and become None.

Common situations: Agents reusing the bare-name style that apply() accepts for some theorems; passing a theorem string whose parentheses were stripped or never included.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/e94ae41643ee9f6d. Report an issue: GitHub.