Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat/enhance the multi-modal support #8818

Merged
merged 37 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
0eb53a2
feat(api): Enhance multi modal support.
laipz8200 Sep 1, 2024
b39ede9
feat(podcast_generator): add new podcast generation tools
laipz8200 Oct 12, 2024
bfdbbe3
fix(workflow): handle special values for process data consistently
laipz8200 Oct 14, 2024
1bad1da
refactor(prompt): improve handling of variable templates in advanced …
laipz8200 Oct 14, 2024
9305cb9
refactor(core): simplify role handling and improve usability
laipz8200 Oct 15, 2024
a6513c6
fix(memory): filter non-image file types in prompt message content
laipz8200 Oct 15, 2024
fb64397
refactor(core): improve type annotations and file handling consistency
laipz8200 Oct 15, 2024
5da907a
refactor(http_executor): improve HTTP request logging format
laipz8200 Oct 16, 2024
c9f4622
refactor(workflow): improve handling of outputs and inputs
laipz8200 Oct 16, 2024
bca8163
refactor(workflow): rename and restructure list filter components
laipz8200 Oct 16, 2024
849602f
refactor(workflow/nodes): unify filtering and ordering under a single…
laipz8200 Oct 16, 2024
7fdb1d7
refactor(api): enhance file streaming response handling
laipz8200 Oct 16, 2024
d6ca3b6
fix(file-serving): adjust content disposition header for images
laipz8200 Oct 16, 2024
587751b
refactor(tool_node): simplify tool_file_id assignment
laipz8200 Oct 16, 2024
6dbbad7
feat(podcast_audio_generator): improve audio generation workflow
laipz8200 Oct 17, 2024
7f156d9
fix(podcast_audio_generator): remove explicit format specification fo…
laipz8200 Oct 17, 2024
6854491
fix(podcast_audio_generator): specify audio format for file loading
laipz8200 Oct 17, 2024
740d2c8
fix(audio-generation): simplify audio response handling
laipz8200 Oct 17, 2024
849a2ac
feat(file-download): add inline or attachment option for file previews
laipz8200 Oct 17, 2024
900f5f4
fix(tool_files): correct typo in default argument for as_attachment
laipz8200 Oct 17, 2024
e04fcee
fix(tool_files): adjust argument order for as_attachment in parser
laipz8200 Oct 17, 2024
0c2c4c3
refactor(api): update file preview handling and support for audio files
laipz8200 Oct 18, 2024
df1d607
chore(dependencies): update openai package to version 1.52.0
laipz8200 Oct 18, 2024
05bcb6c
chore(dependencies): update openai version constraint
laipz8200 Oct 18, 2024
6ff72e6
chore(dependencies): update pydub version constraint and regenerate l…
laipz8200 Oct 18, 2024
1c1ff05
refactor(tests): improve unit test setup for prompt and document extr…
laipz8200 Oct 20, 2024
33d7eb9
refactor(constants): adjust document extension handling
laipz8200 Oct 20, 2024
69c3267
refactor(document_extractor): update module structure
laipz8200 Oct 20, 2024
8e49ad5
refactor(http_request): streamline HTTP request handling
laipz8200 Oct 20, 2024
2c799a2
refactor(http_request_node): reorganize imports for better readability
laipz8200 Oct 20, 2024
f1d2215
refactor(workflow): reorganize BaseNode import paths
laipz8200 Oct 20, 2024
40b97b0
refactor(workflow): consolidate BaseNodeData and related entities
laipz8200 Oct 20, 2024
d707c5e
delete(api): remove unused BaseIterationState entity
laipz8200 Oct 20, 2024
5cbc375
refactor(workflow): consolidate LLM-related imports and update events
laipz8200 Oct 20, 2024
650581e
refactor(nodes): restructure imports and organization
laipz8200 Oct 20, 2024
1233a5e
refactor(workflow): simplify node type mapping and initialization
laipz8200 Oct 20, 2024
fe47ecd
refactor(models): relocate and update enums usage
laipz8200 Oct 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions api/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ VIKINGDB_SOCKET_TIMEOUT=30
UPLOAD_FILE_SIZE_LIMIT=15
UPLOAD_FILE_BATCH_LIMIT=5
UPLOAD_IMAGE_FILE_SIZE_LIMIT=10
UPLOAD_VIDEO_FILE_SIZE_LIMIT=100
UPLOAD_AUDIO_FILE_SIZE_LIMIT=50

# Model Configuration
MULTIMODAL_SEND_IMAGE_FORMAT=base64
Expand Down Expand Up @@ -310,6 +312,7 @@ INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH=1000
WORKFLOW_MAX_EXECUTION_STEPS=500
WORKFLOW_MAX_EXECUTION_TIME=1200
WORKFLOW_CALL_MAX_DEPTH=5
MAX_VARIABLE_SIZE=204800

