Consejos para Desarrollar Plugins de Dify con Cursor

Usted es un desarrollador senior que me puede ayudar con el desarrollo de Dify Plugin Tool, que es un AI Agent Tool que puede ser usado en AI Agent Development Tool, Dify. Usted va a seguir las siguientes instrucciones para ayudarme a construir un Plugin Tool llamado { }. El autor de esta herramienta es { }. El autor de esta herramienta es { }. Esta Herramienta debe tener la funcionalidad de { }. Asegúrese de que está editando sobre la carpeta del proyecto existente: { } y la estructura del archivo. Lo más importante, la sangría del archivo yaml y la estructura del archivo yaml. Lo más importante es que la sangría y el formato del archivo yaml sigan estrictamente los ejemplos del archivo yaml. Una vez que la herramienta plugin esté lista, configure venv e instale todos los requisitos del plugin. Una vez que la herramienta plugin esté lista, configura venv e instala todos los requisitos en el directorio del plugin. Sólo debes cambiar el archivo que las instrucciones te indican que cambies. No cambies nada más, por ejemplo el archivo env.example .
Antes de aplicar nada, quiero que {leas la documentación de la API de acceso de la herramienta}/{comprendas cuál es la funcionalidad de la herramienta, cuál es la entrada de la herramienta, qué funcionalidad tiene, y qué salida tomamos}.
El andamiaje de Dify Plugin Tool se muestra a continuación, y usted debe seguir las siguientes instrucciones para ayudarme a construir la herramienta.
your_plugin/ ├── _assets/ # Directorio para los activos visuales utilizados en los listados de marketplace │ └── icon.svg # Icono del plugin mostrado en la UI de Dify marketplace UI │ ├── provider/ # Configuración y validación de la autenticación │ ├── your_plugin.py # Clase que hereda de ToolProvider; valida las credenciales │ ├── your_plugin.py # Clase que hereda de ToolProvider. valida las credenciales │ └── your_plugin.yaml # Configura los campos, etiquetas y texto de ayuda de auth UI │ ├── tools/ # Archivos de implementación de herramientas │ ├── your_plugin.py your_plugin.py # Clase que hereda de Tool; implementa la funcionalidad de la API │ └── your_plugin.yaml # Define los parámetros de la herramienta, descripciones. │ ├── .diftyignore # Enumera los archivos que deben excluirse al publicar en el marketplace │ ├── .env.example # Plantilla para las variables de entorno necesarias para las pruebas │ # Contiene el marcador de posición REMOTE_INSTALL_KEY │ ├── .gitignore # Archivo estándar de Git ignore para el control de versiones │ ├── [ GUIDE.md]() # Instrucciones de uso detalladas que se muestran a los usuarios en marketplace │ ├── [main.py]() # Punto de entrada para pruebas locales mediante python -m main test │ # Generalmente no debería modificarse │ ├── manifest.yaml # Metadatos básicos para el listado de marketplace: │ # - Número de versión │ # - Compatibilidad info │ # - Capacidades del plugin │ # - Categorización del mercado │ ├── [PRIVACY.md]() # Política de privacidad mostrada en el mercado │ ├── [README .md]() # Documentación general y visión general para desarrolladores │ └── requirements.txt # Dependencias de paquetes Python requeridas por el plugin.
1. Cómo editar manifest.yaml
Usted tiene la tarea de crear el archivo manifest.yaml para un plugin de Dify. Este archivo es el archivo de configuración central que describe todo su plugin para el Mercado de Dify. Este archivo es el archivo de configuración central que describe todo su plugin para el Mercado de Dify. Te guiaré a través de la creación de este archivo, explicando qué partes afectan la apariencia de su plugin en el Mercado.
Fichero Finalidad
El archivo manifest.yaml sirve como archivo de configuración principal para su plugin, definiendo.
Información básica sobre los plugins mostrada en el Mercado
Versión y recursos necesarios
Permisos que necesita su plugin
Referencias a sus proveedores de herramientas
Ejemplo de aplicación (Dropbox)
Este es el aspecto del archivo manifest.yaml para una herramienta de Dropbox.
versión: 0.0.1
tipo: plugin
autor: langgenius
nombre: dropbox
etiqueta.
en_US: Dropbox
ja_JP: Dropbox
zh_Hans: Dropbox
pt_BR: Dropbox
zh_Hant: Dropbox
descripción.
es_US: Interactúa con los archivos y carpetas de Dropbox. Permite listar, buscar, subir, descargar y gestionar archivos.
ja_JP: Dropbox のファイルとフォルダ を操作します。 Es posible la lista de archivos, la búsqueda, la app, la descarga y la gestión.
zh_Hans: Interactúa con archivos y carpetas de Dropbox. Permite listar, buscar, cargar, descargar y gestionar archivos.
pt_BR: Interactúa con archivos y carpetas de Dropbox. Permite listar, buscar, cargar, descargar y gestionar archivos.
zh_Hant: Interactúa con archivos y carpetas de Dropbox. Lista, buscar, cargar, descargar y gestionar archivos.
icono: icon.svg
recurso.
memoria: 268435456
permiso.
herramienta.
activado: true
modelo.
activado: true
llm: true
text_embedding: false
rerank: false
tts: falso
speech2text: false
moderación: false
almacenamiento.
activado: true
tamaño: 1048576
plugins.
herramientas.
- proveedor/dropbox.yaml
meta.
versión: 0.0.1
arco.
- amd64
- brazo64
corredor.
idioma: python
versión: "3.12"
punto de entrada: main
created_at: 2025-04-03T17:41:08.159756+08:00
privacidad: PRIVACY.md
Componentes clave que afectan a la exposición en el mercado
Información básica (mostrada en el listado de plugins).
version: Número de versión de su plugin
autor: el nombre de su organización aparece en el Mercado
name: Nombre interno de su plugin
label: Nombre para mostrar en diferentes idiomas
created_at: Hora de creación en formato RFC3339 (debe ser en el pasado)
icon: Ruta al icono de su plugin
descripción: descripción completa en varios idiomas
tags: Categorías para tu plugin. Sólo puedes establecer una etiqueta a la vez. (Ahora las etiquetas sólo tienen búsqueda', 'imagen', 'vídeos', 'tiempo', 'finanzas', 'diseño', ' travel', 'social', 'news', 'medical', 'productivity', 'education', 'business', 'entertainment', 'utilities' or 'other')
Requisitos de recursos (se muestran en la sección de requisitos).
resource.memory: Uso máximo de memoria en bytes (por ejemplo, 1048576 = 1MB)
resource.permission: Permisos necesarios para su plugin
Referencias de plugins.
plugins.tools: ruta a los archivos YAML del proveedor
Impacto en el mercado
Si observa la captura de pantalla de Marketplace que nos ha proporcionado, podrá ver cómo aparecen estos campos.
El nombre del plugin, el icono y la descripción aparecen en la parte superior
El nombre del autor y el número de versión aparecen debajo de la descripción
Las etiquetas aparecen en la sección "TAGS
Los requisitos de memoria se muestran en la sección "REQUISITOS".
Notas importantes
La mayoría de los campos pueden dejarse como se configuraron inicialmente en la plantilla, especialmente.
tipo: Mantener como "plugin"
meta sección: Mantener los valores por defecto
resource.permission: Sólo cambiar si su plugin necesita permisos específicos
Campos que debe personalizar.
version: Número de versión de su plugin
autor: Nombre de su organización
name: Un identificador único para su plugin
label: El nombre para mostrar en diferentes idiomas
descripción: Una descripción clara de lo que hace su plugin
tags: Categorías relevantes para su plugin
plugins.tools: ruta a los archivos YAML del proveedor
Para crear su propio archivo manifest.yaml, comience con la plantilla y personalice los campos que afectan a la forma en que su plugin aparece en el Marketplace. La clave es proporcionar información clara y concisa que ayude a los usuarios a entender lo que hace tu plugin. Sin embargo, con todo esto dicho, siempre debes dejar el archivo tal cual, ya que todo se configura durante la inicialización.
2. Cómo editar provider/your_plugin.yaml
Usted tiene la tarea de crear el archivo YAML de configuración del proveedor para un plugin de Dify. Este archivo define las credenciales requeridas para su servicio y la forma en la que el proveedor de Dify lo utilizará. Te guiaré a través de la creación de este archivo paso a paso, utilizando Google Search como ejemplo.
Fichero Finalidad
El archivo YAML del proveedor (your_plugin.yaml) define.
Qué credenciales deben proporcionar los usuarios para utilizar su servicio
Cómo se recogen estas credenciales y se muestran en la interfaz de usuario
Qué herramientas incluye su plugin
El archivo Python que valida estas credenciales
Componentes necesarios
sección identity: metadatos básicos de su plugin (obligatorio, pero no afectará a la apariencia de Marketplace)
sección credentials_for_provider: define qué credenciales de autenticación deben proporcionar los usuarios.
sección de herramientas: enumera los archivos de configuración de herramientas que se incluyen
sección extra: Especifica el archivo Python utilizado para la validación de credenciales
Ejemplo de aplicación
Este es el aspecto del archivo YAML del proveedor para la herramienta Dropbox.
identidad.
autor: lcandy
nombre: dropbox
etiqueta.
en_US: Dropbox
zh_Hans: Dropbox
pt_BR: Dropbox
ja_JP: Dropbox
zh_Hant: Dropbox
descripción.
es_US: Interactuar con archivos y carpetas de Dropbox
zh_Hans: Interacción con archivos y carpetas de Dropbox
pt_BR: Interaja com arquivos e pastas do Dropbox
ja_jp: Dropbox のファイルとフォルダを操作します
zh_Hant: Interacción con archivos y carpetas de Dropbox
icono: icon.svg
credenciales_para_el_proveedor.
access_token.
tipo: secreto-entrada
obligatorio: true
etiqueta.
es_US: Acceso Ficha
zh_Hans: código de acceso
pt_BR: Token de Acesso
ja_jp: fogonero acústico
zh_Hant: Acceso al cetro
marcador de posición.
en_US: Introduce tu token de acceso a Dropbox
zh_Hans: ¡Introduce tu token de acceso a Dropbox!
pt_BR: Por favor, inserta tu token de acceso a Dropbox
ja_jp: Dropbox アクセストークンを入力してください
zh_Hant: Por favor, introduce tu clave de acceso a Dropbox.
Ayuda.
es_US: Obtén tu token de acceso de la Consola de la aplicación de Dropbox
zh_Hans: Obtención del token de acceso desde la consola de la aplicación de Dropbox
pt_BR: Obtén tu token de acceso en la Consola de Aplicaciones de Dropbox
ja_JP: Dropbox アプリコンソールからアクセストークンを取得してください
zh_Hant: Obtén tu stick de acceso desde la consola de la aplicación de Dropbox.
url.
herramientas.
- tools/list_files.yaml
- tools/arch_files.yaml
- herramientas/cargar_archivo.yaml
- tools/archivo_descarga.yaml
- tools/create_folder.yaml
- tools/borrar_archivo.yaml
extra.
python.
fuente: provider/dropbox.py
Puntos clave
Sección Identidad: Aunque no afecta al Marketplace, sigue siendo necesaria en la estructura del archivo. Incluye información básica como nombre, autor y descripción. Las etiquetas deben heredar del archivo manifest.yaml.
Sección de Credenciales.
Cada credencial necesita un identificador único (como el token de acceso a Dropbox)
opciones de tipo.
secret-input: Para información sensible que será encriptada
text-input: Para información de texto normal
select: Para la selección desplegable
boolean: Para interruptores basculantes
tool-selector: Para objetos de configuración de herramientas
Incluir obligatorio: true/false para indicar si la credencial es obligatoria
Proporcionar etiquetas, marcadores de posición y texto de ayuda fáciles de usar en diferentes idiomas.
El campo url enlaza con la documentación para obtener las credenciales
Sección Herramientas.
Lista los archivos YAML de cada herramienta de su plugin
Las rutas deben ser relativas a la raíz del plugin
Sección Extra.
Especifica el archivo Python que valida las credenciales
Este archivo debe coincidir con el creado en su "provider/your_plugin.py".
Creación del archivo YAML
Para adaptarlo a su propio servicio.
Modifique la sección de identidad con la información básica de su plugin
Defina qué credenciales requiere su servicio en la sección credentials_for_provider
Enumere sus archivos YAML de herramientas en la sección de herramientas
Especifique su archivo de validación de Python en la sección extra
Recuerde que este archivo YAML funciona junto con su archivo de validación Python, que utilizará estas credenciales para autenticarse con su servicio.
3. Cómo editar provider/your_plugin.py
Usted tiene la tarea de crear el archivo de autenticación del proveedor para un plugin de Dify. Este archivo validará las credenciales necesarias para acceder a una API de terceros. Te guiaré a través de la creación de este archivo, utilizando la integración de Google Search API como ejemplo.
Fichero Finalidad
El archivo Python proveedor (provider_name.py) sirve como el módulo de pruebas de autenticación para su plugin de Dify. Su responsabilidad principal es probar si las credenciales proporcionadas por los usuarios son válidas haciendo una simple llamada a la API del servicio.
Componentes necesarios
Su clase de proveedor debe heredar de dify_plugin.
Debe implementar el método _validate_credentials
Debe utilizar ToolProviderCredentialValidationError para la gestión de errores
Cómo funciona
El flujo de autenticación sigue estos pasos.
El usuario introduce sus credenciales en la interfaz de usuario de Dify
Dify pasa estas credenciales a su método _validate_credentials
Su código intenta una simple llamada a la API utilizando las credenciales proporcionadas
Si tiene éxito, la autenticación es válida; si no, se produce un error
Ejemplo de aplicación
Así es como se implementaría un archivo de proveedor para la herramienta Dropbox
from typing import Cualquier

from dify_plugin import ToolProvider
from dify_plugin.errors.tool.import ToolProviderCredentialValidationError
importar dropbox
from dropbox.exceptions import AuthError

from dropbox_utils import DropboxUtils

clase DropboxProvider(ToolProvider).
def _validate_credentials(self, credentials: dict[str, Any]) -> None.
Inténtalo.
# Comprobar si se proporciona access_token en las credenciales
if "access_token" not in credentials or not credentials.get("access_token"):.
raise ToolProviderCredentialValidationError("Se requiere token de acceso a Dropbox.")

# Intenta autenticarte con Dropbox utilizando el token de acceso
Inténtalo.
# Utilice la función de utilidad para obtener un cliente
DropboxUtils.get_client(credentials.get("access_token"))
excepto AuthError como e.
raise ToolProviderCredentialValidationError(f "Token de acceso a Dropbox no válido: {str(e)}")
excepto Excepción como e.
raise ToolProviderCredentialValidationError(f "Error al conectar con Dropbox: {str(e)}")

excepto Excepción como e.
raise ToolProviderCredentialValidationError(str(e))
Puntos clave
Utilice siempre la clase de herramientas: El proveedor no realiza llamadas a la API directamente, sino que utiliza la clase de herramientas a través del método from_credentials.
Utilice una consulta de prueba mínima: Haga que su prueba de validación sea sencilla, lo suficiente para confirmar que las credenciales funcionan.
Manejo apropiado de errores: Siempre envuelva su validación en un bloque try/except y convierta cualquier excepción al estándar ToolProviderCredentialValidationError.
Diccionario genérico de credenciales: El parámetro de credenciales contiene todos los parámetros de autenticación definidos en su archivo provider_name.yaml.
Manejo del generador: Observe la sintaxis for _ in ... utilizada para manejar el generador devuelto por el método invocar.
4. Cómo editar tools/your_plugin.yaml
Usted tiene la tarea de crear el archivo YAML de configuración de la herramienta para un plugin de Dify. Este archivo define cómo aparece su herramienta en la interfaz de Dify, qué parámetros acepta y cómo se presentan estos parámetros tanto a los usuarios como al agente de IA. parámetros que acepta, y cómo estos parámetros se presentan tanto a los usuarios como al agente de IA. Te guiaré a través de la creación de este archivo, utilizando la búsqueda de Google como ejemplo. Search como ejemplo.
Esquema Yaml de tools/your_plugin.yaml.
importar base64
importar contextlib
importar uuid
from colecciones.abc import Mapeo
from enum import Enum, StrEnum
from typing import Cualquiera, Opcional, Unión

from pydantic import (
ModeloBase.
Campo.
serializador_campo.
validador_campo.
validador_modelo,
)

from dify_plugin.core.utils.yaml_loader import load_yaml_file
from dify_plugin.entities import I18nObject
from dify_plugin.entities.model.message.import PromptMessageTool

clase LogMetadata(str, Enum).
STARTED_AT = "started_at"
FINISHED_AT = "finished_at"
ELAPSED_TIME = "tiempo_transcurrido"
PRECIO_TOTAL = "precio_total"
TOTAL_TOKENS = "total_tokens"
proveedor = "proveedor"
MONEDA = "moneda"

clase CommonParameterType(Enum).
SECRET_INPUT = "entrada secreta"
TEXT_INPUT = "texto-entrada"
SELECT = "seleccionar"
STRING = "cadena"
NÚMERO = "número"
ARCHIVO = "archivo"
ARCHIVOS = "archivos"
BOOLEAN = "booleano"
APP_SELECTOR = "app-selector"
SELECTOR_MODELO = "selector-modelo"
# TOOL_SELECTOR = "herramienta-selector"
TOOLS_SELECTOR = "array[tools]"

clase AppSelectorScope(Enum).
ALL = "todos"
CHAT = "chat"
FLUJO DE TRABAJO = "flujo de trabajo"
COMPLETION = "finalización"

clase ModelConfigScope(Enum).
LLM = "llm"
TEXT_EMBEDDING = "incrustación de texto"
RERANK = "rerank"
TTS = "tts"
SPEECH2TEXT = "speech2text"
MODERACIÓN = "moderación"
VISIÓN = "visión"

clase ToolSelectorScope(Enum).
ALL = "todos"
PLUGIN = "plugin"
API = "api"
WORKFLOW = "flujo de trabajo"

clase ToolRuntime(BaseModel).
credentials: dict[str, Any]user_id: Optional[str]session_id: Optional[str]

clase ToolInvokeMessage(BaseModel).
clase TextMessage(BaseModel).
texto: str

def to_dict(self).
return {"texto": auto.texto}

clase JsonMessage(BaseModel).
json_object: dict

def to_dict(self).
return {"objeto_json": self.objeto_json}

clase BlobMessage(BaseModel).
blob: bytes

clase BlobChunkMessage(BaseModel).
id: str = Campo(... , description="Id de la mancha")
secuencia: int = Campo(... , description="La secuencia del trozo")
longitud_total: int = Field(... , description="Longitud total de la mancha")
blob: bytes = Campo(... , description="Los datos blob del chunk")
end: bool = Campo(... , description="Si el trozo es el último trozo")

clase MensajeVariable(ModeloBase).
nombre_variable: str = Campo(
...,
description="El nombre de la variable, sólo admite variables de nivel raíz".
)
valor_variable: Any = Campo(... , description="Valor de la variable")
stream: bool = Field(por defecto=False, descripción="Si la variable se transmite en flujo")

@model_validator(mode="before")
@classmethod
def validar_variable_valor_y_flujo(cls, valores).
# omitir validación si values no es un dict
si no isinstance(valores, dict):: si no isinstance(valores, dict): si no isinstance(valores, dict).
valores de retorno

si values.get("flujo") y no isinstance(values.get("valor_variable"), str).
raise ValueError("Cuando 'stream' es True, 'variable_value' debe ser una cadena.")
valores de retorno

clase LogMessage(BaseModel).
clase LogStatus(Enum).
START = "inicio"
ERROR = "error"
SUCCESS = "éxito"

id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="El id del registro")
label: str = Campo(... , description="La etiqueta del registro")
parent_id: Optional[str] = Field(por defecto=None, descripción="Dejar vacío para el registro raíz")
error: Optional[str] = Field(por defecto=None, descripción="El mensaje de error")
estado: LogStatus = Field(... , description="Estado del registro")
datos: Mapeo[str, Cualquiera] = Campo(... , description="Datos de registro detallados")
metadata: Optional[Mapping[LogMetadata, Any]] = Field(default=None, description="Los metadatos del registro")

