深度智能体—持久化后端

      1.配置持久化后端

        在《深度智能体—智能体加强版》中说明有四种持久化后端,可以在创建智能体时使用backend参数配置使用哪一种后端。

      1.1 基于状态的持久化后端

        调用create_deep_agent时如果未指定持久化后端,则缺省使用基于状态的持久化后端,基于状态的持久化是线程级的,数据保存线程状态中。

        基于状态的持久化后端作为智能体的缓存可用于保存中间结果,可以对大量中间结果进行整理并根据需要从后端读取。

      1.2基于文件系统的持久化后端

        如下代码在创建智能体时指定使用基于文件系统的持久化后端:

from deepagents.backends import FilesystemBackend

"""

    root_dir:指定文件系统路径

    virtual_mode: 指定是否为虚拟化模式,如果为True则使用沙箱隔离

"""

agent = create_deep_agent(

    model=llm,
    backend=FilesystemBackend(root_dir=".", virtual_mode=True)
)

      1.3基于store的持久化后端

        如下代码在创建深度智能体指定基于store的持久化后端:

from langgraph.store.memory import InMemoryStore
from deepagents.backends import StoreBackend

agent = create_deep_agent(

    model=llm,
    backend=(lambda rt: StoreBackend(rt)), 
    store=InMemoryStore()
)

      1.4混合持久化后端

        如下代码在创建深度智能体指定使用混合持久化后端:

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, FilesystemBackend

#创建混合持久化后端。缺省为基于状态的后端,另外一个是基于文件系统的后端

composite_backend = lambda rt: CompositeBackend(
    default=StateBackend(rt),

    """

    基于文件系统后端通过root_dir指定具体的路径。/memories/是路由,所有以/memories

    开头的路径均指向基于文件系统的后端,非/memories开头的路径指向缺省的持久化后端

    """
    routes={
        "/memories/": FilesystemBackend(root_dir="/deepagents/myagent", virtual_mode=True),
    },
)

agent = create_deep_agent(
    model=llm,
    backend=composite_backend)

      2.自定义持久化后端

        以上四种是标准的持久化后端,还可以基于其他的存储,比如数据库创建持久化后端。自定义持久化后端时要集成BackendProtocol,并重载ls_info、read、write、edit、glob_info和grep_raw方法,其中:

        1)ls_info:至少要包含path,is_dir,size和modified

        2)read:返回从指定偏移开始的指定数量的内容,如果文件不存在,则必须返回"Error: File '/x' not found"

        3)write:针对仅允许创建的场景。如果对指定文件写,则返回WriteResult(error=...)。写成功后,WriteResult要包括path=...,如果是基于状态的持久化后端需要包括files_update={...},如果是外部持久化后端(比如数据库),则要包含files_update=None

         4)edit:同linux sed命令。替换指定字符串,可以全局替换,也可以仅仅替换第一个。

         5)glob_info:同linux find命令。返回匹配的文件列表。

        6)grep_raw:同linux grep命令。查找与指定模式匹配的行。如果正则表达式错误,则返回"Invalid regex pattern: ..."

        如下代码基于PostgresSQL构建持久化后端:

 (path text primary key, content text, created_at timestamptz, modified_at timestamptz)

from deepagents.backends.protocol import BackendProtocol, WriteResult, EditResult
from deepagents.backends.utils import FileInfo, GrepMatch

class PgBackend(BackendProtocol):

    def ls_info(self, path: str) -> list[FileInfo]:
         """

            使用 WHERE path LIKE $1 || '%'查询数据库,然后每一行构建一个FileInfo,

            返回FileInfo列表

        """

    def read(self, file_path: str, offset: int = 0, limit: int = 2000) -> str:
        """

            使用WHERE path=$1查询数据库获取content,然后根据从offset开始提取数据,

            最多2000个字符, 实现逻辑如下:

            count = min(limit, len(content))
            return content[offset:count]

        """

    def grep_raw(self, pattern: str, path: str | None = None, glob: str | None = None) -> list[GrepMatch] | str:
        """

           使用where根据glob查找符号条件的记录,然后遍历每条记录content,使用

           正则表达式查找content中与pattern模式匹配的行,每个匹配组装成一个GrepMathch,

           最后返回GrepMatch列表

        """
    def glob_info(self, pattern: str, path: str = "/") -> list[FileInfo]:
        """

            使用where从数据库查找路径以path参数开头的并且与pattern匹配的记录,

            最后返回FileInfo列表

        """

    def write(self, file_path: str, content: str) -> WriteResult:
        """

            在数据库中查询一条新的记录,或者如果已经存在则直接覆盖其中的内容。

            该方法可以仅支持增加文件信息。在返回的结果中WriteResult(path=file_path,

            files_update=None)

        """

    def edit(self, file_path: str, old_string: str, new_string: str, replace_all: bool = False) -> EditResult:

        """

            针对指定的文件,获取其content,然后用re.sub执行替换操作

          (用new_string替换old_string),再使用update用更新文件内容。

            返回结果中包含替换次数    

            replace_all如果为False则仅替换old_string第一次出现的地方,否则全文替换。        

        """
        

     3.后端过滤器

        正如在web应用中通过过滤器实现一些额外处理,比如防SQL,XSS攻击一样。也可以在可以对持久化后端做进一步封装,制作自己的过滤器,在过滤器中实现用户自己的业务规则,比如限制对某些目录的读写。

        实现后端过滤器,可以直接继承标准后端,比如StateBackend或者FileSystemBackend,也可以继承BackendProtocol。如下代码继承后者,实现对于部分路径下文件访问保护,比如仅允许读,不允许写。

from deepagents.backends.protocol import BackendProtocol, WriteResult, EditResult
from deepagents.backends.utils import FileInfo, GrepMatch

"""

    所有的读操作均直接调用实际的持久化后端,所有的写操作,需要先判断是否允许写,

    如果允许写,则调用实际的持久化后端执行写操作,否则返回错误。

"""

class PolicyWrapper(BackendProtocol):
    def __init__(self, inner: BackendProtocol, deny_prefixes: list[str] | None = None):

        #inner一般是自定义的持久化后端,比如上面的PgBckend
        self.inner = inner

        #deny_prefixes是一个目录列表。这些目录下的文件仅能读,不能写。
        self.deny_prefixes = [p if p.endswith("/") else p + "/" for p in (deny_prefixes or [])]

    def _deny(self, path: str) -> bool:
        return any(path.startswith(p) for p in self.deny_prefixes)

    def ls_info(self, path: str) -> list[FileInfo]:
        return self.inner.ls_info(path)
    def read(self, file_path: str, offset: int = 0, limit: int = 2000) -> str:
        return self.inner.read(file_path, offset=offset, limit=limit)
    def grep_raw(self, pattern: str, path: str | None = None, glob: str | None = None) -> list[GrepMatch] | str:
        return self.inner.grep_raw(pattern, path, glob)
    def glob_info(self, pattern: str, path: str = "/") -> list[FileInfo]:
        return self.inner.glob_info(pattern, path)
    def write(self, file_path: str, content: str) -> WriteResult:
        if self._deny(file_path):
            return WriteResult(error=f"Writes are not allowed under {file_path}")
        return self.inner.write(file_path, content)
    def edit(self, file_path: str, old_string: str, new_string: str, replace_all: bool = False) -> EditResult:
        if self._deny(file_path):
            return EditResult(error=f"Edits are not allowed under {file_path}")
        return self.inner.edit(file_path, old_string, new_string, replace_all)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值