From 7920714f49be39ab2fdb7568303974d07ce45a39 Mon Sep 17 00:00:00 2001 From: jyong <718720800@qq.com> Date: Mon, 1 Sep 2025 14:45:56 +0800 Subject: [PATCH] add recommended rag plugin endpoint --- .../rag_pipeline/rag_pipeline_workflow.py | 8 ++++ ..._15_1558-b35c3db83d09_add_pipeline_info.py | 2 +- ..._1138-17d4db47800c_add_pipeline_info_16.py | 2 +- ..._1443-8c5088481127_add_pipeline_info_17.py | 38 +++++++++++++++++++ api/models/dataset.py | 12 ++++++ api/services/rag_pipeline/rag_pipeline.py | 38 ++++++++++++++++++- 6 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 api/migrations/versions/2025_09_01_1443-8c5088481127_add_pipeline_info_17.py diff --git a/api/controllers/console/datasets/rag_pipeline/rag_pipeline_workflow.py b/api/controllers/console/datasets/rag_pipeline/rag_pipeline_workflow.py index f4031ec5a9..83b441f37b 100644 --- a/api/controllers/console/datasets/rag_pipeline/rag_pipeline_workflow.py +++ b/api/controllers/console/datasets/rag_pipeline/rag_pipeline_workflow.py @@ -981,6 +981,14 @@ class RagPipelineDatasourceVariableApi(Resource): ) return workflow_node_execution +class RagPipelineRecommendedPluginApi(Resource): + @setup_required + @login_required + @account_initialization_required + def get(self): + rag_pipeline_service = RagPipelineService() + recommended_plugins = rag_pipeline_service.get_recommended_plugins() + return recommended_plugins api.add_resource( DraftRagPipelineApi, diff --git a/api/migrations/versions/2025_05_15_1558-b35c3db83d09_add_pipeline_info.py b/api/migrations/versions/2025_05_15_1558-b35c3db83d09_add_pipeline_info.py index 961589a87e..5238c8e34f 100644 --- a/api/migrations/versions/2025_05_15_1558-b35c3db83d09_add_pipeline_info.py +++ b/api/migrations/versions/2025_05_15_1558-b35c3db83d09_add_pipeline_info.py @@ -12,7 +12,7 @@ from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. revision = 'b35c3db83d09' -down_revision = '0ab65e1cc7fa' +down_revision = '0e154742a5fa' branch_labels = None depends_on = None diff --git a/api/migrations/versions/2025_08_11_1138-17d4db47800c_add_pipeline_info_16.py b/api/migrations/versions/2025_08_11_1138-17d4db47800c_add_pipeline_info_16.py index 6b056be4e9..3e773631b1 100644 --- a/api/migrations/versions/2025_08_11_1138-17d4db47800c_add_pipeline_info_16.py +++ b/api/migrations/versions/2025_08_11_1138-17d4db47800c_add_pipeline_info_16.py @@ -12,7 +12,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. revision = '17d4db47800c' -down_revision = '223c3f882c69' +down_revision = '74e5f667f4b7' branch_labels = None depends_on = None diff --git a/api/migrations/versions/2025_09_01_1443-8c5088481127_add_pipeline_info_17.py b/api/migrations/versions/2025_09_01_1443-8c5088481127_add_pipeline_info_17.py new file mode 100644 index 0000000000..0269c6a32d --- /dev/null +++ b/api/migrations/versions/2025_09_01_1443-8c5088481127_add_pipeline_info_17.py @@ -0,0 +1,38 @@ +"""add_pipeline_info_17 + +Revision ID: 8c5088481127 +Revises: 17d4db47800c +Create Date: 2025-09-01 14:43:48.417869 + +""" +from alembic import op +import models as models +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '8c5088481127' +down_revision = '17d4db47800c' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('pipeline_recommended_plugins', + sa.Column('id', models.types.StringUUID(), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('plugin_id', sa.Text(), nullable=False), + sa.Column('provider_name', sa.Text(), nullable=False), + sa.Column('position', sa.Integer(), nullable=False), + sa.Column('active', sa.Boolean(), nullable=False), + sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), + sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), + sa.PrimaryKeyConstraint('id', name='pipeline_recommended_plugin_pkey') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('pipeline_recommended_plugins') + # ### end Alembic commands ### diff --git a/api/models/dataset.py b/api/models/dataset.py index ff9559d7d8..931af91fa4 100644 --- a/api/models/dataset.py +++ b/api/models/dataset.py @@ -1307,3 +1307,15 @@ class DocumentPipelineExecutionLog(Base): input_data = db.Column(db.JSON, nullable=False) created_by = db.Column(StringUUID, nullable=True) created_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp()) + +class PipelineRecommendedPlugin(Base): + __tablename__ = "pipeline_recommended_plugins" + __table_args__ = (db.PrimaryKeyConstraint("id", name="pipeline_recommended_plugin_pkey"),) + + id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()")) + plugin_id = db.Column(db.Text, nullable=False) + provider_name = db.Column(db.Text, nullable=False) + position = db.Column(db.Integer, nullable=False, default=0) + active = db.Column(db.Boolean, nullable=False, default=True) + created_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp()) + updated_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp()) \ No newline at end of file diff --git a/api/services/rag_pipeline/rag_pipeline.py b/api/services/rag_pipeline/rag_pipeline.py index 550253429f..3e361cab10 100644 --- a/api/services/rag_pipeline/rag_pipeline.py +++ b/api/services/rag_pipeline/rag_pipeline.py @@ -27,6 +27,7 @@ from core.datasource.entities.datasource_entities import ( from core.datasource.online_document.online_document_plugin import OnlineDocumentDatasourcePlugin from core.datasource.online_drive.online_drive_plugin import OnlineDriveDatasourcePlugin from core.datasource.website_crawl.website_crawl_plugin import WebsiteCrawlDatasourcePlugin +from core.helper import marketplace from core.rag.entities.event import ( DatasourceCompletedEvent, DatasourceErrorEvent, @@ -52,7 +53,7 @@ from core.workflow.workflow_entry import WorkflowEntry from extensions.ext_database import db from libs.infinite_scroll_pagination import InfiniteScrollPagination from models.account import Account -from models.dataset import Document, Pipeline, PipelineCustomizedTemplate # type: ignore +from models.dataset import Document, Pipeline, PipelineCustomizedTemplate, PipelineRecommendedPlugin # type: ignore from models.enums import WorkflowRunTriggeredFrom from models.model import EndUser from models.workflow import ( @@ -70,6 +71,7 @@ from services.entities.knowledge_entities.rag_pipeline_entities import ( ) from services.errors.app import WorkflowHashNotEqualError from services.rag_pipeline.pipeline_template.pipeline_template_factory import PipelineTemplateRetrievalFactory +from services.tools.builtin_tools_manage_service import BuiltinToolManageService from services.workflow_draft_variable_service import DraftVariableSaver, DraftVarLoader logger = logging.getLogger(__name__) @@ -1226,3 +1228,37 @@ class RagPipelineService: ) session.commit() return workflow_node_execution_db_model + + def get_recommended_plugins(self) -> list[dict]: + # Query active recommended plugins + pipeline_recommended_plugins = ( + db.session.query(PipelineRecommendedPlugin) + .filter(PipelineRecommendedPlugin.active == True) + .order_by(PipelineRecommendedPlugin.position.asc()) + .all() + ) + + if not pipeline_recommended_plugins: + return [] + + # Batch fetch plugin manifests + plugin_ids = [plugin.plugin_id for plugin in pipeline_recommended_plugins] + plugin_manifests = marketplace.batch_fetch_plugin_manifests(plugin_ids) + + builtin_tools = BuiltinToolManageService.list_builtin_tools( + user_id=current_user.id, + tenant_id=current_user.current_tenant_id, + ) + installed_plugin_ids = {tool.plugin_id for tool in builtin_tools} + + # Build recommended plugins list + return [ + { + "plugin_id": manifest.plugin_id, + "name": manifest.name, + "icon": manifest.icon, + "plugin_unique_identifier": manifest.latest_package_identifier, + "installed": manifest.plugin_id in installed_plugin_ids, + } + for manifest in plugin_manifests + ] \ No newline at end of file