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
22d39ec7
Commit
22d39ec7
authored
Feb 28, 2024
by
crazywoola
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'fix/2559-upload-powered-by-brand-image-not-showing-up' into deploy/dev
parents
c4352960
0f53fc86
Changes
49
Hide whitespace changes
Inline
Side-by-side
Showing
49 changed files
with
595 additions
and
190 deletions
+595
-190
celerybeat-schedule.db
api/celerybeat-schedule.db
+0
-0
app.py
api/controllers/console/app/app.py
+3
-9
data_source.py
api/controllers/console/datasets/data_source.py
+4
-2
datasets.py
api/controllers/console/datasets/datasets.py
+2
-1
datasets_document.py
api/controllers/console/datasets/datasets_document.py
+2
-1
cached_embedding.py
api/core/embedding/cached_embedding.py
+1
-1
annotation_reply.py
api/core/features/annotation_reply.py
+1
-1
assistant_base_runner.py
api/core/features/assistant_base_runner.py
+36
-30
assistant_cot_runner.py
api/core/features/assistant_cot_runner.py
+10
-3
indexing_runner.py
api/core/indexing_runner.py
+2
-1
_position.yaml
api/core/model_runtime/model_providers/_position.yaml
+1
-0
__init__.py
api/core/model_runtime/model_providers/mistralai/__init__.py
+0
-0
icon_l_en.png
...l_runtime/model_providers/mistralai/_assets/icon_l_en.png
+0
-0
icon_s_en.png
...l_runtime/model_providers/mistralai/_assets/icon_s_en.png
+0
-0
_position.yaml
...odel_runtime/model_providers/mistralai/llm/_position.yaml
+5
-0
llm.py
api/core/model_runtime/model_providers/mistralai/llm/llm.py
+31
-0
mistral-large-latest.yaml
...e/model_providers/mistralai/llm/mistral-large-latest.yaml
+50
-0
mistral-medium-latest.yaml
.../model_providers/mistralai/llm/mistral-medium-latest.yaml
+50
-0
mistral-small-latest.yaml
...e/model_providers/mistralai/llm/mistral-small-latest.yaml
+50
-0
open-mistral-7b.yaml
...untime/model_providers/mistralai/llm/open-mistral-7b.yaml
+50
-0
open-mixtral-8x7b.yaml
...time/model_providers/mistralai/llm/open-mixtral-8x7b.yaml
+50
-0
mistralai.py
...core/model_runtime/model_providers/mistralai/mistralai.py
+30
-0
mistralai.yaml
...re/model_runtime/model_providers/mistralai/mistralai.yaml
+31
-0
llm.py
api/core/model_runtime/model_providers/moonshot/llm/llm.py
+1
-0
retrieval_service.py
api/core/rag/datasource/retrieval_service.py
+4
-3
field.py
api/core/rag/datasource/vdb/field.py
+1
-1
milvus_vector.py
api/core/rag/datasource/vdb/milvus/milvus_vector.py
+6
-1
extract_setting.py
api/core/rag/extractor/entity/extract_setting.py
+1
-0
extract_processor.py
api/core/rag/extractor/extract_processor.py
+2
-1
html_extractor.py
api/core/rag/extractor/html_extractor.py
+13
-50
notion_extractor.py
api/core/rag/extractor/notion_extractor.py
+3
-1
api_tool.py
api/core/tools/tool/api_tool.py
+1
-1
parser.py
api/core/tools/utils/parser.py
+42
-5
hit_testing_service.py
api/services/hit_testing_service.py
+3
-2
workspace_service.py
api/services/workspace_service.py
+13
-1
document_indexing_sync_task.py
api/tasks/document_indexing_sync_task.py
+2
-1
index.tsx
web/app/components/base/button/index.tsx
+9
-5
logo-site.tsx
web/app/components/base/logo/logo-site.tsx
+3
-1
index.tsx
web/app/components/billing/billing-page/index.tsx
+7
-11
index.tsx
web/app/components/custom/custom-web-app-brand/index.tsx
+1
-3
template.en.mdx
web/app/components/develop/template/template.en.mdx
+2
-2
template.zh.mdx
web/app/components/develop/template/template.zh.mdx
+2
-2
template_chat.en.mdx
web/app/components/develop/template/template_chat.en.mdx
+4
-4
template_chat.zh.mdx
web/app/components/develop/template/template_chat.zh.mdx
+4
-4
index.tsx
web/app/components/explore/app-list/index.tsx
+51
-31
index.tsx
web/app/components/header/account-setting/index.tsx
+4
-8
index.tsx
web/app/components/header/index.tsx
+1
-1
explore.ts
web/models/explore.ts
+1
-1
explore.ts
web/service/explore.ts
+5
-1
No files found.
api/celerybeat-schedule.db
deleted
100644 → 0
View file @
c4352960
File deleted
api/controllers/console/app/app.py
View file @
22d39ec7
...
...
@@ -124,19 +124,13 @@ class AppListApi(Resource):
available_models_names
=
[
f
'{model.provider.provider}.{model.model}'
for
model
in
available_models
]
provider_model
=
f
"{model_config_dict['model']['provider']}.{model_config_dict['model']['name']}"
if
provider_model
not
in
available_models_names
:
model_manager
=
ModelManager
()
model_instance
=
model_manager
.
get_default_model_instance
(
tenant_id
=
current_user
.
current_tenant_id
,
model_type
=
ModelType
.
LLM
)
if
not
model_instance
:
if
not
default_model_entity
:
raise
ProviderNotInitializeError
(
"No Default System Reasoning Model available. Please configure "
"in the Settings -> Model Provider."
)
else
:
model_config_dict
[
"model"
][
"provider"
]
=
model_instance
.
provider
model_config_dict
[
"model"
][
"name"
]
=
model_instance
.
model
model_config_dict
[
"model"
][
"provider"
]
=
default_model_entity
.
provider
model_config_dict
[
"model"
][
"name"
]
=
default_model_entity
.
model
model_configuration
=
AppModelConfigService
.
validate_configuration
(
tenant_id
=
current_user
.
current_tenant_id
,
...
...
api/controllers/console/datasets/data_source.py
View file @
22d39ec7
...
...
@@ -178,7 +178,8 @@ class DataSourceNotionApi(Resource):
notion_workspace_id
=
workspace_id
,
notion_obj_id
=
page_id
,
notion_page_type
=
page_type
,
notion_access_token
=
data_source_binding
.
access_token
notion_access_token
=
data_source_binding
.
access_token
,
tenant_id
=
current_user
.
current_tenant_id
)
text_docs
=
extractor
.
extract
()
...
...
@@ -208,7 +209,8 @@ class DataSourceNotionApi(Resource):
notion_info
=
{
"notion_workspace_id"
:
workspace_id
,
"notion_obj_id"
:
page
[
'page_id'
],
"notion_page_type"
:
page
[
'type'
]
"notion_page_type"
:
page
[
'type'
],
"tenant_id"
:
current_user
.
current_tenant_id
},
document_model
=
args
[
'doc_form'
]
)
...
...
api/controllers/console/datasets/datasets.py
View file @
22d39ec7
...
...
@@ -298,7 +298,8 @@ class DatasetIndexingEstimateApi(Resource):
notion_info
=
{
"notion_workspace_id"
:
workspace_id
,
"notion_obj_id"
:
page
[
'page_id'
],
"notion_page_type"
:
page
[
'type'
]
"notion_page_type"
:
page
[
'type'
],
"tenant_id"
:
current_user
.
current_tenant_id
},
document_model
=
args
[
'doc_form'
]
)
...
...
api/controllers/console/datasets/datasets_document.py
View file @
22d39ec7
...
...
@@ -455,7 +455,8 @@ class DocumentBatchIndexingEstimateApi(DocumentResource):
notion_info
=
{
"notion_workspace_id"
:
data_source_info
[
'notion_workspace_id'
],
"notion_obj_id"
:
data_source_info
[
'notion_page_id'
],
"notion_page_type"
:
data_source_info
[
'type'
]
"notion_page_type"
:
data_source_info
[
'type'
],
"tenant_id"
:
current_user
.
current_tenant_id
},
document_model
=
document
.
doc_form
)
...
...
api/core/embedding/cached_embedding.py
View file @
22d39ec7
...
...
@@ -3,12 +3,12 @@ import logging
from
typing
import
Optional
,
cast
import
numpy
as
np
from
langchain.embeddings.base
import
Embeddings
from
sqlalchemy.exc
import
IntegrityError
from
core.model_manager
import
ModelInstance
from
core.model_runtime.entities.model_entities
import
ModelPropertyKey
from
core.model_runtime.model_providers.__base.text_embedding_model
import
TextEmbeddingModel
from
core.rag.datasource.entity.embedding
import
Embeddings
from
extensions.ext_database
import
db
from
extensions.ext_redis
import
redis_client
from
libs
import
helper
...
...
api/core/features/annotation_reply.py
View file @
22d39ec7
...
...
@@ -59,7 +59,7 @@ class AnnotationReplyFeature:
documents
=
vector
.
search_by_vector
(
query
=
query
,
k
=
1
,
top_
k
=
1
,
score_threshold
=
score_threshold
,
filter
=
{
'group_id'
:
[
dataset
.
id
]
...
...
api/core/features/assistant_base_runner.py
View file @
22d39ec7
...
...
@@ -606,36 +606,42 @@ class BaseAssistantApplicationRunner(AppRunner):
for
message
in
messages
:
result
.
append
(
UserPromptMessage
(
content
=
message
.
query
))
agent_thoughts
:
list
[
MessageAgentThought
]
=
message
.
agent_thoughts
for
agent_thought
in
agent_thoughts
:
tools
=
agent_thought
.
tool
if
tools
:
tools
=
tools
.
split
(
';'
)
tool_calls
:
list
[
AssistantPromptMessage
.
ToolCall
]
=
[]
tool_call_response
:
list
[
ToolPromptMessage
]
=
[]
tool_inputs
=
json
.
loads
(
agent_thought
.
tool_input
)
for
tool
in
tools
:
# generate a uuid for tool call
tool_call_id
=
str
(
uuid
.
uuid4
())
tool_calls
.
append
(
AssistantPromptMessage
.
ToolCall
(
id
=
tool_call_id
,
type
=
'function'
,
function
=
AssistantPromptMessage
.
ToolCall
.
ToolCallFunction
(
if
agent_thoughts
:
for
agent_thought
in
agent_thoughts
:
tools
=
agent_thought
.
tool
if
tools
:
tools
=
tools
.
split
(
';'
)
tool_calls
:
list
[
AssistantPromptMessage
.
ToolCall
]
=
[]
tool_call_response
:
list
[
ToolPromptMessage
]
=
[]
tool_inputs
=
json
.
loads
(
agent_thought
.
tool_input
)
for
tool
in
tools
:
# generate a uuid for tool call
tool_call_id
=
str
(
uuid
.
uuid4
())
tool_calls
.
append
(
AssistantPromptMessage
.
ToolCall
(
id
=
tool_call_id
,
type
=
'function'
,
function
=
AssistantPromptMessage
.
ToolCall
.
ToolCallFunction
(
name
=
tool
,
arguments
=
json
.
dumps
(
tool_inputs
.
get
(
tool
,
{})),
)
))
tool_call_response
.
append
(
ToolPromptMessage
(
content
=
agent_thought
.
observation
,
name
=
tool
,
arguments
=
json
.
dumps
(
tool_inputs
.
get
(
tool
,
{})),
)
))
tool_call_response
.
append
(
ToolPromptMessage
(
content
=
agent_thought
.
observation
,
name
=
tool
,
tool_call_id
=
tool_call_id
,
))
result
.
extend
([
AssistantPromptMessage
(
content
=
agent_thought
.
thought
,
tool_calls
=
tool_calls
,
),
*
tool_call_response
])
tool_call_id
=
tool_call_id
,
))
result
.
extend
([
AssistantPromptMessage
(
content
=
agent_thought
.
thought
,
tool_calls
=
tool_calls
,
),
*
tool_call_response
])
if
not
tools
:
result
.
append
(
AssistantPromptMessage
(
content
=
agent_thought
.
thought
))
else
:
if
message
.
answer
:
result
.
append
(
AssistantPromptMessage
(
content
=
message
.
answer
))
return
result
\ No newline at end of file
api/core/features/assistant_cot_runner.py
View file @
22d39ec7
...
...
@@ -154,7 +154,7 @@ class AssistantCotApplicationRunner(BaseAssistantApplicationRunner):
thought
=
''
,
action_str
=
''
,
observation
=
''
,
action
=
None
action
=
None
,
)
# publish agent thought if it's first iteration
...
...
@@ -469,7 +469,7 @@ class AssistantCotApplicationRunner(BaseAssistantApplicationRunner):
thought
=
message
.
content
,
action_str
=
''
,
action
=
None
,
observation
=
None
observation
=
None
,
)
if
message
.
tool_calls
:
try
:
...
...
@@ -484,7 +484,7 @@ class AssistantCotApplicationRunner(BaseAssistantApplicationRunner):
elif
isinstance
(
message
,
ToolPromptMessage
):
if
current_scratchpad
:
current_scratchpad
.
observation
=
message
.
content
return
agent_scratchpad
def
_check_cot_prompt_messages
(
self
,
mode
:
Literal
[
"completion"
,
"chat"
],
...
...
@@ -607,6 +607,13 @@ class AssistantCotApplicationRunner(BaseAssistantApplicationRunner):
prompt_message
.
content
=
system_message
overridden
=
True
break
# convert tool prompt messages to user prompt messages
for
idx
,
prompt_message
in
enumerate
(
prompt_messages
):
if
isinstance
(
prompt_message
,
ToolPromptMessage
):
prompt_messages
[
idx
]
=
UserPromptMessage
(
content
=
prompt_message
.
content
)
if
not
overridden
:
prompt_messages
.
insert
(
0
,
SystemPromptMessage
(
...
...
api/core/indexing_runner.py
View file @
22d39ec7
...
...
@@ -366,7 +366,8 @@ class IndexingRunner:
"notion_workspace_id"
:
data_source_info
[
'notion_workspace_id'
],
"notion_obj_id"
:
data_source_info
[
'notion_page_id'
],
"notion_page_type"
:
data_source_info
[
'type'
],
"document"
:
dataset_document
"document"
:
dataset_document
,
"tenant_id"
:
dataset_document
.
tenant_id
},
document_model
=
dataset_document
.
doc_form
)
...
...
api/core/model_runtime/model_providers/_position.yaml
View file @
22d39ec7
...
...
@@ -6,6 +6,7 @@
-
bedrock
-
togetherai
-
ollama
-
mistralai
-
replicate
-
huggingface_hub
-
zhipuai
...
...
api/core/model_runtime/model_providers/mistralai/__init__.py
0 → 100644
View file @
22d39ec7
api/core/model_runtime/model_providers/mistralai/_assets/icon_l_en.png
0 → 100644
View file @
22d39ec7
6.9 KB
api/core/model_runtime/model_providers/mistralai/_assets/icon_s_en.png
0 → 100644
View file @
22d39ec7
2.3 KB
api/core/model_runtime/model_providers/mistralai/llm/_position.yaml
0 → 100644
View file @
22d39ec7
-
open-mistral-7b
-
open-mixtral-8x7b
-
mistral-small-latest
-
mistral-medium-latest
-
mistral-large-latest
api/core/model_runtime/model_providers/mistralai/llm/llm.py
0 → 100644
View file @
22d39ec7
from
collections.abc
import
Generator
from
typing
import
Optional
,
Union
from
core.model_runtime.entities.llm_entities
import
LLMResult
from
core.model_runtime.entities.message_entities
import
PromptMessage
,
PromptMessageTool
from
core.model_runtime.model_providers.openai_api_compatible.llm.llm
import
OAIAPICompatLargeLanguageModel
class
MistralAILargeLanguageModel
(
OAIAPICompatLargeLanguageModel
):
def
_invoke
(
self
,
model
:
str
,
credentials
:
dict
,
prompt_messages
:
list
[
PromptMessage
],
model_parameters
:
dict
,
tools
:
Optional
[
list
[
PromptMessageTool
]]
=
None
,
stop
:
Optional
[
list
[
str
]]
=
None
,
stream
:
bool
=
True
,
user
:
Optional
[
str
]
=
None
)
\
->
Union
[
LLMResult
,
Generator
]:
self
.
_add_custom_parameters
(
credentials
)
# mistral dose not support user/stop arguments
stop
=
[]
user
=
None
return
super
()
.
_invoke
(
model
,
credentials
,
prompt_messages
,
model_parameters
,
tools
,
stop
,
stream
,
user
)
def
validate_credentials
(
self
,
model
:
str
,
credentials
:
dict
)
->
None
:
self
.
_add_custom_parameters
(
credentials
)
super
()
.
validate_credentials
(
model
,
credentials
)
@
staticmethod
def
_add_custom_parameters
(
credentials
:
dict
)
->
None
:
credentials
[
'mode'
]
=
'chat'
credentials
[
'endpoint_url'
]
=
'https://api.mistral.ai/v1'
api/core/model_runtime/model_providers/mistralai/llm/mistral-large-latest.yaml
0 → 100644
View file @
22d39ec7
model
:
mistral-large-latest
label
:
zh_Hans
:
mistral-large-latest
en_US
:
mistral-large-latest
model_type
:
llm
features
:
-
agent-thought
model_properties
:
context_size
:
32000
parameter_rules
:
-
name
:
temperature
use_template
:
temperature
default
:
0.7
min
:
0
max
:
1
-
name
:
top_p
use_template
:
top_p
default
:
1
min
:
0
max
:
1
-
name
:
max_tokens
use_template
:
max_tokens
default
:
1024
min
:
1
max
:
8000
-
name
:
safe_prompt
defulat
:
false
type
:
boolean
help
:
en_US
:
Whether to inject a safety prompt before all conversations.
zh_Hans
:
是否开启提示词审查
label
:
en_US
:
SafePrompt
zh_Hans
:
提示词审查
-
name
:
random_seed
type
:
int
help
:
en_US
:
The seed to use for random sampling. If set, different calls will generate deterministic results.
zh_Hans
:
当开启随机数种子以后,你可以通过指定一个固定的种子来使得回答结果更加稳定
label
:
en_US
:
RandomSeed
zh_Hans
:
随机数种子
default
:
0
min
:
0
max
:
2147483647
pricing
:
input
:
'
0.008'
output
:
'
0.024'
unit
:
'
0.001'
currency
:
USD
api/core/model_runtime/model_providers/mistralai/llm/mistral-medium-latest.yaml
0 → 100644
View file @
22d39ec7
model
:
mistral-medium-latest
label
:
zh_Hans
:
mistral-medium-latest
en_US
:
mistral-medium-latest
model_type
:
llm
features
:
-
agent-thought
model_properties
:
context_size
:
32000
parameter_rules
:
-
name
:
temperature
use_template
:
temperature
default
:
0.7
min
:
0
max
:
1
-
name
:
top_p
use_template
:
top_p
default
:
1
min
:
0
max
:
1
-
name
:
max_tokens
use_template
:
max_tokens
default
:
1024
min
:
1
max
:
8000
-
name
:
safe_prompt
defulat
:
false
type
:
boolean
help
:
en_US
:
Whether to inject a safety prompt before all conversations.
zh_Hans
:
是否开启提示词审查
label
:
en_US
:
SafePrompt
zh_Hans
:
提示词审查
-
name
:
random_seed
type
:
int
help
:
en_US
:
The seed to use for random sampling. If set, different calls will generate deterministic results.
zh_Hans
:
当开启随机数种子以后,你可以通过指定一个固定的种子来使得回答结果更加稳定
label
:
en_US
:
RandomSeed
zh_Hans
:
随机数种子
default
:
0
min
:
0
max
:
2147483647
pricing
:
input
:
'
0.0027'
output
:
'
0.0081'
unit
:
'
0.001'
currency
:
USD
api/core/model_runtime/model_providers/mistralai/llm/mistral-small-latest.yaml
0 → 100644
View file @
22d39ec7
model
:
mistral-small-latest
label
:
zh_Hans
:
mistral-small-latest
en_US
:
mistral-small-latest
model_type
:
llm
features
:
-
agent-thought
model_properties
:
context_size
:
32000
parameter_rules
:
-
name
:
temperature
use_template
:
temperature
default
:
0.7
min
:
0
max
:
1
-
name
:
top_p
use_template
:
top_p
default
:
1
min
:
0
max
:
1
-
name
:
max_tokens
use_template
:
max_tokens
default
:
1024
min
:
1
max
:
8000
-
name
:
safe_prompt
defulat
:
false
type
:
boolean
help
:
en_US
:
Whether to inject a safety prompt before all conversations.
zh_Hans
:
是否开启提示词审查
label
:
en_US
:
SafePrompt
zh_Hans
:
提示词审查
-
name
:
random_seed
type
:
int
help
:
en_US
:
The seed to use for random sampling. If set, different calls will generate deterministic results.
zh_Hans
:
当开启随机数种子以后,你可以通过指定一个固定的种子来使得回答结果更加稳定
label
:
en_US
:
RandomSeed
zh_Hans
:
随机数种子
default
:
0
min
:
0
max
:
2147483647
pricing
:
input
:
'
0.002'
output
:
'
0.006'
unit
:
'
0.001'
currency
:
USD
api/core/model_runtime/model_providers/mistralai/llm/open-mistral-7b.yaml
0 → 100644
View file @
22d39ec7
model
:
open-mistral-7b
label
:
zh_Hans
:
open-mistral-7b
en_US
:
open-mistral-7b
model_type
:
llm
features
:
-
agent-thought
model_properties
:
context_size
:
8000
parameter_rules
:
-
name
:
temperature
use_template
:
temperature
default
:
0.7
min
:
0
max
:
1
-
name
:
top_p
use_template
:
top_p
default
:
1
min
:
0
max
:
1
-
name
:
max_tokens
use_template
:
max_tokens
default
:
1024
min
:
1
max
:
2048
-
name
:
safe_prompt
defulat
:
false
type
:
boolean
help
:
en_US
:
Whether to inject a safety prompt before all conversations.
zh_Hans
:
是否开启提示词审查
label
:
en_US
:
SafePrompt
zh_Hans
:
提示词审查
-
name
:
random_seed
type
:
int
help
:
en_US
:
The seed to use for random sampling. If set, different calls will generate deterministic results.
zh_Hans
:
当开启随机数种子以后,你可以通过指定一个固定的种子来使得回答结果更加稳定
label
:
en_US
:
RandomSeed
zh_Hans
:
随机数种子
default
:
0
min
:
0
max
:
2147483647
pricing
:
input
:
'
0.00025'
output
:
'
0.00025'
unit
:
'
0.001'
currency
:
USD
api/core/model_runtime/model_providers/mistralai/llm/open-mixtral-8x7b.yaml
0 → 100644
View file @
22d39ec7
model
:
open-mixtral-8x7b
label
:
zh_Hans
:
open-mixtral-8x7b
en_US
:
open-mixtral-8x7b
model_type
:
llm
features
:
-
agent-thought
model_properties
:
context_size
:
32000
parameter_rules
:
-
name
:
temperature
use_template
:
temperature
default
:
0.7
min
:
0
max
:
1
-
name
:
top_p
use_template
:
top_p
default
:
1
min
:
0
max
:
1
-
name
:
max_tokens
use_template
:
max_tokens
default
:
1024
min
:
1
max
:
8000
-
name
:
safe_prompt
defulat
:
false
type
:
boolean
help
:
en_US
:
Whether to inject a safety prompt before all conversations.
zh_Hans
:
是否开启提示词审查
label
:
en_US
:
SafePrompt
zh_Hans
:
提示词审查
-
name
:
random_seed
type
:
int
help
:
en_US
:
The seed to use for random sampling. If set, different calls will generate deterministic results.
zh_Hans
:
当开启随机数种子以后,你可以通过指定一个固定的种子来使得回答结果更加稳定
label
:
en_US
:
RandomSeed
zh_Hans
:
随机数种子
default
:
0
min
:
0
max
:
2147483647
pricing
:
input
:
'
0.0007'
output
:
'
0.0007'
unit
:
'
0.001'
currency
:
USD
api/core/model_runtime/model_providers/mistralai/mistralai.py
0 → 100644
View file @
22d39ec7
import
logging
from
core.model_runtime.entities.model_entities
import
ModelType
from
core.model_runtime.errors.validate
import
CredentialsValidateFailedError
from
core.model_runtime.model_providers.__base.model_provider
import
ModelProvider
logger
=
logging
.
getLogger
(
__name__
)
class
MistralAIProvider
(
ModelProvider
):
def
validate_provider_credentials
(
self
,
credentials
:
dict
)
->
None
:
"""
Validate provider credentials
if validate failed, raise exception
:param credentials: provider credentials, credentials form defined in `provider_credential_schema`.
"""
try
:
model_instance
=
self
.
get_model_instance
(
ModelType
.
LLM
)
model_instance
.
validate_credentials
(
model
=
'open-mistral-7b'
,
credentials
=
credentials
)
except
CredentialsValidateFailedError
as
ex
:
raise
ex
except
Exception
as
ex
:
logger
.
exception
(
f
'{self.get_provider_schema().provider} credentials validate failed'
)
raise
ex
api/core/model_runtime/model_providers/mistralai/mistralai.yaml
0 → 100644
View file @
22d39ec7
provider
:
mistralai
label
:
en_US
:
MistralAI
description
:
en_US
:
Models provided by MistralAI, such as open-mistral-7b and mistral-large-latest.
zh_Hans
:
MistralAI 提供的模型,例如 open-mistral-7b 和 mistral-large-latest。
icon_small
:
en_US
:
icon_s_en.png
icon_large
:
en_US
:
icon_l_en.png
background
:
"
#FFFFFF"
help
:
title
:
en_US
:
Get your API Key from MistralAI
zh_Hans
:
从 MistralAI 获取 API Key
url
:
en_US
:
https://console.mistral.ai/api-keys/
supported_model_types
:
-
llm
configurate_methods
:
-
predefined-model
provider_credential_schema
:
credential_form_schemas
:
-
variable
:
api_key
label
:
en_US
:
API Key
type
:
secret-input
required
:
true
placeholder
:
zh_Hans
:
在此输入您的 API Key
en_US
:
Enter your API Key
api/core/model_runtime/model_providers/moonshot/llm/llm.py
View file @
22d39ec7
...
...
@@ -13,6 +13,7 @@ class MoonshotLargeLanguageModel(OAIAPICompatLargeLanguageModel):
stream
:
bool
=
True
,
user
:
Optional
[
str
]
=
None
)
\
->
Union
[
LLMResult
,
Generator
]:
self
.
_add_custom_parameters
(
credentials
)
user
=
user
[:
32
]
if
user
else
None
return
super
()
.
_invoke
(
model
,
credentials
,
prompt_messages
,
model_parameters
,
tools
,
stop
,
stream
,
user
)
def
validate_credentials
(
self
,
model
:
str
,
credentials
:
dict
)
->
None
:
...
...
api/core/rag/datasource/retrieval_service.py
View file @
22d39ec7
...
...
@@ -39,7 +39,8 @@ class RetrievalService:
'flask_app'
:
current_app
.
_get_current_object
(),
'dataset_id'
:
dataset_id
,
'query'
:
query
,
'top_k'
:
top_k
'top_k'
:
top_k
,
'all_documents'
:
all_documents
})
threads
.
append
(
keyword_thread
)
keyword_thread
.
start
()
...
...
@@ -100,7 +101,7 @@ class RetrievalService:
documents
=
keyword
.
search
(
query
,
k
=
top_k
top_
k
=
top_k
)
all_documents
.
extend
(
documents
)
...
...
@@ -120,7 +121,7 @@ class RetrievalService:
documents
=
vector
.
search_by_vector
(
query
,
search_type
=
'similarity_score_threshold'
,
k
=
top_k
,
top_
k
=
top_k
,
score_threshold
=
score_threshold
,
filter
=
{
'group_id'
:
[
dataset
.
id
]
...
...
api/core/rag/datasource/vdb/field.py
View file @
22d39ec7
...
...
@@ -7,4 +7,4 @@ class Field(Enum):
GROUP_KEY
=
"group_id"
VECTOR
=
"vector"
TEXT_KEY
=
"text"
PRIMARY_KEY
=
"
id"
PRIMARY_KEY
=
"id"
api/core/rag/datasource/vdb/milvus/milvus_vector.py
View file @
22d39ec7
...
...
@@ -124,7 +124,12 @@ class MilvusVector(BaseVector):
def
delete_by_ids
(
self
,
doc_ids
:
list
[
str
])
->
None
:
self
.
_client
.
delete
(
collection_name
=
self
.
_collection_name
,
pks
=
doc_ids
)
result
=
self
.
_client
.
query
(
collection_name
=
self
.
_collection_name
,
filter
=
f
'metadata["doc_id"] in {doc_ids}'
,
output_fields
=
[
"id"
])
if
result
:
ids
=
[
item
[
"id"
]
for
item
in
result
]
self
.
_client
.
delete
(
collection_name
=
self
.
_collection_name
,
pks
=
ids
)
def
delete
(
self
)
->
None
:
alias
=
uuid4
()
.
hex
...
...
api/core/rag/extractor/entity/extract_setting.py
View file @
22d39ec7
...
...
@@ -12,6 +12,7 @@ class NotionInfo(BaseModel):
notion_obj_id
:
str
notion_page_type
:
str
document
:
Document
=
None
tenant_id
:
str
class
Config
:
arbitrary_types_allowed
=
True
...
...
api/core/rag/extractor/extract_processor.py
View file @
22d39ec7
...
...
@@ -132,7 +132,8 @@ class ExtractProcessor:
notion_workspace_id
=
extract_setting
.
notion_info
.
notion_workspace_id
,
notion_obj_id
=
extract_setting
.
notion_info
.
notion_obj_id
,
notion_page_type
=
extract_setting
.
notion_info
.
notion_page_type
,
document_model
=
extract_setting
.
notion_info
.
document
document_model
=
extract_setting
.
notion_info
.
document
,
tenant_id
=
extract_setting
.
notion_info
.
tenant_id
,
)
return
extractor
.
extract
()
else
:
...
...
api/core/rag/extractor/html_extractor.py
View file @
22d39ec7
"""Abstract interface for document loader implementations."""
from
typing
import
Optional
from
bs4
import
BeautifulSoup
from
core.rag.extractor.extractor_base
import
BaseExtractor
from
core.rag.extractor.helpers
import
detect_file_encodings
from
core.rag.models.document
import
Document
class
HtmlExtractor
(
BaseExtractor
):
"""Load html files.
"""
Load html files.
Args:
...
...
@@ -15,57 +16,19 @@ class HtmlExtractor(BaseExtractor):
"""
def
__init__
(
self
,
file_path
:
str
,
encoding
:
Optional
[
str
]
=
None
,
autodetect_encoding
:
bool
=
False
,
source_column
:
Optional
[
str
]
=
None
,
csv_args
:
Optional
[
dict
]
=
None
,
self
,
file_path
:
str
):
"""Initialize with file path."""
self
.
_file_path
=
file_path
self
.
_encoding
=
encoding
self
.
_autodetect_encoding
=
autodetect_encoding
self
.
source_column
=
source_column
self
.
csv_args
=
csv_args
or
{}
def
extract
(
self
)
->
list
[
Document
]:
"""Load data into document objects."""
try
:
with
open
(
self
.
_file_path
,
newline
=
""
,
encoding
=
self
.
_encoding
)
as
csvfile
:
docs
=
self
.
_read_from_file
(
csvfile
)
except
UnicodeDecodeError
as
e
:
if
self
.
_autodetect_encoding
:
detected_encodings
=
detect_file_encodings
(
self
.
_file_path
)
for
encoding
in
detected_encodings
:
try
:
with
open
(
self
.
_file_path
,
newline
=
""
,
encoding
=
encoding
.
encoding
)
as
csvfile
:
docs
=
self
.
_read_from_file
(
csvfile
)
break
except
UnicodeDecodeError
:
continue
else
:
raise
RuntimeError
(
f
"Error loading {self._file_path}"
)
from
e
return
docs
return
[
Document
(
page_content
=
self
.
_load_as_text
())]
def
_read_from_file
(
self
,
csvfile
)
->
list
[
Document
]:
docs
=
[]
csv_reader
=
csv
.
DictReader
(
csvfile
,
**
self
.
csv_args
)
# type: ignore
for
i
,
row
in
enumerate
(
csv_reader
):
content
=
"
\n
"
.
join
(
f
"{k.strip()}: {v.strip()}"
for
k
,
v
in
row
.
items
())
try
:
source
=
(
row
[
self
.
source_column
]
if
self
.
source_column
is
not
None
else
''
)
except
KeyError
:
raise
ValueError
(
f
"Source column '{self.source_column}' not found in CSV file."
)
metadata
=
{
"source"
:
source
,
"row"
:
i
}
doc
=
Document
(
page_content
=
content
,
metadata
=
metadata
)
docs
.
append
(
doc
)
def
_load_as_text
(
self
)
->
str
:
with
open
(
self
.
_file_path
,
"rb"
)
as
fp
:
soup
=
BeautifulSoup
(
fp
,
'html.parser'
)
text
=
soup
.
get_text
()
text
=
text
.
strip
()
if
text
else
''
return
docs
return
text
\ No newline at end of file
api/core/rag/extractor/notion_extractor.py
View file @
22d39ec7
...
...
@@ -30,8 +30,10 @@ class NotionExtractor(BaseExtractor):
notion_workspace_id
:
str
,
notion_obj_id
:
str
,
notion_page_type
:
str
,
tenant_id
:
str
,
document_model
:
Optional
[
DocumentModel
]
=
None
,
notion_access_token
:
Optional
[
str
]
=
None
notion_access_token
:
Optional
[
str
]
=
None
,
):
self
.
_notion_access_token
=
None
self
.
_document_model
=
document_model
...
...
api/core/tools/tool/api_tool.py
View file @
22d39ec7
...
...
@@ -200,7 +200,7 @@ class ApiTool(Tool):
# replace path parameters
for
name
,
value
in
path_params
.
items
():
url
=
url
.
replace
(
f
'{{{name}}}'
,
value
)
url
=
url
.
replace
(
f
'{{{name}}}'
,
f
'{value}'
)
# parse http body data if needed, for GET/HEAD/OPTIONS/TRACE, the body is ignored
if
'Content-Type'
in
headers
:
...
...
api/core/tools/utils/parser.py
View file @
22d39ec7
import
re
import
uuid
from
json
import
loads
as
json_loads
from
requests
import
get
...
...
@@ -46,7 +48,7 @@ class ApiBasedToolSchemaParser:
parameters
=
[]
if
'parameters'
in
interface
[
'operation'
]:
for
parameter
in
interface
[
'operation'
][
'parameters'
]:
parameters
.
append
(
ToolParameter
(
tool_parameter
=
ToolParameter
(
name
=
parameter
[
'name'
],
label
=
I18nObject
(
en_US
=
parameter
[
'name'
],
...
...
@@ -61,7 +63,14 @@ class ApiBasedToolSchemaParser:
form
=
ToolParameter
.
ToolParameterForm
.
LLM
,
llm_description
=
parameter
.
get
(
'description'
),
default
=
parameter
[
'schema'
][
'default'
]
if
'schema'
in
parameter
and
'default'
in
parameter
[
'schema'
]
else
None
,
))
)
# check if there is a type
typ
=
ApiBasedToolSchemaParser
.
_get_tool_parameter_type
(
parameter
)
if
typ
:
tool_parameter
.
type
=
typ
parameters
.
append
(
tool_parameter
)
# create tool bundle
# check if there is a request body
if
'requestBody'
in
interface
[
'operation'
]:
...
...
@@ -80,13 +89,14 @@ class ApiBasedToolSchemaParser:
root
=
root
[
ref
]
# overwrite the content
interface
[
'operation'
][
'requestBody'
][
'content'
][
content_type
][
'schema'
]
=
root
# parse body parameters
if
'schema'
in
interface
[
'operation'
][
'requestBody'
][
'content'
][
content_type
]:
body_schema
=
interface
[
'operation'
][
'requestBody'
][
'content'
][
content_type
][
'schema'
]
required
=
body_schema
[
'required'
]
if
'required'
in
body_schema
else
[]
properties
=
body_schema
[
'properties'
]
if
'properties'
in
body_schema
else
{}
for
name
,
property
in
properties
.
items
():
parameters
.
append
(
ToolParameter
(
tool
=
ToolParameter
(
name
=
name
,
label
=
I18nObject
(
en_US
=
name
,
...
...
@@ -101,7 +111,14 @@ class ApiBasedToolSchemaParser:
form
=
ToolParameter
.
ToolParameterForm
.
LLM
,
llm_description
=
property
[
'description'
]
if
'description'
in
property
else
''
,
default
=
property
[
'default'
]
if
'default'
in
property
else
None
,
))
)
# check if there is a type
typ
=
ApiBasedToolSchemaParser
.
_get_tool_parameter_type
(
property
)
if
typ
:
tool
.
type
=
typ
parameters
.
append
(
tool
)
# check if parameters is duplicated
parameters_count
=
{}
...
...
@@ -119,7 +136,11 @@ class ApiBasedToolSchemaParser:
path
=
interface
[
'path'
]
if
interface
[
'path'
]
.
startswith
(
'/'
):
path
=
interface
[
'path'
][
1
:]
path
=
path
.
replace
(
'/'
,
'_'
)
# remove special characters like / to ensure the operation id is valid ^[a-zA-Z0-9_-]{1,64}$
path
=
re
.
sub
(
r'[^a-zA-Z0-9_-]'
,
''
,
path
)
if
not
path
:
path
=
str
(
uuid
.
uuid4
())
interface
[
'operation'
][
'operationId'
]
=
f
'{path}_{interface["method"]}'
bundles
.
append
(
ApiBasedToolBundle
(
...
...
@@ -134,7 +155,23 @@ class ApiBasedToolSchemaParser:
))
return
bundles
@
staticmethod
def
_get_tool_parameter_type
(
parameter
:
dict
)
->
ToolParameter
.
ToolParameterType
:
parameter
=
parameter
or
{}
typ
=
None
if
'type'
in
parameter
:
typ
=
parameter
[
'type'
]
elif
'schema'
in
parameter
and
'type'
in
parameter
[
'schema'
]:
typ
=
parameter
[
'schema'
][
'type'
]
if
typ
==
'integer'
or
typ
==
'number'
:
return
ToolParameter
.
ToolParameterType
.
NUMBER
elif
typ
==
'boolean'
:
return
ToolParameter
.
ToolParameterType
.
BOOLEAN
elif
typ
==
'string'
:
return
ToolParameter
.
ToolParameterType
.
STRING
@
staticmethod
def
parse_openapi_yaml_to_tool_bundle
(
yaml
:
str
,
extra_info
:
dict
=
None
,
warning
:
dict
=
None
)
->
list
[
ApiBasedToolBundle
]:
"""
...
...
api/services/hit_testing_service.py
View file @
22d39ec7
...
...
@@ -133,8 +133,9 @@ class HitTestingService:
if
embedding_length
<=
1
:
return
[{
'x'
:
0
,
'y'
:
0
}]
concatenate_data
=
np
.
array
(
embeddings
)
.
reshape
(
embedding_length
,
-
1
)
# concatenate_data = np.concatenate(embeddings)
noise
=
np
.
random
.
normal
(
0
,
1e-4
,
np
.
array
(
embeddings
)
.
shape
)
concatenate_data
=
np
.
array
(
embeddings
)
+
noise
concatenate_data
=
concatenate_data
.
reshape
(
embedding_length
,
-
1
)
perplexity
=
embedding_length
/
2
+
1
if
perplexity
>=
embedding_length
:
...
...
api/services/workspace_service.py
View file @
22d39ec7
from
flask
import
current_app
from
flask_login
import
current_user
from
extensions.ext_database
import
db
...
...
@@ -31,7 +33,17 @@ class WorkspaceService:
can_replace_logo
=
FeatureService
.
get_features
(
tenant_info
[
'id'
])
.
can_replace_logo
if
can_replace_logo
and
TenantService
.
has_roles
(
tenant
,
[
TenantAccountJoinRole
.
OWNER
,
TenantAccountJoinRole
.
ADMIN
]):
if
can_replace_logo
and
TenantService
.
has_roles
(
tenant
,
[
TenantAccountJoinRole
.
OWNER
,
TenantAccountJoinRole
.
ADMIN
]):
base_url
=
current_app
.
config
.
get
(
'FILES_URL'
)
replace_webapp_logo
=
f
'{base_url}/files/workspaces/{tenant.id}/webapp-logo'
if
tenant
.
custom_config_dict
.
get
(
'replace_webapp_logo'
)
else
None
remove_webapp_brand
=
tenant
.
custom_config_dict
.
get
(
'remove_webapp_brand'
,
False
)
# Make sure the custom_config_dict is updated with the new values
tenant
.
custom_config_dict
.
update
({
'remove_webapp_brand'
:
remove_webapp_brand
,
'replace_webapp_logo'
:
replace_webapp_logo
,
})
tenant_info
[
'custom_config'
]
=
tenant
.
custom_config_dict
return
tenant_info
api/tasks/document_indexing_sync_task.py
View file @
22d39ec7
...
...
@@ -58,7 +58,8 @@ def document_indexing_sync_task(dataset_id: str, document_id: str):
notion_workspace_id
=
workspace_id
,
notion_obj_id
=
page_id
,
notion_page_type
=
page_type
,
notion_access_token
=
data_source_binding
.
access_token
notion_access_token
=
data_source_binding
.
access_token
,
tenant_id
=
document
.
tenant_id
)
last_edited_time
=
loader
.
get_notion_last_edited_time
()
...
...
web/app/components/base/button/index.tsx
View file @
22d39ec7
...
...
@@ -3,13 +3,16 @@ import React from 'react'
import
Spinner
from
'../spinner'
export
type
IButtonProps
=
{
type
?:
string
/**
* The style of the button
*/
type
?:
'primary'
|
'warning'
|
(
string
&
{})
className
?:
string
disabled
?:
boolean
loading
?:
boolean
tabIndex
?:
number
children
:
React
.
ReactNode
onClick
?:
MouseEventHandler
<
HTML
Div
Element
>
onClick
?:
MouseEventHandler
<
HTML
Button
Element
>
}
const
Button
:
FC
<
IButtonProps
>
=
({
...
...
@@ -35,15 +38,16 @@ const Button: FC<IButtonProps> = ({
}
return
(
<
div
<
button
className=
{
`btn ${style} ${className && className}`
}
tabIndex=
{
tabIndex
}
onClick=
{
disabled
?
undefined
:
onClick
}
disabled=
{
disabled
}
onClick=
{
onClick
}
>
{
children
}
{
/* Spinner is hidden when loading is false */
}
<
Spinner
loading=
{
loading
}
className=
'!text-white !h-3 !w-3 !border-2 !ml-1'
/>
</
div
>
</
button
>
)
}
...
...
web/app/components/base/logo/logo-site.tsx
View file @
22d39ec7
import
type
{
FC
}
from
'react'
import
classNames
from
'classnames'
type
LogoSiteProps
=
{
className
?:
string
}
const
LogoSite
:
FC
<
LogoSiteProps
>
=
({
className
,
})
=>
{
return
(
<
img
src=
'/logo/logo-site.png'
className=
{
`block w-auto h-10 ${className}`
}
className=
{
classNames
(
'block w-auto h-10'
,
className
)
}
alt=
'logo'
/>
)
...
...
web/app/components/billing/billing-page/index.tsx
View file @
22d39ec7
'use client'
import
type
{
FC
}
from
'react'
import
React
,
{
useEffect
}
from
'react'
import
React
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
useSWR
from
'swr'
import
PlanComp
from
'../plan'
import
{
ReceiptList
}
from
'../../base/icons/src/vender/line/financeAndECommerce'
import
{
LinkExternal01
}
from
'../../base/icons/src/vender/line/general'
...
...
@@ -12,17 +13,11 @@ import { useProviderContext } from '@/context/provider-context'
const
Billing
:
FC
=
()
=>
{
const
{
t
}
=
useTranslation
()
const
{
isCurrentWorkspaceManager
}
=
useAppContext
()
const
[
billingUrl
,
setBillingUrl
]
=
React
.
useState
(
''
)
const
{
enableBilling
}
=
useProviderContext
()
useEffect
(()
=>
{
if
(
!
enableBilling
||
!
isCurrentWorkspaceManager
)
return
(
async
()
=>
{
const
{
url
}
=
await
fetchBillingUrl
()
setBillingUrl
(
url
)
})()
},
[
isCurrentWorkspaceManager
])
const
{
data
:
billingUrl
}
=
useSWR
(
(
!
enableBilling
||
!
isCurrentWorkspaceManager
)
?
null
:
[
'/billing/invoices'
],
()
=>
fetchBillingUrl
().
then
(
data
=>
data
.
url
),
)
return
(
<
div
>
...
...
@@ -39,4 +34,5 @@ const Billing: FC = () => {
</
div
>
)
}
export
default
React
.
memo
(
Billing
)
web/app/components/custom/custom-web-app-brand/index.tsx
View file @
22d39ec7
...
...
@@ -16,8 +16,6 @@ import {
updateCurrentWorkspace
,
}
from
'@/service/common'
import
{
useAppContext
}
from
'@/context/app-context'
import
{
API_PREFIX
}
from
'@/config'
import
{
getPurifyHref
}
from
'@/utils'
const
ALLOW_FILE_EXTENSIONS
=
[
'svg'
,
'png'
]
...
...
@@ -123,7 +121,7 @@ const CustomWebAppBrand = () => {
POWERED BY
{
webappLogo
?
<
img
key=
{
webappLogo
}
src=
{
`${getPurifyHref(API_PREFIX.slice(0, -12))}/files/workspaces/${currentWorkspace.id}/webapp-logo`
}
alt=
'logo'
className=
'ml-2 block w-auto h-5'
/>
?
<
img
key=
{
webappLogo
}
src=
{
webappLogo
}
alt=
'logo'
className=
'ml-2 block w-auto h-5'
/>
:
<
LogoSite
className=
'ml-2 !h-5'
/>
}
</
div
>
...
...
web/app/components/develop/template/template.en.mdx
View file @
22d39ec7
...
...
@@ -289,9 +289,9 @@ The text generation application offers non-session support and is ideal for tran
</Col>
<Col sticky>
### Request Example
<CodeGroup title="Request" tag="POST" label="/completion-messages/:task_id/stop" targetCode={`curl -X POST '
https://cloud.dify.ai
/v1/completion-messages/:task_id/stop' \\\n-H 'Authorization: Bearer {api_key}' \\\n-H 'Content-Type: application/json' \\\n--data-raw '{ "user": "abc-123"}'`}>
<CodeGroup title="Request" tag="POST" label="/completion-messages/:task_id/stop" targetCode={`curl -X POST '
${props.appDetail.api_base_url}
/v1/completion-messages/:task_id/stop' \\\n-H 'Authorization: Bearer {api_key}' \\\n-H 'Content-Type: application/json' \\\n--data-raw '{ "user": "abc-123"}'`}>
```bash {{ title: 'cURL' }}
curl -X POST '
https://cloud.dify.ai
/v1/completion-messages/:task_id/stop' \
curl -X POST '
${props.appDetail.api_base_url}
/v1/completion-messages/:task_id/stop' \
-H 'Authorization: Bearer {api_key}' \
-H 'Content-Type: application/json' \
--data-raw '{
...
...
web/app/components/develop/template/template.zh.mdx
View file @
22d39ec7
...
...
@@ -266,9 +266,9 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
- `result` (string) 固定返回 success
</Col>
<Col sticky>
<CodeGroup title="Request" tag="POST" label="/completion-messages/:task_id/stop" targetCode={`curl -X POST '
https://cloud.dify.ai
/v1/completion-messages/:task_id/stop' \\\n-H 'Authorization: Bearer {api_key}' \\\n-H 'Content-Type: application/json' \\\n--data-raw '{ "user": "abc-123"}'`}>
<CodeGroup title="Request" tag="POST" label="/completion-messages/:task_id/stop" targetCode={`curl -X POST '
${props.appDetail.api_base_url}
/v1/completion-messages/:task_id/stop' \\\n-H 'Authorization: Bearer {api_key}' \\\n-H 'Content-Type: application/json' \\\n--data-raw '{ "user": "abc-123"}'`}>
```bash {{ title: 'cURL' }}
curl -X POST '
https://cloud.dify.ai
/v1/completion-messages/:task_id/stop' \
curl -X POST '
${props.appDetail.api_base_url}
/v1/completion-messages/:task_id/stop' \
-H 'Authorization: Bearer {api_key}' \
-H 'Content-Type: application/json' \
--data-raw '{
...
...
web/app/components/develop/template/template_chat.en.mdx
View file @
22d39ec7
...
...
@@ -344,9 +344,9 @@ Chat applications support session persistence, allowing previous chat history to
</Col>
<Col sticky>
### Request Example
<CodeGroup title="Request" tag="POST" label="/chat-messages/:task_id/stop" targetCode={`curl -X POST '
https://cloud.dify.ai
/v1/chat-messages/:task_id/stop' \\\n-H 'Authorization: Bearer {api_key}' \\\n-H 'Content-Type: application/json' \\\n--data-raw '{"user": "abc-123"}'`}>
<CodeGroup title="Request" tag="POST" label="/chat-messages/:task_id/stop" targetCode={`curl -X POST '
${props.appDetail.api_base_url}
/v1/chat-messages/:task_id/stop' \\\n-H 'Authorization: Bearer {api_key}' \\\n-H 'Content-Type: application/json' \\\n--data-raw '{"user": "abc-123"}'`}>
```bash {{ title: 'cURL' }}
curl -X POST '
https://cloud.dify.ai
/v1/chat-messages/:task_id/stop' \
curl -X POST '
${props.appDetail.api_base_url}
/v1/chat-messages/:task_id/stop' \
-H 'Authorization: Bearer {api_key}' \
-H 'Content-Type: application/json' \
--data-raw '{
...
...
@@ -1025,9 +1025,9 @@ Chat applications support session persistence, allowing previous chat history to
- (string) url of icon
</Col>
<Col>
<CodeGroup title="Request" tag="POST" label="/meta" targetCode={`curl -X GET '
https://cloud.dify.ai
/v1/meta?user=abc-123' \\\n-H 'Authorization: Bearer {api_key}'`}>
<CodeGroup title="Request" tag="POST" label="/meta" targetCode={`curl -X GET '
${props.appDetail.api_base_url}
/v1/meta?user=abc-123' \\\n-H 'Authorization: Bearer {api_key}'`}>
```bash {{ title: 'cURL' }}
curl -X GET '
https://cloud.dify.ai
/v1/meta?user=abc-123' \
curl -X GET '
${props.appDetail.api_base_url}
/v1/meta?user=abc-123' \
-H 'Authorization: Bearer {api_key}'
```
...
...
web/app/components/develop/template/template_chat.zh.mdx
View file @
22d39ec7
...
...
@@ -360,9 +360,9 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
- `result` (string) 固定返回 success
</Col>
<Col sticky>
<CodeGroup title="Request" tag="POST" label="/chat-messages/:task_id/stop" targetCode={`curl -X POST '
https://cloud.dify.ai
/v1/chat-messages/:task_id/stop' \\\n-H 'Authorization: Bearer {api_key}' \\\n-H 'Content-Type: application/json' \\\n--data-raw '{ "user": "abc-123"}'`}>
<CodeGroup title="Request" tag="POST" label="/chat-messages/:task_id/stop" targetCode={`curl -X POST '
${props.appDetail.api_base_url}
/v1/chat-messages/:task_id/stop' \\\n-H 'Authorization: Bearer {api_key}' \\\n-H 'Content-Type: application/json' \\\n--data-raw '{ "user": "abc-123"}'`}>
```bash {{ title: 'cURL' }}
curl -X POST '
https://cloud.dify.ai
/v1/chat-messages/:task_id/stop' \
curl -X POST '
${props.appDetail.api_base_url}
/v1/chat-messages/:task_id/stop' \
-H 'Authorization: Bearer {api_key}' \
-H 'Content-Type: application/json' \
--data-raw '{
...
...
@@ -1022,9 +1022,9 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
- (string) 图标URL
</Col>
<Col>
<CodeGroup title="Request" tag="POST" label="/meta" targetCode={`curl -X GET '
https://cloud.dify.ai
/v1/meta?user=abc-123' \\\n-H 'Authorization: Bearer {api_key}'`}>
<CodeGroup title="Request" tag="POST" label="/meta" targetCode={`curl -X GET '
${props.appDetail.api_base_url}
/v1/meta?user=abc-123' \\\n-H 'Authorization: Bearer {api_key}'`}>
```bash {{ title: 'cURL' }}
curl -X GET '
https://cloud.dify.ai
/v1/meta?user=abc-123' \
curl -X GET '
${props.appDetail.api_base_url}
/v1/meta?user=abc-123' \
-H 'Authorization: Bearer {api_key}'
```
...
...
web/app/components/explore/app-list/index.tsx
View file @
22d39ec7
'use client'
import
type
{
FC
}
from
'react'
import
React
,
{
useEffect
}
from
'react'
import
React
from
'react'
import
{
useRouter
}
from
'next/navigation'
import
{
useTranslation
}
from
'react-i18next'
import
{
useContext
}
from
'use-context-selector'
import
useSWR
from
'swr'
import
Toast
from
'../../base/toast'
import
s
from
'./style.module.css'
import
ExploreContext
from
'@/context/explore-context'
import
type
{
App
,
AppCategory
}
from
'@/models/explore'
import
type
{
App
}
from
'@/models/explore'
import
Category
from
'@/app/components/explore/category'
import
AppCard
from
'@/app/components/explore/app-card'
import
{
fetchAppDetail
,
fetchAppList
}
from
'@/service/explore'
...
...
@@ -25,34 +26,44 @@ const Apps: FC = () => {
const
{
isCurrentWorkspaceManager
}
=
useAppContext
()
const
router
=
useRouter
()
const
{
hasEditPermission
}
=
useContext
(
ExploreContext
)
const
allCategoriesEn
=
t
(
'explore.apps.allCategories'
,
{
lng
:
'en'
})
const
[
currCategory
,
setCurrCategory
]
=
useTabSearchParams
({
defaultTab
:
''
,
defaultTab
:
allCategoriesEn
,
})
const
[
allList
,
setAllList
]
=
React
.
useState
<
App
[]
>
([])
const
[
isLoaded
,
setIsLoaded
]
=
React
.
useState
(
false
)
const
{
data
:
{
categories
,
allList
},
isLoading
,
}
=
useSWR
(
[
'/explore/apps'
],
()
=>
fetchAppList
().
then
(({
categories
,
recommended_apps
})
=>
({
categories
,
allList
:
recommended_apps
.
sort
((
a
,
b
)
=>
a
.
position
-
b
.
position
),
})),
{
fallbackData
:
{
categories
:
[],
allList
:
[],
},
},
)
const
currList
=
(()
=>
{
if
(
currCategory
===
''
)
if
(
currCategory
===
allCategoriesEn
)
return
allList
return
allList
.
filter
(
item
=>
item
.
category
===
currCategory
)
})()
const
[
categories
,
setCategories
]
=
React
.
useState
<
AppCategory
[]
>
([])
useEffect
(()
=>
{
(
async
()
=>
{
const
{
categories
,
recommended_apps
}:
any
=
await
fetchAppList
()
const
sortedRecommendedApps
=
[...
recommended_apps
]
sortedRecommendedApps
.
sort
((
a
,
b
)
=>
a
.
position
-
b
.
position
)
// position from small to big
setCategories
(
categories
)
setAllList
(
sortedRecommendedApps
)
setIsLoaded
(
true
)
})()
},
[])
const
[
currApp
,
setCurrApp
]
=
React
.
useState
<
App
|
null
>
(
null
)
const
[
isShowCreateModal
,
setIsShowCreateModal
]
=
React
.
useState
(
false
)
const
onCreate
:
CreateAppModalProps
[
'onConfirm'
]
=
async
({
name
,
icon
,
icon_background
})
=>
{
const
{
app_model_config
:
model_config
}
=
await
fetchAppDetail
(
currApp
?.
app
.
id
as
string
)
const
onCreate
:
CreateAppModalProps
[
'onConfirm'
]
=
async
({
name
,
icon
,
icon_background
,
})
=>
{
const
{
app_model_config
:
model_config
}
=
await
fetchAppDetail
(
currApp
?.
app
.
id
as
string
,
)
try
{
const
app
=
await
createApp
({
...
...
@@ -68,36 +79,45 @@ const Apps: FC = () => {
message
:
t
(
'app.newApp.appCreated'
),
})
localStorage
.
setItem
(
NEED_REFRESH_APP_LIST_KEY
,
'1'
)
router
.
push
(
`/app/
${
app
.
id
}
/
${
isCurrentWorkspaceManager
?
'configuration'
:
'overview'
}
`
)
router
.
push
(
`/app/
${
app
.
id
}
/
${
isCurrentWorkspaceManager
?
'configuration'
:
'overview'
}
`
,
)
}
catch
(
e
)
{
Toast
.
notify
({
type
:
'error'
,
message
:
t
(
'app.newApp.appCreateFailed'
)
})
}
}
if
(
!
isLoad
ed
)
{
if
(
!
isLoad
ing
)
{
return
(
<
div
className=
'flex h-full items-center'
>
<
Loading
type=
'area'
/>
<
div
className=
"flex h-full items-center"
>
<
Loading
type=
"area"
/>
</
div
>
)
}
return
(
<
div
className=
'h-full flex flex-col border-l border-gray-200'
>
<
div
className=
'shrink-0 pt-6 px-12'
>
<
div
className=
{
`mb-1 ${s.textGradient} text-xl font-semibold`
}
>
{
t
(
'explore.apps.title'
)
}
</
div
>
<
div
className=
'text-gray-500 text-sm'
>
{
t
(
'explore.apps.description'
)
}
</
div
>
<
div
className=
"h-full flex flex-col border-l border-gray-200"
>
<
div
className=
"shrink-0 pt-6 px-12"
>
<
div
className=
{
`mb-1 ${s.textGradient} text-xl font-semibold`
}
>
{
t
(
'explore.apps.title'
)
}
</
div
>
<
div
className=
"text-gray-500 text-sm"
>
{
t
(
'explore.apps.description'
)
}
</
div
>
</
div
>
<
Category
className=
'mt-6 px-12'
className=
"mt-6 px-12"
list=
{
categories
}
value=
{
currCategory
}
onChange=
{
setCurrCategory
}
/>
<
div
className=
'relative flex flex-1 mt-6 pb-6 flex-col overflow-auto bg-gray-100 shrink-0 grow'
>
<
div
className=
"relative flex flex-1 mt-6 pb-6 flex-col overflow-auto bg-gray-100 shrink-0 grow"
>
<
nav
className=
{
`${s.appList} grid content-start gap-4 px-6 sm:px-12 shrink-0`
}
>
className=
{
`${s.appList} grid content-start gap-4 px-6 sm:px-12 shrink-0`
}
>
{
currList
.
map
(
app
=>
(
<
AppCard
key=
{
app
.
app_id
}
...
...
web/app/components/header/account-setting/index.tsx
View file @
22d39ec7
...
...
@@ -138,16 +138,12 @@ export default function AccountSetting({
]
const
scrollRef
=
useRef
<
HTMLDivElement
>
(
null
)
const
[
scrolled
,
setScrolled
]
=
useState
(
false
)
const
scrollHandle
=
(
e
:
Event
)
=>
{
if
((
e
.
target
as
HTMLDivElement
).
scrollTop
>
0
)
setScrolled
(
true
)
else
setScrolled
(
false
)
}
useEffect
(()
=>
{
const
targetElement
=
scrollRef
.
current
const
scrollHandle
=
(
e
:
Event
)
=>
{
const
userScrolled
=
(
e
.
target
as
HTMLDivElement
).
scrollTop
>
0
setScrolled
(
userScrolled
)
}
targetElement
?.
addEventListener
(
'scroll'
,
scrollHandle
)
return
()
=>
{
targetElement
?.
removeEventListener
(
'scroll'
,
scrollHandle
)
...
...
web/app/components/header/index.tsx
View file @
22d39ec7
...
...
@@ -54,7 +54,7 @@ const Header = () => {
</
div
>
}
{
!
isMobile
&&
<>
<
Link
href=
"/apps"
className=
'flex items-center mr-4'
>
<
LogoSite
/>
<
LogoSite
className=
'object-contain'
/>
</
Link
>
<
GithubStar
/>
</>
}
...
...
web/models/explore.ts
View file @
22d39ec7
...
...
@@ -16,7 +16,7 @@ export type App = {
app_id
:
string
description
:
string
copyright
:
string
privacy_policy
:
string
privacy_policy
:
string
|
null
category
:
AppCategory
position
:
number
is_listed
:
boolean
...
...
web/service/explore.ts
View file @
22d39ec7
import
{
del
,
get
,
patch
,
post
}
from
'./base'
import
type
{
App
,
AppCategory
}
from
'@/models/explore'
export
const
fetchAppList
=
()
=>
{
return
get
(
'/explore/apps'
)
return
get
<
{
categories
:
AppCategory
[]
recommended_apps
:
App
[]
}
>
(
'/explore/apps'
)
}
export
const
fetchAppDetail
=
(
id
:
string
):
Promise
<
any
>
=>
{
...
...
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