From da2877a1001fe70b8dfd8bfdd59566ac70792a30 Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 16 Jan 2024 22:44:47 -0500 Subject: [PATCH] Add utilities --- docs/api_reference/utilities/images.md | 1 + docs/api_reference/utilities/python.md | 1 + docs/api_reference/utilities/testing.md | 1 + mkdocs.yml | 12 ++++++--- src/marvin/utilities/context.py | 3 ++- src/marvin/utilities/python.py | 36 +++++++++++++++++++++++++ src/marvin/utilities/testing.py | 20 +++++++++++++- src/marvin/utilities/tools.py | 7 +++++ 8 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 docs/api_reference/utilities/images.md create mode 100644 docs/api_reference/utilities/python.md create mode 100644 docs/api_reference/utilities/testing.md diff --git a/docs/api_reference/utilities/images.md b/docs/api_reference/utilities/images.md new file mode 100644 index 000000000..2a1af20a7 --- /dev/null +++ b/docs/api_reference/utilities/images.md @@ -0,0 +1 @@ +::: marvin.utilities.images \ No newline at end of file diff --git a/docs/api_reference/utilities/python.md b/docs/api_reference/utilities/python.md new file mode 100644 index 000000000..95fc58de7 --- /dev/null +++ b/docs/api_reference/utilities/python.md @@ -0,0 +1 @@ +::: marvin.utilities.python \ No newline at end of file diff --git a/docs/api_reference/utilities/testing.md b/docs/api_reference/utilities/testing.md new file mode 100644 index 000000000..8b9cfbed7 --- /dev/null +++ b/docs/api_reference/utilities/testing.md @@ -0,0 +1 @@ +::: marvin.utilities.testing \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index bf07cc419..95eeb2222 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -47,7 +47,6 @@ nav: - marvin.ai.text: api_reference/ai/text.md - marvin.ai.images: api_reference/ai/images.md - marvin.ai.audio: api_reference/ai/audio.md - - Beta AI modules: - marvin.beta.vision: api_reference/beta/vision.md - marvin.beta.assistants: @@ -57,23 +56,30 @@ nav: - marvin.beta.assistants.runs: api_reference/beta/assistants/runs.md - marvin.beta.assistants.formatting: api_reference/beta/assistants/formatting.md - marvin.beta.applications: api_reference/beta/applications.md - - Object schemas: - marvin.types: api_reference/types.md - Settings: - marvin.settings: api_reference/settings.md - Utilities: - marvin.utilities.asyncio: api_reference/utilities/asyncio.md + - marvin.utilities.context: api_reference/utilities/context.md + - marvin.utilities.images: api_reference/utilities/images.md - marvin.utilities.jinja: api_reference/utilities/jinja.md - marvin.utilities.logging: api_reference/utilities/logging.md - - marvin.utilities.tools: api_reference/utilities/tools.md + - marvin.utilities.openai: api_reference/utilities/openai.md + - marvin.utilities.pydantic: api_reference/utilities/pydantic.md + - marvin.utilities.python: api_reference/utilities/python.md - marvin.utilities.strings: api_reference/utilities/strings.md + - marvin.utilities.testing: api_reference/utilities/testing.md + - marvin.utilities.tools: api_reference/utilities/tools.md + - Cookbook: - Entity deduplication: examples/deduplication.md # - GitHub Activity Digest: examples/github_digest.md - Slackbot: examples/slackbot.md - Python augmented prompts: examples/python_augmented_prompts.md - Being specific about types: examples/being_specific_about_types.md + - Community: - community/index.md - Feedback 💙: community/feedback.md diff --git a/src/marvin/utilities/context.py b/src/marvin/utilities/context.py index e34399c65..1a0d8bf88 100644 --- a/src/marvin/utilities/context.py +++ b/src/marvin/utilities/context.py @@ -6,7 +6,8 @@ class ScopedContext: - """`ScopedContext` provides a context management mechanism using `contextvars`. + """ + `ScopedContext` provides a context management mechanism using `contextvars`. This class allows setting and retrieving key-value pairs in a scoped context, which is preserved across asynchronous tasks and threads within the same context. diff --git a/src/marvin/utilities/python.py b/src/marvin/utilities/python.py index fae9a6dbd..253fa0113 100644 --- a/src/marvin/utilities/python.py +++ b/src/marvin/utilities/python.py @@ -15,6 +15,21 @@ class ParameterModel(BaseModel): class PythonFunction(BaseModel): + """ + A Pydantic model representing a Python function. + + Attributes: + function (Callable): The original function object. + signature (inspect.Signature): The signature object of the function. + name (str): The name of the function. + docstring (Optional[str]): The docstring of the function. + parameters (List[ParameterModel]): The parameters of the function. + return_annotation (Optional[Any]): The return annotation of the function. + source_code (str): The source code of the function. + bound_parameters (dict[str, Any]): The parameters of the function bound with values. + return_value (Optional[Any]): The return value of the function call. + """ + model_config = dict(arbitrary_types_allowed=True) function: Callable = Field(description="Original function object") signature: inspect.Signature = Field(description="Function signature object") @@ -44,6 +59,16 @@ def definition(self) -> str: @classmethod def from_function(cls, func: Callable, **kwargs) -> "PythonFunction": + """ + Create a PythonFunction instance from a function. + + Args: + func (Callable): The function to create a PythonFunction instance from. + **kwargs: Additional keyword arguments to set as attributes on the PythonFunction instance. + + Returns: + PythonFunction: The created PythonFunction instance. + """ name = kwargs.pop("name", func.__name__) docstring = kwargs.pop("docstring", func.__doc__) sig = inspect.signature(func) @@ -79,6 +104,17 @@ def from_function(cls, func: Callable, **kwargs) -> "PythonFunction": @classmethod def from_function_call(cls, func: Callable, *args, **kwargs) -> "PythonFunction": + """ + Create a PythonFunction instance from a function call. + + Args: + func (Callable): The function to call. + *args: Positional arguments to pass to the function call. + **kwargs: Keyword arguments to pass to the function call. + + Returns: + PythonFunction: The created PythonFunction instance, with the return value of the function call set as an attribute. + """ sig = inspect.signature(func) bound = sig.bind(*args, **kwargs) diff --git a/src/marvin/utilities/testing.py b/src/marvin/utilities/testing.py index 03602cf11..d555132fa 100644 --- a/src/marvin/utilities/testing.py +++ b/src/marvin/utilities/testing.py @@ -1,4 +1,4 @@ -"""Module for testing utlities.""" +"""Utilities for running unit tests.""" from typing import Any, Optional @@ -19,6 +19,24 @@ class Assertion(BaseModel): def assert_equal(llm_output: Any, expected: Any) -> bool: + """ + Asserts whether the LLM output meets the expected output. + + This function uses an LLM to assess whether the provided output (llm_output) + meets some expectation. It allows us to make semantic claims like "the output + is a list of first names" to make assertions about stochastic LLM outputs. + + Args: + llm_output (Any): The output from the LLM. + expected (Any): The expected output. + + Returns: + bool: True if the LLM output meets the expectation, False otherwise. + + Raises: + AssertionError: If the LLM output does not meet the expectation. + """ + result = _assert_equal(llm_output, expected) assert ( result.is_equal diff --git a/src/marvin/utilities/tools.py b/src/marvin/utilities/tools.py index a934fd38e..f55f1caa0 100644 --- a/src/marvin/utilities/tools.py +++ b/src/marvin/utilities/tools.py @@ -64,6 +64,9 @@ def generate(self, schema: Any, mode: JsonSchemaMode = "validation"): def tool_from_type(type_: U, tool_name: str = None) -> Tool[U]: + """ + Creates an OpenAI-compatible tool from a Python type. + """ annotated_metadata = getattr(type_, "__metadata__", []) if isinstance(next(iter(annotated_metadata), None), FieldInfo): metadata = next(iter(annotated_metadata)) @@ -144,6 +147,10 @@ def call_function_tool( function_arguments_json: str, return_string: bool = False, ) -> str: + """ + Helper function for calling a function tool from a list of tools, using the arguments + provided by an LLM as a JSON string. This function handles many common errors. + """ tool = next( ( tool