Merge branch 'main' into feat/plugins

pull/12372/head
zxhlyh 1 year ago
commit 04054954c5

@ -433,3 +433,5 @@ RESET_PASSWORD_TOKEN_EXPIRY_MINUTES=5
CREATE_TIDB_SERVICE_JOB_ENABLED=false CREATE_TIDB_SERVICE_JOB_ENABLED=false
# Maximum number of submitted thread count in a ThreadPool for parallel node execution
MAX_SUBMIT_COUNT=100

@ -439,6 +439,17 @@ class WorkflowConfig(BaseSettings):
) )
class WorkflowNodeExecutionConfig(BaseSettings):
"""
Configuration for workflow node execution
"""
MAX_SUBMIT_COUNT: PositiveInt = Field(
description="Maximum number of submitted thread count in a ThreadPool for parallel node execution",
default=100,
)
class AuthConfig(BaseSettings): class AuthConfig(BaseSettings):
""" """
Configuration for authentication and OAuth Configuration for authentication and OAuth
@ -775,6 +786,7 @@ class FeatureConfig(
ToolConfig, ToolConfig,
UpdateConfig, UpdateConfig,
WorkflowConfig, WorkflowConfig,
WorkflowNodeExecutionConfig,
WorkspaceConfig, WorkspaceConfig,
LoginConfig, LoginConfig,
# hosted services config # hosted services config

@ -9,7 +9,7 @@ class PackagingInfo(BaseSettings):
CURRENT_VERSION: str = Field( CURRENT_VERSION: str = Field(
description="Dify version", description="Dify version",
default="0.13.2", default="0.14.0",
) )
COMMIT_SHA: str = Field( COMMIT_SHA: str = Field(

@ -10,6 +10,7 @@ from core.model_runtime.entities.llm_entities import (
from core.model_runtime.entities.message_entities import ( from core.model_runtime.entities.message_entities import (
AssistantPromptMessage, AssistantPromptMessage,
PromptMessage, PromptMessage,
PromptMessageContentType,
PromptMessageTool, PromptMessageTool,
SystemPromptMessage, SystemPromptMessage,
ToolPromptMessage, ToolPromptMessage,
@ -105,7 +106,11 @@ class BaichuanLanguageModel(LargeLanguageModel):
if isinstance(message.content, str): if isinstance(message.content, str):
message_dict = {"role": "user", "content": message.content} message_dict = {"role": "user", "content": message.content}
else: else:
raise ValueError("User message content must be str") for message_content in message.content:
if message_content.type == PromptMessageContentType.TEXT:
message_dict = {"role": "user", "content": message_content.data}
elif message_content.type == PromptMessageContentType.IMAGE:
raise ValueError("Content object type not support image_url")
elif isinstance(message, AssistantPromptMessage): elif isinstance(message, AssistantPromptMessage):
message = cast(AssistantPromptMessage, message) message = cast(AssistantPromptMessage, message)
message_dict = {"role": "assistant", "content": message.content} message_dict = {"role": "assistant", "content": message.content}

@ -24,6 +24,9 @@ class DeepseekLargeLanguageModel(OAIAPICompatLargeLanguageModel):
user: Optional[str] = None, user: Optional[str] = None,
) -> Union[LLMResult, Generator]: ) -> Union[LLMResult, Generator]:
self._add_custom_parameters(credentials) self._add_custom_parameters(credentials)
# {"response_format": "xx"} need convert to {"response_format": {"type": "xx"}}
if "response_format" in model_parameters:
model_parameters["response_format"] = {"type": model_parameters.get("response_format")}
return super()._invoke(model, credentials, prompt_messages, model_parameters, tools, stop, stream) return super()._invoke(model, credentials, prompt_messages, model_parameters, tools, stop, stream)
def validate_credentials(self, model: str, credentials: dict) -> None: def validate_credentials(self, model: str, credentials: dict) -> None:

@ -68,7 +68,12 @@ class MaaSClient(MaasService):
content = [] content = []
for message_content in message.content: for message_content in message.content:
if message_content.type == PromptMessageContentType.TEXT: if message_content.type == PromptMessageContentType.TEXT:
raise ValueError("Content object type only support image_url") content.append(
{
"type": "text",
"text": message_content.data,
}
)
elif message_content.type == PromptMessageContentType.IMAGE: elif message_content.type == PromptMessageContentType.IMAGE:
message_content = cast(ImagePromptMessageContent, message_content) message_content = cast(ImagePromptMessageContent, message_content)
image_data = re.sub(r"^data:image\/[a-zA-Z]+;base64,", "", message_content.data) image_data = re.sub(r"^data:image\/[a-zA-Z]+;base64,", "", message_content.data)

@ -9,6 +9,7 @@ from typing import Any, Optional, cast
from flask import Flask, current_app from flask import Flask, current_app
from configs import dify_config
from core.app.apps.base_app_queue_manager import GenerateTaskStoppedError from core.app.apps.base_app_queue_manager import GenerateTaskStoppedError
from core.app.entities.app_invoke_entities import InvokeFrom from core.app.entities.app_invoke_entities import InvokeFrom
from core.workflow.entities.node_entities import NodeRunMetadataKey, NodeRunResult from core.workflow.entities.node_entities import NodeRunMetadataKey, NodeRunResult
@ -52,7 +53,12 @@ logger = logging.getLogger(__name__)
class GraphEngineThreadPool(ThreadPoolExecutor): class GraphEngineThreadPool(ThreadPoolExecutor):
def __init__( def __init__(
self, max_workers=None, thread_name_prefix="", initializer=None, initargs=(), max_submit_count=100 self,
max_workers=None,
thread_name_prefix="",
initializer=None,
initargs=(),
max_submit_count=dify_config.MAX_SUBMIT_COUNT,
) -> None: ) -> None:
super().__init__(max_workers, thread_name_prefix, initializer, initargs) super().__init__(max_workers, thread_name_prefix, initializer, initargs)
self.max_submit_count = max_submit_count self.max_submit_count = max_submit_count
@ -92,7 +98,7 @@ class GraphEngine:
max_execution_time: int, max_execution_time: int,
thread_pool_id: Optional[str] = None, thread_pool_id: Optional[str] = None,
) -> None: ) -> None:
thread_pool_max_submit_count = 100 thread_pool_max_submit_count = dify_config.MAX_SUBMIT_COUNT
thread_pool_max_workers = 10 thread_pool_max_workers = 10
# init thread pool # init thread pool

@ -163,7 +163,9 @@ class IterationNode(BaseNode[IterationNodeData]):
if self.node_data.is_parallel: if self.node_data.is_parallel:
futures: list[Future] = [] futures: list[Future] = []
q: Queue = Queue() q: Queue = Queue()
thread_pool = GraphEngineThreadPool(max_workers=self.node_data.parallel_nums, max_submit_count=100) thread_pool = GraphEngineThreadPool(
max_workers=self.node_data.parallel_nums, max_submit_count=dify_config.MAX_SUBMIT_COUNT
)
for index, item in enumerate(iterator_list_value): for index, item in enumerate(iterator_list_value):
future: Future = thread_pool.submit( future: Future = thread_pool.submit(
self._run_single_iter_parallel, self._run_single_iter_parallel,

@ -225,8 +225,10 @@ class Workflow(db.Model):
from models.tools import WorkflowToolProvider from models.tools import WorkflowToolProvider
return ( return (
db.session.query(WorkflowToolProvider).filter(WorkflowToolProvider.app_id == self.app_id).first() db.session.query(WorkflowToolProvider)
is not None .filter(WorkflowToolProvider.tenant_id == self.tenant_id, WorkflowToolProvider.app_id == self.app_id)
.count()
> 0
) )
@property @property

@ -2,7 +2,7 @@ version: '3'
services: services:
# API service # API service
api: api:
image: langgenius/dify-api:0.13.2 image: langgenius/dify-api:0.14.0
restart: always restart: always
environment: environment:
# Startup mode, 'api' starts the API server. # Startup mode, 'api' starts the API server.
@ -227,7 +227,7 @@ services:
# worker service # worker service
# The Celery worker for processing the queue. # The Celery worker for processing the queue.
worker: worker:
image: langgenius/dify-api:0.13.2 image: langgenius/dify-api:0.14.0
restart: always restart: always
environment: environment:
CONSOLE_WEB_URL: '' CONSOLE_WEB_URL: ''
@ -397,7 +397,7 @@ services:
# Frontend web application. # Frontend web application.
web: web:
image: langgenius/dify-web:0.13.2 image: langgenius/dify-web:0.14.0
restart: always restart: always
environment: environment:
# The base URL of console application api server, refers to the Console base URL of WEB service if console domain is # The base URL of console application api server, refers to the Console base URL of WEB service if console domain is

@ -292,7 +292,7 @@ x-shared-env: &shared-api-worker-env
services: services:
# API service # API service
api: api:
image: langgenius/dify-api:0.13.2 image: langgenius/dify-api:0.14.0
restart: always restart: always
environment: environment:
# Use the shared environment variables. # Use the shared environment variables.
@ -312,7 +312,7 @@ services:
# worker service # worker service
# The Celery worker for processing the queue. # The Celery worker for processing the queue.
worker: worker:
image: langgenius/dify-api:0.13.2 image: langgenius/dify-api:0.14.0
restart: always restart: always
environment: environment:
# Use the shared environment variables. # Use the shared environment variables.
@ -331,7 +331,7 @@ services:
# Frontend web application. # Frontend web application.
web: web:
image: langgenius/dify-web:0.13.2 image: langgenius/dify-web:0.14.0
restart: always restart: always
environment: environment:
CONSOLE_API_URL: ${CONSOLE_API_URL:-} CONSOLE_API_URL: ${CONSOLE_API_URL:-}

@ -192,6 +192,7 @@ export const useWorkflowRun = () => {
const newNodes = produce(nodes, (draft) => { const newNodes = produce(nodes, (draft) => {
draft.forEach((node) => { draft.forEach((node) => {
node.data._waitingRun = true node.data._waitingRun = true
node.data._runningBranchId = undefined
}) })
}) })
setNodes(newNodes) setNodes(newNodes)

@ -52,6 +52,12 @@ const useConfig = (id: string, payload: IterationNodeType) => {
[VarType.number]: VarType.arrayNumber, [VarType.number]: VarType.arrayNumber,
[VarType.object]: VarType.arrayObject, [VarType.object]: VarType.arrayObject,
[VarType.file]: VarType.arrayFile, [VarType.file]: VarType.arrayFile,
// list operator node can output array
[VarType.array]: VarType.array,
[VarType.arrayFile]: VarType.arrayFile,
[VarType.arrayString]: VarType.arrayString,
[VarType.arrayNumber]: VarType.arrayNumber,
[VarType.arrayObject]: VarType.arrayObject,
} as Record<VarType, VarType>)[outputItemType] || VarType.arrayString } as Record<VarType, VarType>)[outputItemType] || VarType.arrayString
}) })
setInputs(newInputs) setInputs(newInputs)

