Files
goose/CONTRIBUTING.md
Luke Alvoeiro dd126afa6c chore: initial commit
Co-authored-by: Lifei Zhou <lifei@squareup.com>
Co-authored-by: Mic Neale <micn@tbd.email>
Co-authored-by: Lily Delalande <ldelalande@squareup.com>
Co-authored-by: Bradley Axen <baxen@squareup.com>
Co-authored-by: Andy Lane <alane@squareup.com>
Co-authored-by: Elena Zherdeva <ezherdeva@squareup.com>
Co-authored-by: Zaki Ali <zaki@squareup.com>
Co-authored-by: Salman Mohammed <smohammed@squareup.com>
2024-08-23 16:39:04 -07:00

3.8 KiB

Contributing

We welcome Pull Requests for general contributions. If you have a larger new feature or any questions on how to develop a fix, we recommend you open an issue before starting.

Prerequisites

goose uses uv for dependency management, and formats with ruff.

We provide a shortcut to standard commands using just in our justfile.

Developing

Now that you have a local environment, you can make edits and run our tests.

uv run pytest tests -m "not integration"

or, as a shortcut,

just test

Evaluations

Given that so much of goose involves interactions with LLMs, our unit tests only go so far to confirming things work as intended.

We're currently developing a suite of evalutions, to make it easier to make improvements to goose more confidently.

In the meantime, we typically incubate any new additions that change the behavior of the goose through opt-in plugins - Toolkits, Moderators, and Providers. We welcome contributions of plugins that add new capabilities to goose. We recommend sending in several examples of the new capabilities in action with your pull request.

Additions to the developer toolkit change the core performance, and so will need to be measured carefully.

Build a Toolkit

To add a toolkit, start out with a plugin as mentioned above. In your code (which doesn't necessarily need to be in the goose package thanks to plugin metadata!), create a class that derives from Toolkit.

import os
import platform

from goose.toolkit.base import Toolkit, tool


class Demo(Toolkit):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    # Provide any additional tools as needed!
    # The docstring of the tool provides instructions to the LLM, so they are important to tune
    # you do not have to provide any tools, but any function decorated with @tool will be available
    @tool
    def authenticate(self, user: str):
        """Output an authentication code for this user

        Args:
            user (str): The username to authenticate for
        """
        # notifier supports any rich renderable https://rich.readthedocs.io/en/stable/introduction.html#quick-start
        self.notifier.log(f"[bold red]auth: {str(hash(user))}[/]")

    # Provide any system instructions for the model
    # This can be generated dynamically, and is run at startup time
    def system(self) -> str:
        print("new")
        return f"""**You must preceed your first message by using the authenticate tool for the current user**

        ```
        platform: {platform.system()}
        cwd: {os.getcwd()}
        user: {os.environ.get('USER')}
        ```
        """

To make the toolkit available, add it as a plugin. For example in a pyproject.toml

[project.entry-points."goose.toolkit"]
developer = "goose.toolkit.developer:Developer"
github = "goose.toolkit.github:Github"
# Add a line like this - the key becomes the name used in profiles
demo = "goose.toolkit.demo:Demo"

And then to setup a profile that uses it, add something to ~/.config/goose/profiles.yaml

default:
  provider: openai
  processor: gpt-4o
  accelerator: gpt-4o-mini
  moderator: passive
  toolkits:
    - name: developer
      requires: {}
demo:
  provider: openai
  processor: gpt-4o
  accelerator: gpt-4o-mini
  moderator: passive
  toolkits:
    - developer
    - demo

And now you can run goose with this new profile to use the new toolkit!

goose session start --profile demo