clase MessageType(Enum).
TEXTO = "texto"
ARCHIVO = "archivo"
BLOB = "blob"
JSON = "json"
LINK = "enlace"
IMAGEN = "imagen"
IMAGE_LINK = "enlace_de_imagen"
VARIABLE = "variable"
BLOB_CHUNK = "blob_chunk"
LOG = "log"

tipo: MessageType
# TODO: pydantic validará y construirá el mensaje uno a uno, hasta que encuentre un tipo correcto
# necesitamos optimizar el proceso de construcción
mensaje: TextMessage | JsonMessage | VariableMessage | BlobMessage | BlobChunkMessage | LogMessage | None
meta: Opcional[dict] = Ninguno

@field_validator("mensaje", mode="antes")
@classmethod
def decode_blob_message(cls, v).
si isinstance(v, dict) y "blob" en v.
con contextlib.suppress(Exception).
v["blob"] = base64.b64decode(v["blob"])
devolver v

@field_serializer("mensaje")
def serializar_mensaje(self, v).
if isinstance(v, self.BlobMessage)::
return {"blob": base64.b64encode(v.blob).decode("utf-8")}
elif isinstance(v, self.BlobChunkMessage)::
devolver {
"id": v.id,
"secuencia": v.secuencia,
"longitud_total": v.longitud_total,
"blob": base64.b64encode(v.blob).decode("utf-8"),
"end": v.end,
}
devolver v

clase ToolIdentity(BaseModel).
autor: str = Field(... , description="El autor de la herramienta")
nombre: str = Campo(... , description="Nombre de la herramienta")
label: I18nObject = Campo(... , description="La etiqueta de la herramienta")

clase ToolParameterOption(BaseModel).
valor: str = Campo(... , description="El valor de la opción")
label: I18nObject = Campo(... , description="Etiqueta de la opción")

@field_validator("valor", mode="antes")
@classmethod
def transformar_id_a_str(cls, valor) -> str.
si no isinstance(valor, str): si no isinstance(valor, str).
devolver str(valor)
si no.
valor de retorno

clase ParameterAutoGenerate(BaseModel).
clase Tipo(StrEnum).
PROMPT_INSTRUCTION = "prompt_instruction"

tipo: Tipo

clase ParameterTemplate(BaseModel).
enabled: bool = Campo(... , description="Si el parámetro está habilitado para jinja")

clase ToolParameter(BaseModel).
clase ToolParameterType(str, Enum).
STRING = CommonParameterType.STRING.value
NUMBER = CommonParameterType.NUMBER.value
BOOLEAN = CommonParameterType.BOOLEAN.value
SELECT = CommonParameterType.SELECT.value
SECRET_INPUT = CommonParameterType.SECRET_INPUT.value
FILE = CommonParameterType.FILE.value
FILES = CommonParameterType.FILES.value
MODEL_SELECTOR = CommonParameterType.MODEL_SELECTOR.value
APP_SELECTOR = CommonParameterType.APP_SELECTOR.value
# TOOL_SELECTOR = CommonParameterType.TOOL_SELECTOR.value

