mirror of
https://github.com/csunny/DB-GPT.git
synced 2025-09-04 10:34:30 +00:00
refactor(agent): Refactor resource of agents (#1518)
This commit is contained in:
112
dbgpt/util/cache_utils.py
Normal file
112
dbgpt/util/cache_utils.py
Normal file
@@ -0,0 +1,112 @@
|
||||
"""Cache utils.
|
||||
|
||||
Adapted from https://github.com/hephex/asyncache/blob/master/asyncache/__init__.py.
|
||||
It has stopped updating since 2022. So I copied the code here for future reference.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import functools
|
||||
from contextlib import AbstractContextManager
|
||||
from typing import Any, Callable, MutableMapping, Optional, Protocol, TypeVar
|
||||
|
||||
from cachetools import keys
|
||||
|
||||
_KT = TypeVar("_KT")
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
class IdentityFunction(Protocol): # pylint: disable=too-few-public-methods
|
||||
"""
|
||||
Type for a function returning the same type as the one it received.
|
||||
"""
|
||||
|
||||
def __call__(self, __x: _T) -> _T:
|
||||
...
|
||||
|
||||
|
||||
class NullContext:
|
||||
"""A class for noop context managers."""
|
||||
|
||||
def __enter__(self):
|
||||
"""Return ``self`` upon entering the runtime context."""
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
"""Raise any exception triggered within the runtime context."""
|
||||
return None
|
||||
|
||||
async def __aenter__(self):
|
||||
"""Return ``self`` upon entering the runtime context."""
|
||||
return self
|
||||
|
||||
async def __aexit__(self, exc_type, exc_value, traceback):
|
||||
"""Raise any exception triggered within the runtime context."""
|
||||
return None
|
||||
|
||||
|
||||
def cached(
|
||||
cache: Optional[MutableMapping[_KT, Any]],
|
||||
# ignoring the mypy error to be consistent with the type used
|
||||
# in https://github.com/python/typeshed/tree/master/stubs/cachetools
|
||||
key: Callable[..., _KT] = keys.hashkey, # type:ignore
|
||||
lock: Optional["AbstractContextManager[Any]"] = None,
|
||||
) -> IdentityFunction:
|
||||
"""
|
||||
Decorator to wrap a function or a coroutine with a memoizing callable
|
||||
that saves results in a cache.
|
||||
|
||||
When ``lock`` is provided for a standard function, it's expected to
|
||||
implement ``__enter__`` and ``__exit__`` that will be used to lock
|
||||
the cache when gets updated. If it wraps a coroutine, ``lock``
|
||||
must implement ``__aenter__`` and ``__aexit__``.
|
||||
"""
|
||||
lock = lock or NullContext()
|
||||
|
||||
def decorator(func):
|
||||
if asyncio.iscoroutinefunction(func):
|
||||
|
||||
async def wrapper(*args, **kwargs):
|
||||
k = key(*args, **kwargs)
|
||||
try:
|
||||
async with lock:
|
||||
return cache[k]
|
||||
|
||||
except KeyError:
|
||||
pass # key not found
|
||||
|
||||
val = await func(*args, **kwargs)
|
||||
|
||||
try:
|
||||
async with lock:
|
||||
cache[k] = val
|
||||
|
||||
except ValueError:
|
||||
pass # val too large
|
||||
|
||||
return val
|
||||
|
||||
else:
|
||||
|
||||
def wrapper(*args, **kwargs):
|
||||
k = key(*args, **kwargs)
|
||||
try:
|
||||
with lock:
|
||||
return cache[k]
|
||||
|
||||
except KeyError:
|
||||
pass # key not found
|
||||
|
||||
val = func(*args, **kwargs)
|
||||
|
||||
try:
|
||||
with lock:
|
||||
cache[k] = val
|
||||
|
||||
except ValueError:
|
||||
pass # val too large
|
||||
|
||||
return val
|
||||
|
||||
return functools.wraps(func)(wrapper)
|
||||
|
||||
return decorator
|
@@ -1,9 +1,20 @@
|
||||
import asyncio
|
||||
import inspect
|
||||
from functools import wraps
|
||||
from typing import Any, get_args, get_origin, get_type_hints
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
List,
|
||||
Optional,
|
||||
Union,
|
||||
_UnionGenericAlias,
|
||||
get_args,
|
||||
get_origin,
|
||||
get_type_hints,
|
||||
)
|
||||
|
||||
from typeguard import check_type
|
||||
from typing_extensions import Annotated, Doc, _AnnotatedAlias
|
||||
|
||||
|
||||
def _is_typing(obj):
|
||||
@@ -119,3 +130,61 @@ def rearrange_args_by_type(func):
|
||||
return await func(*sorted_args, **sorted_kwargs)
|
||||
|
||||
return async_wrapper if asyncio.iscoroutinefunction(func) else sync_wrapper
|
||||
|
||||
|
||||
def type_to_string(obj: Any, default_type: str = "unknown") -> str:
|
||||
"""Convert a type to a string representation."""
|
||||
type_map = {
|
||||
int: "integer",
|
||||
str: "string",
|
||||
float: "float",
|
||||
bool: "boolean",
|
||||
Any: "any",
|
||||
List: "array",
|
||||
dict: "object",
|
||||
}
|
||||
# Check NoneType
|
||||
if obj is type(None):
|
||||
return "null"
|
||||
|
||||
# Get the origin of the type
|
||||
origin = getattr(obj, "__origin__", None)
|
||||
if origin:
|
||||
if _is_typing(origin) and not isinstance(obj, _UnionGenericAlias):
|
||||
obj = origin
|
||||
origin = origin.__origin__
|
||||
# Handle special cases like List[int]
|
||||
if origin is Union and hasattr(obj, "__args__"):
|
||||
subtypes = ", ".join(
|
||||
type_to_string(t) for t in obj.__args__ if t is not type(None)
|
||||
)
|
||||
# return f"Optional[{subtypes}]"
|
||||
return subtypes
|
||||
elif origin is list or origin is List:
|
||||
subtypes = ", ".join(type_to_string(t) for t in obj.__args__)
|
||||
# return f"List[{subtypes}]"
|
||||
return "array"
|
||||
elif origin in [dict, Dict]:
|
||||
key_type, value_type = (type_to_string(t) for t in obj.__args__)
|
||||
# return f"Dict[{key_type}, {value_type}]"
|
||||
return "object"
|
||||
return type_map.get(origin, default_type)
|
||||
else:
|
||||
if hasattr(obj, "__args__"):
|
||||
subtypes = ", ".join(
|
||||
type_to_string(t) for t in obj.__args__ if t is not type(None)
|
||||
)
|
||||
return subtypes
|
||||
|
||||
return type_map.get(obj, default_type)
|
||||
|
||||
|
||||
def parse_param_description(name: str, obj: Any) -> str:
|
||||
default_type_title = name.replace("_", " ").title()
|
||||
if isinstance(obj, _AnnotatedAlias):
|
||||
metadata = obj.__metadata__
|
||||
docs = [arg for arg in metadata if isinstance(arg, Doc)]
|
||||
doc_str = docs[0].documentation if docs else default_type_title
|
||||
else:
|
||||
doc_str = default_type_title
|
||||
return doc_str
|
||||
|
@@ -104,6 +104,9 @@ class BaseParameters:
|
||||
"""
|
||||
return _dict_to_command_args(asdict(self), args_prefix=args_prefix)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return asdict(self)
|
||||
|
||||
|
||||
def _get_dataclass_print_str(obj):
|
||||
class_name = obj.__class__.__name__
|
||||
|
Reference in New Issue
Block a user