dify_plugin 0.6.2__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/PKG-INFO +2 -2
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/entities/invocation.py +2 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/entities/plugin/request.py +23 -2
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/plugin_executor.py +28 -0
- dify_plugin-0.7.0/dify_plugin/entities/model/rerank.py +57 -0
- dify_plugin-0.7.0/dify_plugin/entities/model/text_embedding.py +71 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/tool.py +0 -9
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/openai_compatible/llm.py +3 -1
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/rerank_model.py +48 -1
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/text_embedding_model.py +44 -1
- dify_plugin-0.7.0/dify_plugin/invocations/model/rerank.py +49 -0
- dify_plugin-0.7.0/dify_plugin/invocations/model/text_embedding.py +57 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/plugin.py +12 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/pyproject.toml +2 -2
- dify_plugin-0.7.0/tests/interfaces/model/openai_compatible/test_plugin_config.py +70 -0
- dify_plugin-0.7.0/tests/interfaces/model/test_rerank.py +104 -0
- dify_plugin-0.7.0/tests/interfaces/model/test_text_embedding.py +117 -0
- dify_plugin-0.6.2/dify_plugin/entities/model/rerank.py +0 -34
- dify_plugin-0.6.2/dify_plugin/entities/model/text_embedding.py +0 -39
- dify_plugin-0.6.2/dify_plugin/invocations/model/rerank.py +0 -22
- dify_plugin-0.6.2/dify_plugin/invocations/model/text_embedding.py +0 -28
- dify_plugin-0.6.2/tests/interfaces/model/test_text_embedding.py +0 -50
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/LICENSE +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/README.md +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/cli.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/commands/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/commands/generate_docs.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/config/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/config/config.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/config/integration_config.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/config/logger_format.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/documentation/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/documentation/generator.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/documentation/schema_doc.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/entities/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/entities/message.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/entities/plugin/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/entities/plugin/io.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/entities/plugin/parameter_type.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/entities/plugin/setup.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/entities/providers.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/model_factory.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/plugin_registration.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/runtime.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/__base/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/__base/filter_reader.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/__base/request_reader.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/__base/response_writer.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/__base/writer_entities.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/io_server.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/router.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/serverless/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/serverless/request_reader.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/serverless/response_writer.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/stdio/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/stdio/request_reader.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/stdio/response_writer.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/tcp/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/server/tcp/request_reader.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/trigger_factory.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/utils/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/utils/class_loader.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/utils/http_parser.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/utils/position_helper.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/core/utils/yaml_loader.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/agent.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/datasource.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/datasource_manifest.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/endpoint.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/invoke_message.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/model/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/model/llm.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/model/message.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/model/moderation.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/model/provider.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/model/speech2text.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/model/tts.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/oauth.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/provider_config.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/trigger.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/entities/workflow_node.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/errors/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/errors/model.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/errors/tool.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/errors/trigger.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/file/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/file/constants.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/file/entities.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/file/file.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/integration/entities.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/integration/exc.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/integration/run.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/agent/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/datasource/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/datasource/online_document.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/datasource/online_drive.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/datasource/website.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/endpoint/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/exec/ai_model.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/ai_model.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/audio.mp3 +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/large_language_model.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/moderation_model.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/openai_compatible/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/openai_compatible/common.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/openai_compatible/provider.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/openai_compatible/rerank.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/openai_compatible/speech2text.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/openai_compatible/text_embedding.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/openai_compatible/tts.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/speech2text_model.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/tts_model.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/tool/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/trigger/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/app/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/app/chat.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/app/completion.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/app/workflow.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/file.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/model/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/model/llm.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/model/llm_structured_output.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/model/moderation.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/model/speech2text.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/model/tts.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/storage.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/tool.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/workflow_node/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/workflow_node/parameter_extractor.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/invocations/workflow_node/question_classifier.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/protocol/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/protocol/dynamic_select.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/protocol/oauth.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/tool/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/tool/entities.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/__mock_server/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/__mock_server/openai.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/config/test_config.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/consts/mockserver.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/entities/endpoint/test_endpoint_group.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/entities/models/test_llm.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/entities/plugin/test_declaration.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/integration/test_invoke_llm.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/agent/test_agent.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/datasource/test_construct_datasource.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/datasource/test_construct_datasource_provider.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/model/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/model/openai_compatible/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/model/openai_compatible/test_increase_tool_call.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/model/test_ai_model_timing_context.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/model/test_construct_model_provider.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/model/test_llm_timing_context.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/model/test_model_registry_get_model.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/model/utils.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/tool/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/tool/test_construct_tool_provider.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/tool/test_costruct_tool.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/trigger/__init__.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/trigger/test_construct_trigger.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/interfaces/trigger/test_construct_trigger_provider.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/invocations/test_storage.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/servers/test_session.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/servers/test_stdio.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/test_llm_result.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/test_model_registry_get_model.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/test_prompt_message.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/test_tool_call_model_init.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/test_trigger_factory.py +0 -0
- {dify_plugin-0.6.2 → dify_plugin-0.7.0}/tests/utils/test_http_parser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dify_plugin
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Dify Plugin SDK
|
|
5
5
|
Keywords: dify,plugin,sdk
|
|
6
6
|
Author-Email: langgenius <hello@dify.ai>
|
|
@@ -8,7 +8,7 @@ License: Apache2.0
|
|
|
8
8
|
Project-URL: Homepage, https://github.com/langgenius/dify-plugin-sdks.git
|
|
9
9
|
Requires-Python: >=3.11
|
|
10
10
|
Requires-Dist: Flask~=3.0.3
|
|
11
|
-
Requires-Dist: Werkzeug~=3.
|
|
11
|
+
Requires-Dist: Werkzeug~=3.1.4
|
|
12
12
|
Requires-Dist: dpkt~=1.9.8
|
|
13
13
|
Requires-Dist: gevent~=25.5.1
|
|
14
14
|
Requires-Dist: httpx~=0.28.1
|
|
@@ -6,7 +6,9 @@ class InvokeType(Enum):
|
|
|
6
6
|
LLM = "llm"
|
|
7
7
|
LLMStructuredOutput = "llm_structured_output"
|
|
8
8
|
TextEmbedding = "text_embedding"
|
|
9
|
+
MultimodalEmbedding = "multimodal_embedding"
|
|
9
10
|
Rerank = "rerank"
|
|
11
|
+
MultimodalRerank = "multimodal_rerank"
|
|
10
12
|
TTS = "tts"
|
|
11
13
|
Speech2Text = "speech2text"
|
|
12
14
|
Moderation = "moderation"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from collections.abc import Mapping
|
|
1
|
+
from collections.abc import Mapping, Sequence
|
|
2
2
|
from enum import StrEnum
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@ from dify_plugin.entities.datasource import (
|
|
|
9
9
|
OnlineDriveBrowseFilesRequest,
|
|
10
10
|
OnlineDriveDownloadFileRequest,
|
|
11
11
|
)
|
|
12
|
-
from dify_plugin.entities.model import ModelType
|
|
12
|
+
from dify_plugin.entities.model import EmbeddingInputType, ModelType
|
|
13
13
|
from dify_plugin.entities.model.message import (
|
|
14
14
|
AssistantPromptMessage,
|
|
15
15
|
PromptMessage,
|
|
@@ -19,6 +19,7 @@ from dify_plugin.entities.model.message import (
|
|
|
19
19
|
ToolPromptMessage,
|
|
20
20
|
UserPromptMessage,
|
|
21
21
|
)
|
|
22
|
+
from dify_plugin.entities.model.text_embedding import MultiModalContent
|
|
22
23
|
from dify_plugin.entities.provider_config import CredentialType
|
|
23
24
|
from dify_plugin.entities.trigger import Subscription
|
|
24
25
|
|
|
@@ -59,8 +60,10 @@ class ModelActions(StrEnum):
|
|
|
59
60
|
InvokeLLM = "invoke_llm"
|
|
60
61
|
GetLLMNumTokens = "get_llm_num_tokens"
|
|
61
62
|
InvokeTextEmbedding = "invoke_text_embedding"
|
|
63
|
+
InvokeMultimodalEmbedding = "invoke_multimodal_embedding"
|
|
62
64
|
GetTextEmbeddingNumTokens = "get_text_embedding_num_tokens"
|
|
63
65
|
InvokeRerank = "invoke_rerank"
|
|
66
|
+
InvokeMultimodalRerank = "invoke_multimodal_rerank"
|
|
64
67
|
InvokeTTS = "invoke_tts"
|
|
65
68
|
GetTTSVoices = "get_tts_model_voices"
|
|
66
69
|
InvokeSpeech2Text = "invoke_speech2text"
|
|
@@ -202,6 +205,14 @@ class ModelInvokeTextEmbeddingRequest(PluginAccessModelRequest):
|
|
|
202
205
|
texts: list[str]
|
|
203
206
|
|
|
204
207
|
|
|
208
|
+
class ModelInvokeMultimodalEmbeddingRequest(PluginAccessModelRequest):
|
|
209
|
+
action: ModelActions = ModelActions.InvokeMultimodalEmbedding
|
|
210
|
+
model_type: ModelType = ModelType.TEXT_EMBEDDING
|
|
211
|
+
|
|
212
|
+
documents: list[MultiModalContent]
|
|
213
|
+
input_type: EmbeddingInputType = EmbeddingInputType.DOCUMENT
|
|
214
|
+
|
|
215
|
+
|
|
205
216
|
class ModelGetTextEmbeddingNumTokens(PluginAccessModelRequest):
|
|
206
217
|
action: ModelActions = ModelActions.GetTextEmbeddingNumTokens
|
|
207
218
|
|
|
@@ -217,6 +228,16 @@ class ModelInvokeRerankRequest(PluginAccessModelRequest):
|
|
|
217
228
|
top_n: int | None
|
|
218
229
|
|
|
219
230
|
|
|
231
|
+
class ModelInvokeMultimodalRerankRequest(PluginAccessModelRequest):
|
|
232
|
+
action: ModelActions = ModelActions.InvokeMultimodalRerank
|
|
233
|
+
model_type: ModelType = ModelType.RERANK
|
|
234
|
+
|
|
235
|
+
query: MultiModalContent
|
|
236
|
+
docs: Sequence[MultiModalContent]
|
|
237
|
+
score_threshold: float | None
|
|
238
|
+
top_n: int | None
|
|
239
|
+
|
|
240
|
+
|
|
220
241
|
class ModelInvokeTTSRequest(PluginAccessModelRequest):
|
|
221
242
|
action: ModelActions = ModelActions.InvokeTTS
|
|
222
243
|
|
|
@@ -22,6 +22,8 @@ from dify_plugin.core.entities.plugin.request import (
|
|
|
22
22
|
ModelGetTTSVoices,
|
|
23
23
|
ModelInvokeLLMRequest,
|
|
24
24
|
ModelInvokeModerationRequest,
|
|
25
|
+
ModelInvokeMultimodalEmbeddingRequest,
|
|
26
|
+
ModelInvokeMultimodalRerankRequest,
|
|
25
27
|
ModelInvokeRerankRequest,
|
|
26
28
|
ModelInvokeSpeech2TextRequest,
|
|
27
29
|
ModelInvokeTextEmbeddingRequest,
|
|
@@ -219,6 +221,18 @@ class PluginExecutor:
|
|
|
219
221
|
else:
|
|
220
222
|
raise ValueError(f"Model `{data.model_type}` not found for provider `{data.provider}`")
|
|
221
223
|
|
|
224
|
+
def invoke_multimodal_embedding(self, session: Session, data: ModelInvokeMultimodalEmbeddingRequest):
|
|
225
|
+
model_instance = self.registration.get_model_instance(data.provider, data.model_type)
|
|
226
|
+
if isinstance(model_instance, TextEmbeddingModel):
|
|
227
|
+
return model_instance.invoke_multimodal(
|
|
228
|
+
data.model,
|
|
229
|
+
data.credentials,
|
|
230
|
+
data.documents,
|
|
231
|
+
user=data.user_id,
|
|
232
|
+
input_type=data.input_type,
|
|
233
|
+
)
|
|
234
|
+
raise ValueError(f"Model `{data.model_type}` not found for provider `{data.provider}`")
|
|
235
|
+
|
|
222
236
|
def get_text_embedding_num_tokens(self, session: Session, data: ModelGetTextEmbeddingNumTokens):
|
|
223
237
|
model_instance = self.registration.get_model_instance(data.provider, data.model_type)
|
|
224
238
|
if isinstance(model_instance, TextEmbeddingModel):
|
|
@@ -247,6 +261,20 @@ class PluginExecutor:
|
|
|
247
261
|
else:
|
|
248
262
|
raise ValueError(f"Model `{data.model_type}` not found for provider `{data.provider}`")
|
|
249
263
|
|
|
264
|
+
def invoke_multimodal_rerank(self, session: Session, data: ModelInvokeMultimodalRerankRequest):
|
|
265
|
+
model_instance = self.registration.get_model_instance(data.provider, data.model_type)
|
|
266
|
+
if isinstance(model_instance, RerankModel):
|
|
267
|
+
return model_instance.invoke_multimodal(
|
|
268
|
+
data.model,
|
|
269
|
+
data.credentials,
|
|
270
|
+
data.query,
|
|
271
|
+
data.docs,
|
|
272
|
+
score_threshold=data.score_threshold,
|
|
273
|
+
top_n=data.top_n,
|
|
274
|
+
user=data.user_id,
|
|
275
|
+
)
|
|
276
|
+
raise ValueError(f"Model `{data.model_type}` not found for provider `{data.provider}`")
|
|
277
|
+
|
|
250
278
|
def invoke_tts(self, session: Session, data: ModelInvokeTTSRequest):
|
|
251
279
|
model_instance = self.registration.get_model_instance(data.provider, data.model_type)
|
|
252
280
|
if isinstance(model_instance, TTSModel):
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
2
|
+
|
|
3
|
+
from dify_plugin.entities.model import BaseModelConfig, ModelType
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RerankDocument(BaseModel):
|
|
7
|
+
"""
|
|
8
|
+
Model class for rerank document.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
index: int
|
|
12
|
+
text: str
|
|
13
|
+
score: float
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class RerankResult(BaseModel):
|
|
17
|
+
"""
|
|
18
|
+
Model class for rerank result.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
model: str
|
|
22
|
+
docs: list[RerankDocument]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class RerankModelConfig(BaseModelConfig):
|
|
26
|
+
"""
|
|
27
|
+
Model class for rerank model config.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
model_type: ModelType = ModelType.RERANK
|
|
31
|
+
score_threshold: float
|
|
32
|
+
top_n: int
|
|
33
|
+
|
|
34
|
+
model_config = ConfigDict(protected_namespaces=())
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class MultiModalRerankResult(BaseModel):
|
|
38
|
+
"""Rerank response produced by a multimodal rerank model."""
|
|
39
|
+
|
|
40
|
+
model: str = Field(..., description="Identifier of the model producing the reranked documents.")
|
|
41
|
+
docs: list[RerankDocument] = Field(..., description="Reranked documents with scores.")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class MultiModalRerankModelConfig(BaseModelConfig):
|
|
45
|
+
"""Configuration payload for invoking a multimodal rerank model."""
|
|
46
|
+
|
|
47
|
+
model_type: ModelType = ModelType.RERANK
|
|
48
|
+
score_threshold: float | None = Field(
|
|
49
|
+
default=None,
|
|
50
|
+
description="Optional threshold for filtering documents based on score.",
|
|
51
|
+
)
|
|
52
|
+
top_n: int | None = Field(
|
|
53
|
+
default=None,
|
|
54
|
+
description="Optional limit on the number of documents returned.",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
model_config = ConfigDict(protected_namespaces=())
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
from enum import StrEnum
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
5
|
+
|
|
6
|
+
from dify_plugin.entities.model import BaseModelConfig, ModelType, ModelUsage
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class EmbeddingUsage(ModelUsage):
|
|
10
|
+
"""
|
|
11
|
+
Model class for embedding usage.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
tokens: int
|
|
15
|
+
total_tokens: int
|
|
16
|
+
unit_price: Decimal
|
|
17
|
+
price_unit: Decimal
|
|
18
|
+
total_price: Decimal
|
|
19
|
+
currency: str
|
|
20
|
+
latency: float
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TextEmbeddingResult(BaseModel):
|
|
24
|
+
"""
|
|
25
|
+
Model class for text embedding result.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
model: str
|
|
29
|
+
embeddings: list[list[float]]
|
|
30
|
+
usage: EmbeddingUsage
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TextEmbeddingModelConfig(BaseModelConfig):
|
|
34
|
+
"""
|
|
35
|
+
Model class for text embedding model config.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
model_type: ModelType = ModelType.TEXT_EMBEDDING
|
|
39
|
+
|
|
40
|
+
model_config = ConfigDict(protected_namespaces=())
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class MultiModalContentType(StrEnum):
|
|
44
|
+
"""Supported content types for multimodal inputs."""
|
|
45
|
+
|
|
46
|
+
TEXT = "text"
|
|
47
|
+
IMAGE = "image"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class MultiModalContent(BaseModel):
|
|
51
|
+
"""A multimodal content payload provided by the caller."""
|
|
52
|
+
|
|
53
|
+
content: str = Field(..., description="The payload content, plain text or base64 encoded file data.")
|
|
54
|
+
content_type: MultiModalContentType = Field(..., description="The modality of the provided content.")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class MultiModalEmbeddingResult(BaseModel):
|
|
58
|
+
"""Embedding response produced by a multimodal embedding model."""
|
|
59
|
+
|
|
60
|
+
model: str = Field(..., description="Identifier of the model generating embeddings.")
|
|
61
|
+
embeddings: list[list[float]] = Field(..., description="Embedding vectors for provided contents.")
|
|
62
|
+
usage: EmbeddingUsage = Field(..., description="Usage metrics associated with the inference.")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class MultiModalEmbeddingModelConfig(BaseModelConfig):
|
|
66
|
+
"""Configuration payload for invoking a multimodal embedding model."""
|
|
67
|
+
|
|
68
|
+
model_type: ModelType = ModelType.TEXT_EMBEDDING
|
|
69
|
+
tenant_id: str = Field(..., description="Vendor tenant identifier associated with the dataset.")
|
|
70
|
+
|
|
71
|
+
model_config = ConfigDict(protected_namespaces=())
|
|
@@ -20,15 +20,6 @@ from dify_plugin.entities.provider_config import (
|
|
|
20
20
|
CredentialType,
|
|
21
21
|
ProviderConfig,
|
|
22
22
|
)
|
|
23
|
-
from dify_plugin.entities.provider_config import (
|
|
24
|
-
LogMetadata as CommonLogMetadata,
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
# TODO: this is a temporary solution to avoid breaking changes from agent imports
|
|
28
|
-
# ImportError: cannot import name "LogMetadata" from "dify_plugin.entities.tool"
|
|
29
|
-
# which will be removed in 0.5.0
|
|
30
|
-
# ISSUE: https://github.com/langgenius/dify-plugin-sdks/issues/181
|
|
31
|
-
LogMetadata = CommonLogMetadata
|
|
32
23
|
|
|
33
24
|
|
|
34
25
|
class ToolRuntime(BaseModel):
|
{dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/openai_compatible/llm.py
RENAMED
|
@@ -47,6 +47,8 @@ from dify_plugin.interfaces.model.openai_compatible.common import _CommonOaiApiC
|
|
|
47
47
|
|
|
48
48
|
logger = logging.getLogger(__name__)
|
|
49
49
|
|
|
50
|
+
_plugin_config = DifyPluginEnv()
|
|
51
|
+
|
|
50
52
|
|
|
51
53
|
def _gen_tool_call_id() -> str:
|
|
52
54
|
return f"chatcmpl-tool-{uuid.uuid4().hex!s}"
|
|
@@ -473,7 +475,7 @@ class OAICompatLargeLanguageModel(_CommonOaiApiCompat, LargeLanguageModel):
|
|
|
473
475
|
endpoint_url,
|
|
474
476
|
headers=headers,
|
|
475
477
|
json=data,
|
|
476
|
-
timeout=(10,
|
|
478
|
+
timeout=(10, _plugin_config.MAX_REQUEST_TIMEOUT),
|
|
477
479
|
stream=stream,
|
|
478
480
|
)
|
|
479
481
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
|
+
from collections.abc import Sequence
|
|
2
3
|
|
|
3
4
|
from dify_plugin.entities.model import ModelType
|
|
4
|
-
from dify_plugin.entities.model.rerank import RerankResult
|
|
5
|
+
from dify_plugin.entities.model.rerank import MultiModalRerankResult, RerankResult
|
|
6
|
+
from dify_plugin.entities.model.text_embedding import MultiModalContent
|
|
5
7
|
from dify_plugin.interfaces.model.ai_model import AIModel
|
|
6
8
|
|
|
7
9
|
|
|
@@ -41,6 +43,23 @@ class RerankModel(AIModel):
|
|
|
41
43
|
"""
|
|
42
44
|
raise NotImplementedError
|
|
43
45
|
|
|
46
|
+
def _invoke_multimodal(
|
|
47
|
+
self,
|
|
48
|
+
model: str,
|
|
49
|
+
credentials: dict,
|
|
50
|
+
query: MultiModalContent,
|
|
51
|
+
docs: Sequence[MultiModalContent],
|
|
52
|
+
score_threshold: float | None = None,
|
|
53
|
+
top_n: int | None = None,
|
|
54
|
+
user: str | None = None,
|
|
55
|
+
) -> MultiModalRerankResult:
|
|
56
|
+
"""Invoke a multimodal rerank model."""
|
|
57
|
+
|
|
58
|
+
raise NotImplementedError(
|
|
59
|
+
f"{self.__class__.__name__} does not implement `_invoke_multimodal`. "
|
|
60
|
+
"Implement this method to support multimodal rerank invocations."
|
|
61
|
+
)
|
|
62
|
+
|
|
44
63
|
############################################################
|
|
45
64
|
# For executor use only #
|
|
46
65
|
############################################################
|
|
@@ -73,3 +92,31 @@ class RerankModel(AIModel):
|
|
|
73
92
|
return self._invoke(model, credentials, query, docs, score_threshold, top_n, user)
|
|
74
93
|
except Exception as e:
|
|
75
94
|
raise self._transform_invoke_error(e) from e
|
|
95
|
+
|
|
96
|
+
def invoke_multimodal(
|
|
97
|
+
self,
|
|
98
|
+
model: str,
|
|
99
|
+
credentials: dict,
|
|
100
|
+
query: MultiModalContent,
|
|
101
|
+
docs: Sequence[MultiModalContent],
|
|
102
|
+
score_threshold: float | None = None,
|
|
103
|
+
top_n: int | None = None,
|
|
104
|
+
user: str | None = None,
|
|
105
|
+
) -> MultiModalRerankResult:
|
|
106
|
+
"""Invoke a multimodal rerank model."""
|
|
107
|
+
|
|
108
|
+
with self.timing_context():
|
|
109
|
+
try:
|
|
110
|
+
return self._invoke_multimodal(
|
|
111
|
+
model,
|
|
112
|
+
credentials,
|
|
113
|
+
query,
|
|
114
|
+
docs,
|
|
115
|
+
score_threshold,
|
|
116
|
+
top_n,
|
|
117
|
+
user,
|
|
118
|
+
)
|
|
119
|
+
except NotImplementedError:
|
|
120
|
+
raise
|
|
121
|
+
except Exception as e:
|
|
122
|
+
raise self._transform_invoke_error(e) from e
|
{dify_plugin-0.6.2 → dify_plugin-0.7.0}/dify_plugin/interfaces/model/text_embedding_model.py
RENAMED
|
@@ -3,7 +3,11 @@ from abc import abstractmethod
|
|
|
3
3
|
from pydantic import ConfigDict
|
|
4
4
|
|
|
5
5
|
from dify_plugin.entities.model import EmbeddingInputType, ModelPropertyKey, ModelType
|
|
6
|
-
from dify_plugin.entities.model.text_embedding import
|
|
6
|
+
from dify_plugin.entities.model.text_embedding import (
|
|
7
|
+
MultiModalContent,
|
|
8
|
+
MultiModalEmbeddingResult,
|
|
9
|
+
TextEmbeddingResult,
|
|
10
|
+
)
|
|
7
11
|
from dify_plugin.interfaces.model.ai_model import AIModel
|
|
8
12
|
|
|
9
13
|
|
|
@@ -42,6 +46,21 @@ class TextEmbeddingModel(AIModel):
|
|
|
42
46
|
"""
|
|
43
47
|
raise NotImplementedError
|
|
44
48
|
|
|
49
|
+
def _invoke_multimodal(
|
|
50
|
+
self,
|
|
51
|
+
model: str,
|
|
52
|
+
credentials: dict,
|
|
53
|
+
documents: list[MultiModalContent],
|
|
54
|
+
user: str | None = None,
|
|
55
|
+
input_type: EmbeddingInputType = EmbeddingInputType.DOCUMENT,
|
|
56
|
+
) -> MultiModalEmbeddingResult:
|
|
57
|
+
"""Invoke a multimodal embedding model."""
|
|
58
|
+
|
|
59
|
+
raise NotImplementedError(
|
|
60
|
+
f"{self.__class__.__name__} does not implement `_invoke_multimodal`. "
|
|
61
|
+
"Implement this method to support multimodal embeddings."
|
|
62
|
+
)
|
|
63
|
+
|
|
45
64
|
@abstractmethod
|
|
46
65
|
def get_num_tokens(self, model: str, credentials: dict, texts: list[str]) -> list[int]:
|
|
47
66
|
"""
|
|
@@ -115,3 +134,27 @@ class TextEmbeddingModel(AIModel):
|
|
|
115
134
|
return self._invoke(model, credentials, texts, user, input_type)
|
|
116
135
|
except Exception as e:
|
|
117
136
|
raise self._transform_invoke_error(e) from e
|
|
137
|
+
|
|
138
|
+
def invoke_multimodal(
|
|
139
|
+
self,
|
|
140
|
+
model: str,
|
|
141
|
+
credentials: dict,
|
|
142
|
+
documents: list[MultiModalContent],
|
|
143
|
+
user: str | None = None,
|
|
144
|
+
input_type: EmbeddingInputType = EmbeddingInputType.DOCUMENT,
|
|
145
|
+
) -> MultiModalEmbeddingResult:
|
|
146
|
+
"""Invoke a multimodal embedding model."""
|
|
147
|
+
|
|
148
|
+
with self.timing_context():
|
|
149
|
+
try:
|
|
150
|
+
return self._invoke_multimodal(
|
|
151
|
+
model,
|
|
152
|
+
credentials,
|
|
153
|
+
documents,
|
|
154
|
+
user,
|
|
155
|
+
input_type,
|
|
156
|
+
)
|
|
157
|
+
except NotImplementedError:
|
|
158
|
+
raise
|
|
159
|
+
except Exception as e:
|
|
160
|
+
raise self._transform_invoke_error(e) from e
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from dify_plugin.core.entities.invocation import InvokeType
|
|
2
|
+
from dify_plugin.core.runtime import BackwardsInvocation
|
|
3
|
+
from dify_plugin.entities.model.rerank import (
|
|
4
|
+
MultiModalRerankModelConfig,
|
|
5
|
+
MultiModalRerankResult,
|
|
6
|
+
RerankModelConfig,
|
|
7
|
+
RerankResult,
|
|
8
|
+
)
|
|
9
|
+
from dify_plugin.entities.model.text_embedding import MultiModalContent
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class RerankInvocation(BackwardsInvocation[RerankResult]):
|
|
13
|
+
def invoke(self, model_config: RerankModelConfig, docs: list[str], query: str) -> RerankResult:
|
|
14
|
+
"""
|
|
15
|
+
Invoke rerank
|
|
16
|
+
"""
|
|
17
|
+
for data in self._backwards_invoke(
|
|
18
|
+
InvokeType.Rerank,
|
|
19
|
+
RerankResult,
|
|
20
|
+
{
|
|
21
|
+
**model_config.model_dump(),
|
|
22
|
+
"docs": docs,
|
|
23
|
+
"query": query,
|
|
24
|
+
},
|
|
25
|
+
):
|
|
26
|
+
return data
|
|
27
|
+
|
|
28
|
+
raise Exception("No response from rerank")
|
|
29
|
+
|
|
30
|
+
def invoke_multimodal(
|
|
31
|
+
self,
|
|
32
|
+
model_config: MultiModalRerankModelConfig,
|
|
33
|
+
query: MultiModalContent,
|
|
34
|
+
docs: list[MultiModalContent],
|
|
35
|
+
) -> MultiModalRerankResult:
|
|
36
|
+
payload = {
|
|
37
|
+
**model_config.model_dump(),
|
|
38
|
+
"query": query.model_dump() if isinstance(query, MultiModalContent) else query,
|
|
39
|
+
"docs": [doc.model_dump() if isinstance(doc, MultiModalContent) else doc for doc in docs],
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for data in self._backwards_invoke(
|
|
43
|
+
InvokeType.MultimodalRerank,
|
|
44
|
+
MultiModalRerankResult,
|
|
45
|
+
payload,
|
|
46
|
+
):
|
|
47
|
+
return data
|
|
48
|
+
|
|
49
|
+
raise Exception("No response from multimodal rerank")
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from dify_plugin.core.entities.invocation import InvokeType
|
|
2
|
+
from dify_plugin.core.runtime import BackwardsInvocation
|
|
3
|
+
from dify_plugin.entities.model import EmbeddingInputType
|
|
4
|
+
from dify_plugin.entities.model.text_embedding import (
|
|
5
|
+
MultiModalContent,
|
|
6
|
+
MultiModalEmbeddingModelConfig,
|
|
7
|
+
MultiModalEmbeddingResult,
|
|
8
|
+
TextEmbeddingModelConfig,
|
|
9
|
+
TextEmbeddingResult,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TextEmbeddingInvocation(BackwardsInvocation[TextEmbeddingResult]):
|
|
14
|
+
def invoke(
|
|
15
|
+
self,
|
|
16
|
+
model_config: TextEmbeddingModelConfig,
|
|
17
|
+
texts: list[str],
|
|
18
|
+
input_type: EmbeddingInputType = EmbeddingInputType.QUERY,
|
|
19
|
+
) -> TextEmbeddingResult:
|
|
20
|
+
"""
|
|
21
|
+
Invoke text embedding
|
|
22
|
+
"""
|
|
23
|
+
for data in self._backwards_invoke(
|
|
24
|
+
InvokeType.TextEmbedding,
|
|
25
|
+
TextEmbeddingResult,
|
|
26
|
+
{
|
|
27
|
+
**model_config.model_dump(),
|
|
28
|
+
"texts": texts,
|
|
29
|
+
"input_type": input_type.value,
|
|
30
|
+
},
|
|
31
|
+
):
|
|
32
|
+
return data
|
|
33
|
+
|
|
34
|
+
raise Exception("No response from text embedding")
|
|
35
|
+
|
|
36
|
+
def invoke_multimodal(
|
|
37
|
+
self,
|
|
38
|
+
model_config: MultiModalEmbeddingModelConfig,
|
|
39
|
+
documents: list[MultiModalContent],
|
|
40
|
+
input_type: EmbeddingInputType = EmbeddingInputType.QUERY,
|
|
41
|
+
) -> MultiModalEmbeddingResult:
|
|
42
|
+
payload = {
|
|
43
|
+
**model_config.model_dump(),
|
|
44
|
+
"documents": [
|
|
45
|
+
document.model_dump() if isinstance(document, MultiModalContent) else document for document in documents
|
|
46
|
+
],
|
|
47
|
+
"input_type": input_type.value,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
for data in self._backwards_invoke(
|
|
51
|
+
InvokeType.MultimodalEmbedding,
|
|
52
|
+
MultiModalEmbeddingResult,
|
|
53
|
+
payload,
|
|
54
|
+
):
|
|
55
|
+
return data
|
|
56
|
+
|
|
57
|
+
raise Exception("No response from multimodal embedding")
|
|
@@ -266,6 +266,12 @@ class Plugin(IOServer, Router):
|
|
|
266
266
|
and data.get("action") == ModelActions.InvokeTextEmbedding.value,
|
|
267
267
|
)
|
|
268
268
|
|
|
269
|
+
self.register_route(
|
|
270
|
+
self.plugin_executer.invoke_multimodal_embedding,
|
|
271
|
+
lambda data: data.get("type") == PluginInvokeType.Model.value
|
|
272
|
+
and data.get("action") == ModelActions.InvokeMultimodalEmbedding.value,
|
|
273
|
+
)
|
|
274
|
+
|
|
269
275
|
self.register_route(
|
|
270
276
|
self.plugin_executer.get_text_embedding_num_tokens,
|
|
271
277
|
lambda data: data.get("type") == PluginInvokeType.Model.value
|
|
@@ -278,6 +284,12 @@ class Plugin(IOServer, Router):
|
|
|
278
284
|
and data.get("action") == ModelActions.InvokeRerank.value,
|
|
279
285
|
)
|
|
280
286
|
|
|
287
|
+
self.register_route(
|
|
288
|
+
self.plugin_executer.invoke_multimodal_rerank,
|
|
289
|
+
lambda data: data.get("type") == PluginInvokeType.Model.value
|
|
290
|
+
and data.get("action") == ModelActions.InvokeMultimodalRerank.value,
|
|
291
|
+
)
|
|
292
|
+
|
|
281
293
|
self.register_route(
|
|
282
294
|
self.plugin_executer.invoke_tts,
|
|
283
295
|
lambda data: data.get("type") == PluginInvokeType.Model.value
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dify_plugin"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.0"
|
|
4
4
|
description = "Dify Plugin SDK"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "langgenius", email = "hello@dify.ai" },
|
|
7
7
|
]
|
|
8
8
|
dependencies = [
|
|
9
9
|
"Flask~=3.0.3",
|
|
10
|
-
"Werkzeug~=3.
|
|
10
|
+
"Werkzeug~=3.1.4",
|
|
11
11
|
"dpkt~=1.9.8",
|
|
12
12
|
"gevent~=25.5.1",
|
|
13
13
|
"httpx~=0.28.1",
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for _plugin_config configuration object in openai_compatible/llm.py
|
|
3
|
+
|
|
4
|
+
These tests verify:
|
|
5
|
+
1. Configuration object is properly instantiated at module level
|
|
6
|
+
2. Configuration object is a singleton (only one instance at module level)
|
|
7
|
+
3. Configuration object has correct default values
|
|
8
|
+
4. Configuration object has correct types
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from dify_plugin.config.config import DifyPluginEnv
|
|
12
|
+
from dify_plugin.interfaces.model.openai_compatible import llm
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_plugin_config_exists():
|
|
16
|
+
"""Test that _plugin_config object exists"""
|
|
17
|
+
assert hasattr(llm, "_plugin_config")
|
|
18
|
+
assert llm._plugin_config is not None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_plugin_config_type():
|
|
22
|
+
"""Test that _plugin_config is an instance of DifyPluginEnv"""
|
|
23
|
+
assert isinstance(llm._plugin_config, DifyPluginEnv)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_plugin_config_has_max_request_timeout():
|
|
27
|
+
"""Test that _plugin_config has MAX_REQUEST_TIMEOUT attribute"""
|
|
28
|
+
assert hasattr(llm._plugin_config, "MAX_REQUEST_TIMEOUT")
|
|
29
|
+
assert isinstance(llm._plugin_config.MAX_REQUEST_TIMEOUT, int)
|
|
30
|
+
# Default value should be 300 seconds (unless overridden by environment variable)
|
|
31
|
+
assert llm._plugin_config.MAX_REQUEST_TIMEOUT > 0
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_plugin_config_has_max_invocation_timeout():
|
|
35
|
+
"""Test that _plugin_config has MAX_INVOCATION_TIMEOUT attribute"""
|
|
36
|
+
assert hasattr(llm._plugin_config, "MAX_INVOCATION_TIMEOUT")
|
|
37
|
+
assert isinstance(llm._plugin_config.MAX_INVOCATION_TIMEOUT, int)
|
|
38
|
+
# Default value should be 250 seconds (unless overridden by environment variable)
|
|
39
|
+
assert llm._plugin_config.MAX_INVOCATION_TIMEOUT > 0
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_plugin_config_singleton():
|
|
43
|
+
"""Test that configuration object is instantiated only once at module level"""
|
|
44
|
+
# Get the id of the config object
|
|
45
|
+
config_id_1 = id(llm._plugin_config)
|
|
46
|
+
|
|
47
|
+
# Import again, should be the same object
|
|
48
|
+
from dify_plugin.interfaces.model.openai_compatible import llm as llm2
|
|
49
|
+
|
|
50
|
+
config_id_2 = id(llm2._plugin_config)
|
|
51
|
+
|
|
52
|
+
# Verify it's the same object
|
|
53
|
+
assert config_id_1 == config_id_2
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_plugin_config_timeout_values_reasonable():
|
|
57
|
+
"""Test that timeout configuration values are within reasonable range"""
|
|
58
|
+
# MAX_REQUEST_TIMEOUT should be between 1 and 3600 seconds
|
|
59
|
+
assert 1 <= llm._plugin_config.MAX_REQUEST_TIMEOUT <= 3600
|
|
60
|
+
|
|
61
|
+
# MAX_INVOCATION_TIMEOUT should be between 1 and 3600 seconds
|
|
62
|
+
assert 1 <= llm._plugin_config.MAX_INVOCATION_TIMEOUT <= 3600
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_plugin_config_can_create_new_instance():
|
|
66
|
+
"""Test that new DifyPluginEnv instances can be created (verify the config class itself works)"""
|
|
67
|
+
new_config = DifyPluginEnv()
|
|
68
|
+
assert isinstance(new_config, DifyPluginEnv)
|
|
69
|
+
assert hasattr(new_config, "MAX_REQUEST_TIMEOUT")
|
|
70
|
+
assert hasattr(new_config, "MAX_INVOCATION_TIMEOUT")
|