Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
dify
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tech
dify
Commits
6e3cd62e
Commit
6e3cd62e
authored
Feb 27, 2024
by
takatost
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor app mode
add app import and export
parent
61b4bedc
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
370 additions
and
687 deletions
+370
-687
languages.py
api/constants/languages.py
+0
-436
model_template.py
api/constants/model_template.py
+39
-58
app.py
api/controllers/console/app/app.py
+161
-78
workflow.py
api/controllers/console/app/workflow.py
+6
-5
wraps.py
api/controllers/console/app/wraps.py
+5
-13
installed_app.py
api/controllers/console/explore/installed_app.py
+1
-2
recommended_app.py
api/controllers/console/explore/recommended_app.py
+36
-28
provider_manager.py
api/core/provider_manager.py
+1
-1
app_fields.py
api/fields/app_fields.py
+0
-12
installed_app_fields.py
api/fields/installed_app_fields.py
+1
-2
b289e2408ee2_add_workflow.py
api/migrations/versions/b289e2408ee2_add_workflow.py
+0
-2
cc04d0998d4d_set_model_config_column_nullable.py
...versions/cc04d0998d4d_set_model_config_column_nullable.py
+70
-0
model.py
api/models/model.py
+12
-41
workflow_converter.py
api/services/workflow/workflow_converter.py
+1
-3
workflow_service.py
api/services/workflow_service.py
+37
-6
No files found.
api/constants/languages.py
View file @
6e3cd62e
This diff is collapsed.
Click to expand it.
api/constants/model_template.py
View file @
6e3cd62e
import
json
from
models.model
import
AppMode
model
_templates
=
{
default_app
_templates
=
{
# workflow default mode
'workflow_default'
:
{
AppMode
.
WORKFLOW
:
{
'app'
:
{
'mode'
:
'workflow'
,
'mode'
:
AppMode
.
WORKFLOW
.
value
,
'enable_site'
:
True
,
'enable_api'
:
True
,
'is_demo'
:
False
,
'api_rpm'
:
0
,
'api_rph'
:
0
,
'status'
:
'normal'
'enable_api'
:
True
},
'model_config'
:
{
'provider'
:
''
,
'model_id'
:
''
,
'configs'
:
{}
}
'model_config'
:
{}
},
# chat default mode
'chat_default'
:
{
AppMode
.
CHAT
:
{
'app'
:
{
'mode'
:
'chat'
,
'mode'
:
AppMode
.
CHAT
.
value
,
'enable_site'
:
True
,
'enable_api'
:
True
,
'is_demo'
:
False
,
'api_rpm'
:
0
,
'api_rph'
:
0
,
'status'
:
'normal'
'enable_api'
:
True
},
'model_config'
:
{
'provider'
:
'openai'
,
'model_id'
:
'gpt-4'
,
'configs'
:
{
'prompt_template'
:
''
,
'prompt_variables'
:
[],
'completion_params'
:
{
'max_token'
:
512
,
'temperature'
:
1
,
'top_p'
:
1
,
'presence_penalty'
:
0
,
'frequency_penalty'
:
0
,
}
},
'model'
:
json
.
dumps
({
'model'
:
{
"provider"
:
"openai"
,
"name"
:
"gpt-4"
,
"mode"
:
"chat"
,
...
...
@@ -55,36 +30,42 @@ model_templates = {
"presence_penalty"
:
0
,
"frequency_penalty"
:
0
}
}
)
}
}
},
# a
gen
t default mode
'agent_default'
:
{
# a
dvanced-cha
t default mode
AppMode
.
ADVANCED_CHAT
:
{
'app'
:
{
'mode'
:
'agent'
,
'mode'
:
AppMode
.
ADVANCED_CHAT
.
value
,
'enable_site'
:
True
,
'enable_api'
:
True
,
'is_demo'
:
False
,
'api_rpm'
:
0
,
'api_rph'
:
0
,
'status'
:
'normal'
'enable_api'
:
True
},
'model_config'
:
{
'provider'
:
'openai'
,
'model_id'
:
'gpt-4'
,
'configs'
:
{
'prompt_template'
:
''
,
'prompt_variables'
:
[],
'completion_params'
:
{
'max_token'
:
512
,
'temperature'
:
1
,
'top_p'
:
1
,
'presence_penalty'
:
0
,
'frequency_penalty'
:
0
,
'model'
:
{
"provider"
:
"openai"
,
"name"
:
"gpt-4"
,
"mode"
:
"chat"
,
"completion_params"
:
{
"max_tokens"
:
512
,
"temperature"
:
1
,
"top_p"
:
1
,
"presence_penalty"
:
0
,
"frequency_penalty"
:
0
}
},
'model'
:
json
.
dumps
({
}
}
},
# agent-chat default mode
AppMode
.
AGENT_CHAT
:
{
'app'
:
{
'mode'
:
AppMode
.
AGENT_CHAT
.
value
,
'enable_site'
:
True
,
'enable_api'
:
True
},
'model_config'
:
{
'model'
:
{
"provider"
:
"openai"
,
"name"
:
"gpt-4"
,
"mode"
:
"chat"
,
...
...
@@ -95,7 +76,7 @@ model_templates = {
"presence_penalty"
:
0
,
"frequency_penalty"
:
0
}
}
)
}
}
},
}
...
...
api/controllers/console/app/app.py
View file @
6e3cd62e
This diff is collapsed.
Click to expand it.
api/controllers/console/app/workflow.py
View file @
6e3cd62e
...
...
@@ -7,7 +7,7 @@ from controllers.console.setup import setup_required
from
controllers.console.wraps
import
account_initialization_required
from
fields.workflow_fields
import
workflow_fields
from
libs.login
import
current_user
,
login_required
from
models.model
import
App
,
AppMode
,
ChatbotAppEngine
from
models.model
import
App
,
AppMode
from
services.workflow_service
import
WorkflowService
...
...
@@ -15,7 +15,7 @@ class DraftWorkflowApi(Resource):
@
setup_required
@
login_required
@
account_initialization_required
@
get_app_model
(
mode
=
[
AppMode
.
CHAT
,
AppMode
.
WORKFLOW
],
app_engine
=
ChatbotAppEngine
.
WORKFLOW
)
@
get_app_model
(
mode
=
[
AppMode
.
ADVANCED_CHAT
,
AppMode
.
WORKFLOW
]
)
@
marshal_with
(
workflow_fields
)
def
get
(
self
,
app_model
:
App
):
"""
...
...
@@ -34,7 +34,7 @@ class DraftWorkflowApi(Resource):
@
setup_required
@
login_required
@
account_initialization_required
@
get_app_model
(
mode
=
[
AppMode
.
CHAT
,
AppMode
.
WORKFLOW
],
app_engine
=
ChatbotAppEngine
.
WORKFLOW
)
@
get_app_model
(
mode
=
[
AppMode
.
ADVANCED_CHAT
,
AppMode
.
WORKFLOW
]
)
def
post
(
self
,
app_model
:
App
):
"""
Sync draft workflow
...
...
@@ -55,7 +55,7 @@ class DefaultBlockConfigApi(Resource):
@
setup_required
@
login_required
@
account_initialization_required
@
get_app_model
(
mode
=
[
AppMode
.
CHAT
,
AppMode
.
WORKFLOW
],
app_engine
=
ChatbotAppEngine
.
WORKFLOW
)
@
get_app_model
(
mode
=
[
AppMode
.
ADVANCED_CHAT
,
AppMode
.
WORKFLOW
]
)
def
get
(
self
,
app_model
:
App
):
"""
Get default block config
...
...
@@ -72,7 +72,8 @@ class ConvertToWorkflowApi(Resource):
@
get_app_model
(
mode
=
[
AppMode
.
CHAT
,
AppMode
.
COMPLETION
])
def
post
(
self
,
app_model
:
App
):
"""
Convert basic mode of chatbot app(expert mode) to workflow mode
Convert basic mode of chatbot app to workflow mode
Convert expert mode of chatbot app to workflow mode
Convert Completion App to Workflow App
"""
# convert to workflow mode
...
...
api/controllers/console/app/wraps.py
View file @
6e3cd62e
...
...
@@ -5,12 +5,11 @@ from typing import Optional, Union
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
,
ChatbotAppEngine
from
models.model
import
App
,
AppMode
def
get_app_model
(
view
:
Optional
[
Callable
]
=
None
,
*
,
mode
:
Union
[
AppMode
,
list
[
AppMode
]]
=
None
,
app_engine
:
ChatbotAppEngine
=
None
):
mode
:
Union
[
AppMode
,
list
[
AppMode
]]
=
None
):
def
decorator
(
view_func
):
@
wraps
(
view_func
)
def
decorated_view
(
*
args
,
**
kwargs
):
...
...
@@ -32,6 +31,9 @@ def get_app_model(view: Optional[Callable] = None, *,
raise
AppNotFoundError
()
app_mode
=
AppMode
.
value_of
(
app_model
.
mode
)
if
app_mode
==
AppMode
.
CHANNEL
:
raise
AppNotFoundError
()
if
mode
is
not
None
:
if
isinstance
(
mode
,
list
):
modes
=
mode
...
...
@@ -42,16 +44,6 @@ def get_app_model(view: Optional[Callable] = None, *,
mode_values
=
{
m
.
value
for
m
in
modes
}
raise
AppNotFoundError
(
f
"App mode is not in the supported list: {mode_values}"
)
if
app_engine
is
not
None
:
if
app_mode
not
in
[
AppMode
.
CHAT
,
AppMode
.
WORKFLOW
]:
raise
AppNotFoundError
(
f
"App mode is not supported for {app_engine.value} app engine."
)
if
app_mode
==
AppMode
.
CHAT
:
# fetch current app model config
app_model_config
=
app_model
.
app_model_config
if
not
app_model_config
or
app_model_config
.
chatbot_app_engine
!=
app_engine
.
value
:
raise
AppNotFoundError
(
f
"{app_engine.value} app engine is not supported."
)
kwargs
[
'app_model'
]
=
app_model
return
view_func
(
*
args
,
**
kwargs
)
...
...
api/controllers/console/explore/installed_app.py
View file @
6e3cd62e
...
...
@@ -34,8 +34,7 @@ class InstalledAppsListApi(Resource):
'is_pinned'
:
installed_app
.
is_pinned
,
'last_used_at'
:
installed_app
.
last_used_at
,
'editable'
:
current_user
.
role
in
[
"owner"
,
"admin"
],
'uninstallable'
:
current_tenant_id
==
installed_app
.
app_owner_tenant_id
,
'is_agent'
:
installed_app
.
is_agent
'uninstallable'
:
current_tenant_id
==
installed_app
.
app_owner_tenant_id
}
for
installed_app
in
installed_apps
]
...
...
api/controllers/console/explore/recommended_app.py
View file @
6e3cd62e
import
json
import
yaml
from
flask_login
import
current_user
from
flask_restful
import
Resource
,
fields
,
marshal_with
,
reqparse
...
...
@@ -6,6 +9,7 @@ from controllers.console import api
from
controllers.console.app.error
import
AppNotFoundError
from
extensions.ext_database
import
db
from
models.model
import
App
,
RecommendedApp
from
services.workflow_service
import
WorkflowService
app_fields
=
{
'id'
:
fields
.
String
,
...
...
@@ -23,8 +27,7 @@ recommended_app_fields = {
'privacy_policy'
:
fields
.
String
,
'category'
:
fields
.
String
,
'position'
:
fields
.
Integer
,
'is_listed'
:
fields
.
Boolean
,
'is_agent'
:
fields
.
Boolean
'is_listed'
:
fields
.
Boolean
}
recommended_app_list_fields
=
{
...
...
@@ -73,8 +76,7 @@ class RecommendedAppListApi(Resource):
'privacy_policy'
:
site
.
privacy_policy
,
'category'
:
recommended_app
.
category
,
'position'
:
recommended_app
.
position
,
'is_listed'
:
recommended_app
.
is_listed
,
"is_agent"
:
app
.
is_agent
'is_listed'
:
recommended_app
.
is_listed
}
recommended_apps_result
.
append
(
recommended_app_result
)
...
...
@@ -84,27 +86,6 @@ class RecommendedAppListApi(Resource):
class
RecommendedAppApi
(
Resource
):
model_config_fields
=
{
'opening_statement'
:
fields
.
String
,
'suggested_questions'
:
fields
.
Raw
(
attribute
=
'suggested_questions_list'
),
'suggested_questions_after_answer'
:
fields
.
Raw
(
attribute
=
'suggested_questions_after_answer_dict'
),
'more_like_this'
:
fields
.
Raw
(
attribute
=
'more_like_this_dict'
),
'model'
:
fields
.
Raw
(
attribute
=
'model_dict'
),
'user_input_form'
:
fields
.
Raw
(
attribute
=
'user_input_form_list'
),
'pre_prompt'
:
fields
.
String
,
'agent_mode'
:
fields
.
Raw
(
attribute
=
'agent_mode_dict'
),
}
app_simple_detail_fields
=
{
'id'
:
fields
.
String
,
'name'
:
fields
.
String
,
'icon'
:
fields
.
String
,
'icon_background'
:
fields
.
String
,
'mode'
:
fields
.
String
,
'app_model_config'
:
fields
.
Nested
(
model_config_fields
),
}
@
marshal_with
(
app_simple_detail_fields
)
def
get
(
self
,
app_id
):
app_id
=
str
(
app_id
)
...
...
@@ -118,11 +99,38 @@ class RecommendedAppApi(Resource):
raise
AppNotFoundError
# get app detail
app
=
db
.
session
.
query
(
App
)
.
filter
(
App
.
id
==
app_id
)
.
first
()
if
not
app
or
not
app
.
is_public
:
app
_model
=
db
.
session
.
query
(
App
)
.
filter
(
App
.
id
==
app_id
)
.
first
()
if
not
app
_model
or
not
app_model
.
is_public
:
raise
AppNotFoundError
return
app
app_model_config
=
app_model
.
app_model_config
export_data
=
{
"app"
:
{
"name"
:
app_model
.
name
,
"mode"
:
app_model
.
mode
,
"icon"
:
app_model
.
icon
,
"icon_background"
:
app_model
.
icon_background
},
"model_config"
:
app_model_config
.
to_dict
(),
}
if
app_model_config
.
workflow_id
:
export_data
[
'workflow_graph'
]
=
json
.
loads
(
app_model_config
.
workflow
.
graph
)
else
:
# get draft workflow
workflow_service
=
WorkflowService
()
workflow
=
workflow_service
.
get_draft_workflow
(
app_model
)
export_data
[
'workflow_graph'
]
=
json
.
loads
(
workflow
.
graph
)
return
{
'id'
:
app_model
.
id
,
'name'
:
app_model
.
name
,
'icon'
:
app_model
.
icon
,
'icon_background'
:
app_model
.
icon_background
,
'mode'
:
app_model
.
mode
,
'export_data'
:
yaml
.
dump
(
export_data
)
}
api
.
add_resource
(
RecommendedAppListApi
,
'/explore/apps'
)
...
...
api/core/provider_manager.py
View file @
6e3cd62e
...
...
@@ -235,7 +235,7 @@ class ProviderManager:
if
available_models
:
found
=
False
for
available_model
in
available_models
:
if
available_model
.
model
==
"gpt-
3.5-turbo-1106
"
:
if
available_model
.
model
==
"gpt-
4
"
:
default_model
=
TenantDefaultModel
(
tenant_id
=
tenant_id
,
model_type
=
model_type
.
to_origin_model_type
(),
...
...
api/fields/app_fields.py
View file @
6e3cd62e
...
...
@@ -42,14 +42,10 @@ app_detail_fields = {
'id'
:
fields
.
String
,
'name'
:
fields
.
String
,
'mode'
:
fields
.
String
,
'is_agent'
:
fields
.
Boolean
,
'icon'
:
fields
.
String
,
'icon_background'
:
fields
.
String
,
'enable_site'
:
fields
.
Boolean
,
'enable_api'
:
fields
.
Boolean
,
'api_rpm'
:
fields
.
Integer
,
'api_rph'
:
fields
.
Integer
,
'is_demo'
:
fields
.
Boolean
,
'model_config'
:
fields
.
Nested
(
model_config_fields
,
attribute
=
'app_model_config'
),
'created_at'
:
TimestampField
}
...
...
@@ -67,12 +63,8 @@ app_partial_fields = {
'id'
:
fields
.
String
,
'name'
:
fields
.
String
,
'mode'
:
fields
.
String
,
'is_agent'
:
fields
.
Boolean
,
'icon'
:
fields
.
String
,
'icon_background'
:
fields
.
String
,
'enable_site'
:
fields
.
Boolean
,
'enable_api'
:
fields
.
Boolean
,
'is_demo'
:
fields
.
Boolean
,
'model_config'
:
fields
.
Nested
(
model_config_partial_fields
,
attribute
=
'app_model_config'
),
'created_at'
:
TimestampField
}
...
...
@@ -122,10 +114,6 @@ app_detail_fields_with_site = {
'icon_background'
:
fields
.
String
,
'enable_site'
:
fields
.
Boolean
,
'enable_api'
:
fields
.
Boolean
,
'api_rpm'
:
fields
.
Integer
,
'api_rph'
:
fields
.
Integer
,
'is_agent'
:
fields
.
Boolean
,
'is_demo'
:
fields
.
Boolean
,
'model_config'
:
fields
.
Nested
(
model_config_fields
,
attribute
=
'app_model_config'
),
'site'
:
fields
.
Nested
(
site_fields
),
'api_base_url'
:
fields
.
String
,
...
...
api/fields/installed_app_fields.py
View file @
6e3cd62e
...
...
@@ -17,8 +17,7 @@ installed_app_fields = {
'is_pinned'
:
fields
.
Boolean
,
'last_used_at'
:
TimestampField
,
'editable'
:
fields
.
Boolean
,
'uninstallable'
:
fields
.
Boolean
,
'is_agent'
:
fields
.
Boolean
,
'uninstallable'
:
fields
.
Boolean
}
installed_app_list_fields
=
{
...
...
api/migrations/versions/b289e2408ee2_add_workflow.py
View file @
6e3cd62e
...
...
@@ -107,7 +107,6 @@ def upgrade():
batch_op
.
create_index
(
'workflow_version_idx'
,
[
'tenant_id'
,
'app_id'
,
'version'
],
unique
=
False
)
with
op
.
batch_alter_table
(
'app_model_configs'
,
schema
=
None
)
as
batch_op
:
batch_op
.
add_column
(
sa
.
Column
(
'chatbot_app_engine'
,
sa
.
String
(
length
=
255
),
server_default
=
sa
.
text
(
"'normal'::character varying"
),
nullable
=
False
))
batch_op
.
add_column
(
sa
.
Column
(
'workflow_id'
,
postgresql
.
UUID
(),
nullable
=
True
))
with
op
.
batch_alter_table
(
'messages'
,
schema
=
None
)
as
batch_op
:
...
...
@@ -123,7 +122,6 @@ def downgrade():
with
op
.
batch_alter_table
(
'app_model_configs'
,
schema
=
None
)
as
batch_op
:
batch_op
.
drop_column
(
'workflow_id'
)
batch_op
.
drop_column
(
'chatbot_app_engine'
)
with
op
.
batch_alter_table
(
'workflows'
,
schema
=
None
)
as
batch_op
:
batch_op
.
drop_index
(
'workflow_version_idx'
)
...
...
api/migrations/versions/cc04d0998d4d_set_model_config_column_nullable.py
0 → 100644
View file @
6e3cd62e
"""set model config column nullable
Revision ID: cc04d0998d4d
Revises: b289e2408ee2
Create Date: 2024-02-27 03:47:47.376325
"""
from
alembic
import
op
import
sqlalchemy
as
sa
from
sqlalchemy.dialects
import
postgresql
# revision identifiers, used by Alembic.
revision
=
'cc04d0998d4d'
down_revision
=
'b289e2408ee2'
branch_labels
=
None
depends_on
=
None
def
upgrade
():
# ### commands auto generated by Alembic - please adjust! ###
with
op
.
batch_alter_table
(
'app_model_configs'
,
schema
=
None
)
as
batch_op
:
batch_op
.
alter_column
(
'provider'
,
existing_type
=
sa
.
VARCHAR
(
length
=
255
),
nullable
=
True
)
batch_op
.
alter_column
(
'model_id'
,
existing_type
=
sa
.
VARCHAR
(
length
=
255
),
nullable
=
True
)
batch_op
.
alter_column
(
'configs'
,
existing_type
=
postgresql
.
JSON
(
astext_type
=
sa
.
Text
()),
nullable
=
True
)
with
op
.
batch_alter_table
(
'apps'
,
schema
=
None
)
as
batch_op
:
batch_op
.
alter_column
(
'api_rpm'
,
existing_type
=
sa
.
Integer
(),
server_default
=
'0'
,
nullable
=
False
)
batch_op
.
alter_column
(
'api_rph'
,
existing_type
=
sa
.
Integer
(),
server_default
=
'0'
,
nullable
=
False
)
# ### end Alembic commands ###
def
downgrade
():
# ### commands auto generated by Alembic - please adjust! ###
with
op
.
batch_alter_table
(
'apps'
,
schema
=
None
)
as
batch_op
:
batch_op
.
alter_column
(
'api_rpm'
,
existing_type
=
sa
.
Integer
(),
server_default
=
None
,
nullable
=
False
)
batch_op
.
alter_column
(
'api_rph'
,
existing_type
=
sa
.
Integer
(),
server_default
=
None
,
nullable
=
False
)
with
op
.
batch_alter_table
(
'app_model_configs'
,
schema
=
None
)
as
batch_op
:
batch_op
.
alter_column
(
'configs'
,
existing_type
=
postgresql
.
JSON
(
astext_type
=
sa
.
Text
()),
nullable
=
False
)
batch_op
.
alter_column
(
'model_id'
,
existing_type
=
sa
.
VARCHAR
(
length
=
255
),
nullable
=
False
)
batch_op
.
alter_column
(
'provider'
,
existing_type
=
sa
.
VARCHAR
(
length
=
255
),
nullable
=
False
)
# ### end Alembic commands ###
api/models/model.py
View file @
6e3cd62e
...
...
@@ -31,7 +31,9 @@ class AppMode(Enum):
COMPLETION
=
'completion'
WORKFLOW
=
'workflow'
CHAT
=
'chat'
AGENT
=
'agent'
ADVANCED_CHAT
=
'advanced-chat'
AGENT_CHAT
=
'agent-chat'
CHANNEL
=
'channel'
@
classmethod
def
value_of
(
cls
,
value
:
str
)
->
'AppMode'
:
...
...
@@ -64,8 +66,8 @@ class App(db.Model):
status
=
db
.
Column
(
db
.
String
(
255
),
nullable
=
False
,
server_default
=
db
.
text
(
"'normal'::character varying"
))
enable_site
=
db
.
Column
(
db
.
Boolean
,
nullable
=
False
)
enable_api
=
db
.
Column
(
db
.
Boolean
,
nullable
=
False
)
api_rpm
=
db
.
Column
(
db
.
Integer
,
nullable
=
False
)
api_rph
=
db
.
Column
(
db
.
Integer
,
nullable
=
False
)
api_rpm
=
db
.
Column
(
db
.
Integer
,
nullable
=
False
,
server_default
=
db
.
text
(
'0'
)
)
api_rph
=
db
.
Column
(
db
.
Integer
,
nullable
=
False
,
server_default
=
db
.
text
(
'0'
)
)
is_demo
=
db
.
Column
(
db
.
Boolean
,
nullable
=
False
,
server_default
=
db
.
text
(
'false'
))
is_public
=
db
.
Column
(
db
.
Boolean
,
nullable
=
False
,
server_default
=
db
.
text
(
'false'
))
is_universal
=
db
.
Column
(
db
.
Boolean
,
nullable
=
False
,
server_default
=
db
.
text
(
'false'
))
...
...
@@ -92,19 +94,7 @@ class App(db.Model):
def
tenant
(
self
):
tenant
=
db
.
session
.
query
(
Tenant
)
.
filter
(
Tenant
.
id
==
self
.
tenant_id
)
.
first
()
return
tenant
@
property
def
is_agent
(
self
)
->
bool
:
app_model_config
=
self
.
app_model_config
if
not
app_model_config
:
return
False
if
not
app_model_config
.
agent_mode
:
return
False
if
self
.
app_model_config
.
agent_mode_dict
.
get
(
'enabled'
,
False
)
\
and
self
.
app_model_config
.
agent_mode_dict
.
get
(
'strategy'
,
''
)
in
[
'function_call'
,
'react'
]:
return
True
return
False
@
property
def
deleted_tools
(
self
)
->
list
:
# get agent mode tools
...
...
@@ -153,11 +143,6 @@ class App(db.Model):
return
deleted_tools
class
ChatbotAppEngine
(
Enum
):
NORMAL
=
'normal'
WORKFLOW
=
'workflow'
class
AppModelConfig
(
db
.
Model
):
__tablename__
=
'app_model_configs'
__table_args__
=
(
...
...
@@ -167,9 +152,9 @@ class AppModelConfig(db.Model):
id
=
db
.
Column
(
UUID
,
server_default
=
db
.
text
(
'uuid_generate_v4()'
))
app_id
=
db
.
Column
(
UUID
,
nullable
=
False
)
provider
=
db
.
Column
(
db
.
String
(
255
),
nullable
=
Fals
e
)
model_id
=
db
.
Column
(
db
.
String
(
255
),
nullable
=
Fals
e
)
configs
=
db
.
Column
(
db
.
JSON
,
nullable
=
Fals
e
)
provider
=
db
.
Column
(
db
.
String
(
255
),
nullable
=
Tru
e
)
model_id
=
db
.
Column
(
db
.
String
(
255
),
nullable
=
Tru
e
)
configs
=
db
.
Column
(
db
.
JSON
,
nullable
=
Tru
e
)
created_at
=
db
.
Column
(
db
.
DateTime
,
nullable
=
False
,
server_default
=
db
.
text
(
'CURRENT_TIMESTAMP(0)'
))
updated_at
=
db
.
Column
(
db
.
DateTime
,
nullable
=
False
,
server_default
=
db
.
text
(
'CURRENT_TIMESTAMP(0)'
))
opening_statement
=
db
.
Column
(
db
.
Text
)
...
...
@@ -191,7 +176,6 @@ class AppModelConfig(db.Model):
dataset_configs
=
db
.
Column
(
db
.
Text
)
external_data_tools
=
db
.
Column
(
db
.
Text
)
file_upload
=
db
.
Column
(
db
.
Text
)
chatbot_app_engine
=
db
.
Column
(
db
.
String
(
255
),
nullable
=
False
,
server_default
=
db
.
text
(
"'normal'::character varying"
))
workflow_id
=
db
.
Column
(
UUID
)
@
property
...
...
@@ -301,9 +285,6 @@ class AppModelConfig(db.Model):
def
to_dict
(
self
)
->
dict
:
return
{
"provider"
:
""
,
"model_id"
:
""
,
"configs"
:
{},
"opening_statement"
:
self
.
opening_statement
,
"suggested_questions"
:
self
.
suggested_questions_list
,
"suggested_questions_after_answer"
:
self
.
suggested_questions_after_answer_dict
,
...
...
@@ -327,9 +308,6 @@ class AppModelConfig(db.Model):
}
def
from_model_config_dict
(
self
,
model_config
:
dict
):
self
.
provider
=
""
self
.
model_id
=
""
self
.
configs
=
{}
self
.
opening_statement
=
model_config
[
'opening_statement'
]
self
.
suggested_questions
=
json
.
dumps
(
model_config
[
'suggested_questions'
])
self
.
suggested_questions_after_answer
=
json
.
dumps
(
model_config
[
'suggested_questions_after_answer'
])
...
...
@@ -358,15 +336,13 @@ class AppModelConfig(db.Model):
if
model_config
.
get
(
'dataset_configs'
)
else
None
self
.
file_upload
=
json
.
dumps
(
model_config
.
get
(
'file_upload'
))
\
if
model_config
.
get
(
'file_upload'
)
else
None
self
.
workflow_id
=
model_config
.
get
(
'workflow_id'
)
return
self
def
copy
(
self
):
new_app_model_config
=
AppModelConfig
(
id
=
self
.
id
,
app_id
=
self
.
app_id
,
provider
=
""
,
model_id
=
""
,
configs
=
{},
opening_statement
=
self
.
opening_statement
,
suggested_questions
=
self
.
suggested_questions
,
suggested_questions_after_answer
=
self
.
suggested_questions_after_answer
,
...
...
@@ -385,7 +361,8 @@ class AppModelConfig(db.Model):
chat_prompt_config
=
self
.
chat_prompt_config
,
completion_prompt_config
=
self
.
completion_prompt_config
,
dataset_configs
=
self
.
dataset_configs
,
file_upload
=
self
.
file_upload
file_upload
=
self
.
file_upload
,
workflow_id
=
self
.
workflow_id
)
return
new_app_model_config
...
...
@@ -446,12 +423,6 @@ class InstalledApp(db.Model):
tenant
=
db
.
session
.
query
(
Tenant
)
.
filter
(
Tenant
.
id
==
self
.
tenant_id
)
.
first
()
return
tenant
@
property
def
is_agent
(
self
)
->
bool
:
app
=
self
.
app
if
not
app
:
return
False
return
app
.
is_agent
class
Conversation
(
db
.
Model
):
__tablename__
=
'conversations'
...
...
api/services/workflow/workflow_converter.py
View file @
6e3cd62e
...
...
@@ -21,7 +21,7 @@ from events.app_event import app_was_created
from
extensions.ext_database
import
db
from
models.account
import
Account
from
models.api_based_extension
import
APIBasedExtension
,
APIBasedExtensionPoint
from
models.model
import
App
,
AppMode
,
AppModelConfig
,
ChatbotAppEngine
,
Site
from
models.model
import
App
,
AppMode
,
AppModelConfig
,
Site
from
models.workflow
import
Workflow
,
WorkflowType
...
...
@@ -85,8 +85,6 @@ class WorkflowConverter:
new_app_model_config
.
chat_prompt_config
=
''
new_app_model_config
.
completion_prompt_config
=
''
new_app_model_config
.
dataset_configs
=
''
new_app_model_config
.
chatbot_app_engine
=
ChatbotAppEngine
.
WORKFLOW
.
value
\
if
app_model
.
mode
==
AppMode
.
CHAT
.
value
else
ChatbotAppEngine
.
NORMAL
.
value
new_app_model_config
.
workflow_id
=
workflow
.
id
db
.
session
.
add
(
new_app_model_config
)
...
...
api/services/workflow_service.py
View file @
6e3cd62e
import
json
from
datetime
import
datetime
from
typing
import
Optional
from
extensions.ext_database
import
db
from
models.account
import
Account
from
models.model
import
App
,
AppMode
,
ChatbotAppEngine
from
models.model
import
App
,
AppMode
from
models.workflow
import
Workflow
,
WorkflowType
from
services.workflow.defaults
import
default_block_configs
from
services.workflow.workflow_converter
import
WorkflowConverter
...
...
@@ -58,6 +59,40 @@ class WorkflowService:
# return draft workflow
return
workflow
def
publish_draft_workflow
(
self
,
app_model
:
App
,
account
:
Account
,
draft_workflow
:
Optional
[
Workflow
]
=
None
)
->
Workflow
:
"""
Publish draft workflow
:param app_model: App instance
:param account: Account instance
:param draft_workflow: Workflow instance
"""
if
not
draft_workflow
:
# fetch draft workflow by app_model
draft_workflow
=
self
.
get_draft_workflow
(
app_model
=
app_model
)
if
not
draft_workflow
:
raise
ValueError
(
'No valid workflow found.'
)
# create new workflow
workflow
=
Workflow
(
tenant_id
=
app_model
.
tenant_id
,
app_id
=
app_model
.
id
,
type
=
draft_workflow
.
type
,
version
=
str
(
datetime
.
utcnow
()),
graph
=
draft_workflow
.
graph
,
created_by
=
account
.
id
)
# commit db session changes
db
.
session
.
add
(
workflow
)
db
.
session
.
commit
()
# return new workflow
return
workflow
def
get_default_block_configs
(
self
)
->
dict
:
"""
Get default block configs
...
...
@@ -77,11 +112,7 @@ class WorkflowService:
# chatbot convert to workflow mode
workflow_converter
=
WorkflowConverter
()
if
app_model
.
mode
==
AppMode
.
CHAT
.
value
:
# check if chatbot app is in basic mode
if
app_model
.
app_model_config
.
chatbot_app_engine
!=
ChatbotAppEngine
.
NORMAL
:
raise
ValueError
(
'Chatbot app already in workflow mode'
)
elif
app_model
.
mode
!=
AppMode
.
COMPLETION
.
value
:
if
app_model
.
mode
not
in
[
AppMode
.
CHAT
.
value
,
AppMode
.
COMPLETION
.
value
]:
raise
ValueError
(
f
'Current App mode: {app_model.mode} is not supported convert to workflow.'
)
# convert to workflow
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment