Files
dify/api/services/dify_builder/agent/resources.py
T

87 lines
2.7 KiB
Python

"""Read-only tenant resource inventory for Dify Builder cognition/grounding.
One entry point -- list_tenant_resources -- returns the tenant's configured
models, datasets, and tools normalized to id+label. Each source degrades to
an empty list on failure so a missing provider never breaks the advance.
"""
import logging
from dataclasses import dataclass
from typing import Any
from sqlalchemy import select
from sqlalchemy.orm import Session
from core.workflow.generator.tool_catalogue import build_tool_catalogue
from extensions.ext_database import db
from models.dataset import Dataset
from services.model_provider_service import ModelProviderService
logger = logging.getLogger(__name__)
@dataclass(frozen=True)
class ResourceRef:
id: str
label: str
meta: str = ""
readiness: str = "ready"
@dataclass(frozen=True)
class TenantResources:
models: list[ResourceRef]
datasets: list[ResourceRef]
tools: list[ResourceRef]
def _list_models(tenant_id: str) -> list[Any]:
return ModelProviderService().get_models_by_model_type(tenant_id=tenant_id, model_type="llm")
def _list_datasets(tenant_id: str) -> list[Any]:
with Session(db.engine) as session:
return list(session.scalars(select(Dataset).where(Dataset.tenant_id == tenant_id)).all())
def _list_tools(tenant_id: str) -> list[dict]:
return list(build_tool_catalogue(tenant_id))
def _safe(build, source: str) -> list:
try:
return build()
except Exception: # a missing/mis-configured source degrades to empty, never raises
logger.warning(
"Dify Builder: resource source %r failed for the current tenant; treating as empty",
source,
exc_info=True,
)
return []
def list_tenant_resources(tenant_id: str) -> TenantResources:
def build_models():
models: list[ResourceRef] = []
for prov in _list_models(tenant_id):
for m in getattr(prov, "models", []):
name = getattr(m, "model", "")
model_id = f"{prov.provider}/{name}"
models.append(ResourceRef(id=model_id, label=model_id))
return models
def build_datasets():
return [ResourceRef(id=str(d.id), label=str(d.name)) for d in _list_datasets(tenant_id)]
def build_tools():
return [
ResourceRef(id=f"{t['provider_name']}/{t['tool_name']}", label=str(t.get("tool_label") or t["tool_name"]),
meta=str(t.get("description") or ""))
for t in _list_tools(tenant_id)
]
models = _safe(build_models, "models")
datasets = _safe(build_datasets, "datasets")
tools = _safe(build_tools, "tools")
return TenantResources(models=models, datasets=datasets, tools=tools)