# App configuration
APP_MAX_EXECUTION_TIME=1200
Expand Down
15 changes: 11 additions & 4 deletions api/.vscode/launch.json.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
{
"version": "0.2.0",
"compounds": [
{
"name": "Launch Flask and Celery",
"configurations": ["Python: Flask", "Python: Celery"]
}
],
"configurations": [
{
"name": "Python: Flask",
"consoleName": "Flask",
"type": "debugpy",
"request": "launch",
"python": "${workspaceFolder}/.venv/bin/python",
Expand All @@ -17,12 +24,12 @@
},
"args": [
"run",
"--host=0.0.0.0",
"--port=5001"
]
},
{
"name": "Python: Celery",
"consoleName": "Celery",
"type": "debugpy",
"request": "launch",
"python": "${workspaceFolder}/.venv/bin/python",
Expand All @@ -45,10 +52,10 @@
"-c",
"1",
"--loglevel",
"info",
"DEBUG",
"-Q",
"dataset,generation,mail,ops_trace,app_deletion"
]
},
}
]
}
}
12 changes: 6 additions & 6 deletions api/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from libs.helper import email as email_validate
from libs.password import hash_password, password_pattern, valid_password
from libs.rsa import generate_key_pair
from models.account import Tenant
from models import Tenant
from models.dataset import Dataset, DatasetCollectionBinding, DocumentSegment
from models.dataset import Document as DatasetDocument
from models.model import Account, App, AppAnnotationSetting, AppMode, Conversation, MessageAnnotation
Expand Down Expand Up @@ -426,14 +426,14 @@ def convert_to_agent_apps():
# fetch first 1000 apps
sql_query = """SELECT a.id AS id FROM apps a
INNER JOIN app_model_configs am ON a.app_model_config_id=am.id
WHERE a.mode = 'chat'
AND am.agent_mode is not null
WHERE a.mode = 'chat'
AND am.agent_mode is not null
AND (
am.agent_mode like '%"strategy": "function_call"%'
am.agent_mode like '%"strategy": "function_call"%'
OR am.agent_mode like '%"strategy": "react"%'
)
)
AND (
am.agent_mode like '{"enabled": true%'
am.agent_mode like '{"enabled": true%'
OR am.agent_mode like '{"max_iteration": %'
) ORDER BY a.created_at DESC LIMIT 1000
"""
Expand Down
21 changes: 16 additions & 5 deletions api/configs/feature/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ class SecurityConfig(BaseSettings):
Security-related configurations for the application
"""

SECRET_KEY: Optional[str] = Field(
SECRET_KEY: str = Field(
description="Secret key for secure session cookie signing."
"Make sure you are changing this key for your deployment with a strong key."
"Generate a strong key using `openssl rand -base64 42` or set via the `SECRET_KEY` environment variable.",
default=None,
default="",
)

RESET_PASSWORD_TOKEN_EXPIRY_HOURS: PositiveInt = Field(
Expand Down Expand Up @@ -186,6 +186,16 @@ class FileUploadConfig(BaseSettings):
default=10,
)

UPLOAD_VIDEO_FILE_SIZE_LIMIT: NonNegativeInt = Field(
description="video file size limit in Megabytes for uploading files",
default=100,
)

UPLOAD_AUDIO_FILE_SIZE_LIMIT: NonNegativeInt = Field(
description="audio file size limit in Megabytes for uploading files",
default=50,
)

BATCH_UPLOAD_LIMIT: NonNegativeInt = Field(
description="Maximum number of files allowed in a batch upload operation",
default=20,
Expand Down Expand Up @@ -364,8 +374,8 @@ class WorkflowConfig(BaseSettings):
)

MAX_VARIABLE_SIZE: PositiveInt = Field(
description="Maximum size in bytes for a single variable in workflows. Default to 5KB.",
default=5 * 1024,
description="Maximum size in bytes for a single variable in workflows. Default to 200 KB.",
default=200 * 1024,
)


Expand Down Expand Up @@ -493,6 +503,7 @@ class RagEtlConfig(BaseSettings):
Configuration for RAG ETL processes
"""