clase ToolParameterForm(Enum).
SCHEMA = "schema" # debe establecerse al añadir la herramienta
FORM = "form" # debe establecerse antes de invocar la herramienta.
LLM = "llm" # será fijado por LLM

nombre: str = Campo(... , description="El nombre del parámetro")
label: I18nObject = Campo(... , description="La etiqueta presentada al usuario")
human_description: I18nObjeto = Campo(... , description="La descripción presentada al usuario")
tipo: ToolParameterType = Field(... , description="Tipo de parámetro")
auto_generate: Opcional[ParameterAutoGenerate] = Campo(
default=None, description="La autogeneración del parámetro"
)
template: Optional[ParameterTemplate] = Field(por defecto=None, descripción="La plantilla del parámetro")
ámbito: str | Ninguno = Ninguno
form: ToolParameterForm = Field(... , description="La forma del parámetro, schema/form/llm")
llm_description: Opcional[str] = Ninguno
requerido: Opcional[bool] = False
por defecto: Optional[Union[int, float, str]] = None
min: Opcional[Unión[float, int]] = Ninguno
max: Opcional[Unión[float, int]] = Ninguno
precisión: Opcional[int] = Ninguno
options: Optional[list[ToolParameterOption]] = None

clase ToolDescription(BaseModel).
humano: I18nObjeto = Campo(... , description="La descripción presentada al usuario")
llm: str = Campo(... , description="La descripción presentada al LLM")

clase ToolConfigurationExtra(BaseModel).
clase Python(BaseModel).
fuente: str

python: Python

clase ToolConfiguration(BaseModel).
identidad: ToolIdentity
parameters: list[ToolParameter] = Field(default=[], description="Los parámetros de la herramienta")
descripción: ToolDescription
extra: HerramientaConfiguraciónExtra
has_runtime_parameters: bool = Field(por defecto=False, descripción="Si la herramienta tiene parámetros de tiempo de ejecución")
output_schema: Optional[Mapping[str, Any]] = None

clase ToolLabelEnum(Enum).
BUSCAR = "buscar"
IMAGEN = "imagen"
VIDEOS = "vídeos"
WEATHER = "tiempo"
FINANCE = "finanzas"
DISEÑO = "diseño"
VIAJE = "viaje"
SOCIAL = "social"
NEWS = "noticias"
MÉDICO = "médico"
PRODUCTIVIDAD = "productividad"
EDUCACIÓN = "educación"
BUSINESS = "negocio"
ENTRETENIMIENTO = "entretenimiento"
UTILIDADES = "utilidades"
OTRO = "otro"

clase ToolCredentialsOption(BaseModel).
valor: str = Campo(... , description="El valor de la opción")
label: I18nObject = Campo(... , description="Etiqueta de la opción")

clase ProviderConfig(BaseModel).
clase Config(Enum).
SECRET_INPUT = CommonParameterType.SECRET_INPUT.value
TEXT_INPUT = CommonParameterType.TEXT_INPUT.value
SELECT = CommonParameterType.SELECT.value
BOOLEAN = CommonParameterType.BOOLEAN.value
MODEL_SELECTOR = CommonParameterType.MODEL_SELECTOR.value
APP_SELECTOR = CommonParameterType.APP_SELECTOR.value
# TOOL_SELECTOR = CommonParameterType.TOOL_SELECTOR.value
TOOLS_SELECTOR = CommonParameterType.TOOLS_SELECTOR.value

@classmethod
def valor_de(cls, valor: str) -> "ProviderConfig.
"""
Obtener el valor del modo dado.

:param valor: modo valor
:return: modo
"""
para mode en cls.
si modo.valor == valor.
modo de retorno
raise ValueError(f "valor de modo no válido {valor}")

nombre: str = Campo(... , description="Nombre de las credenciales")
tipo: Config = Field(..., description="El tipo de las credenciales") , description="Tipo de credenciales")
ámbito: str | Ninguno = Ninguno
obligatorio: bool = False
por defecto: Optional[Union[int, float, str]] = None
options: Optional[list[ToolCredentialsOption]] = None
etiqueta: I18nObject
ayuda: Optional[I18nObject] = None
url: Opcional[str] = Ninguno
marcador de posición: Optional[I18nObject] = None

clase ToolProviderIdentity(BaseModel).
autor: str = Field(... , description="El autor de la herramienta")
nombre: str = Campo(... , description="Nombre de la herramienta")
descripción: I18nObject = Field(... , description="Descripción de la herramienta")
icono: str = Campo(... , description="El icono de la herramienta")
label: I18nObject = Campo(... , description="La etiqueta de la herramienta")
tags: list[ToolLabelEnum] = Field(
por defecto=[],
description="Las etiquetas de la herramienta".
)

clase ToolProviderConfigurationExtra(BaseModel).
clase Python(BaseModel).
fuente: str

python: Python

clase ToolProviderConfiguration(BaseModel).
identidad: ToolProviderIdentity
esquema_credenciales: lista[ProviderConfig] = Field(
default_factory=lista,
alias="credenciales_para_proveedor",
description="Esquema de credenciales del proveedor de la herramienta".
)
tools: list[ToolConfiguration] = Field(default=[], description="Las herramientas del proveedor de herramientas")
extra: ToolProviderConfigurationExtra

