mirror of
https://github.com/TheR1D/shell_gpt.git
synced 2026-06-02 06:14:32 +02:00
4ea2f834cf
* Migrate to OpenAI v2 package * Remove Click direct package dependency * Minor handler improvements * Change README.md demo video * Version bump, release 1.5.0
68 lines
2.1 KiB
Python
68 lines
2.1 KiB
Python
import importlib.util
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Any, Callable, Dict, List
|
|
|
|
from pydantic import BaseModel
|
|
|
|
from .config import cfg
|
|
|
|
|
|
class Function:
|
|
def __init__(self, path: str):
|
|
module = self._read(path)
|
|
self._function = module.Function.execute
|
|
self._openai_schema = module.Function.openai_schema()
|
|
self._name = self._openai_schema["function"]["name"]
|
|
|
|
@property
|
|
def name(self) -> str:
|
|
return self._name # type: ignore
|
|
|
|
@property
|
|
def openai_schema(self) -> dict[str, Any]:
|
|
return self._openai_schema # type: ignore
|
|
|
|
@property
|
|
def execute(self) -> Callable[..., str]:
|
|
return self._function # type: ignore
|
|
|
|
@classmethod
|
|
def _read(cls, path: str) -> Any:
|
|
module_name = path.replace("/", ".").rstrip(".py")
|
|
spec = importlib.util.spec_from_file_location(module_name, path)
|
|
module = importlib.util.module_from_spec(spec) # type: ignore
|
|
sys.modules[module_name] = module
|
|
spec.loader.exec_module(module) # type: ignore
|
|
|
|
if not issubclass(module.Function, BaseModel):
|
|
raise TypeError(
|
|
f"Function {module_name} must be a subclass of pydantic.BaseModel"
|
|
)
|
|
if not hasattr(module.Function, "execute"):
|
|
raise TypeError(
|
|
f"Function {module_name} must have an 'execute' classmethod"
|
|
)
|
|
if not hasattr(module.Function, "openai_schema"):
|
|
raise TypeError(
|
|
f"Function {module_name} must have an 'openai_schema' classmethod"
|
|
)
|
|
|
|
return module
|
|
|
|
|
|
functions_folder = Path(cfg.get("OPENAI_FUNCTIONS_PATH"))
|
|
functions_folder.mkdir(parents=True, exist_ok=True)
|
|
functions = [Function(str(path)) for path in functions_folder.glob("*.py")]
|
|
|
|
|
|
def get_function(name: str) -> Callable[..., Any]:
|
|
for function in functions:
|
|
if function.name == name:
|
|
return function.execute
|
|
raise ValueError(f"Function {name} not found")
|
|
|
|
|
|
def get_openai_schemas() -> List[Dict[str, Any]]:
|
|
return [function.openai_schema for function in functions]
|