# TODO: This config is not only for rag etl, it is also for file upload, we should move it to file upload config
ETL_TYPE: str = Field(
description="RAG ETL type ('dify' or 'Unstructured'), default to 'dify'",
default="dify",
Expand Down Expand Up @@ -559,7 +570,7 @@ class IndexingConfig(BaseSettings):


class ImageFormatConfig(BaseSettings):
MULTIMODAL_SEND_IMAGE_FORMAT: str = Field(
MULTIMODAL_SEND_IMAGE_FORMAT: Literal["base64", "url"] = Field(
description="Format for sending images in multimodal contexts ('base64' or 'url'), default is base64",
default="base64",
)
Expand Down
20 changes: 20 additions & 0 deletions api/constants/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,22 @@
from configs import dify_config

HIDDEN_VALUE = "[__HIDDEN__]"
UUID_NIL = "00000000-0000-0000-0000-000000000000"

IMAGE_EXTENSIONS = ["jpg", "jpeg", "png", "webp", "gif", "svg"]
IMAGE_EXTENSIONS.extend([ext.upper() for ext in IMAGE_EXTENSIONS])

VIDEO_EXTENSIONS = ["mp4", "mov", "mpeg", "mpga"]
VIDEO_EXTENSIONS.extend([ext.upper() for ext in VIDEO_EXTENSIONS])

AUDIO_EXTENSIONS = ["mp3", "m4a", "wav", "webm", "amr"]
AUDIO_EXTENSIONS.extend([ext.upper() for ext in AUDIO_EXTENSIONS])


if dify_config.ETL_TYPE == "Unstructured":
DOCUMENT_EXTENSIONS = ["txt", "markdown", "md", "pdf", "html", "htm", "xlsx", "xls"]
DOCUMENT_EXTENSIONS.extend(("docx", "csv", "eml", "msg", "pptx", "ppt", "xml", "epub"))
DOCUMENT_EXTENSIONS.extend([ext.upper() for ext in DOCUMENT_EXTENSIONS])
else:
DOCUMENT_EXTENSIONS = ["txt", "markdown", "md", "pdf", "html", "htm", "xlsx", "xls", "docx", "csv"]
DOCUMENT_EXTENSIONS.extend([ext.upper() for ext in DOCUMENT_EXTENSIONS])
6 changes: 4 additions & 2 deletions api/contexts/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from contextvars import ContextVar
from typing import TYPE_CHECKING

from core.workflow.entities.variable_pool import VariablePool
if TYPE_CHECKING:
from core.workflow.entities.variable_pool import VariablePool

tenant_id: ContextVar[str] = ContextVar("tenant_id")

workflow_variable_pool: ContextVar[VariablePool] = ContextVar("workflow_variable_pool")
workflow_variable_pool: ContextVar["VariablePool"] = ContextVar("workflow_variable_pool")
3 changes: 2 additions & 1 deletion api/controllers/console/app/conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
)
from libs.helper import DatetimeString
from libs.login import login_required
from models.model import AppMode, Conversation, EndUser, Message, MessageAnnotation
from models import Conversation, EndUser, Message, MessageAnnotation
from models.model import AppMode


class CompletionConversationApi(Resource):
Expand Down
2 changes: 1 addition & 1 deletion api/controllers/console/app/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from extensions.ext_database import db
from fields.app_fields import app_site_fields
from libs.login import login_required
from models.model import Site
from models import Site


def parse_app_site_args():
Expand Down
32 changes: 17 additions & 15 deletions api/controllers/console/app/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
from controllers.console.wraps import account_initialization_required
from core.app.apps.base_app_queue_manager import AppQueueManager
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.segments import factory
from core.errors.error import AppInvokeQuotaExceededError
from factories import variable_factory
from fields.workflow_fields import workflow_fields
from fields.workflow_run_fields import workflow_run_node_execution_fields
from libs import helper
from libs.helper import TimestampField, uuid_value
from libs.login import current_user, login_required
from models.model import App, AppMode
from models import App
from models.model import AppMode
from services.app_dsl_service import AppDslService
from services.app_generate_service import AppGenerateService
from services.errors.app import WorkflowHashNotEqualError
Expand Down Expand Up @@ -101,9 +101,13 @@ def post(self, app_model: App):

try:
environment_variables_list = args.get("environment_variables") or []
environment_variables = [factory.build_variable_from_mapping(obj) for obj in environment_variables_list]
environment_variables = [
variable_factory.build_variable_from_mapping(obj) for obj in environment_variables_list
]
conversation_variables_list = args.get("conversation_variables") or []
conversation_variables = [factory.build_variable_from_mapping(obj) for obj in conversation_variables_list]
conversation_variables = [
variable_factory.build_variable_from_mapping(obj) for obj in conversation_variables_list
]
workflow = workflow_service.sync_draft_workflow(
app_model=app_model,
graph=args["graph"],
Expand Down Expand Up @@ -273,17 +277,15 @@ def post(self, app_model: App):
parser.add_argument("files", type=list, required=False, location="json")
args = parser.parse_args()

try:
response = AppGenerateService.generate(
app_model=app_model, user=current_user, args=args, invoke_from=InvokeFrom.DEBUGGER, streaming=True
)
response = AppGenerateService.generate(
app_model=app_model,
user=current_user,
args=args,
invoke_from=InvokeFrom.DEBUGGER,
streaming=True,
)

return helper.compact_generate_response(response)
except (ValueError, AppInvokeQuotaExceededError) as e:
raise e
except Exception as e:
logging.exception("internal server error.")
raise InternalServerError()
return helper.compact_generate_response(response)


class WorkflowTaskStopApi(Resource):
Expand Down
3 changes: 2 additions & 1 deletion api/controllers/console/app/workflow_app_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from controllers.console.wraps import account_initialization_required
from fields.workflow_app_log_fields import workflow_app_log_pagination_fields
from libs.login import login_required
from models.model import App, AppMode
from models import App
from models.model import AppMode
from services.workflow_app_service import WorkflowAppService


Expand Down
3 changes: 2 additions & 1 deletion api/controllers/console/app/workflow_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
)
from libs.helper import uuid_value
from libs.login import login_required
from models.model import App, AppMode
from models import App
from models.model import AppMode
from services.workflow_run_service import WorkflowRunService


Expand Down
2 changes: 1 addition & 1 deletion api/controllers/console/app/workflow_statistic.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
from extensions.ext_database import db
from libs.helper import DatetimeString
from libs.login import login_required
from models.enums import WorkflowRunTriggeredFrom
from models.model import AppMode
from models.workflow import WorkflowRunTriggeredFrom


class WorkflowDailyRunsStatistic(Resource):
Expand Down
3 changes: 2 additions & 1 deletion api/controllers/console/app/wraps.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from controllers.console.app.error import AppNotFoundError
from extensions.ext_database import db
from libs.login import current_user
from models.model import App, AppMode
from models import App
from models.model import AppMode


def get_app_model(view: Optional[Callable] = None, *, mode: Union[AppMode, list[AppMode]] = None):
Expand Down
3 changes: 2 additions & 1 deletion api/controllers/console/auth/oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
from extensions.ext_database import db
from libs.helper import extract_remote_ip
from libs.oauth import GitHubOAuth, GoogleOAuth, OAuthUserInfo
from models.account import Account, AccountStatus
from models import Account
from models.account import AccountStatus
from services.account_service import AccountService, RegisterService, TenantService
from services.errors.account import AccountNotFoundError
from services.errors.workspace import WorkSpaceNotAllowedCreateError, WorkSpaceNotFoundError
Expand Down
3 changes: 1 addition & 2 deletions api/controllers/console/datasets/data_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
from extensions.ext_database import db
from fields.data_source_fields import integrate_list_fields, integrate_notion_info_list_fields
from libs.login import login_required
from models.dataset import Document
from models.source import DataSourceOauthBinding
from models import DataSourceOauthBinding, Document
from services.dataset_service import DatasetService, DocumentService
from tasks.document_indexing_sync_task import document_indexing_sync_task

Expand Down
4 changes: 2 additions & 2 deletions api/controllers/console/datasets/datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
from fields.dataset_fields import dataset_detail_fields, dataset_query_detail_fields
from fields.document_fields import document_status_fields
from libs.login import login_required
from models.dataset import Dataset, DatasetPermissionEnum, Document, DocumentSegment
from models.model import ApiToken, UploadFile
from models import ApiToken, Dataset, Document, DocumentSegment, UploadFile
from models.dataset import DatasetPermissionEnum
from services.dataset_service import DatasetPermissionService, DatasetService, DocumentService


Expand Down
3 changes: 1 addition & 2 deletions api/controllers/console/datasets/datasets_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@
document_with_segments_fields,
)
from libs.login import login_required
from models.dataset import Dataset, DatasetProcessRule, Document, DocumentSegment
from models.model import UploadFile
from models import Dataset, DatasetProcessRule, Document, DocumentSegment, UploadFile
from services.dataset_service import DatasetService, DocumentService
from tasks.add_document_to_index_task import add_document_to_index_task
from tasks.remove_document_from_index_task import remove_document_from_index_task
Expand Down
2 changes: 1 addition & 1 deletion api/controllers/console/datasets/datasets_segments.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from extensions.ext_redis import redis_client
from fields.segment_fields import segment_fields
from libs.login import login_required
from models.dataset import DocumentSegment
from models import DocumentSegment
from services.dataset_service import DatasetService, DocumentService, SegmentService
from tasks.batch_create_segment_to_index_task import batch_create_segment_to_index_task
from tasks.disable_segment_from_index_task import disable_segment_from_index_task
Expand Down
Loading
Loading