@ -59,20 +59,12 @@ const InputVarList: FC<Props> = ({
const newValue = produce(value, (draft: ToolVarInputs) => { const newValue = produce(value, (draft: ToolVarInputs) => {
const target = draft[variable] const target = draft[variable]
if (target) { if (target) {
if (!isSupportConstantValue || varKindType === VarKindType.variable) { target.type = varKindType
if (isSupportConstantValue) target.value = varValue
target.type = VarKindType.variable
target.value = varValue as ValueSelector
}
else {
target.type = VarKindType.constant
target.value = varValue as string
}
} }
else { else {
draft[variable] = { draft[variable] = {
type: VarKindType.variable, type: varKindType,
value: varValue, value: varValue,
} }
} }
@ -170,7 +162,7 @@ const InputVarList: FC<Props> = ({
value={varInput?.type === VarKindType.constant ? (varInput?.value || '') : (varInput?.value || [])} value={varInput?.type === VarKindType.constant ? (varInput?.value || '') : (varInput?.value || [])}
onChange={handleNotMixedTypeChange(variable)} onChange={handleNotMixedTypeChange(variable)}
onOpen={handleOpen(index)} onOpen={handleOpen(index)}
defaultVarKindType={isNumber ? VarKindType.constant : VarKindType.variable} defaultVarKindType={varInput?.type || (isNumber ? VarKindType.constant : VarKindType.variable)}
isSupportConstantValue={isSupportConstantValue} isSupportConstantValue={isSupportConstantValue}
filterVar={isNumber ? filterVar : undefined} filterVar={isNumber ? filterVar : undefined}
availableVars={isSelect ? availableVars : undefined} availableVars={isSelect ? availableVars : undefined}

@ -214,8 +214,13 @@ const useConfig = (id: string, payload: ToolNodeType) => {
.map(k => inputs.tool_parameters[k]) .map(k => inputs.tool_parameters[k])
const varInputs = getInputVars(hadVarParams.map((p) => { const varInputs = getInputVars(hadVarParams.map((p) => {
if (p.type === VarType.variable) if (p.type === VarType.variable) {
// handle the old wrong value not crash the page
if (!(p.value as any).join)
return `{{#${p.value}#}}`
return `{{#${(p.value as ValueSelector).join('.')}#}}` return `{{#${(p.value as ValueSelector).join('.')}#}}`
}
return p.value as string return p.value as string
})) }))

@ -1,6 +1,6 @@
{ {
"name": "dify-web", "name": "dify-web",
"version": "0.13.2", "version": "0.14.0",
"private": true, "private": true,
"engines": { "engines": {
"node": ">=18.17.0" "node": ">=18.17.0"

Loading…
Cancel
Save