mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-24 02:15:24 +00:00
Add a document extractor tool with an extract_document action that converts an input artifact (PDF, docx, pptx, ...) into structured JSON by running a fixed Docling program in the sandbox (the document and parameters travel as data, so nothing in them can execute). Output is a compact payload bounded by an input size cap, a head-and-tail markdown window, and per-table caps, can be validated against a JSON schema, and is persisted as a data artifact by reference. Docling is heavy, so it stays out of the base image and ships in an opt-in sandbox image variant.
78 lines
2.7 KiB
Python
78 lines
2.7 KiB
Python
import importlib
|
|
import inspect
|
|
import os
|
|
import pkgutil
|
|
|
|
from application.agents.tools.base import Tool
|
|
|
|
|
|
class ToolManager:
|
|
def __init__(self, config):
|
|
self.config = config
|
|
self.tools = {}
|
|
self.load_tools()
|
|
|
|
def load_tools(self):
|
|
tools_dir = os.path.join(os.path.dirname(__file__))
|
|
for finder, name, ispkg in pkgutil.iter_modules([tools_dir]):
|
|
if name == "base" or name.startswith("__"):
|
|
continue
|
|
module = importlib.import_module(f"application.agents.tools.{name}")
|
|
for member_name, obj in inspect.getmembers(module, inspect.isclass):
|
|
if issubclass(obj, Tool) and obj is not Tool and not obj.internal:
|
|
tool_config = self.config.get(name, {})
|
|
self.tools[name] = obj(tool_config)
|
|
|
|
def load_tool(self, tool_name, tool_config, user_id=None):
|
|
self.config[tool_name] = tool_config
|
|
module = importlib.import_module(f"application.agents.tools.{tool_name}")
|
|
for member_name, obj in inspect.getmembers(module, inspect.isclass):
|
|
if issubclass(obj, Tool) and obj is not Tool:
|
|
if (
|
|
tool_name
|
|
in {
|
|
"mcp_tool",
|
|
"notes",
|
|
"memory",
|
|
"todo_list",
|
|
"scheduler",
|
|
"remote_device",
|
|
"code_executor",
|
|
"artifact_generator",
|
|
"document_extractor",
|
|
}
|
|
and user_id
|
|
):
|
|
return obj(tool_config, user_id)
|
|
else:
|
|
return obj(tool_config)
|
|
|
|
def execute_action(self, tool_name, action_name, user_id=None, **kwargs):
|
|
if tool_name not in self.tools:
|
|
raise ValueError(f"Tool '{tool_name}' not loaded")
|
|
if (
|
|
tool_name
|
|
in {
|
|
"mcp_tool",
|
|
"memory",
|
|
"todo_list",
|
|
"notes",
|
|
"scheduler",
|
|
"remote_device",
|
|
"code_executor",
|
|
"artifact_generator",
|
|
"document_extractor",
|
|
}
|
|
and user_id
|
|
):
|
|
tool_config = self.config.get(tool_name, {})
|
|
tool = self.load_tool(tool_name, tool_config, user_id)
|
|
return tool.execute_action(action_name, **kwargs)
|
|
return self.tools[tool_name].execute_action(action_name, **kwargs)
|
|
|
|
def get_all_actions_metadata(self):
|
|
metadata = []
|
|
for tool in self.tools.values():
|
|
metadata.extend(tool.get_actions_metadata())
|
|
return metadata
|