Returns an OpenAI API compatible description using a functions docstring and type hints. Assumptions: * The docstring can be in various formats, e.g. REST where arguments are documented like ':param x:'. * The docstring's short description and long description will b
(self, function_: Callable)
| 56 | ) |
| 57 | |
| 58 | def analyze_function(self, function_: Callable) -> dict: |
| 59 | """ |
| 60 | Returns an OpenAI API compatible description using a functions docstring and type hints. |
| 61 | Assumptions: |
| 62 | * The docstring can be in various formats, e.g. REST where arguments are documented like ':param x:'. |
| 63 | * The docstring's short description and long description will be concatenated with a space. |
| 64 | * Newlines in the description will be replaced with space. |
| 65 | * All arguments of the function must have a type hint. Only simple types are supported. |
| 66 | * All arguments of the function must be documented in the docstring. |
| 67 | * 'self' and 'return' are neglected if appearing in arguments, type hints, or docstring. |
| 68 | """ |
| 69 | function_name = function_.__name__ |
| 70 | |
| 71 | # Directly return if an override tool description was provided. |
| 72 | if function_name in self.override_tool_descriptions: |
| 73 | if function_name in self.override_docstrings: |
| 74 | raise AssertionError( |
| 75 | f"Function '{function_name}' has an override for docstring and tool description." |
| 76 | ) |
| 77 | return self.override_tool_descriptions[function_name] |
| 78 | |
| 79 | # Get all the arguments of the function. Remove 'self'. |
| 80 | arguments = inspect.getfullargspec(function_).args |
| 81 | if "self" in arguments: |
| 82 | arguments.remove("self") |
| 83 | |
| 84 | # Get the type hints of the arguments. Remove 'return' and 'self'. |
| 85 | type_hints = typing.get_type_hints(function_) |
| 86 | type_hints.pop("return", None) |
| 87 | type_hints.pop("self", None) |
| 88 | |
| 89 | # Check that each argument has a type hint. |
| 90 | if any(argument not in type_hints for argument in arguments): |
| 91 | raise AssertionError( |
| 92 | f"Function '{function_name}' has arguments '{arguments}' but type hints only for '{type_hints}'." |
| 93 | ) |
| 94 | |
| 95 | # Get well-defined arguments. |
| 96 | well_defined_arguments = [ |
| 97 | argument |
| 98 | for argument, type_ in type_hints.items() |
| 99 | if not ( |
| 100 | typing.get_origin(type_) is Union |
| 101 | and type(None) in typing.get_args(type_) |
| 102 | ) |
| 103 | ] |
| 104 | # Get required arguments. |
| 105 | signature = inspect.signature(function_) |
| 106 | required_arguments = [ |
| 107 | arg |
| 108 | for arg in well_defined_arguments |
| 109 | if signature.parameters.get(arg).default is inspect.Parameter.empty |
| 110 | ] |
| 111 | # Convert type hints to basic types. |
| 112 | type_hints_basic = { |
| 113 | argument: ( |
| 114 | type_ |
| 115 | if argument in well_defined_arguments |
no outgoing calls
no test coverage detected