@model_validator(mode="before")
@classmethod
def validar_esquema_credenciales(cls, datos: dict) -> dict.
credenciales_originales_para_proveedor: dict[str, dict] = data.get("credenciales_para_proveedor", {})

credenciales_para_proveedor: list[dict[str, Any]] = []for nombre, credencial in credenciales_originales_para_proveedor.items():
credencial["nombre"] = nombre
credentials_for_provider.append(credencial)

data["credenciales_para_proveedor"] = credenciales_para_proveedor
devolver datos

@field_validator("herramientas", mode="antes")
@classmethod
def validate_tools(cls, value) -> lista[ToolConfiguration].
si no isinstance(valor, lista):: si no isinstance(valor, lista): si no isinstance(valor, lista).
raise ValueError("las herramientas deberían ser una lista")

herramientas: lista[ToolConfiguration] = []

para herramienta en valor:
# leer de yaml
si no isinstance(tool, str): si no isinstance(tool, str).
raise ValueError("la ruta de la herramienta debe ser una cadena")
Inténtalo.
file = load_yaml_file(tool)
tools.append(
HerramientaConfiguración(
identity=HerramientaIdentidad(**fichero["identidad"]),
parameters=[ToolParameter(**param) for param in file.get("parámetro", []) or []],
description=Descripción de la herramienta(**fichero["descripción"]),
extra=HerramientaConfiguraciónExtra(**file.get("extra", {})),
output_schema=file.get("output_schema", None),
)
)
excepto Excepción como e.
raise ValueError(f "Error al cargar la configuración de la herramienta: {str(e)}") from e

herramientas de retorno

clase ToolProviderType(Enum).
"""
Clase Enum para el proveedor de herramientas
"""

BUILT_IN = "incorporado"
WORKFLOW = "flujo de trabajo"
API = "api"
APP = "app"
DATASET_RETRIEVAL = "conjunto de datos-recuperación"

@classmethod
def valor_de(cls, valor: str) -> "ToolProviderType".
"""
Obtener el valor del modo dado.

:param valor: modo valor
:return: modo
"""
para mode en cls.
si modo.valor == valor.
modo de retorno
raise ValueError(f "valor de modo no válido {valor}")

clase ToolSelector(BaseModel).
clase Parámetro(ModeloBase).
nombre: str = Campo(... , description="El nombre del parámetro")
tipo: ToolParameter.ToolParameterType = Field(... , description="Tipo del parámetro")
requerido: bool = Campo(... , description="Si el parámetro es obligatorio")
descripción: str = Campo(... , description="La descripción del parámetro")
por defecto: Optional[Union[int, float, str]] = None
options: Optional[list[ToolParameterOption]] = None

provider_id: str = Campo(... , description="Id del proveedor")
nombre_herramienta: str = Field(... , description="Nombre de la herramienta")
tool_description: str = Campo(... , description="Descripción de la herramienta")
tool_configuration: Asignación[str, Any] = Campo(... , description="Configuración, tipo formulario")
tool_parameters: Asignación[str, Parámetro] = Campo(... , description="Parámetros, tipo llm")

def to_prompt_message(self) -> PromptMessageTool.
"""
Convertir el selector de herramientas en una herramienta de mensajes de aviso, basada en openai llamada a funciones esquema.
"""
tool = PromptMessageTool(
name=nombre_de_la_herramienta,
description=self.descripción_herramienta,
parámetros={
"tipo": "objeto",
"propiedades": {},
"requerido": [],
},
)

para nombre, parámetro en self.tool_parameters.items()::
tool.parameters[name] = {
"tipo": parámetro.tipo.valor,
"descripción": parámetro.descripción,
}

si parámetro.requerido.
tool.parameters["required"].append(nombre)

si parámetro.opciones.
tool.parameters[name]["enum"] = [option.value for option in parameter.options]

