Giter Site home page Giter Site logo

aronweiler / assistant Goto Github PK

View Code? Open in Web Editor NEW
49.0 2.0 7.0 15.19 MB

An intellligent AI assistant that can do anything!

License: GNU General Public License v3.0

PowerShell 0.37% Python 99.18% Mako 0.06% Dockerfile 0.16% Jinja 0.22%
ai database large-language-models llm openai pgvector polly-voice postgres postgresql python

assistant's Introduction

Exciting News! ๐Ÿš€

I'm thrilled to announce that my AI Assistant (formerly known as Jarvis) is evolving, and the team is growing!

We've taken everything you love about this intelligent assistant and are transforming it into a more powerful, sleeker product: ZipBot.ai. This new platform will not only include all the features you've come to rely on but also introduce a host of new capabilities designed to make your life even easier.

๐Ÿ‘‰ What does this mean for you? More power, more features, and an even better user experience.

But, before we officially launch, we want YOU to be a part of our journey. Sign up for the beta at https://zipbot.ai and be the first to experience the future of intelligent assistance.

Your feedback during this beta phase will be invaluable as we fine-tune ZipBot.ai to perfection. Don't miss out on this opportunity to shape the future of AI assistance.

Thank you for your continued support and enthusiasm. We can't wait to embark on this exciting new chapter with you!

Thanks,

The ZipBot.ai Team


AI Assistant (Jarvis)

An intelligent assistant. This is a work in progress. Don't hate over the name... I was younger, and less creative.

Features

  • โœ… Chat with the AI (Conversation-Only Mode)
  • โœ… AI Assistant (Tool-Using Mode)
    • โœ… Get the News, Weather, etc.
    • โœ… Upload your Documents, and talk about them with the AI, including:
      • Search for information
      • Review and comment on documents
      • Summarize a topic or whole documents
      • Perform multi-hop queries, such as "What is the capital of the country that has the highest population in Europe?"
  • โœ… Software Engineering Assistant
    • โœ… Ingest your GitHub or GitLab repositories!
    • โœ… Code Understanding
      • โœ… Ask the AI to perform tasks, such as:
        • Coding work, while taking into context existing code
        • Summarization of code functionality
        • Code reviews
        • Code documentation
        • Unit test creation

Streamlit UI

Running Jarvis in Docker

In order to install the assistant using Docker, you'll need the following:

Pre-requisites for running in Docker

The steps to run the docker version is as follows:

Running Jarvis

  1. Get the files
  2. Edit the .env.template file, changing the following items:
    • OPENAI_API_KEY - This is your Open AI API key (required for interacting with OpenAI models- the primary model for this application).
    • POSTGRES_* entries can be pretty much anything you want, all of this will be local to your machine.
    • USER_EMAIL - Put your email in here (required for a user on the system- some features will use this)
  3. Rename the .env.template to .env
  4. Using a command line, navigate to the directory where you cloned the code, and run docker-compose up -d
  5. Browse to http://localhost:8500

Updating Jarvis (Docker)

If you are currently at version 0.64 or earlier, you will need to follow these instructions.

๐Ÿฅณ Following these update instructions WILL NOT ERASE YOUR DATA ๐Ÿฅณ

Run the following commands in a terminal window in the same directory as the Jarvis docker-compose.yml:

  • docker-compose down assistant-ui
  • docker pull aronweiler/assistant:latest
    • Alternatively, you can use the version number in place of latest, e.g. docker pull aronweiler/assistant:0.45
  • docker-compose up -d assistant-ui
  • Navigate to http://localhost:8500

Note: After updating you will need to re-enable/disable any tools that you previously changed on the Settings page.

โš ๏ธ DATABASE CONTAINER WARNING โš ๏ธ

The docker container that has the database in it is currently used primarily by me for development, so it does not mount a volume for the database.
When you delete the DB docker container, ALL OF YOUR DATA WILL BE ERASED.

Feel free to alter this behavior on your instance, if you like.

FireFox Browser UI Compatibility

In FireFox, the :has() CSS feature is turned off, which can cause weird display issues. To enable it, follow these steps:

  1. Open Firefox.
  2. Type about:config in the address bar and press Enter.
  3. Click "Accept the Risk and Continue" to access the advanced settings.
  4. Use the search bar at the top to find the setting for enabling experimental features. This might be something like layout.css.has-selector.enabled.
  5. If you find the relevant setting for :has(), click on the toggle button to set its value to true.

