mirror of https://github.com/langgenius/dify.git
Merge remote-tracking branch 'upstream/feat/rag-2' into feat/rag-2
This commit is contained in:
commit
eb7b21c7f1
|
|
@ -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,
|
||||
|
|
@ -1090,3 +1098,8 @@ api.add_resource(
|
|||
RagPipelineDatasourceVariableApi,
|
||||
"/rag/pipelines/<uuid:pipeline_id>/workflows/draft/datasource/variables-inspect",
|
||||
)
|
||||
|
||||
api.add_resource(
|
||||
RagPipelineRecommendedPluginApi,
|
||||
"/rag/pipelines/recommended-plugins",
|
||||
)
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ###
|
||||
|
|
@ -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())
|
||||
|
|
@ -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
|
||||
]
|
||||
|
|
@ -66,7 +66,7 @@ const DropDown = ({
|
|||
const a = document.createElement('a')
|
||||
const file = new Blob([data], { type: 'application/yaml' })
|
||||
a.href = URL.createObjectURL(file)
|
||||
a.download = `${name}.yml`
|
||||
a.download = `${name}.pipeline`
|
||||
a.click()
|
||||
}
|
||||
catch {
|
||||
|
|
|
|||
|
|
@ -17,12 +17,16 @@ export type Props = {
|
|||
file: File | undefined
|
||||
updateFile: (file?: File) => void
|
||||
className?: string
|
||||
accept?: string
|
||||
displayName?: string
|
||||
}
|
||||
|
||||
const Uploader: FC<Props> = ({
|
||||
file,
|
||||
updateFile,
|
||||
className,
|
||||
accept = '.yaml,.yml',
|
||||
displayName = 'YAML',
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useContext(ToastContext)
|
||||
|
|
@ -95,9 +99,9 @@ const Uploader: FC<Props> = ({
|
|||
<input
|
||||
ref={fileUploader}
|
||||
style={{ display: 'none' }}
|
||||
type="file"
|
||||
id="fileUploader"
|
||||
accept='.yaml,.yml'
|
||||
type='file'
|
||||
id='fileUploader'
|
||||
accept={accept}
|
||||
onChange={fileChangeHandle}
|
||||
/>
|
||||
<div ref={dropRef}>
|
||||
|
|
@ -116,12 +120,12 @@ const Uploader: FC<Props> = ({
|
|||
{file && (
|
||||
<div className={cn('group flex items-center rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg shadow-xs', ' hover:bg-components-panel-on-panel-item-bg-hover')}>
|
||||
<div className='flex items-center justify-center p-3'>
|
||||
<YamlIcon className="h-6 w-6 shrink-0" />
|
||||
<YamlIcon className='h-6 w-6 shrink-0' />
|
||||
</div>
|
||||
<div className='flex grow flex-col items-start gap-0.5 py-1 pr-2'>
|
||||
<span className='font-inter max-w-[calc(100%_-_30px)] overflow-hidden text-ellipsis whitespace-nowrap text-[12px] font-medium leading-4 text-text-secondary'>{file.name}</span>
|
||||
<div className='font-inter flex h-3 items-center gap-1 self-stretch text-[10px] font-medium uppercase leading-3 text-text-tertiary'>
|
||||
<span>YAML</span>
|
||||
<span>{displayName}</span>
|
||||
<span className='text-text-quaternary'>·</span>
|
||||
<span>{formatFileSize(file.size)}</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ const Uploader: FC<Props> = ({
|
|||
style={{ display: 'none' }}
|
||||
type='file'
|
||||
id='fileUploader'
|
||||
accept='.yaml,.yml'
|
||||
accept='.pipeline'
|
||||
onChange={fileChangeHandle}
|
||||
/>
|
||||
<div ref={dropRef}>
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ const TemplateCard = ({
|
|||
const blob = new Blob([res.data], { type: 'application/yaml' })
|
||||
downloadFile({
|
||||
data: blob,
|
||||
fileName: `${pipeline.name}.yml`,
|
||||
fileName: `${pipeline.name}.pipeline`,
|
||||
})
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ const DatasetCard = ({
|
|||
const a = document.createElement('a')
|
||||
const file = new Blob([data], { type: 'application/yaml' })
|
||||
a.href = URL.createObjectURL(file)
|
||||
a.download = `${name}.yml`
|
||||
a.download = `${name}.pipeline`
|
||||
a.click()
|
||||
}
|
||||
catch {
|
||||
|
|
|
|||
|
|
@ -233,6 +233,8 @@ const UpdateDSLModal = ({
|
|||
file={currentFile}
|
||||
updateFile={handleFile}
|
||||
className='!mt-0 w-full'
|
||||
accept='.pipeline'
|
||||
displayName='PIPELINE'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export const useDSL = () => {
|
|||
const a = document.createElement('a')
|
||||
const file = new Blob([data], { type: 'application/yaml' })
|
||||
a.href = URL.createObjectURL(file)
|
||||
a.download = `${knowledgeName}.yml`
|
||||
a.download = `${knowledgeName}.pipeline`
|
||||
a.click()
|
||||
}
|
||||
catch {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ export const usePipelineTemplate = () => {
|
|||
...knowledgeBaseDefault.defaultValue as KnowledgeBaseNodeType,
|
||||
type: knowledgeBaseDefault.metaData.type,
|
||||
title: t(`workflow.blocks.${knowledgeBaseDefault.metaData.type}`),
|
||||
selected: true,
|
||||
},
|
||||
position: {
|
||||
x: START_INITIAL_POSITION.x + 500,
|
||||
|
|
|
|||
Loading…
Reference in New Issue