herramienta de devolución
Fichero Finalidad
El archivo YAML de la herramienta (your_plugin.yaml) define.
Información básica sobre la identidad de su herramienta
Descripciones tanto para los humanos como para el agente de IA
Parámetros que acepta su herramienta
Cómo se presentan y recogen estos parámetros
Ejemplo de aplicación
Este es el aspecto de los archivos YAML de la herramienta para Dropbox.
ceate_folder.yaml.
identidad.
nombre: crear_carpeta
autor: lcandy
etiqueta.
es_US: Crear carpeta
zh_Hans: Creación de carpetas
pt_BR: Criar Pasta
ja_jp: Doblado
zh_Hant: Crear carpeta
descripción.
humano.
es_US: Crear una nueva carpeta en Dropbox
zh_Hans: Creación de nuevas carpetas en Dropbox
pt_BR: Crear una nueva pasta en Dropbox
ja_jp: ¡Dropbox hace una nueva versión de Frida!
zh_Hant: Creación de una nueva carpeta en Dropbox
llm: Crea una nueva carpeta en la ruta especificada en Dropbox. Devuelve información sobre la carpeta creada, incluida la ruta y el ID.
parámetros.
- nombre: ruta_carpeta
tipo: cadena
obligatorio: true
etiqueta.
es_US: Ruta de la carpeta
zh_Hans: ruta de la carpeta
pt_BR: Caminho da Pasta
ja_jp:ォルダパス
zh_Hant: ruta de la carpeta
descripción_humana.
es_US: La ruta donde se creará la carpeta en Dropbox
zh_Hans: ruta de creación de carpetas en Dropbox
pt_BR: El camino de la pasta se crea en Dropbox
ja_jp: Dropbox でフォルダを作成するパス
zh_Hant: la ruta a la carpeta que quieres crear en Dropbox
llm_description: La ruta donde se creará la carpeta en Dropbox. Debe especificarse como una ruta completa, como '/Documentos/Proyectos' o '/Fotos/ Vacaciones2023'. Las rutas distinguen entre mayúsculas y minúsculas y deben empezar por una barra oblicua.
forma: llm
extra.
python.
fuente: tools/create_folder.py
borrar_archivo.yaml.
identidad.
nombre: borrar_archivo
autor: lcandy
etiqueta.
en_US: Borrar Archivo/Carpeta
zh_Hans: Eliminar archivos/carpetas
pt_BR: Excluir Arquivo/Pasta
ja_jp: ファイル/フォルダ削除
zh_Hant: Borrar Archivo/Carpeta
descripción.
humano.
es_US: Eliminar un archivo o una carpeta de Dropbox
zh_Hans: Eliminación de archivos o carpetas de Dropbox
pt_BR: Excluir un archivo o pasta de Dropbox
ja_jp: Dropbox からファイルやフォルダを削除します
zh_Hant: Eliminar archivo o carpeta de Dropbox
llm: Elimina permanentemente un archivo o una carpeta de Dropbox en la ruta especificada. Devuelve información de confirmación sobre el elemento eliminado.
parámetros.
- nombre: file_path
tipo: cadena
obligatorio: true
etiqueta.
es_US: Ruta de archivo/carpeta
zh_Hans: ruta de archivo/carpeta
pt_BR: Caminho do Arquivo/Pasta
ja_jp:ファイル/フォルダパス
zh_Hant: ruta de archivo/carpeta
descripción_humana.
es_US: La ruta del archivo o carpeta a eliminar de Dropbox
zh_Hans: Ruta al archivo o carpeta que se va a eliminar de Dropbox
pt_BR: El camino del archivo o pasta para excluir de Dropbox
ja_jp: Dropbox から削除するファイルやフォルダのパス
zh_Hant: Ruta al archivo o carpeta que deseas eliminar de Dropbox
llm_description: La ruta del archivo o carpeta que se va a eliminar de Dropbox. Debe especificarse como una ruta completa, como '/Documents/report.txt' o '/Photos /Vacaciones2023". Las rutas distinguen entre mayúsculas y minúsculas y deben empezar por una barra diagonal. ADVERTENCIA: se trata de una eliminación permanente.
forma: llm
extra.
python.
fuente: tools/delete_file.py
descargar_archivo.py.
identidad.
nombre: descargar_archivo
autor: lcandy
etiqueta.
en_US: Descargar archivo
zh_Hans: Descargar archivo
pt_BR: Baixar Arquivo
ja_jp: ファイルダウンロード
zh_Hant: Descargar archivo
descripción.
humano.
es_US: Descargar un archivo de Dropbox
zh_Hans: Descarga de archivos de Dropbox
pt_BR: Descargar un archivo de Dropbox
ja_jp: Dropbox からファイルをダウンロードします
zh_Hant: Descarga archivos de Dropbox
llm: Descarga un archivo de Dropbox en la ruta especificada. Devuelve los metadatos del archivo y, opcionalmente, el contenido del archivo (como base64 para archivos binarios o texto para archivos de texto). texto).
parámetros.
- nombre: file_path
tipo: cadena
obligatorio: true
etiqueta.
en_US: Ruta del archivo
zh_Hans: ruta del archivo
pt_BR: Caminho do Arquivo
ja_jp: ファイルパス
zh_Hant: Rutas de archivos
descripción_humana.
es_US: La ruta del archivo a descargar de Dropbox
zh_Hans: ruta del archivo a descargar de Dropbox
pt_BR: El camino del archivo para descargar de Dropbox
ja_JP: Dropbox からダウンロードするファイルのパス
zh_Hant: la ruta del archivo que quieres descargar de Dropbox
llm_description: La ruta del archivo que se descargará de Dropbox. Debe incluir la ruta completa con el nombre del archivo y la extensión, como '/Documents/report. txt'. Las rutas distinguen entre mayúsculas y minúsculas y deben empezar por una barra oblicua.
forma: llm
- nombre: incluir_contenido
tipo: booleano
obligatorio: false
por defecto: false
etiqueta.
en_US: Incluir contenido
zh_Hans: Contenido
pt_BR: Incluir Conteúdo
ja_JP: Contenido
zh_Hant: Contiene contenido
descripción_humana.
en_US: Incluir o no el contenido del fichero en la respuesta
zh_Hans: incluir o no el contenido del fichero en la respuesta
pt_BR: Se debe incluir el contenido del archivo en la respuesta
ja_jp: El contenido de la película en los Rathponies está incluido en la película.
zh_Hant: incluir o no el contenido del archivo en la respuesta
llm_description: Establecer a true para incluir el contenido del archivo en la respuesta. Para archivos de texto pequeños, el contenido se proporcionará como texto. Para archivos binarios, el contenido se proporcionará como cadena codificada en base64. Por defecto es false.
forma: llm
extra.
python.
fuente: tools/download_file.py

dropbox.yaml.
identidad.
nombre: dropbox
autor: lcandy
etiqueta.
en_US: Dropbox
zh_Hans: Dropbox
pt_BR: Dropbox
ja_JP: Dropbox
zh_Hant: Dropbox
descripción.
humano.
en_US: Interactúa con Dropbox
zh_Hans: Interacción con Dropbox
pt_BR: Interactuar con Dropbox
ja_JP: Dropbox y conectividad
zh_Hant: Interacción con Dropbox
llm: Proporciona acceso a los servicios de Dropbox, permitiéndote interactuar con archivos y carpetas en una cuenta de Dropbox.
parámetros.
- nombre: query
tipo: cadena
obligatorio: true
etiqueta.
en_US: Cadena de consulta
zh_Hans: Declaración de consulta
pt_BR: Termo de consulta
ja_jp: Columnas de texto K'eri
zh_Hant: Declaración de consulta
descripción_humana.
en_US: Introduce tu consulta de operación de Dropbox
zh_Hans: Introduce tu consulta de operación de Dropbox
pt_BR: Digite su consulta de operación de Dropbox
ja_JP: Operación Dropbox クエリを入力してください
zh_Hant: Introduce la operación de Dropbox que deseas realizar.
llm_description: La consulta que describe la operación de Dropbox que deseas realizar.
forma: llm
extra.
python.
fuente: tools/dropbox.py
Componentes clave
Sección Identidad.
name: Nombre interno de la herramienta (debe coincidir con el nombre del archivo)
autor: quién ha creado la herramienta
label: Nombre para mostrar en diferentes idiomas
Sección Descripción.
humano: Descripción mostrada a usuarios humanos en diferentes idiomas
llm: Descripción proporcionada al agente de IA para que comprenda qué hace su herramienta y cómo utilizarla.
Sección Parámetros.
Lista de parámetros que acepta su herramienta, cada uno con.
name: Identificador del parámetro (utilizado en su código Python)
type: Tipo de datos (cadena, número, booleano, etc.)
required: si este parámetro es obligatorio
etiqueta: nombre fácil de usar en distintos idiomas
human_description: Explicación para usuarios humanos en diferentes idiomas.
llm_description: Explicación para que el agente de IA comprenda este parámetro.
forma: cómo se recoge el parámetro
llm: agente de IA extrae de las consultas de los usuarios
flujo de trabajo: El usuario debe proporcionar como una variable en la interfaz de usuario
Opcional: default: Valor por defecto para este parámetro
Sección Extra.
python.source: Ruta al archivo de implementación de Python de su herramienta.
Notas importantes
Separación de archivos.
¡¡¡¡Importante!!!! Si su herramienta tiene diferentes funcionalidades, como leer y escribir un correo electrónico, o leer o actualizar una base de datos, debe separar el archivo yaml en más de uno. El principio es que cada archivo yaml y de código son exclusivamente para cada tipo de ejecución de la herramienta. El archivo en sí sólo debe extraer parámetro que la herramienta Por ejemplo, para leer y actualizar una base de datos, debe utilizar dos archivos yaml: read_database.yaml y update_ database.yaml por separado. database.yaml por separado.
Descripciones LLM.
La descripción llm tanto de la herramienta como de los parámetros es crucial, ya que indica al agente de IA cómo utilizar la herramienta.
Aclare qué parámetros se necesitan y qué información devolverá la herramienta.
Esto ayuda al agente de IA a decidir cuándo utilizar su herramienta y cómo extraer parámetros de las consultas de los usuarios.
Configuración de parámetros.
Para cada parámetro, especifique si es obligatorio
Elija el tipo de datos adecuado
Establezca el formulario como llm si desea que la IA lo extraiga de las consultas de los usuarios
Configure el formulario como flujo de trabajo si desea que los usuarios lo proporcionen directamente
Localización.
Traducciones de etiquetas y descripciones en varios idiomas, según sea necesario.
Como mínimo, incluya inglés (en_US)
Para crear su propio archivo YAML de herramienta, adapte esta estructura a su herramienta específica, definiendo claramente qué parámetros necesita y cómo deben presentarse tanto a los humanos como al agente de IA.
5. Cómo editar tools/your_plugin.py
Usted tiene la tarea de crear el archivo de implementación de la herramienta para un plugin de Dify. Este archivo contiene la lógica real para su herramienta que hace peticiones a la API y procesa los resultados. Este archivo contiene la lógica real para su herramienta que hace peticiones a la API y procesa los resultados. Le guiaré a través de la creación de este archivo, utilizando Google Search como ejemplo.
Fichero Finalidad
El archivo Python de la herramienta (your_plugin.py) es responsable de.
Realizar solicitudes API a su servicio
Tratamiento de las respuestas
Devolución de los resultados en un formato utilizable por Dify
Componentes necesarios
Su clase de herramienta debe heredar de dify_plugin.
Debe implementar el método _invoke que devuelve un generador
Debe incluir estas importaciones esenciales.
from colecciones.abc import Generador
from typing import Cualquier
from dify_plugin import Herramienta
from dify_plugin.entities.tool.import ToolInvokeMessage
Ejemplo de aplicación
Este es el aspecto de la implementación de la herramienta para Dropbox.
ceate_folder.yaml.
from colecciones.abc import Generador
from typing import Cualquier

