stanfordnlp / dspy

DSPy: The framework for programming—not prompting—foundation models
https://dspy-docs.vercel.app/
MIT License
17.03k stars 1.31k forks source link

Error: 'Name' object has no attribute 'ops' #1534

Open arthurgreef opened 20 hours ago

arthurgreef commented 20 hours ago

When using ProgramOfThought and code is generated with named conditionals like this:

Previous Code:
from datetime import datetime

data = {
    "ExpenseReport": "002",
    "ExpenseAmount": "USD30.0",
    "AuthorizationLevel": "94",
    "ExpenseDate": "2024-01-17",
    "SubmittedDate": "2024-02-14",
    "WorkLocation": "US",
    "ExpenseCategory": "hotel",
    "ReceiptAttached": "yes"
}

# Convert amounts to float for comparison
expense_amount = float(data["ExpenseAmount"].replace("USD", ""))
authorization_level = int(data["AuthorizationLevel"])

# Convert dates to datetime objects
expense_date = datetime.strptime(data["ExpenseDate"], "%Y-%m-%d")
submitted_date = datetime.strptime(data["SubmittedDate"], "%Y-%m-%d")
days_difference = (submitted_date - expense_date).days

# Check each policy
policy_1_violated = (expense_amount > 100.00 and authorization_level < 100) or (expense_amount > 25000.00)
policy_2_violated = ((submitted_date.weekday() >= 5) or (days_difference > 30 and data["WorkLocation"] == "US") or (days_difference > 60 and data["WorkLocation"] == "Europe"))
policy_3_violated = (data["ExpenseCategory"] == "hotel" and data["ReceiptAttached"].lower() != "yes")

# Determine status_reason
if policy_1_violated:
    status_reason = "Policy 1 Violated"
elif policy_2_violated:
    status_reason = "Policy 2 Violated"
elif policy_3_violated:
    status_reason = "Policy 3 Violated"
else:
    status_reason = "Approved"

status_reason

The following error message is generated. Error: 'Name' object has no attribute 'ops'

This can be fixed by adding the 'elif isinstance(condition, ast.Name):' statement in python_interpreter.py as shown below.

    def _execute_condition(self, condition):
        if isinstance(condition, ast.BoolOp):
            if isinstance(condition.op, ast.And):
                results = [self._execute_ast(value) for value in condition.values]
                return all(results)
            elif isinstance(condition.op, ast.Or):
                results = [self._execute_ast(value) for value in condition.values]
                return any(results)
            else: #TODO - add any other BoolOps missing
                raise InterpreterError(f"Boolean operator {condition.op} is not supported")
        elif isinstance(condition, ast.Name):
            return self._execute_name(name=condition)
okhat commented 16 hours ago

Hey @arthurgreef ! Thanks a lot. Do you want to open a PR with these improvements for the interpreter?