Here's a lot of info on running this in Python!

Note: This is probably out of date, as I don't really support anyone looking at my gross code ๐Ÿคฃ

Python Prerequisites

1. Install the python requirements:

pip install -r requirements.txt

Install Whisper and Torch (for Voice Interactions)

I'm using their github, but feel free to use the python packages.

pip install --upgrade --no-deps --force-reinstall git+https://github.com/openai/whisper.git

pip3 install --force-reinstall --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu121

2. Set up the database

The database is required for conversations, file upload, user management, etc.

Database-related Environment Variables

Set the following environment variables for database access:

POSTGRES_DB=<your desired database name>
POSTGRES_USER=<user>
POSTGRES_PASSWORD=<password>
POSTGRES_HOST=<database location>
POSTGRES_PORT=5432

Note: When setting the database up, the create/migration scripts have their own settings - so you may need to adjust these.

- Run the PGVector (postgres) docker image:

Pull and run the PGVector docker file, following instructions here: PGVector GitHub

You can also run my docker-compose file via docker-compose up -d from the database folder.

- Create the database

After creating and running the database docker image, you need to create the actual database.

Run the create_database.py python script.

This creates the database... but for some reason the vector extension is not create.

Connect to the new database, and run: CREATE EXTENSION IF NOT EXISTS vector;

- Set up database migrations:

Migrations make it easy to add/change/remove things from the database when you already have data in there.

- Alembic for migrations setup:

To use Alembic for migrations, you'll need to set up a directory structure for Alembic to manage the migrations. First, create a directory named migrations in your project root. Then, initialize Alembic inside this directory:

alembic init migrations

This will create an alembic.ini file and a versions directory inside the migrations directory. The versions directory is required, but the alembic.ini is not!

- Running migrations:

  1. Run generate_migration.py
    • This will generate the migrations that contain the changes (or just the initial database) between the current DB and any modifications that have been made to the DB models in code.
  2. Run run_migration.py
    • This will push those changes to the database, safely migrating your data.

More info on the database

See Memory

assistant's People

Contributors

aronweiler avatar jmcoreymvmd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

assistant's Issues

Jarvis AI review of src/utilities/instance_utility.py (ref: main)

The file src/utilities/instance_utility.py
was reviewed by Jarvis AI with the following findings:

  1. The constructor_kwargs parameter is not type-annotated. It's recommended to use type hints for all function parameters for better code clarity and type checking.

    Existing code snippet:

    constructor_kwargs=None

    Suggested code snippet:

    constructor_kwargs: Optional[Dict[str, Any]] = None
  2. Consider providing a default value for constructor_kwargs to ensure it's always a dictionary. This simplifies the logic in lines 11-14.

    Existing code snippet:

    constructor_kwargs=None

    Suggested code snippet:

    constructor_kwargs={}
  3. Using getattr to dynamically instantiate a class can lead to Insecure Direct Object References if the class_name is controlled by user input. Ensure that class_name is validated or derived from a safe source.

    Existing code snippet:

    instance = getattr(module, class_name)(**constructor_kwargs)

    Suggested code snippet:

    if class_name in safe_class_list: instance = getattr(module, class_name)(**constructor_kwargs)
  4. The conditional check for constructor_kwargs is unnecessary if it's always a dictionary. This can be simplified by using the default value as an empty dictionary.

    Existing code snippet:

    if constructor_kwargs is not None:
        instance = getattr(module, class_name)(**constructor_kwargs)
    else:
        instance = getattr(module, class_name)()

    Suggested code snippet:

    instance = getattr(module, class_name)(**constructor_kwargs)
  5. Catching a general exception can hide bugs and make debugging difficult. It's better to catch specific exceptions or at least log the traceback for more context.

    Existing code snippet:

    except Exception as e:

    Suggested code snippet:

    except (ImportError, AttributeError) as e:  # Add specific exceptions as needed
  6. Using a broad except Exception clause can catch exceptions that you might not want to handle here. It's better to catch specific exceptions that you expect could occur during the dynamic import and instantiation process.

    Existing code snippet:

    except Exception as e:

    Suggested code snippet:

    except (ImportError, AttributeError) as e:
  7. Logging the error without re-raising it can lead to silent failures where the calling code is unaware an error occurred. Consider re-raising the exception after logging or returning a more informative result.

    Existing code snippet:

    logging.error(f"Error creating an instance of {class_name} class: {str(e)}")

    Suggested code snippet:

    logging.error(f"Error creating an instance of {class_name} class: {str(e)}"); raise
  8. Logging the error is good, but returning None can make it difficult for the caller to distinguish between a successful return of None and an error case. Consider raising a custom exception or using a result object to provide more context.

    Existing code snippet:

    return None

    Suggested code snippet:

    raise CustomException(f"Error creating an instance of {class_name} class: {str(e)}")