from dify_plugin import Herramienta
from dify_plugin.entities.tool.import ToolInvokeMessage
from dropbox.exceptions import ApiError, AuthError

from dropbox_utils import DropboxUtils

clase CreateFolderTool(Tool).
def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage, None, None].
"""
Crear una carpeta en Dropbox
"""
# Obtener parámetros
ruta_carpeta = tool_parameters.get("ruta_carpeta", "")

# Validar parámetros
si no ruta_carpeta: si no ruta_carpeta: si no ruta_carpeta.
yield self.create_text_message("Se requiere la ruta de la carpeta en Dropbox.")
devolver

# Asegúrese de que la ruta de la carpeta empieza por /
if not ruta_carpeta.startswith("/"):.
ruta_carpeta = "/" + ruta_carpeta

Inténtalo.
# Obtener token de acceso a partir de credenciales
access_token = self.runtime.credentials.get("access_token")
si no es access_token.
yield self.create_text_message("Se requiere token de acceso a Dropbox.")
devolver

# Obtener cliente Dropbox
Inténtalo.
dbx = DropboxUtils.get_client(access_token)
excepto AuthError como e.
yield self.create_text_message(f "Error de autenticación: {str(e)}")
devolver
excepto Excepción como e.
yield self.create_text_message(f "Error al conectar con Dropbox: {str(e)}")
devolver

# Crear la carpeta
Inténtalo.
result = DropboxUtils.create_folder(dbx, ruta_carpeta)

# Crear respuesta
summary = f "Carpeta '{result['nombre']}' creada con éxito en '{result['ruta']}'"
yield self.crear_mensaje_texto(resumen)
yield self.crear_mensaje_json(resultado)

except ApiError as e.
si "ruta/conflicto" en str(e).
yield self.create_text_message(f "Ya existe una carpeta en '{ruta_carpeta}'")
si no.
yield self.create_text_message(f "Error al crear carpeta: {str(e)}")
devolver

excepto Excepción como e.
yield self.create_text_message(f "Error: {str(e)}")
devolver
borrar_archivo.py
from colecciones.abc import Generador
from typing import Cualquier

from dify_plugin import Herramienta
from dify_plugin.entities.tool.import ToolInvokeMessage
from dropbox.exceptions import ApiError, AuthError

from dropbox_utils import DropboxUtils

clase DeleteFileTool(Tool).
def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage, None, None].
"""
Eliminar un archivo o una carpeta de Dropbox
"""
# Obtener parámetros
file_path = tool_parameters.get("file_path", "")

# Validar parámetros
si no ruta_archivo: si no ruta_archivo: si no ruta_archivo.
yield self.create_text_message("Se requiere la ruta del archivo o carpeta en Dropbox.")
devolver

# Asegúrese de que la ruta empieza por /
if not file_path.startswith("/"):.
ruta_archivo = "/" + ruta_archivo

Inténtalo.
# Obtener token de acceso a partir de credenciales
access_token = self.runtime.credentials.get("access_token")
si no es access_token.
yield self.create_text_message("Se requiere token de acceso a Dropbox.")
devolver

# Obtener cliente Dropbox
Inténtalo.
dbx = DropboxUtils.get_client(access_token)
excepto AuthError como e.
yield self.create_text_message(f "Error de autenticación: {str(e)}")
devolver
excepto Excepción como e.
yield self.create_text_message(f "Error al conectar con Dropbox: {str(e)}")
devolver

# Borrar el archivo o la carpeta
Inténtalo.
result = DropboxUtils.delete_file(dbx, file_path)

# Crear respuesta
summary = f"'{result['nombre']}' borrado con éxito"
yield self.crear_mensaje_texto(resumen)
yield self.crear_mensaje_json(resultado)

except ApiError as e.
if "ruta/no_encontrada" in str(e)::
yield self.create_text_message(f "Archivo o carpeta no encontrado en '{ruta_archivo}'")
si no.
yield self.create_text_message(f "Error al borrar archivo/carpeta: {str(e)}")
devolver

excepto Excepción como e.
yield self.create_text_message(f "Error: {str(e)}")
devolver
descargar_archivo.yaml.
from colecciones.abc import Generador
importar base64
from typing import Cualquier

from dify_plugin import Herramienta
from dify_plugin.entities.tool.import ToolInvokeMessage
from dropbox.exceptions import ApiError, AuthError

from dropbox_utils import DropboxUtils

clase DownloadFileTool(Tool).
def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage, None, None].
"""
Descargar un archivo de Dropbox
"""
# Obtener parámetros
file_path = tool_parameters.get("file_path", "")
include_content = tool_parameters.get("include_content", False)

# Validar parámetros
si no ruta_archivo: si no ruta_archivo: si no ruta_archivo.
yield self.create_text_message("Se requiere la ruta del archivo en Dropbox.")
devolver

# Asegúrese de que la ruta del archivo empieza por /
if not file_path.startswith("/"):.
ruta_archivo = "/" + ruta_archivo

Inténtalo.
# Obtener token de acceso a partir de credenciales
access_token = self.runtime.credentials.get("access_token")
si no es access_token.
yield self.create_text_message("Se requiere token de acceso a Dropbox.")
devolver

# Obtener cliente Dropbox
Inténtalo.
dbx = DropboxUtils.get_client(access_token)
excepto AuthError como e.
yield self.create_text_message(f "Error de autenticación: {str(e)}")
devolver
excepto Excepción como e.
yield self.create_text_message(f "Error al conectar con Dropbox: {str(e)}")
devolver

# Descargar el archivo
Inténtalo.
result = DropboxUtils.download_file(dbx, file_path)

