mirror of https://github.com/langgenius/dify.git
merge main
This commit is contained in:
commit
c15677634f
|
|
@ -128,7 +128,7 @@ At the same time, please consider supporting Dify by sharing it on social media
|
|||
|
||||
### Translations
|
||||
|
||||
We are looking for contributors to help with translating Dify to languages other than Mandarin or English. If you are interested in helping, please see the [i18n README](https://github.com/langgenius/dify/blob/main/web/i18n/README_EN.md) for more information, and leave us a comment in the `global-users` channel of our [Discord Community Server](https://discord.gg/AhzKf7dNgk).
|
||||
We are looking for contributors to help with translating Dify to languages other than Mandarin or English. If you are interested in helping, please see the [i18n README](https://github.com/langgenius/dify/blob/main/web/i18n/README.md) for more information, and leave us a comment in the `global-users` channel of our [Discord Community Server](https://discord.gg/AhzKf7dNgk).
|
||||
|
||||
## Community & Support
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ DEFAULTS = {
|
|||
'SERVICE_API_URL': 'https://api.dify.ai',
|
||||
'APP_WEB_URL': 'https://udify.app',
|
||||
'FILES_URL': '',
|
||||
'S3_ADDRESS_STYLE': 'auto',
|
||||
'STORAGE_TYPE': 'local',
|
||||
'STORAGE_LOCAL_PATH': 'storage',
|
||||
'CHECK_UPDATE_URL': 'https://updates.dify.ai',
|
||||
|
|
@ -64,7 +65,8 @@ DEFAULTS = {
|
|||
'KEYWORD_STORE': 'jieba',
|
||||
'BATCH_UPLOAD_LIMIT': 20,
|
||||
'CODE_EXECUTION_ENDPOINT': '',
|
||||
'CODE_EXECUTION_API_KEY': ''
|
||||
'CODE_EXECUTION_API_KEY': '',
|
||||
'TOOL_ICON_CACHE_MAX_AGE': 3600,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -186,6 +188,7 @@ class Config:
|
|||
self.S3_ACCESS_KEY = get_env('S3_ACCESS_KEY')
|
||||
self.S3_SECRET_KEY = get_env('S3_SECRET_KEY')
|
||||
self.S3_REGION = get_env('S3_REGION')
|
||||
self.S3_ADDRESS_STYLE = get_env('S3_ADDRESS_STYLE')
|
||||
self.AZURE_BLOB_ACCOUNT_NAME = get_env('AZURE_BLOB_ACCOUNT_NAME')
|
||||
self.AZURE_BLOB_ACCOUNT_KEY = get_env('AZURE_BLOB_ACCOUNT_KEY')
|
||||
self.AZURE_BLOB_CONTAINER_NAME = get_env('AZURE_BLOB_CONTAINER_NAME')
|
||||
|
|
@ -311,6 +314,7 @@ class Config:
|
|||
self.CODE_EXECUTION_API_KEY = get_env('CODE_EXECUTION_API_KEY')
|
||||
|
||||
self.API_COMPRESSION_ENABLED = get_bool_env('API_COMPRESSION_ENABLED')
|
||||
self.TOOL_ICON_CACHE_MAX_AGE = get_env('TOOL_ICON_CACHE_MAX_AGE')
|
||||
|
||||
|
||||
class CloudEditionConfig(Config):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import io
|
||||
|
||||
from flask import send_file
|
||||
from flask import current_app, send_file
|
||||
from flask_login import current_user
|
||||
from flask_restful import Resource, reqparse
|
||||
from werkzeug.exceptions import Forbidden
|
||||
|
|
@ -81,7 +81,8 @@ class ToolBuiltinProviderIconApi(Resource):
|
|||
@setup_required
|
||||
def get(self, provider):
|
||||
icon_bytes, minetype = ToolManageService.get_builtin_tool_provider_icon(provider)
|
||||
return send_file(io.BytesIO(icon_bytes), mimetype=minetype)
|
||||
icon_cache_max_age = int(current_app.config.get('TOOL_ICON_CACHE_MAX_AGE'))
|
||||
return send_file(io.BytesIO(icon_bytes), mimetype=minetype, max_age=icon_cache_max_age)
|
||||
|
||||
class ToolModelProviderIconApi(Resource):
|
||||
@setup_required
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ class BaseAgentRunner(AppRunner):
|
|||
result += f"result link: {response.message}. please tell user to check it."
|
||||
elif response.type == ToolInvokeMessage.MessageType.IMAGE_LINK or \
|
||||
response.type == ToolInvokeMessage.MessageType.IMAGE:
|
||||
result += "image has been created and sent to user already, you should tell user to check it now."
|
||||
result += "image has been created and sent to user already, you do not need to create it, just tell the user to check it now."
|
||||
else:
|
||||
result += f"tool response: {response.message}."
|
||||
|
||||
|
|
@ -497,7 +497,11 @@ class BaseAgentRunner(AppRunner):
|
|||
tools = tools.split(';')
|
||||
tool_calls: list[AssistantPromptMessage.ToolCall] = []
|
||||
tool_call_response: list[ToolPromptMessage] = []
|
||||
tool_inputs = json.loads(agent_thought.tool_input)
|
||||
try:
|
||||
tool_inputs = json.loads(agent_thought.tool_input)
|
||||
except Exception as e:
|
||||
logging.warning("tool execution error: {}, tool_input: {}.".format(str(e), agent_thought.tool_input))
|
||||
tool_inputs = { agent_thought.tool: agent_thought.tool_input }
|
||||
for tool in tools:
|
||||
# generate a uuid for tool call
|
||||
tool_call_id = str(uuid.uuid4())
|
||||
|
|
@ -530,4 +534,4 @@ class BaseAgentRunner(AppRunner):
|
|||
|
||||
db.session.close()
|
||||
|
||||
return result
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ class CotAgentRunner(BaseAgentRunner):
|
|||
delta=LLMResultChunkDelta(
|
||||
index=0,
|
||||
message=AssistantPromptMessage(
|
||||
content=json.dumps(chunk)
|
||||
content=json.dumps(chunk, ensure_ascii=False) # if ensure_ascii=True, the text in webui maybe garbled text
|
||||
),
|
||||
usage=None
|
||||
)
|
||||
|
|
@ -689,4 +689,4 @@ class CotAgentRunner(BaseAgentRunner):
|
|||
try:
|
||||
return json.dumps(tools, ensure_ascii=False)
|
||||
except json.JSONDecodeError:
|
||||
return json.dumps(tools)
|
||||
return json.dumps(tools)
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@
|
|||
|
||||
- `input` (float) Input price, i.e., Prompt price
|
||||
- `output` (float) Output price, i.e., returned content price
|
||||
- `unit` (float) Pricing unit, e.g., per 100K price is `0.000001`
|
||||
- `unit` (float) Pricing unit, e.g., if the price is meausred in 1M tokens, the corresponding token amount for the unit price is `0.000001`.
|
||||
- `currency` (string) Currency unit
|
||||
|
||||
### ProviderCredentialSchema
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@
|
|||
|
||||
- `input` (float) 输入单价,即 Prompt 单价
|
||||
- `output` (float) 输出单价,即返回内容单价
|
||||
- `unit` (float) 价格单位,如:每 100K 的单价为 `0.000001`
|
||||
- `unit` (float) 价格单位,如以 1M tokens 计价,则单价对应的单位 token 数为 `0.000001`
|
||||
- `currency` (string) 货币单位
|
||||
|
||||
### ProviderCredentialSchema
|
||||
|
|
|
|||
|
|
@ -73,8 +73,8 @@ PARAMETER_RULE_TEMPLATE: dict[DefaultParameterName, dict] = {
|
|||
},
|
||||
'type': 'int',
|
||||
'help': {
|
||||
'en_US': 'The maximum number of tokens to generate. Requests can use up to 2048 tokens shared between prompt and completion.',
|
||||
'zh_Hans': '要生成的标记的最大数量。请求可以使用最多2048个标记,这些标记在提示和完成之间共享。',
|
||||
'en_US': 'Specifies the upper limit on the length of generated results. If the generated results are truncated, you can increase this parameter.',
|
||||
'zh_Hans': '指定生成结果长度的上限。如果生成结果截断,可以调大该参数。',
|
||||
},
|
||||
'required': False,
|
||||
'default': 64,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
model: jina-colbert-v1-en
|
||||
model_type: rerank
|
||||
model_properties:
|
||||
context_size: 8192
|
||||
|
|
@ -37,7 +37,7 @@ parameter_rules:
|
|||
zh_Hans: 控制生成结果的随机性。数值越小,随机性越弱;数值越大,随机性越强。一般而言,top_p 和 temperature 两个参数选择一个进行调整即可。
|
||||
en_US: Control the randomness of generated results. The smaller the value, the weaker the randomness; the larger the value, the stronger the randomness. Generally speaking, you can adjust one of the two parameters top_p and temperature.
|
||||
pricing:
|
||||
input: '0.0025'
|
||||
output: '0.0025'
|
||||
unit: '0.00001'
|
||||
input: '2.5'
|
||||
output: '2.5'
|
||||
unit: '0.000001'
|
||||
currency: RMB
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ parameter_rules:
|
|||
zh_Hans: 控制生成结果的随机性。数值越小,随机性越弱;数值越大,随机性越强。一般而言,top_p 和 temperature 两个参数选择一个进行调整即可。
|
||||
en_US: Control the randomness of generated results. The smaller the value, the weaker the randomness; the larger the value, the stronger the randomness. Generally speaking, you can adjust one of the two parameters top_p and temperature.
|
||||
pricing:
|
||||
input: '0.012'
|
||||
output: '0.012'
|
||||
unit: '0.00001'
|
||||
input: '12'
|
||||
output: '12'
|
||||
unit: '0.000001'
|
||||
currency: RMB
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ parameter_rules:
|
|||
zh_Hans: 控制生成结果的随机性。数值越小,随机性越弱;数值越大,随机性越强。一般而言,top_p 和 temperature 两个参数选择一个进行调整即可。
|
||||
en_US: Control the randomness of generated results. The smaller the value, the weaker the randomness; the larger the value, the stronger the randomness. Generally speaking, you can adjust one of the two parameters top_p and temperature.
|
||||
pricing:
|
||||
input: '0.01'
|
||||
output: '0.03'
|
||||
unit: '0.001'
|
||||
currency: USD
|
||||
input: '6'
|
||||
output: '6'
|
||||
unit: '0.000001'
|
||||
currency: RMB
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from core.model_runtime.entities.llm_entities import LLMResult, LLMResultChunk,
|
|||
from core.model_runtime.entities.message_entities import (
|
||||
AssistantPromptMessage,
|
||||
PromptMessage,
|
||||
PromptMessageContent,
|
||||
PromptMessageContentType,
|
||||
PromptMessageRole,
|
||||
PromptMessageTool,
|
||||
|
|
@ -31,6 +32,7 @@ And you should always end the block with a "```" to indicate the end of the JSON
|
|||
|
||||
```JSON"""
|
||||
|
||||
|
||||
class ZhipuAILargeLanguageModel(_CommonZhipuaiAI, LargeLanguageModel):
|
||||
|
||||
def _invoke(self, model: str, credentials: dict,
|
||||
|
|
@ -159,7 +161,7 @@ class ZhipuAILargeLanguageModel(_CommonZhipuaiAI, LargeLanguageModel):
|
|||
|
||||
if len(prompt_messages) == 0:
|
||||
raise ValueError('At least one message is required')
|
||||
|
||||
|
||||
if prompt_messages[0].role == PromptMessageRole.SYSTEM:
|
||||
if not prompt_messages[0].content:
|
||||
prompt_messages = prompt_messages[1:]
|
||||
|
|
@ -185,7 +187,7 @@ class ZhipuAILargeLanguageModel(_CommonZhipuaiAI, LargeLanguageModel):
|
|||
continue
|
||||
|
||||
if new_prompt_messages and new_prompt_messages[-1].role == PromptMessageRole.USER and \
|
||||
copy_prompt_message.role == PromptMessageRole.USER:
|
||||
copy_prompt_message.role == PromptMessageRole.USER:
|
||||
new_prompt_messages[-1].content += "\n\n" + copy_prompt_message.content
|
||||
else:
|
||||
if copy_prompt_message.role == PromptMessageRole.USER:
|
||||
|
|
@ -205,31 +207,7 @@ class ZhipuAILargeLanguageModel(_CommonZhipuaiAI, LargeLanguageModel):
|
|||
new_prompt_messages.append(copy_prompt_message)
|
||||
|
||||
if model == 'glm-4v':
|
||||
params = {
|
||||
'model': model,
|
||||
'messages': [{
|
||||
'role': prompt_message.role.value,
|
||||
'content':
|
||||
[
|
||||
{
|
||||
'type': 'text',
|
||||
'text': prompt_message.content
|
||||
}
|
||||
] if isinstance(prompt_message.content, str) else
|
||||
[
|
||||
{
|
||||
'type': 'image',
|
||||
'image_url': {
|
||||
'url': content.data
|
||||
}
|
||||
} if content.type == PromptMessageContentType.IMAGE else {
|
||||
'type': 'text',
|
||||
'text': content.data
|
||||
} for content in prompt_message.content
|
||||
],
|
||||
} for prompt_message in new_prompt_messages],
|
||||
**model_parameters
|
||||
}
|
||||
params = self._construct_glm_4v_parameter(model, new_prompt_messages, model_parameters)
|
||||
else:
|
||||
params = {
|
||||
'model': model,
|
||||
|
|
@ -277,8 +255,8 @@ class ZhipuAILargeLanguageModel(_CommonZhipuaiAI, LargeLanguageModel):
|
|||
for prompt_message in new_prompt_messages:
|
||||
# merge system message to user message
|
||||
if prompt_message.role == PromptMessageRole.SYSTEM or \
|
||||
prompt_message.role == PromptMessageRole.TOOL or \
|
||||
prompt_message.role == PromptMessageRole.USER:
|
||||
prompt_message.role == PromptMessageRole.TOOL or \
|
||||
prompt_message.role == PromptMessageRole.USER:
|
||||
if len(params['messages']) > 0 and params['messages'][-1]['role'] == 'user':
|
||||
params['messages'][-1]['content'] += "\n\n" + prompt_message.content
|
||||
else:
|
||||
|
|
@ -306,8 +284,44 @@ class ZhipuAILargeLanguageModel(_CommonZhipuaiAI, LargeLanguageModel):
|
|||
|
||||
response = client.chat.completions.create(**params, **extra_model_kwargs)
|
||||
return self._handle_generate_response(model, credentials_kwargs, tools, response, prompt_messages)
|
||||
|
||||
def _handle_generate_response(self, model: str,
|
||||
|
||||
def _construct_glm_4v_parameter(self, model: str, prompt_messages: list[PromptMessage],
|
||||
model_parameters: dict):
|
||||
messages = [
|
||||
{
|
||||
'role': message.role.value,
|
||||
'content': self._construct_glm_4v_messages(message.content)
|
||||
}
|
||||
for message in prompt_messages
|
||||
]
|
||||
|
||||
params = {
|
||||
'model': model,
|
||||
'messages': messages,
|
||||
**model_parameters
|
||||
}
|
||||
|
||||
return params
|
||||
|
||||
def _construct_glm_4v_messages(self, prompt_message: Union[str | list[PromptMessageContent]]) -> list[dict]:
|
||||
if isinstance(prompt_message, str):
|
||||
return [{'type': 'text', 'text': prompt_message}]
|
||||
|
||||
return [
|
||||
{'type': 'image_url', 'image_url': {'url': self._remove_image_header(item.data)}}
|
||||
if item.type == PromptMessageContentType.IMAGE else
|
||||
{'type': 'text', 'text': item.data}
|
||||
|
||||
for item in prompt_message
|
||||
]
|
||||
|
||||
def _remove_image_header(self, image: str) -> str:
|
||||
if image.startswith('data:image'):
|
||||
return image.split(',')[1]
|
||||
|
||||
return image
|
||||
|
||||
def _handle_generate_response(self, model: str,
|
||||
credentials: dict,
|
||||
tools: Optional[list[PromptMessageTool]],
|
||||
response: Completion,
|
||||
|
|
@ -338,7 +352,7 @@ class ZhipuAILargeLanguageModel(_CommonZhipuaiAI, LargeLanguageModel):
|
|||
)
|
||||
|
||||
text += choice.message.content or ''
|
||||
|
||||
|
||||
prompt_usage = response.usage.prompt_tokens
|
||||
completion_usage = response.usage.completion_tokens
|
||||
|
||||
|
|
@ -358,7 +372,7 @@ class ZhipuAILargeLanguageModel(_CommonZhipuaiAI, LargeLanguageModel):
|
|||
|
||||
return result
|
||||
|
||||
def _handle_generate_stream_response(self, model: str,
|
||||
def _handle_generate_stream_response(self, model: str,
|
||||
credentials: dict,
|
||||
tools: Optional[list[PromptMessageTool]],
|
||||
responses: Generator[ChatCompletionChunk, None, None],
|
||||
|
|
@ -380,7 +394,7 @@ class ZhipuAILargeLanguageModel(_CommonZhipuaiAI, LargeLanguageModel):
|
|||
|
||||
if delta.finish_reason is None and (delta.delta.content is None or delta.delta.content == ''):
|
||||
continue
|
||||
|
||||
|
||||
assistant_tool_calls: list[AssistantPromptMessage.ToolCall] = []
|
||||
for tool_call in delta.delta.tool_calls or []:
|
||||
if tool_call.type == 'function':
|
||||
|
|
@ -454,8 +468,8 @@ class ZhipuAILargeLanguageModel(_CommonZhipuaiAI, LargeLanguageModel):
|
|||
|
||||
return message_text
|
||||
|
||||
|
||||
def _convert_messages_to_prompt(self, messages: list[PromptMessage], tools: Optional[list[PromptMessageTool]] = None) -> str:
|
||||
def _convert_messages_to_prompt(self, messages: list[PromptMessage],
|
||||
tools: Optional[list[PromptMessageTool]] = None) -> str:
|
||||
"""
|
||||
:param messages: List of PromptMessage to combine.
|
||||
:return: Combined string with necessary human_prompt and ai_prompt tags.
|
||||
|
|
@ -473,4 +487,4 @@ class ZhipuAILargeLanguageModel(_CommonZhipuaiAI, LargeLanguageModel):
|
|||
text += f"\n{tool.json()}"
|
||||
|
||||
# trim off the trailing ' ' that might come from the "Assistant: "
|
||||
return text.rstrip()
|
||||
return text.rstrip()
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ class ApiTool(Tool):
|
|||
value = ''
|
||||
if parameter['name'] in parameters:
|
||||
value = parameters[parameter['name']]
|
||||
elif parameter['required']:
|
||||
elif parameter.get('required', False):
|
||||
raise ToolParameterValidationError(f"Missing required parameter {parameter['name']}")
|
||||
else:
|
||||
value = (parameter.get('schema', {}) or {}).get('default', '')
|
||||
|
|
@ -158,7 +158,7 @@ class ApiTool(Tool):
|
|||
value = ''
|
||||
if parameter['name'] in parameters:
|
||||
value = parameters[parameter['name']]
|
||||
elif parameter['required']:
|
||||
elif parameter.get('required', False):
|
||||
raise ToolParameterValidationError(f"Missing required parameter {parameter['name']}")
|
||||
else:
|
||||
value = (parameter.get('schema', {}) or {}).get('default', '')
|
||||
|
|
@ -168,7 +168,7 @@ class ApiTool(Tool):
|
|||
value = ''
|
||||
if parameter['name'] in parameters:
|
||||
value = parameters[parameter['name']]
|
||||
elif parameter['required']:
|
||||
elif parameter.get('required', False):
|
||||
raise ToolParameterValidationError(f"Missing required parameter {parameter['name']}")
|
||||
else:
|
||||
value = (parameter.get('schema', {}) or {}).get('default', '')
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ class Tool(BaseModel, ABC):
|
|||
result += f"result link: {response.message}. please tell user to check it."
|
||||
elif response.type == ToolInvokeMessage.MessageType.IMAGE_LINK or \
|
||||
response.type == ToolInvokeMessage.MessageType.IMAGE:
|
||||
result += "image has been created and sent to user already, you should tell user to check it now."
|
||||
result += "image has been created and sent to user already, you do not need to create it, just tell the user to check it now."
|
||||
elif response.type == ToolInvokeMessage.MessageType.BLOB:
|
||||
if len(response.message) > 114:
|
||||
result += str(response.message[:114]) + '...'
|
||||
|
|
|
|||
|
|
@ -5,6 +5,12 @@ def init_app(app: Flask):
|
|||
if app.config.get('API_COMPRESSION_ENABLED', False):
|
||||
from flask_compress import Compress
|
||||
|
||||
app.config['COMPRESS_MIMETYPES'] = [
|
||||
'application/json',
|
||||
'image/svg+xml',
|
||||
'text/html',
|
||||
]
|
||||
|
||||
compress = Compress()
|
||||
compress.init_app(app)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ from typing import Union
|
|||
|
||||
import boto3
|
||||
from azure.storage.blob import AccountSasPermissions, BlobServiceClient, ResourceTypes, generate_account_sas
|
||||
from botocore.client import Config
|
||||
from botocore.exceptions import ClientError
|
||||
from flask import Flask
|
||||
|
||||
|
|
@ -27,7 +28,8 @@ class Storage:
|
|||
aws_secret_access_key=app.config.get('S3_SECRET_KEY'),
|
||||
aws_access_key_id=app.config.get('S3_ACCESS_KEY'),
|
||||
endpoint_url=app.config.get('S3_ENDPOINT'),
|
||||
region_name=app.config.get('S3_REGION')
|
||||
region_name=app.config.get('S3_REGION'),
|
||||
config=Config(s3={'addressing_style': app.config.get('S3_ADDRESS_STYLE')})
|
||||
)
|
||||
elif self.storage_type == 'azure-blob':
|
||||
self.bucket_name = app.config.get('AZURE_BLOB_CONTAINER_NAME')
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from core.rag.datasource.vdb.vector_factory import Vector
|
|||
from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from models.dataset import Dataset
|
||||
from models.model import App, AppAnnotationSetting
|
||||
from models.model import App, AppAnnotationSetting, MessageAnnotation
|
||||
|
||||
|
||||
@shared_task(queue='dataset')
|
||||
|
|
@ -25,7 +25,7 @@ def disable_annotation_reply_task(job_id: str, app_id: str, tenant_id: str):
|
|||
App.tenant_id == tenant_id,
|
||||
App.status == 'normal'
|
||||
).first()
|
||||
|
||||
annotations_count = db.session.query(MessageAnnotation).filter(MessageAnnotation.app_id == app_id).count()
|
||||
if not app:
|
||||
raise NotFound("App not found")
|
||||
|
||||
|
|
@ -49,8 +49,9 @@ def disable_annotation_reply_task(job_id: str, app_id: str, tenant_id: str):
|
|||
)
|
||||
|
||||
try:
|
||||
vector = Vector(dataset, attributes=['doc_id', 'annotation_id', 'app_id'])
|
||||
vector.delete_by_metadata_field('app_id', app_id)
|
||||
if annotations_count > 0:
|
||||
vector = Vector(dataset, attributes=['doc_id', 'annotation_id', 'app_id'])
|
||||
vector.delete_by_metadata_field('app_id', app_id)
|
||||
except Exception:
|
||||
logging.exception("Delete annotation index failed when annotation deleted.")
|
||||
redis_client.setex(disable_app_annotation_job_key, 600, 'completed')
|
||||
|
|
|
|||
|
|
@ -343,8 +343,10 @@ services:
|
|||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
|
||||
- ./nginx/proxy.conf:/etc/nginx/proxy.conf
|
||||
- ./nginx/conf.d:/etc/nginx/conf.d
|
||||
#- ./nginx/ssl:/etc/ssl
|
||||
depends_on:
|
||||
- api
|
||||
- web
|
||||
ports:
|
||||
- "80:80"
|
||||
#- "443:443"
|
||||
|
|
|
|||
|
|
@ -26,4 +26,13 @@ server {
|
|||
proxy_pass http://web:3000;
|
||||
include proxy.conf;
|
||||
}
|
||||
}
|
||||
|
||||
# If you want to support HTTPS, please uncomment the code snippet below
|
||||
#listen 443 ssl;
|
||||
#ssl_certificate ./../ssl/your_cert_file.cer;
|
||||
#ssl_certificate_key ./../ssl/your_cert_key.key;
|
||||
#ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
|
||||
#ssl_prefer_server_ciphers on;
|
||||
#ssl_session_cache shared:SSL:10m;
|
||||
#ssl_session_timeout 10m;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
'use client'
|
||||
|
||||
import { forwardRef, useState } from 'react'
|
||||
import { forwardRef } from 'react'
|
||||
import classNames from 'classnames'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Link from 'next/link'
|
||||
import style from '../list.module.css'
|
||||
|
||||
const CreateAppCard = forwardRef<HTMLAnchorElement>((_, ref) => {
|
||||
const { t } = useTranslation()
|
||||
const [showNewAppDialog, setShowNewAppDialog] = useState(false)
|
||||
|
||||
return (
|
||||
<a ref={ref} className={classNames(style.listItem, style.newItemCard)} href='/datasets/create'>
|
||||
<Link ref={ref} className={classNames(style.listItem, style.newItemCard)} href='/datasets/create'>
|
||||
<div className={style.listItemTitle}>
|
||||
<span className={style.newItemIcon}>
|
||||
<span className={classNames(style.newItemIconImage, style.newItemIconAdd)} />
|
||||
|
|
@ -21,8 +21,10 @@ const CreateAppCard = forwardRef<HTMLAnchorElement>((_, ref) => {
|
|||
</div>
|
||||
<div className={style.listItemDescription}>{t('dataset.createDatasetIntro')}</div>
|
||||
{/* <div className='text-xs text-gray-500'>{t('app.createFromConfigFile')}</div> */}
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
})
|
||||
|
||||
CreateAppCard.displayName = 'CreateAppCard'
|
||||
|
||||
export default CreateAppCard
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ const BatchModal: FC<IBatchModalProps> = ({
|
|||
type="primary"
|
||||
onClick={handleSend}
|
||||
disabled={isAnnotationFull || !currentCSV}
|
||||
loading={importStatus === ProcessStatus.PROCESSING}
|
||||
loading={importStatus === ProcessStatus.PROCESSING || importStatus === ProcessStatus.WAITING}
|
||||
>
|
||||
{t('appAnnotation.batchModal.run')}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -212,16 +212,18 @@ const Chat: FC<IChatProps> = ({
|
|||
if (i === index) {
|
||||
return {
|
||||
...item,
|
||||
content: answer,
|
||||
annotation: {
|
||||
...item.annotation,
|
||||
logAnnotation: undefined,
|
||||
logAnnotation: {
|
||||
...item.annotation?.logAnnotation,
|
||||
content: answer,
|
||||
},
|
||||
} as any,
|
||||
}
|
||||
}
|
||||
return item
|
||||
}))
|
||||
}, [])
|
||||
}, [chatList])
|
||||
const handleAnnotationAdded = useCallback((annotationId: string, authorName: string, query: string, answer: string, index: number) => {
|
||||
onChatListChange?.(chatList.map((item, i) => {
|
||||
if (i === index - 1) {
|
||||
|
|
@ -251,7 +253,7 @@ const Chat: FC<IChatProps> = ({
|
|||
}
|
||||
return item
|
||||
}))
|
||||
}, [])
|
||||
}, [chatList])
|
||||
const handleAnnotationRemoved = useCallback((index: number) => {
|
||||
onChatListChange?.(chatList.map((item, i) => {
|
||||
if (i === index) {
|
||||
|
|
@ -261,12 +263,13 @@ const Chat: FC<IChatProps> = ({
|
|||
annotation: {
|
||||
...(item.annotation || {}),
|
||||
id: '',
|
||||
logAnnotation: undefined, // remove log
|
||||
} as Annotation,
|
||||
}
|
||||
}
|
||||
return item
|
||||
}))
|
||||
}, [])
|
||||
}, [chatList])
|
||||
|
||||
return (
|
||||
<div className={cn('px-3.5', 'h-full')}>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ const HeaderWrapper = ({
|
|||
children,
|
||||
}: HeaderWrapperProps) => {
|
||||
const pathname = usePathname()
|
||||
const isBordered = ['/apps', '/datasets'].includes(pathname)
|
||||
const isBordered = ['/apps', '/datasets', '/datasets/create'].includes(pathname)
|
||||
|
||||
return (
|
||||
<div className={classNames(
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ const Form: FC<FormProps> = ({
|
|||
flex justify-center items-center mr-2 w-4 h-4 border border-gray-300 rounded-full
|
||||
${value[variable] === option.value && 'border-[5px] border-primary-600'}
|
||||
`} />
|
||||
<div className='text-sm text-gray-900'>{option.label[language]}</div>
|
||||
<div className='text-sm text-gray-900'>{option.label[language] || option.label.en_US}</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
|
|
@ -212,9 +212,9 @@ const Form: FC<FormProps> = ({
|
|||
return option.show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value)
|
||||
|
||||
return true
|
||||
}).map(option => ({ value: option.value, name: option.label[language] }))}
|
||||
}).map(option => ({ value: option.value, name: option.label[language] || option.label.en_US }))}
|
||||
onSelect={item => handleFormChange(variable, item.value as string)}
|
||||
placeholder={placeholder?.[language]}
|
||||
placeholder={placeholder?.[language] || placeholder?.en_US}
|
||||
/>
|
||||
{fieldMoreInfo?.(formSchema)}
|
||||
{validating && changeKey === variable && <ValidatingTip />}
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ const ModelModal: FC<ModelModalProps> = ({
|
|||
const renderTitlePrefix = () => {
|
||||
const prefix = configurateMethod === ConfigurateMethodEnum.customizableModel ? t('common.operation.add') : t('common.operation.setup')
|
||||
|
||||
return `${prefix} ${provider.label[language]}`
|
||||
return `${prefix} ${provider.label[language] || provider.label.en_US}`
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -116,11 +116,11 @@ const ProviderCard: FC<ProviderCardProps> = ({
|
|||
return (
|
||||
<Button
|
||||
key={method}
|
||||
className='h-7 bg-white text-xs text-gray-700'
|
||||
className={'h-7 bg-white text-xs text-gray-700 shrink-0'}
|
||||
onClick={() => onOpenModal(method)}
|
||||
>
|
||||
<Settings01 className='mr-[5px] w-3.5 h-3.5' />
|
||||
{t('common.operation.setup')}
|
||||
<Settings01 className={`mr-[5px] w-3.5 h-3.5 ${s.icon}`} />
|
||||
<span className='text-xs inline-flex items-center justify-center overflow-ellipsis shrink-0'>{t('common.operation.setup')}</span>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ const ProviderIcon: FC<ProviderIconProps> = ({
|
|||
return (
|
||||
<div className={`inline-flex items-center ${className}`}>
|
||||
<div className='text-xs font-semibold text-black'>
|
||||
{provider.label[language]}
|
||||
{provider.label[language] || provider.label.en_US}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,39 +1,210 @@
|
|||
const translation = {
|
||||
you: '(Você)',
|
||||
api: {
|
||||
success: 'Sucesso',
|
||||
actionSuccess: 'Ação bem-sucedida',
|
||||
saved: 'Salvo',
|
||||
create: 'Criado',
|
||||
remove: 'Removido',
|
||||
},
|
||||
operation: {
|
||||
create: 'Criar',
|
||||
confirm: 'Confirmar',
|
||||
cancel: 'Cancelar',
|
||||
clear: 'Limpar',
|
||||
save: 'Salvar',
|
||||
edit: 'Editar',
|
||||
add: 'Adicionar',
|
||||
added: 'Adicionado',
|
||||
refresh: 'Reiniciar',
|
||||
reset: 'Redefinir',
|
||||
search: 'Buscar',
|
||||
change: 'Alterar',
|
||||
remove: 'Remover',
|
||||
send: 'Enviar',
|
||||
copy: 'Copiar',
|
||||
lineBreak: 'Quebra de linha',
|
||||
sure: 'Tenho certeza',
|
||||
download: 'Baixar',
|
||||
delete: 'Excluir',
|
||||
settings: 'Configurações',
|
||||
setup: 'Configuração',
|
||||
getForFree: 'Obter gratuitamente',
|
||||
reload: 'Recarregar',
|
||||
ok: 'OK',
|
||||
log: 'Log',
|
||||
learnMore: 'Saiba Mais',
|
||||
params: 'Parâmetros',
|
||||
},
|
||||
placeholder: {
|
||||
input: 'Por favor, insira',
|
||||
select: 'Por favor, selecione',
|
||||
},
|
||||
voice: {
|
||||
language: {
|
||||
zhHans: 'Chinês',
|
||||
enUS: 'Inglês',
|
||||
deDE: 'Alemão',
|
||||
frFR: 'Francês',
|
||||
esES: 'Espanhol',
|
||||
itIT: 'Italiano',
|
||||
thTH: 'Tailandês',
|
||||
idID: 'Indonésio',
|
||||
jaJP: 'Japonês',
|
||||
koKR: 'Coreano',
|
||||
ptBR: 'Português',
|
||||
ruRU: 'Russo',
|
||||
ukUA: 'Ucraniano',
|
||||
},
|
||||
},
|
||||
unit: {
|
||||
char: 'caracteres',
|
||||
},
|
||||
actionMsg: {
|
||||
noModification: 'Sem modificações no momento.',
|
||||
modifiedSuccessfully: 'Modificado com sucesso',
|
||||
modifiedUnsuccessfully: 'Modificado sem sucesso',
|
||||
copySuccessfully: 'Copiado com sucesso',
|
||||
paySucceeded: 'Pagamento realizado com sucesso',
|
||||
payCancelled: 'Pagamento cancelado',
|
||||
generatedSuccessfully: 'Gerado com sucesso',
|
||||
generatedUnsuccessfully: 'Geração sem sucesso',
|
||||
},
|
||||
model: {
|
||||
params: {
|
||||
temperature: 'Temperatura',
|
||||
temperatureTip:
|
||||
'Controla a aleatoriedade: Diminuir resulta em conclusões menos aleatórias. À medida que a temperatura se aproxima de zero, o modelo se tornará determinístico e repetitivo.',
|
||||
top_p: 'Top P',
|
||||
top_pTip:
|
||||
'Controla a diversidade via amostragem de núcleo: 0.5 significa que metade de todas as opções ponderadas por probabilidade são consideradas.',
|
||||
presence_penalty: 'Penalidade de presença',
|
||||
presence_penaltyTip:
|
||||
'Quanto penalizar novos tokens com base em se eles aparecem no texto até agora.\nAumenta a probabilidade do modelo de falar sobre novos tópicos.',
|
||||
frequency_penalty: 'Penalidade de frequência',
|
||||
frequency_penaltyTip:
|
||||
'Quanto penalizar novos tokens com base em sua frequência existente no texto até agora.\nDiminui a probabilidade do modelo de repetir a mesma linha textualmente.',
|
||||
max_tokens: 'Máximo de tokens',
|
||||
max_tokensTip:
|
||||
'Usado para limitar o comprimento máximo da resposta, em tokens. \nValores maiores podem limitar o espaço restante para palavras de prompt, registros de bate-papo e Conhecimento. \nRecomenda-se defini-lo abaixo de dois terços\ngpt-4-1106-preview, gpt-4-vision-preview max token (entrada 128k saída 4k)',
|
||||
maxTokenSettingTip: 'Sua configuração máxima de token é alta, limitando potencialmente o espaço para palavras de prompt, consultas e dados. Considere definir abaixo de 2/3.',
|
||||
setToCurrentModelMaxTokenTip: 'O máximo de tokens é atualizado para 80% do máximo de token do modelo atual {{maxToken}}.',
|
||||
stop_sequences: 'Sequências de parada',
|
||||
stop_sequencesTip: 'Até quatro sequências onde a API irá parar de gerar mais tokens. O texto retornado não conterá a sequência de parada.',
|
||||
stop_sequencesPlaceholder: 'Digite a sequência e pressione Tab',
|
||||
},
|
||||
tone: {
|
||||
Creative: 'Criativo',
|
||||
Balanced: 'Equilibrado',
|
||||
Precise: 'Preciso',
|
||||
Custom: 'Personalizado',
|
||||
},
|
||||
addMoreModel: 'Vá para configurações para adicionar mais modelos',
|
||||
},
|
||||
menus: {
|
||||
status: 'beta',
|
||||
explore: 'Explorar',
|
||||
apps: 'Estúdio',
|
||||
plugins: 'Plugins',
|
||||
pluginsTips: 'Integre plugins de terceiros ou crie plugins de IA compatíveis com o ChatGPT.',
|
||||
datasets: 'Conhecimento',
|
||||
datasetsTips: 'EM BREVE: Importe seus próprios dados de texto ou escreva dados em tempo real via Webhook para aprimoramento do contexto LLM.',
|
||||
newApp: 'Novo App',
|
||||
newDataset: 'Criar Conhecimento',
|
||||
tools: 'Ferramentas',
|
||||
},
|
||||
userProfile: {
|
||||
settings: 'Configurações',
|
||||
workspace: 'Espaço de trabalho',
|
||||
createWorkspace: 'Criar Espaço de Trabalho',
|
||||
helpCenter: 'Ajuda',
|
||||
roadmapAndFeedback: 'Roadmap e Feedback',
|
||||
community: 'Comunidade',
|
||||
about: 'Sobre',
|
||||
logout: 'Sair',
|
||||
},
|
||||
settings: {
|
||||
accountGroup: 'CONTA',
|
||||
workplaceGroup: 'ESPAÇO DE TRABALHO',
|
||||
account: 'Minha conta',
|
||||
members: 'Membros',
|
||||
billing: 'Faturamento',
|
||||
integrations: 'Integrações',
|
||||
language: 'Idioma',
|
||||
provider: 'Fornecedor de modelo',
|
||||
dataSource: 'Fonte de dados',
|
||||
plugin: 'Plugins',
|
||||
apiBasedExtension: 'Extensão baseada em API',
|
||||
},
|
||||
account: {
|
||||
avatar: 'Avatar',
|
||||
name: 'Nome',
|
||||
email: 'E-mail',
|
||||
password: 'Senha',
|
||||
passwordTip: 'Você pode definir uma senha permanente se não quiser usar códigos de login temporários',
|
||||
setPassword: 'Definir uma senha',
|
||||
resetPassword: 'Redefinir senha',
|
||||
currentPassword: 'Senha atual',
|
||||
newPassword: 'Nova senha',
|
||||
confirmPassword: 'Confirmar senha',
|
||||
notEqual: 'As duas senhas são diferentes.',
|
||||
langGeniusAccount: 'Conta Dify',
|
||||
langGeniusAccountTip: 'Sua conta Dify e dados de usuário associados.',
|
||||
editName: 'Editar Nome',
|
||||
showAppLength: 'Mostrar {{length}} apps',
|
||||
},
|
||||
members: {
|
||||
team: 'Equipe',
|
||||
invite: 'Adicionar',
|
||||
name: 'NOME',
|
||||
lastActive: 'ÚLTIMA ATIVIDADE',
|
||||
role: 'FUNÇÕES',
|
||||
pending: 'Pendente...',
|
||||
owner: 'Proprietário',
|
||||
admin: 'Admin',
|
||||
adminTip: 'Pode criar aplicativos e gerenciar configurações da equipe',
|
||||
normal: 'Normal',
|
||||
normalTip: 'Só pode usar aplicativos, não pode criar aplicativos',
|
||||
inviteTeamMember: 'Adicionar membro da equipe',
|
||||
inviteTeamMemberTip: 'Eles podem acessar os dados da sua equipe diretamente após fazer login.',
|
||||
email: 'E-mail',
|
||||
emailInvalid: 'Formato de e-mail inválido',
|
||||
emailPlaceholder: 'Por favor, insira e-mails',
|
||||
sendInvite: 'Enviar Convite',
|
||||
invitedAsRole: 'Convidado como usuário {{role}}',
|
||||
invitationSent: 'Convite enviado',
|
||||
invitationSentTip: 'Convite enviado e eles podem fazer login no Dify para acessar os dados da sua equipe.',
|
||||
invitationLink: 'Link do Convite',
|
||||
failedinvitationEmails: 'Os seguintes usuários não foram convidados com sucesso',
|
||||
ok: 'OK',
|
||||
removeFromTeam: 'Remover da equipe',
|
||||
removeFromTeamTip: 'Removerá o acesso da equipe',
|
||||
setAdmin: 'Definir como administrador',
|
||||
setMember: 'Definir como membro comum',
|
||||
disinvite: 'Cancelar o convite',
|
||||
deleteMember: 'Excluir Membro',
|
||||
you: '(Você)',
|
||||
},
|
||||
integrations: {
|
||||
connected: 'Conectado',
|
||||
google: 'Google',
|
||||
googleAccount: 'Entrar com conta do Google',
|
||||
googleAccount: 'Faça login com a conta do Google',
|
||||
github: 'GitHub',
|
||||
githubAccount: 'Entrar com conta do GitHub',
|
||||
githubAccount: 'Faça login com a conta do GitHub',
|
||||
connect: 'Conectar',
|
||||
},
|
||||
language: {
|
||||
displayLanguage: 'Idioma de exibição',
|
||||
timezone: 'Fuso horário',
|
||||
},
|
||||
voice: {
|
||||
language: {
|
||||
zhHans: 'chinês',
|
||||
enUS: 'inglês',
|
||||
deDE: 'alemão',
|
||||
frFR: 'francês',
|
||||
esES: 'espanhol',
|
||||
itIT: 'italiano',
|
||||
thTH: 'tailandês',
|
||||
idID: 'indonésio',
|
||||
ukUA: 'ucraniana',
|
||||
},
|
||||
},
|
||||
provider: {
|
||||
apiKey: 'Chave da API',
|
||||
enterYourKey: 'Insira sua chave da API aqui',
|
||||
invalidKey: 'Chave da API inválida',
|
||||
invalidKey: 'Chave da API OpenAI inválida',
|
||||
validatedError: 'Falha na validação: ',
|
||||
validating: 'Validando chave...',
|
||||
saveFailed: 'Falha ao salvar a chave da API',
|
||||
apiKeyExceedBill: 'Esta chave da API não possui cota disponível, por favor leia',
|
||||
addKey: 'Adicionar chave',
|
||||
apiKeyExceedBill: 'Esta CHAVE DE API não tem quota disponível, por favor, leia',
|
||||
addKey: 'Adicionar Chave',
|
||||
comingSoon: 'Em breve',
|
||||
editKey: 'Editar',
|
||||
invalidApiKey: 'Chave da API inválida',
|
||||
|
|
@ -42,49 +213,33 @@ const translation = {
|
|||
apiBasePlaceholder: 'A URL base da API do seu ponto de extremidade Azure OpenAI.',
|
||||
apiKey: 'Chave da API',
|
||||
apiKeyPlaceholder: 'Insira sua chave da API aqui',
|
||||
helpTip: 'Aprenda sobre o Serviço Azure OpenAI',
|
||||
helpTip: 'Saiba mais sobre o Serviço Azure OpenAI',
|
||||
},
|
||||
openaiHosted: {
|
||||
openaiHosted: 'OpenAI Hospedado',
|
||||
onTrial: 'EM TESTE',
|
||||
exhausted: 'COTA ESGOTADA',
|
||||
desc: 'O serviço de hospedagem OpenAI fornecido pela Dify permite que você use modelos como o GPT-3.5. Antes que sua cota de teste seja esgotada, você precisa configurar outros provedores de modelo.',
|
||||
callTimes: 'Número de chamadas',
|
||||
usedUp: 'Cota de teste esgotada. Adicione seu próprio provedor de modelo.',
|
||||
useYourModel: 'Atualmente usando seu próprio provedor de modelo.',
|
||||
desc: 'O serviço de hospedagem OpenAI fornecido pela Dify permite que você use modelos como GPT-3.5. Antes que sua cota de teste seja esgotada, você precisa configurar outros fornecedores de modelos.',
|
||||
callTimes: 'Chamadas',
|
||||
usedUp: 'Cota de teste esgotada. Adicione seu próprio Fornecedor de Modelo.',
|
||||
useYourModel: 'Atualmente usando seu próprio Fornecedor de Modelo.',
|
||||
close: 'Fechar',
|
||||
},
|
||||
voice: {
|
||||
language: {
|
||||
zhHans: 'chinês',
|
||||
enUS: 'inglês',
|
||||
deDE: 'alemão',
|
||||
frFR: 'francês',
|
||||
esES: 'espanhol',
|
||||
itIT: 'italiano',
|
||||
thTH: 'tailandês',
|
||||
idID: 'indonésio',
|
||||
jaJP: 'japonês',
|
||||
koKR: 'coreano',
|
||||
ptBR: 'português',
|
||||
ruRU: 'russo',
|
||||
},
|
||||
},
|
||||
anthropicHosted: {
|
||||
anthropicHosted: 'Anthropic Claude',
|
||||
onTrial: 'EM TESTE',
|
||||
exhausted: 'COTA ESGOTADA',
|
||||
desc: 'Modelo poderoso, que se destaca em uma ampla gama de tarefas, desde diálogos sofisticados e geração de conteúdo criativo até instruções detalhadas.',
|
||||
callTimes: 'Número de chamadas',
|
||||
usedUp: 'Cota de teste esgotada. Adicione seu próprio provedor de modelo.',
|
||||
useYourModel: 'Atualmente usando seu próprio provedor de modelo.',
|
||||
callTimes: 'Chamadas',
|
||||
usedUp: 'Cota de teste esgotada. Adicione seu próprio Fornecedor de Modelo.',
|
||||
useYourModel: 'Atualmente usando seu próprio Fornecedor de Modelo.',
|
||||
close: 'Fechar',
|
||||
},
|
||||
anthropic: {
|
||||
using: 'A capacidade de incorporação está usando',
|
||||
enableTip: 'Para habilitar o modelo Anthropic, você precisa se vincular ao OpenAI ou ao Azure OpenAI Service primeiro.',
|
||||
using: 'A capacidade de incorporação está sendo utilizada',
|
||||
enableTip: 'Para habilitar o modelo da Anthropic, você precisa vincular ao OpenAI ou ao Azure OpenAI Service primeiro.',
|
||||
notEnabled: 'Não habilitado',
|
||||
keyFrom: 'Obtenha sua chave da API do Anthropic',
|
||||
keyFrom: 'Obtenha sua chave da API da Anthropic',
|
||||
},
|
||||
encrypted: {
|
||||
front: 'Sua CHAVE DA API será criptografada e armazenada usando',
|
||||
|
|
@ -92,29 +247,33 @@ const translation = {
|
|||
},
|
||||
},
|
||||
modelProvider: {
|
||||
notConfigured: 'O modelo do sistema ainda não foi totalmente configurado e algumas funções podem não estar disponíveis.',
|
||||
systemModelSettings: 'Configurações do modelo do sistema',
|
||||
notConfigured: 'O modelo do sistema ainda não foi totalmente configurado e algumas funções podem estar indisponíveis.',
|
||||
systemModelSettings: 'Configurações do Modelo do Sistema',
|
||||
systemModelSettingsLink: 'Por que é necessário configurar um modelo do sistema?',
|
||||
selectModel: 'Selecione seu modelo',
|
||||
setupModelFirst: 'Por favor, configure seu modelo primeiro',
|
||||
systemReasoningModel: {
|
||||
key: 'Modelo de raciocínio do sistema',
|
||||
tip: 'Defina o modelo de inferência padrão a ser usado para criar aplicativos, bem como recursos como geração de nome de diálogo e sugestão de próxima pergunta também usarão o modelo de inferência padrão.',
|
||||
key: 'Modelo de Raciocínio do Sistema',
|
||||
tip: 'Defina o modelo de inferência padrão a ser usado para criar aplicativos, bem como recursos como geração de nomes de diálogo e sugestão de próxima pergunta também usarão o modelo de inferência padrão.',
|
||||
},
|
||||
embeddingModel: {
|
||||
key: 'Modelo de incorporação',
|
||||
tip: 'Defina o modelo padrão para o processamento de incorporação de documentos do Conhecimento, tanto a recuperação quanto a importação do Conhecimento usam este modelo de Incorporação para o processamento de vetorização. A troca causará inconsistência na dimensão do vetor entre o Conhecimento importado e a pergunta, resultando em falha na recuperação. Para evitar falhas na recuperação, não altere este modelo indiscriminadamente.',
|
||||
required: 'O modelo de incorporação é obrigatório',
|
||||
key: 'Modelo de Incorporação',
|
||||
tip: 'Defina o modelo padrão para o processamento de incorporação de documentos do Conhecimento, tanto a recuperação quanto a importação do Conhecimento usam este modelo de Incorporação para processamento de vetorização. Alterar causará inconsistência na dimensão do vetor entre o Conhecimento importado e a pergunta, resultando em falha na recuperação. Para evitar falhas na recuperação, não altere este modelo indiscriminadamente.',
|
||||
required: 'O modelo de Incorporação é obrigatório',
|
||||
},
|
||||
speechToTextModel: {
|
||||
key: 'Modelo de fala para texto',
|
||||
tip: 'Defina o modelo padrão para entrada de fala para texto em conversa.',
|
||||
key: 'Modelo de Fala para Texto',
|
||||
tip: 'Defina o modelo padrão para entrada de fala para texto na conversa.',
|
||||
},
|
||||
ttsModel: {
|
||||
key: 'Modelo de Texto para Fala',
|
||||
tip: 'Defina o modelo padrão para entrada de texto para fala na conversa.',
|
||||
},
|
||||
rerankModel: {
|
||||
key: 'Modelo de reclassificação',
|
||||
tip: 'O modelo de reclassificação reordenará a lista de documentos candidatos com base na correspondência semântica com a consulta do usuário, melhorando os resultados da classificação semântica',
|
||||
key: 'Modelo de Reordenação',
|
||||
tip: 'O modelo de reordenaenação reorganizará a lista de documentos candidatos com base na correspondência semântica com a consulta do usuário, melhorando os resultados da classificação semântica',
|
||||
},
|
||||
quota: 'Cota',
|
||||
quota: 'Quota',
|
||||
searchModel: 'Modelo de pesquisa',
|
||||
noModelFound: 'Nenhum modelo encontrado para {{model}}',
|
||||
models: 'Modelos',
|
||||
|
|
@ -122,24 +281,24 @@ const translation = {
|
|||
selector: {
|
||||
tip: 'Este modelo foi removido. Adicione um modelo ou selecione outro modelo.',
|
||||
emptyTip: 'Nenhum modelo disponível',
|
||||
emptySetting: 'Por favor, vá para as configurações para configurar',
|
||||
rerankTip: 'Por favor, configure o modelo de reclassificação',
|
||||
emptySetting: 'Por favor, vá para configurações para configurar',
|
||||
rerankTip: 'Por favor, configure o modelo de reordenação',
|
||||
},
|
||||
card: {
|
||||
quota: 'COTA',
|
||||
quota: 'QUOTA',
|
||||
onTrial: 'Em Teste',
|
||||
paid: 'Pago',
|
||||
quotaExhausted: 'Cota esgotada',
|
||||
callTimes: 'Número de chamadas',
|
||||
quotaExhausted: 'Quota esgotada',
|
||||
callTimes: 'Chamadas',
|
||||
tokens: 'Tokens',
|
||||
buyQuota: 'Comprar Cota',
|
||||
buyQuota: 'Comprar Quota',
|
||||
priorityUse: 'Uso prioritário',
|
||||
removeKey: 'Remover Chave da API',
|
||||
tip: 'A cota paga terá prioridade. A cota de teste será usada após a cota paga ser esgotada.',
|
||||
tip: 'A prioridade será dada à quota paga. A quota de teste será usada após a quota paga ser esgotada.',
|
||||
},
|
||||
item: {
|
||||
deleteDesc: '{{modelName}} está sendo usado como modelos de raciocínio do sistema. Algumas funções não estarão disponíveis após a remoção. Por favor, confirme.',
|
||||
freeQuota: 'COTA GRATUITA',
|
||||
freeQuota: 'QUOTA GRATUITA',
|
||||
},
|
||||
addApiKey: 'Adicionar sua chave da API',
|
||||
invalidApiKey: 'Chave da API inválida',
|
||||
|
|
@ -150,24 +309,25 @@ const translation = {
|
|||
freeQuota: {
|
||||
howToEarn: 'Como ganhar',
|
||||
},
|
||||
addMoreModelProvider: 'ADICIONAR MAIS PROVEDOR DE MODELO',
|
||||
addMoreModelProvider: 'ADICIONAR MAIS FORNECEDOR DE MODELO',
|
||||
addModel: 'Adicionar Modelo',
|
||||
modelsNum: '{{num}} Modelos',
|
||||
showModels: 'Mostrar Modelos',
|
||||
showModelsNum: 'Mostrar {{num}} Modelos',
|
||||
collapse: 'Recolher',
|
||||
config: 'Configurar',
|
||||
config: 'Configuração',
|
||||
modelAndParameters: 'Modelo e Parâmetros',
|
||||
model: 'Modelo',
|
||||
featureSupported: '{{feature}} suportado',
|
||||
callTimes: 'Número de chamadas',
|
||||
buyQuota: 'Comprar Cota',
|
||||
getFreeTokens: 'Obter Tokens gratuitos',
|
||||
callTimes: 'Chamadas',
|
||||
credits: 'Créditos de Mensagem',
|
||||
buyQuota: 'Comprar Quota',
|
||||
getFreeTokens: 'Obter Tokens Gratuitos',
|
||||
priorityUsing: 'Uso prioritário',
|
||||
deprecated: 'Descontinuado',
|
||||
deprecated: 'Obsoleto',
|
||||
confirmDelete: 'confirmar exclusão?',
|
||||
quotaTip: 'Tokens gratuitos disponíveis restantes',
|
||||
loadPresets: 'Carregar presentes',
|
||||
loadPresets: 'Carregar Predefinições',
|
||||
parameters: 'PARÂMETROS',
|
||||
},
|
||||
dataSource: {
|
||||
|
|
@ -197,11 +357,11 @@ const translation = {
|
|||
serpapi: {
|
||||
apiKey: 'Chave da API',
|
||||
apiKeyPlaceholder: 'Insira sua chave da API',
|
||||
keyFrom: 'Obtenha sua chave SerpAPI na página da conta SerpAPI',
|
||||
keyFrom: 'Obtenha sua chave da SerpAPI na página da conta da SerpAPI',
|
||||
},
|
||||
},
|
||||
apiBasedExtension: {
|
||||
title: 'As extensões de API fornecem gerenciamento centralizado de API, simplificando a configuração para uso fácil em aplicativos da Dify.',
|
||||
title: 'As extensões de API fornecem gerenciamento centralizado de API, simplificando a configuração para uso fácil em todos os aplicativos da Dify.',
|
||||
link: 'Saiba como desenvolver sua própria Extensão de API.',
|
||||
linkUrl: 'https://docs.dify.ai/features/extension/api_based_extension',
|
||||
add: 'Adicionar Extensão de API',
|
||||
|
|
@ -230,13 +390,13 @@ const translation = {
|
|||
type: 'Tipo',
|
||||
},
|
||||
about: {
|
||||
changeLog: 'Registro de alterações',
|
||||
changeLog: 'Registro de Alterações',
|
||||
updateNow: 'Atualizar agora',
|
||||
nowAvailable: 'Dify {{version}} está disponível agora.',
|
||||
latestAvailable: 'Dify {{version}} é a versão mais recente disponível.',
|
||||
nowAvailable: 'Dify {{version}} já está disponível.',
|
||||
latestAvailable: 'Dify {{version}} é a última versão disponível.',
|
||||
},
|
||||
appMenus: {
|
||||
overview: 'Visão geral',
|
||||
overview: 'Visão Geral',
|
||||
promptEng: 'Orquestrar',
|
||||
apiAccess: 'Acesso à API',
|
||||
logAndAnn: 'Logs e Anúncios',
|
||||
|
|
@ -248,7 +408,7 @@ const translation = {
|
|||
},
|
||||
appModes: {
|
||||
completionApp: 'Gerador de Texto',
|
||||
chatApp: 'Aplicativo de Chat',
|
||||
chatApp: 'Aplicativo de Bate-papo',
|
||||
},
|
||||
datasetMenus: {
|
||||
documents: 'Documentos',
|
||||
|
|
@ -256,7 +416,7 @@ const translation = {
|
|||
settings: 'Configurações',
|
||||
emptyTip: 'O Conhecimento não foi associado, por favor, vá para o aplicativo ou plug-in para completar a associação.',
|
||||
viewDoc: 'Ver documentação',
|
||||
relatedApp: 'aplicativos vinculados',
|
||||
relatedApp: 'aplicativos relacionados',
|
||||
},
|
||||
voiceInput: {
|
||||
speaking: 'Fale agora...',
|
||||
|
|
@ -268,10 +428,10 @@ const translation = {
|
|||
'gpt-3.5-turbo-16k': 'GPT-3.5-Turbo-16K',
|
||||
'gpt-4': 'GPT-4',
|
||||
'gpt-4-32k': 'GPT-4-32K',
|
||||
'text-davinci-003': 'Text-Davinci-003',
|
||||
'text-embedding-ada-002': 'Text-Embedding-Ada-002',
|
||||
'whisper-1': 'Whisper-1',
|
||||
'claude-instant-1': 'Claude-Instant',
|
||||
'text-davinci-003': 'Texto-Davinci-003',
|
||||
'text-embedding-ada-002': 'Texto-Embutimento-Ada-002',
|
||||
'whisper-1': 'Sussurro-1',
|
||||
'claude-instant-1': 'Claude-Instantâneo',
|
||||
'claude-2': 'Claude-2',
|
||||
},
|
||||
chat: {
|
||||
|
|
@ -281,29 +441,29 @@ const translation = {
|
|||
conversationNameCanNotEmpty: 'Nome da conversa obrigatório',
|
||||
citation: {
|
||||
title: 'CITAÇÕES',
|
||||
linkToDataset: 'Link para o Conhecimento',
|
||||
linkToDataset: 'Link para Conhecimento',
|
||||
characters: 'Personagens:',
|
||||
hitCount: 'Contagem de recuperação:',
|
||||
vectorHash: 'Hash do vetor:',
|
||||
vectorHash: 'Hash de vetor:',
|
||||
hitScore: 'Pontuação de recuperação:',
|
||||
},
|
||||
},
|
||||
promptEditor: {
|
||||
placeholder: 'Escreva sua palavra de estímulo aqui, digite \'{\' para inserir uma variável, digite \'/\' para inserir um bloco de conteúdo de estímulo',
|
||||
placeholder: 'Escreva sua palavra de incentivo aqui, digite \'{\' para inserir uma variável, digite \'/\' para inserir um bloco de conteúdo de incentivo',
|
||||
context: {
|
||||
item: {
|
||||
title: 'Contexto',
|
||||
desc: 'Inserir modelo de contexto',
|
||||
},
|
||||
modal: {
|
||||
title: '{{num}} Conhecimento em Contexto',
|
||||
title: '{{num}} Conhecimentos no Contexto',
|
||||
add: 'Adicionar Contexto',
|
||||
footer: 'Você pode gerenciar os contextos na seção de Contexto abaixo.',
|
||||
footer: 'Você pode gerenciar contextos na seção Contexto abaixo.',
|
||||
},
|
||||
},
|
||||
history: {
|
||||
item: {
|
||||
title: 'Histórico da Conversa',
|
||||
title: 'Histórico de Conversas',
|
||||
desc: 'Inserir modelo de mensagem histórica',
|
||||
},
|
||||
modal: {
|
||||
|
|
@ -329,17 +489,17 @@ const translation = {
|
|||
desc: 'Inserir modelo de consulta do usuário',
|
||||
},
|
||||
},
|
||||
existed: 'Já existe no estímulo',
|
||||
existed: 'Já existe no incentivo',
|
||||
},
|
||||
imageUploader: {
|
||||
uploadFromComputer: 'Enviar do computador',
|
||||
uploadFromComputerReadError: 'Falha na leitura da imagem, por favor, tente novamente.',
|
||||
uploadFromComputerUploadError: 'Falha no envio da imagem, por favor, envie novamente.',
|
||||
uploadFromComputer: 'Enviar do Computador',
|
||||
uploadFromComputerReadError: 'Falha ao ler a imagem, por favor, tente novamente.',
|
||||
uploadFromComputerUploadError: 'Falha ao enviar a imagem, por favor, envie novamente.',
|
||||
uploadFromComputerLimit: 'As imagens enviadas não podem exceder {{size}} MB',
|
||||
pasteImageLink: 'Colar link da imagem',
|
||||
pasteImageLinkInputPlaceholder: 'Cole o link da imagem aqui',
|
||||
pasteImageLinkInvalid: 'Link da imagem inválido',
|
||||
imageUpload: 'Envio de Imagem',
|
||||
imageUpload: 'Enviar Imagem',
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,29 +1,29 @@
|
|||
const translation = {
|
||||
custom: 'Customization',
|
||||
custom: 'Personalização',
|
||||
upgradeTip: {
|
||||
prefix: 'Upgrade your plan to',
|
||||
suffix: 'customize your brand.',
|
||||
prefix: 'Atualize seu plano para',
|
||||
suffix: 'personalizar sua marca.',
|
||||
},
|
||||
webapp: {
|
||||
title: 'Customize WebApp brand',
|
||||
removeBrand: 'Remove Powered by Dify',
|
||||
changeLogo: 'Change Powered by Brand Image',
|
||||
changeLogoTip: 'SVG or PNG format with a minimum size of 40x40px',
|
||||
title: 'Personalizar marca do WebApp',
|
||||
removeBrand: 'Remover Powered by Dify',
|
||||
changeLogo: 'Alterar Imagem da Marca Powered by',
|
||||
changeLogoTip: 'Formato SVG ou PNG com tamanho mínimo de 40x40px',
|
||||
},
|
||||
app: {
|
||||
title: 'Customize app header brand',
|
||||
changeLogoTip: 'SVG or PNG format with a minimum size of 80x80px',
|
||||
title: 'Personalizar cabeçalho do aplicativo',
|
||||
changeLogoTip: 'Formato SVG ou PNG com tamanho mínimo de 80x80px',
|
||||
},
|
||||
upload: 'Upload',
|
||||
uploading: 'Uploading',
|
||||
uploadedFail: 'Image upload failed, please re-upload.',
|
||||
change: 'Change',
|
||||
apply: 'Apply',
|
||||
restore: 'Restore Defaults',
|
||||
upload: 'Enviar',
|
||||
uploading: 'Enviando',
|
||||
uploadedFail: 'Falha no envio da imagem, por favor, envie novamente.',
|
||||
change: 'Alterar',
|
||||
apply: 'Aplicar',
|
||||
restore: 'Restaurar Padrões',
|
||||
customize: {
|
||||
contactUs: ' contact us ',
|
||||
prefix: 'To customize the brand logo within the app, please',
|
||||
suffix: 'to upgrade to the Enterprise edition.',
|
||||
contactUs: ' entre em contato conosco ',
|
||||
prefix: 'Para personalizar o logotipo da marca dentro do aplicativo, por favor',
|
||||
suffix: 'para fazer upgrade para a edição Enterprise.',
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ const translation = {
|
|||
type: {
|
||||
all: 'Todas',
|
||||
builtIn: 'Integradas',
|
||||
custom: 'Personal...',
|
||||
custom: 'Personalizadas',
|
||||
},
|
||||
contribute: {
|
||||
line1: 'Estou interessado em ',
|
||||
|
|
@ -13,7 +13,7 @@ const translation = {
|
|||
},
|
||||
author: 'Por',
|
||||
auth: {
|
||||
unauthorized: 'Não autorizado',
|
||||
unauthorized: 'Para Autorizar',
|
||||
authorized: 'Autorizado',
|
||||
setup: 'Configurar autorização para usar',
|
||||
setupModalTitle: 'Configurar Autorização',
|
||||
|
|
@ -35,8 +35,8 @@ const translation = {
|
|||
urlError: 'Digite uma URL válida',
|
||||
examples: 'Exemplos',
|
||||
exampleOptions: {
|
||||
json: 'Clima (JSON)',
|
||||
yaml: 'Pet Store (YAML)',
|
||||
json: 'Clima(JSON)',
|
||||
yaml: 'Pet Store(YAML)',
|
||||
blankTemplate: 'Modelo em Branco',
|
||||
},
|
||||
availableTools: {
|
||||
|
|
@ -51,18 +51,22 @@ const translation = {
|
|||
authMethod: {
|
||||
title: 'Método de Autorização',
|
||||
type: 'Tipo de Autorização',
|
||||
keyTooltip: 'Chave do Cabeçalho HTTP, você pode deixar como "Authorization" se não tiver ideia do que é ou definir um valor personalizado',
|
||||
types: {
|
||||
none: 'Nenhum',
|
||||
api_key: 'Chave de API',
|
||||
apiKeyPlaceholder: 'Nome do cabeçalho HTTP para a Chave de API',
|
||||
apiValuePlaceholder: 'Digite a Chave de API',
|
||||
},
|
||||
key: 'Chave',
|
||||
value: 'Valor',
|
||||
},
|
||||
authHeaderPrefix: {
|
||||
title: 'Tipo de Autenticação',
|
||||
types: {
|
||||
basic: 'Basic',
|
||||
basic: 'Básica',
|
||||
bearer: 'Bearer',
|
||||
custom: 'Custom',
|
||||
custom: 'Personalizada',
|
||||
},
|
||||
},
|
||||
privacyPolicy: 'Política de Privacidade',
|
||||
|
|
@ -94,7 +98,7 @@ const translation = {
|
|||
},
|
||||
noCustomTool: {
|
||||
title: 'Nenhuma ferramenta personalizada!',
|
||||
content: 'Você não possui ferramentas personalizadas. ',
|
||||
content: 'Adicione e gerencie suas ferramentas personalizadas aqui para construir aplicativos de IA.',
|
||||
createTool: 'Criar Ferramenta',
|
||||
},
|
||||
noSearchRes: {
|
||||
|
|
@ -104,7 +108,8 @@ const translation = {
|
|||
},
|
||||
builtInPromptTitle: 'Prompt',
|
||||
toolRemoved: 'Ferramenta removida',
|
||||
howToGet: 'Como conseguir',
|
||||
notAuthorized: 'Ferramenta não autorizada',
|
||||
howToGet: 'Como obter',
|
||||
}
|
||||
|
||||
export default translation
|
||||
|
|
|
|||
|
|
@ -49,11 +49,14 @@ const translation = {
|
|||
test: 'Перевірка',
|
||||
},
|
||||
authMethod: {
|
||||
title: 'Спосіб авторизації',
|
||||
title: 'Метод авторизації',
|
||||
type: 'Тип авторизації',
|
||||
keyTooltip: 'Ключ HTTP-заголовка. Якщо ви не знаєте, залиште його як "Authorization" або встановіть власне значення',
|
||||
types: {
|
||||
none: 'Немає',
|
||||
api_key: 'API ключі',
|
||||
none: 'Відсутня',
|
||||
api_key: 'API-ключ',
|
||||
apiKeyPlaceholder: 'Назва HTTP-заголовка для API-ключа',
|
||||
apiValuePlaceholder: 'Введіть API-ключ',
|
||||
},
|
||||
key: 'Ключ',
|
||||
value: 'Значення',
|
||||
|
|
|
|||
|
|
@ -72,6 +72,14 @@ const translation = {
|
|||
privacyPolicy: '隐私协议',
|
||||
privacyPolicyPlaceholder: '请输入隐私协议',
|
||||
},
|
||||
test: {
|
||||
title: '测试',
|
||||
parametersValue: '参数和值',
|
||||
parameters: '参数',
|
||||
value: '值',
|
||||
testResult: '测试结果',
|
||||
testResultPlaceholder: '测试结果将显示在这里',
|
||||
},
|
||||
thought: {
|
||||
using: '正在使用',
|
||||
used: '已使用',
|
||||
|
|
|
|||
Loading…
Reference in New Issue