Jarvis AI review of src/utilities/instance_utility.py (ref: main)

The file src/utilities/instance_utility.py
was reviewed by Jarvis AI with the following findings:

  1. Add a module-level docstring to provide an overview of the purpose and usage of this module.

    Existing code snippet:

    import importlib

    Suggested code snippet:

    """
    Module for instance utilities.
    
    This module provides functions for managing instances.
    """
    import importlib
  2. Add a module-level docstring to provide an overview of the purpose and usage of this module.

    Existing code snippet:

    import importlib

    Suggested code snippet:

    """
    Module for instance utilities.
    
    This module provides functions for managing instances.
    """
    import importlib
  3. Add type hints to the function signature for better code readability and maintainability.

    Existing code snippet:

    def create_instance_from_module_and_class(

    Suggested code snippet:

    def create_instance_from_module_and_class(module_name: str, class_name: str, constructor_kwargs=None)
  4. Consider adding specific exception handling instead of catching all exceptions.

    Existing code snippet:

    try:

    Suggested code snippet:

    try:
        # Specific exception handling here
  5. Consider specifying the exception type(s) to catch instead of using a broad 'except' clause.

    Existing code snippet:

    try:

    Suggested code snippet:

    try:
        # code block
  6. Consider using a more descriptive variable name instead of 'module'.

    Existing code snippet:

    module = importlib.import_module(module_name)

    Suggested code snippet:

    imported_module = importlib.import_module(module_name)
  7. Consider using 'is' instead of 'is not' for better code readability.

    Existing code snippet:

    if constructor_kwargs is not None:

    Suggested code snippet:

    if constructor_kwargs is not None:
  8. Consider using a more specific exception instead of catching all exceptions.

    Existing code snippet:

    except Exception as e:

    Suggested code snippet:

    except SpecificException as e:
  9. Consider using a more descriptive variable name instead of 'instance'.

    Existing code snippet:

    instance = getattr(module, class_name)(**constructor_kwargs)

    Suggested code snippet:

    created_instance = getattr(module, class_name)(**constructor_kwargs)
  10. Consider using a more descriptive variable name instead of 'instance'.

    Existing code snippet:

    instance = getattr(module, class_name)()

    Suggested code snippet:

    created_instance = getattr(module, class_name)()
  11. Consider adding a return type hint to improve code readability and maintainability.

    Existing code snippet:

    return instance

    Suggested code snippet:

    return instance  # type: Any
  12. Consider specifying the exception type(s) to catch instead of using a broad 'except' clause.

    Existing code snippet:

    except Exception as e:

    Suggested code snippet:

    except Exception as e:
        # code block
  13. Consider using f-strings for string formatting instead of concatenation.

    Existing code snippet:

    logging.error(f"Error creating an instance of {class_name} class: {str(e)}")

    Suggested code snippet:

    logging.error(f"Error creating an instance of {class_name} class: {e}")
  14. Consider returning None explicitly instead of relying on the default return behavior.

    Existing code snippet:

    return None

    Suggested code snippet:

    return None  # type: Optional[Any]

Jarvis AI review of src/utilities/hash_utilities.py (ref: main)

The file src/utilities/hash_utilities.py
was reviewed by Jarvis AI with the following findings:

  1. Consider adding module-level docstring to provide an overview of the purpose and usage of this module.

    Existing code snippet:

    import hashlib

    Suggested code snippet:

    """
    Module for hash utilities.
    
    This module provides functions for calculating hash values of files.
    """
    import hashlib
  2. Consider adding a function-level docstring to provide an overview of the purpose and usage of this function.

    Existing code snippet:

    def calculate_sha256(file_path):

    Suggested code snippet:

    def calculate_sha256(file_path):
        """
        Calculate the SHA256 hash value of a file.
    
        Args:
            file_path (str): The path to the file.
    
        Returns:
            str: The SHA256 hash value.
        """
  3. Consider using a larger chunk size for reading the file to improve efficiency.

    Existing code snippet:

        # Read the file in chunks for efficiency

    Suggested code snippet:

        # Read the file in larger chunks for efficiency

About synergy

Hi Aron,
How can I connect with you for discussing?
I want to discuss cooperation

Jarvis AI review of src/ai/agents/general/generic_tools_agent.py (ref: main)

The file src/ai/agents/general/generic_tools_agent.py
was reviewed by Jarvis AI with the following findings:

  1. The class GenericToolsAgent contains multiple class-level attributes that are mutable. This can lead to unexpected behavior when instances of the class share the same data. Consider using instance-level attributes or providing a clear warning about the shared state.

    Existing code snippet:

    class GenericToolsAgent(BaseSingleActionAgent): ... wrong_tool_calls: list = []

    Suggested code snippet:

    class GenericToolsAgent(BaseSingleActionAgent): ... def __init__(self): ... self.wrong_tool_calls = []
  2. The GenericToolsAgent class is quite large and contains many methods. Consider breaking it down into smaller classes or modules to improve maintainability and readability.

    Existing code snippet:

    class GenericToolsAgent(BaseSingleActionAgent): ...

    Suggested code snippet:

    Consider refactoring into smaller classes or modules.
  3. The class attributes are not documented. Adding docstrings or comments explaining the purpose of each attribute would improve code maintainability.

    Existing code snippet:

    class GenericToolsAgent(BaseSingleActionAgent): ...

    Suggested code snippet:

    Add comments or docstrings for each class attribute.
  4. The class attributes are initialized with None or primitive types, which could lead to tightly coupled code if they are expected to be specific types. Use dependency injection or factory patterns to improve flexibility.

    Existing code snippet:

    model_configuration: ModelConfiguration = None

    Suggested code snippet:

    Use dependency injection for `model_configuration` and other attributes.
  5. Class attributes are initialized to None or primitive types, which could lead to unintentional sharing of mutable objects across instances if they are changed to mutable types in the future. Consider initializing such attributes inside the __init__ method to ensure each instance has its own copy.

    Existing code snippet:

    model_configuration: ModelConfiguration = None
    conversation_manager: ConversationManager = None
    tools: list = None
    previous_work: str = None
    llm: BaseLanguageModel = None
    streaming: bool = True
    step_plans: dict = None
    step_index: int = -1
    current_retries: int = 0
    wrong_tool_calls: list = []

    Suggested code snippet:

    def __init__(self):
        self.model_configuration = None
        self.conversation_manager = None
        self.tools = None
        self.previous_work = None
        self.llm = None
        self.streaming = True
        self.step_plans = None
        self.step_index = -1
        self.current_retries = 0
        self.wrong_tool_calls = []
  6. The plan method is very long and contains deeply nested code. Refactor to reduce complexity and improve readability.

    Existing code snippet:

    def plan(self, intermediate_steps: Tuple[AgentAction, str], **kwargs: Any) -> Union[AgentAction, AgentFinish]: ...

    Suggested code snippet:

    Split the method into smaller, more focused methods.
  7. Magic numbers are used in the plan method (e.g., self.step_index = -1). Replace them with named constants to improve code clarity.

    Existing code snippet:

    self.step_index = -1

    Suggested code snippet:

    INITIAL_STEP_INDEX = -1
  8. The plan method contains duplicate logic for constructing prompts and handling actions. Consider abstracting common logic into helper methods.

    Existing code snippet:

    plan_steps_prompt = self.get_plan_steps_prompt(...)

    Suggested code snippet:

    Refactor to create a method for common prompt construction logic.
  9. The plan method contains hard-coded strings for logging and error messages. Consider using a centralized approach for message templates to facilitate changes and localization.

    Existing code snippet:

    log="Agent finished."

    Suggested code snippet:

    Use a centralized message template system.
  10. The plan method has inconsistent indentation and formatting, making it difficult to read. Ensure consistent formatting for better readability.

    Existing code snippet:

    if (self.step_index < len(self.step_plans['steps']) and len(self.step_plans['steps']) > 0):

    Suggested code snippet:

    Reformat code for consistent indentation and line breaks.
  11. The plan method contains commented-out code, which is a form of code clutter. Remove or document the reason for keeping the commented-out code.

    Existing code snippet:

    # TODO: Refactor this so we can execute multiple actions at once (and handle dependencies)

    Suggested code snippet:

    Remove or address the TODO comment.
  12. The plan method uses over-complicated expressions, such as checking the length of self.step_plans['steps'] multiple times. Simplify the logic for better readability.

    Existing code snippet:

    if (self.step_index < len(self.step_plans['steps']) and len(self.step_plans['steps']) > 0):

    Suggested code snippet:

    Refactor to simplify the expression.
  13. The get_llm function is called without exception handling, which could lead to an unhandled exception if the function raises one. Consider adding a try-except block to handle potential exceptions.

    Existing code snippet:

    self.llm = get_llm(
        model_configuration=self.model_configuration,
        tags=['generic_tools'],
        callbacks=self.conversation_manager.agent_callbacks,
        streaming=self.streaming,
    )

    Suggested code snippet:

    try:
        self.llm = get_llm(
            model_configuration=self.model_configuration,
            tags=['generic_tools'],
            callbacks=self.conversation_manager.agent_callbacks,
            streaming=self.streaming,
        )
    except Exception as e:
        logging.error(f'Failed to get LLM: {e}')
        # Handle the exception appropriately
  14. The predict method of self.llm is called without exception handling, which could lead to an unhandled exception if the method raises one. Consider adding a try-except block to handle potential exceptions.

    Existing code snippet:

    text = self.llm.predict(
        plan_steps_prompt,
        callbacks=self.conversation_manager.agent_callbacks,
    )

    Suggested code snippet:

    try:
        text = self.llm.predict(
            plan_steps_prompt,
            callbacks=self.conversation_manager.agent_callbacks,
        )
    except Exception as e:
        logging.error(f'LLM prediction failed: {e}')
        # Handle the exception appropriately
  15. The parse_json function is called without exception handling, which could lead to an unhandled exception if the function raises one, especially since JSON parsing is prone to ValueError if the input is not valid JSON. Consider adding a try-except block to handle potential exceptions.

    Existing code snippet:

    self.step_plans = parse_json(
        text,
        llm=self.llm,
    )

    Suggested code snippet:

    try:
        self.step_plans = parse_json(
            text,
            llm=self.llm,
        )
    except ValueError as e:
        logging.error(f'JSON parsing failed: {e}')
        # Handle the exception appropriately
  16. The method remove_steps_without_tool is called within the plan method, which could be called multiple times. This method modifies the self.step_plans attribute directly, which can lead to side effects if plan is called more than once. Consider returning a new list of steps without modifying the original self.step_plans.

    Existing code snippet:

    self.step_plans['steps'] = self.remove_steps_without_tool(self.step_plans['steps'], self.tools)

    Suggested code snippet:

    filtered_steps = self.remove_steps_without_tool(self.step_plans['steps'], self.tools)
  17. The condition self.step_index < len(self.step_plans['steps']) and len(self.step_plans['steps']) > 0 is redundant. The second part of the condition is unnecessary because if self.step_index is less than the length of self.step_plans['steps'], it implies that the list is not empty.

    Existing code snippet:

    if (self.step_index < len(self.step_plans['steps']) and len(self.step_plans['steps']) > 0):

    Suggested code snippet:

    if self.step_index < len(self.step_plans['steps']):
  18. The method remove_steps_without_tool uses a list comprehension to create tool_names but then iterates over steps in a for-loop to filter them. This could be optimized by using a set for tool_names for O(1) lookups and a list comprehension for filtering.

    Existing code snippet:

    tool_names = [tool.name for tool in tools]

    Suggested code snippet:

    tool_names = set(tool.name for tool in tools)
    filtered_steps = [step for step in steps if step['tool'] in tool_names]
  19. The predict method of self.llm is called without exception handling, which could lead to an unhandled exception if the method raises one. Consider adding a try-except block to handle potential exceptions.

    Existing code snippet:

    text = self.llm.predict(
        tool_use_prompt, callbacks=self.conversation_manager.agent_callbacks
    )

    Suggested code snippet:

    try:
        text = self.llm.predict(
            tool_use_prompt, callbacks=self.conversation_manager.agent_callbacks
        )
    except Exception as e:
        logging.error(f'LLM prediction failed: {e}')
        # Handle the exception appropriately
  20. The parse_json function is called without exception handling, which could lead to an unhandled exception if the function raises one. Consider adding a try-except block to handle potential exceptions.

    Existing code snippet:

    action_json = parse_json(
        text,
        llm=self.llm,
    )

    Suggested code snippet:

    try:
        action_json = parse_json(
            text,
            llm=self.llm,
        )
    except ValueError as e:
        logging.error(f'JSON parsing failed: {e}')
        # Handle the exception appropriately
  21. The condition self.step_index == -1 is used to handle the case where no steps could be found. However, this condition is checked after attempting to access self.step_plans['steps'][self.step_index], which could result in an IndexError if self.step_index is -1. This check should be performed before attempting to access the list.

    Existing code snippet:

    step = self.step_plans['steps'][self.step_index]

    Suggested code snippet:

    if self.step_index == -1:
        # Handle the case where no steps could be found
        step = {...}
    else:
        step = self.step_plans['steps'][self.step_index]
  22. The predict method of self.llm is called within the parse_json function without exception handling, which could lead to an unhandled exception if the method raises one. Consider adding a try-except block to handle potential exceptions.

    Existing code snippet:

    action_json = parse_json(
        text=self.llm.predict(
            tool_use_prompt, callbacks=self.conversation_manager.agent_callbacks
        ),
        llm=self.llm,
    )

    Suggested code snippet:

    try:
        action_json = parse_json(
            text=self.llm.predict(
                tool_use_prompt, callbacks=self.conversation_manager.agent_callbacks
            ),
            llm=self.llm,
        )
    except Exception as e:
        logging.error(f'LLM prediction or JSON parsing failed: {e}')
        # Handle the exception appropriately
  23. The method get_tool_calls_from_failed_steps constructs a string by concatenating JSON dumps in a loop. This is inefficient and can be improved by using a list to collect the strings and then joining them at the end.

    Existing code snippet:

    for step in intermediate_steps: context += json.dumps(...)

    Suggested code snippet:

    context_parts = [json.dumps(...) for step in intermediate_steps]
    context = '\n'.join(context_parts)
  24. The try block is used to append a string representation of step[1] to context. However, the except block catches all exceptions and does not log or re-raise them, which could hide bugs. It is recommended to catch specific exceptions and handle them accordingly.

    Existing code snippet:

    try:
        if step[1] is not None:
            context += '\nReturned: ' + str(step[1])
        else:
            context += '\nReturned: None'
    except Exception as e:
        context += '\nReturned: An unknown exception.'

    Suggested code snippet:

    if step[1] is not None:
        context += '\nReturned: ' + str(step[1])
    else:
        context += '\nReturned: None'
  25. The exception handling in the loop is too generic and could mask different types of exceptions. It's better to catch specific exceptions and handle them accordingly. Additionally, the exception message is not informative. Consider logging the actual exception message.

    Existing code snippet:

    try:
        if step[1] is not None:
            context += "\nReturned: " + str(step[1])
        else:
            context += "\nReturned: None"
    except Exception as e:
        context += "\nReturned: An unknown exception."

    Suggested code snippet:

    try:
        if step[1] is not None:
            context += "\nReturned: " + str(step[1])
        else:
            context += "\nReturned: None"
    except Exception as e:
        logging.error(f'Error while processing step: {e}')
        context += f"\nReturned: Exception occurred: {e}"
  26. The method get_helpful_context uses string concatenation in a loop to build the context. This is inefficient as it creates a new string object on each iteration. Use ''.join() for better performance.

    Existing code snippet:

    return '\n----\n'.join(...)

    Suggested code snippet:

    return '\n----\n'.join(f"using the `{s[0].tool}` tool returned:\n'{s[1]}'" for s in intermediate_steps if s[1] is not None)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.