# Crear respuesta
respuesta = {
"nombre": resultado["nombre"],
"ruta": resultado["ruta"],
"id": resultado["id"],
"tamaño": resultado["tamaño"],
"modified": result["modified"]}

# Incluir contenido si se solicita
si incluir_contenido.
# Codificar contenido binario como base64
response["content_base64"] = base64.b64encode(result["content"]).decode('utf-8')

# Intenta decodificar como texto si es lo suficientemente pequeño
if result["size"] < 1024 * 1024: # Menos de 1MB
Inténtalo.
text_content = result["content"].decode('utf-8')
response["content_text"] = text_content
excepto UnicodeDecodeError.
# No es un archivo de texto, sólo incluye base64
pase

summary = f "Archivo '{result['nombre']}' descargado correctamente"
yield self.crear_mensaje_texto(resumen)
yield self.create_json_message(response)

except ApiError as e.
yield self.create_text_message(f "Error al descargar el archivo: {str(e)}")
devolver

excepto Excepción como e.
yield self.create_text_message(f "Error: {str(e)}")
devolver
Puntos clave
Separación de archivos.
Importante: Si su herramienta tiene diferentes funcionalidades, como leer y escribir un correo electrónico, o leer o actualizar una base de datos, debe separar el archivo yaml en más archivos. El principio es que cada archivo yaml y de código son exclusivamente para cada tipo de ejecución de la herramienta. El archivo en sí sólo debe extraer los parámetros que la funcionalidad de la herramienta va a utilizar. Por ejemplo, para leer y actualizar una base de datos, debe utilizar dos archivos yaml: read_database.py y update_ database.py por separado. database.py por separado.
Importaciones obligatorias: Incluya siempre las importaciones esenciales al principio de su archivo.
Herencia de clases: Su clase de herramienta debe heredar de dify_plugin.
Extracción de parámetros.
El diccionario tool_parameters contiene todos los parámetros definidos en el archivo YAML de su herramienta.
Acceder directamente a estos parámetros mediante claves de diccionario, por ejemplo, tool_parameters["query"] Estos parámetros se extraen automáticamente de las consultas de los usuarios El agente de IA extrae automáticamente estos parámetros de las consultas de los usuarios.
Asegúrese de que gestiona todos los parámetros necesarios y de que proporciona un tratamiento de errores adecuado en caso de que falten.
Ejemplo.
query = tool_parameters["query"] # Extraer el parámetro de consultalimit = tool_parameters.get("limit", 10) # Extraer con un valor por defecto# Validación opcionalif not query: raise ValueError("El parámetro de consulta no puede estar vacío")
Acceso a las credenciales.
Accede a tus credenciales de autenticación usando self.runtime.credentials
Las claves coinciden con las definidas en el archivo YAML de su proveedor
Ejemplo: self.runtime.credentials["serpapi_api_key"] Procesamiento de respuestas: Crea un método de ayuda para extraer sólo la información relevante de las respuestas de la API. las respuestas de la API.
Devolución de resultados: Debe utilizar yield con uno de los métodos de creación de mensajes para devolver datos.
Cuando implemente su propia herramienta, asegúrese de extraer correctamente todos los parámetros que necesite del diccionario tool_parameters, y valídelos si es necesario. Los parámetros disponibles se definen en el archivo YAML de su herramienta y el agente de IA los extraerá automáticamente de las consultas de los usuarios.
6. Cómo crear PRIVACY.md y README.md
Tienes la tarea de crear la política de privacidad y los archivos readme para tu plugin de Dify. Estos archivos están escritos en formato Markdown y sirven importantes Estos archivos están escritos en formato Markdown y sirven a propósitos importantes para los usuarios y desarrolladores de su plugin.
PRIVACY.md
El archivo PRIVACY.md esboza Las prácticas de privacidad de tu plugin, incluyendo qué datos recoge y cómo los utiliza. Esta es información crítica para los usuarios preocupados por la privacidad de sus datos. Esta información es fundamental para los usuarios preocupados por la privacidad de sus datos.
Qué incluir
¡¡¡¡¡Basándonos en el texto del marcador de posición que has compartido ("!!!!! Por favor, rellena la política de privacidad del plugin"), deberías incluir.
Qué datos recopila tu plugin
Cómo se almacenan y procesan estos datos
Qué servicios de terceros se utilizan (en su caso)
Derechos de los usuarios sobre sus datos
Cuánto tiempo se conservan los datos
Información de contacto para cuestiones de privacidad
Ejemplo de estructura
# Política de privacidad

## Recogida de datos
[Describa qué datos de usuario recopila su plugin y por qué].

## Tratamiento de datos
[Explique cómo se procesan los datos recogidos].

## Servicios de terceros
[Enumere los servicios de terceros utilizados por su plugin y enlace a sus políticas de privacidad].

## Conservación de datos
[Explique durante cuánto tiempo se almacenan los datos del usuario].

## Derechos del usuario
[Explique qué derechos tienen los usuarios sobre sus datos].

## Información de contacto
[Proporcione información de contacto para consultas relacionadas con la privacidad].

Última actualización: [Fecha]README.md
El archivo README.md proporciona información esencial sobre el complemento, como qué hace, cómo se instala y cómo se utiliza. documento que consultarán la mayoría de los usuarios y desarrolladores.
Qué incluir
Basado en el ejemplo que compartiste (Jira plugin readme), debes incluir.
Nombre del plugin como título principal
Información sobre el autor
Información sobre la versión
Tipo de plugin
Descripción detallada de lo que hace el plugin
Instrucciones de instalación
Ejemplos de uso
Opciones de configuración
Información para la resolución de problemas
Ejemplo de estructura
# Nombre de su plugin

**Autor:** [Su nombre u organización]**Versión:** [Número de versión actual]**Tipo:** [Tipo de plugin]

## Descripción
[Proporcione una descripción detallada de lo que hace su plugin].

## Características
- [Característica 1]- [Característica 2]- [Característica 3]

## Instalación
[Proporcionar instrucciones de instalación paso a paso]

## Configuración
[Explique cómo configurar su plugin]

## Ejemplos de uso
[Proporcione ejemplos de cómo utilizar su plugin].

## Solución de problemas
[Enumere los problemas más comunes y sus soluciones].

## Contribuyente
[Explica cómo pueden contribuir los demás a tu plugin].

## Licencia
[Especifique la licencia bajo la que se publica su plugin]Uso de imágenes
Como usted ha mencionado, si desea incluir imágenes en cualquiera de los documentos.
Guarde las imágenes en la carpeta _assets
Haga referencia a ellos en su Markdown utilizando rutas relativas.
¡! [Descripción de la imagen](_assets/image_name.png)
Ambos archivos deben escribirse en formato Markdown (extensión .md) y colocarse en el directorio raíz del proyecto del plugin. Asegúrate de mantenerlos actualizados a medida que evolucione el plugin. Asegúrate de mantenerlos actualizados a medida que evolucione tu plugin.
Requisitos.txt
Siempre debes usar las últimas dependencias usando ~= en tu archivo txt, y el dify_plugin~=0.0.1b72 es imprescindible.

© declaración de copyright
AiPPT

Artículos relacionados

Sin comentarios

Debe iniciar sesión para participar en los comentarios.
Acceder ahora
ninguno
Sin comentarios...