Sinaptik-AI / pandas-ai

Chat with your database (SQL, CSV, pandas, polars, mongodb, noSQL, etc). PandasAI makes data analysis conversational using LLMs (GPT 3.5 / 4, Anthropic, VertexAI) and RAG.
https://pandas-ai.com
Other
13.57k stars 1.32k forks source link

AttributeError: 'builtin_function_or_method' object has no attribute 'choice' #1422

Open gDanzel opened 3 weeks ago

gDanzel commented 3 weeks ago

System Info

OS version: WIN11 Python version: 3.12 The current version of pandasai being used: 2.3.0

🐛 Describe the bug

I'm requesting LLM to generate plotly plot that able to randomly pick a template, and it returns the code using random module, the code snipet like:

import pandas as pd
import plotly.express as px
import random

......
template_style = random.choice(['ggplot2', 'simple_white'])
fig = px.scatter(incidence_all, x='aesoc', y='incidence_rate', size='unique_subjects', color='randarm', title='Incidence Rate', template=template_style)
fig.update_layout(xaxis_title='AESOC', yaxis_title='Incident Rate')
......

But got error at code execution

error message:

2024-11-03 01:31:06 [INFO] Executing Step 7: CodeExecution
2024-11-03 01:31:06 [ERROR] Failed with error: Traceback (most recent call last):
  File "C:\Users\Danzel\PycharmProjects\yun-ai\.venv\Lib\site-packages\pandasai\pipelines\chat\code_execution.py", line 85, in execute
    result = self.execute_code(code_to_run, code_context)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Danzel\PycharmProjects\yun-ai\.venv\Lib\site-packages\pandasai\pipelines\chat\code_execution.py", line 171, in execute_code
    exec(code, environment)
  File "<string>", line 13, in <module>
AttributeError: 'builtin_function_or_method' object has no attribute 'choice'

I did a simple debug and found it's caused by wronly importing the random.random function instead of random module, the random function dose not have choice attribute cuased the error.

in _check_imports function of code_cleaning.py, it parsed the 'import random', to dependency dic as {"module": "random", "name": "random", "alias": "random"},

    def _check_imports(self, node: Union[ast.Import, ast.ImportFrom]):
        """
        Add whitelisted imports to _additional_dependencies.

        Args:
            node (object): ast.Import or ast.ImportFrom

        Raises:
            BadImportError: If the import is not whitelisted

        """
        module = node.names[0].name if isinstance(node, ast.Import) else node.module
        library = module.split(".")[0]

        if library == "pandas":
            return

        if (
            library
            in WHITELISTED_LIBRARIES + self._config.custom_whitelisted_dependencies
        ):
            for alias in node.names:
                self._additional_dependencies.append(
                    {
                        "module": module,
                        "name": alias.name,
                        "alias": alias.asname or alias.name,
                    }
                )
            return

        if library not in WHITELISTED_BUILTINS:
            raise BadImportError(library)

then later in code cleaning, the function get_environment of optional.py, for dependency 'random', it gose getattr(import_dependency(lib["module"]), lib["name"]) instead of import_dependency(lib["module"]), because if hasattr(import_dependency(lib["module"]), lib["name"]) is true for {"module": "random", "name": "random", "alias": "random"}.

...... lib["alias"]: ( getattr(import_dependency(lib["module"]), lib["name"]) if hasattr(import_dependency(lib["module"]), lib["name"]) else import_dependency(lib["module"]) ) ......

This is a bug that could potential cause problem handling import libs.

dosubot[bot] commented 3 weeks ago

Hey there, @gDanzel! I'm here to help you with any bugs, questions, or contributions you have. Let's tackle this together!

The issue you're encountering is due to a misinterpretation of the import statement for the random module in the _check_imports function. The function incorrectly adds the import as {"module": "random", "name": "random", "alias": "random"}. This leads to the get_environment function using getattr on the random module, which results in the AttributeError because it tries to access random.random instead of the random module itself.

To resolve this, you need to adjust the logic in the _check_imports function to correctly handle the import of the random module. Specifically, ensure that the name field in the dependency dictionary reflects the correct attribute or module being imported. Here's a potential fix:

  1. Modify the _check_imports function to correctly handle the import of the random module by ensuring that the name field is not set to "random" when importing the module itself.

  2. Ensure that the get_environment function correctly imports the module without using getattr when the entire module is needed.

This adjustment should prevent the AttributeError by ensuring that the random module is imported correctly and that its methods, like choice, are accessible.

To continue talking to Dosu, mention @dosu.