Unverified Commit c81e07af authored by Yeuoly's avatar Yeuoly

Merge branch 'main' into feat/enterprise

parents 41f9a690 bc65ee10
...@@ -86,7 +86,7 @@ UPLOAD_IMAGE_FILE_SIZE_LIMIT=10 ...@@ -86,7 +86,7 @@ UPLOAD_IMAGE_FILE_SIZE_LIMIT=10
MULTIMODAL_SEND_IMAGE_FORMAT=base64 MULTIMODAL_SEND_IMAGE_FORMAT=base64
# Mail configuration, support: resend, smtp # Mail configuration, support: resend, smtp
MAIL_TYPE=resend MAIL_TYPE=
MAIL_DEFAULT_SEND_FROM=no-reply <no-reply@dify.ai> MAIL_DEFAULT_SEND_FROM=no-reply <no-reply@dify.ai>
RESEND_API_KEY= RESEND_API_KEY=
RESEND_API_URL=https://api.resend.com RESEND_API_URL=https://api.resend.com
...@@ -135,4 +135,4 @@ UNSTRUCTURED_API_URL= ...@@ -135,4 +135,4 @@ UNSTRUCTURED_API_URL=
SSRF_PROXY_HTTP_URL= SSRF_PROXY_HTTP_URL=
SSRF_PROXY_HTTPS_URL= SSRF_PROXY_HTTPS_URL=
BATCH_UPLOAD_LIMIT=10 BATCH_UPLOAD_LIMIT=10
\ No newline at end of file
...@@ -131,6 +131,8 @@ def vdb_migrate(): ...@@ -131,6 +131,8 @@ def vdb_migrate():
""" """
click.echo(click.style('Start migrate vector db.', fg='green')) click.echo(click.style('Start migrate vector db.', fg='green'))
create_count = 0 create_count = 0
skipped_count = 0
total_count = 0
config = current_app.config config = current_app.config
vector_type = config.get('VECTOR_STORE') vector_type = config.get('VECTOR_STORE')
page = 1 page = 1
...@@ -143,11 +145,16 @@ def vdb_migrate(): ...@@ -143,11 +145,16 @@ def vdb_migrate():
page += 1 page += 1
for dataset in datasets: for dataset in datasets:
total_count = total_count + 1
click.echo(f'Processing the {total_count} dataset {dataset.id}. '
+ f'{create_count} created, ${skipped_count} skipped.')
try: try:
click.echo('Create dataset vdb index: {}'.format(dataset.id)) click.echo('Create dataset vdb index: {}'.format(dataset.id))
if dataset.index_struct_dict: if dataset.index_struct_dict:
if dataset.index_struct_dict['type'] == vector_type: if dataset.index_struct_dict['type'] == vector_type:
skipped_count = skipped_count + 1
continue continue
collection_name = ''
if vector_type == "weaviate": if vector_type == "weaviate":
dataset_id = dataset.id dataset_id = dataset.id
collection_name = Dataset.gen_collection_name_by_id(dataset_id) collection_name = Dataset.gen_collection_name_by_id(dataset_id)
...@@ -186,11 +193,17 @@ def vdb_migrate(): ...@@ -186,11 +193,17 @@ def vdb_migrate():
raise ValueError(f"Vector store {config.get('VECTOR_STORE')} is not supported.") raise ValueError(f"Vector store {config.get('VECTOR_STORE')} is not supported.")
vector = Vector(dataset) vector = Vector(dataset)
click.echo(f"vdb_migrate {dataset.id}") click.echo(f"Start to migrate dataset {dataset.id}.")
try: try:
vector.delete() vector.delete()
click.echo(
click.style(f'Successfully delete vector index {collection_name} for dataset {dataset.id}.',
fg='green'))
except Exception as e: except Exception as e:
click.echo(
click.style(f'Failed to delete vector index {collection_name} for dataset {dataset.id}.',
fg='red'))
raise e raise e
dataset_documents = db.session.query(DatasetDocument).filter( dataset_documents = db.session.query(DatasetDocument).filter(
...@@ -201,6 +214,7 @@ def vdb_migrate(): ...@@ -201,6 +214,7 @@ def vdb_migrate():
).all() ).all()
documents = [] documents = []
segments_count = 0
for dataset_document in dataset_documents: for dataset_document in dataset_documents:
segments = db.session.query(DocumentSegment).filter( segments = db.session.query(DocumentSegment).filter(
DocumentSegment.document_id == dataset_document.id, DocumentSegment.document_id == dataset_document.id,
...@@ -220,15 +234,22 @@ def vdb_migrate(): ...@@ -220,15 +234,22 @@ def vdb_migrate():
) )
documents.append(document) documents.append(document)
segments_count = segments_count + 1
if documents: if documents:
try: try:
click.echo(click.style(
f'Start to created vector index with {len(documents)} documents of {segments_count} segments for dataset {dataset.id}.',
fg='green'))
vector.create(documents) vector.create(documents)
click.echo(
click.style(f'Successfully created vector index for dataset {dataset.id}.', fg='green'))
except Exception as e: except Exception as e:
click.echo(click.style(f'Failed to created vector index for dataset {dataset.id}.', fg='red'))
raise e raise e
click.echo(f"Dataset {dataset.id} create successfully.")
db.session.add(dataset) db.session.add(dataset)
db.session.commit() db.session.commit()
click.echo(f'Successfully migrated dataset {dataset.id}.')
create_count += 1 create_count += 1
except Exception as e: except Exception as e:
db.session.rollback() db.session.rollback()
...@@ -237,7 +258,9 @@ def vdb_migrate(): ...@@ -237,7 +258,9 @@ def vdb_migrate():
fg='red')) fg='red'))
continue continue
click.echo(click.style('Congratulations! Create {} dataset indexes.'.format(create_count), fg='green')) click.echo(
click.style(f'Congratulations! Create {create_count} dataset indexes, and skipped {skipped_count} datasets.',
fg='green'))
def register_commands(app): def register_commands(app):
......
from collections.abc import Generator from collections.abc import Generator
from os.path import join
from typing import cast from typing import cast
from urllib.parse import urljoin
from httpx import Timeout from httpx import Timeout
from openai import ( from openai import (
...@@ -313,10 +313,13 @@ class LocalAILarguageModel(LargeLanguageModel): ...@@ -313,10 +313,13 @@ class LocalAILarguageModel(LargeLanguageModel):
:param credentials: credentials dict :param credentials: credentials dict
:return: client kwargs :return: client kwargs
""" """
if not credentials['server_url'].endswith('/'):
credentials['server_url'] += '/'
client_kwargs = { client_kwargs = {
"timeout": Timeout(315.0, read=300.0, write=10.0, connect=5.0), "timeout": Timeout(315.0, read=300.0, write=10.0, connect=5.0),
"api_key": "1", "api_key": "1",
"base_url": join(credentials['server_url'], 'v1'), "base_url": urljoin(credentials['server_url'], 'v1'),
} }
return client_kwargs return client_kwargs
......
<svg id="logomark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 17.732 24.269"><g id="tiny"><path d="M573.549,280.916l2.266,2.738,6.674-7.84c.353-.47.52-.717.353-1.117a1.218,1.218,0,0,0-1.061-.748h0a.953.953,0,0,0-.712.262Z" transform="translate(-566.984 -271.548)" fill="#bdb9b4"/><path d="M579.525,282.225l-10.606-10.174a1.413,1.413,0,0,0-.834-.5,1.09,1.09,0,0,0-1.027.66c-.167.4-.047.681.319,1.206l8.44,10.242h0l-6.282,7.716a1.336,1.336,0,0,0-.323,1.3,1.114,1.114,0,0,0,1.04.69A.992.992,0,0,0,571,293l8.519-7.92A1.924,1.924,0,0,0,579.525,282.225Z" transform="translate(-566.984 -271.548)" fill="#b31b1b"/><path d="M584.32,293.912l-8.525-10.275,0,0L573.53,280.9l-1.389,1.254a2.063,2.063,0,0,0,0,2.965l10.812,10.419a.925.925,0,0,0,.742.282,1.039,1.039,0,0,0,.953-.667A1.261,1.261,0,0,0,584.32,293.912Z" transform="translate(-566.984 -271.548)" fill="#bdb9b4"/></g></svg>
\ No newline at end of file
from core.tools.errors import ToolProviderCredentialValidationError
from core.tools.provider.builtin.arxiv.tools.arxiv_search import ArxivSearchTool
from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
class ArxivProvider(BuiltinToolProviderController):
def _validate_credentials(self, credentials: dict) -> None:
try:
ArxivSearchTool().fork_tool_runtime(
meta={
"credentials": credentials,
}
).invoke(
user_id='',
tool_parameters={
"query": "John Doe",
},
)
except Exception as e:
raise ToolProviderCredentialValidationError(str(e))
\ No newline at end of file
identity:
author: Yash Parmar
name: arxiv
label:
en_US: ArXiv
zh_Hans: ArXiv
description:
en_US: Access to a vast repository of scientific papers and articles in various fields of research.
zh_Hans: 访问各个研究领域大量科学论文和文章的存储库。
icon: icon.svg
from typing import Any
from langchain.utilities import ArxivAPIWrapper
from pydantic import BaseModel, Field
from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool
class ArxivSearchInput(BaseModel):
query: str = Field(..., description="Search query.")
class ArxivSearchTool(BuiltinTool):
"""
A tool for searching articles on Arxiv.
"""
def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage | list[ToolInvokeMessage]:
"""
Invokes the Arxiv search tool with the given user ID and tool parameters.
Args:
user_id (str): The ID of the user invoking the tool.
tool_parameters (dict[str, Any]): The parameters for the tool, including the 'query' parameter.
Returns:
ToolInvokeMessage | list[ToolInvokeMessage]: The result of the tool invocation, which can be a single message or a list of messages.
"""
query = tool_parameters.get('query', '')
if not query:
return self.create_text_message('Please input query')
arxiv = ArxivAPIWrapper()
response = arxiv.run(query)
return self.create_text_message(self.summary(user_id=user_id, content=response))
identity:
name: arxiv_search
author: Yash Parmar
label:
en_US: Arxiv Search
zh_Hans: Arxiv 搜索
description:
human:
en_US: A tool for searching scientific papers and articles from the Arxiv repository. Input can be an Arxiv ID or an author's name.
zh_Hans: 一个用于从Arxiv存储库搜索科学论文和文章的工具。 输入可以是Arxiv ID或作者姓名。
llm: A tool for searching scientific papers and articles from the Arxiv repository. Input can be an Arxiv ID or an author's name.
parameters:
- name: query
type: string
required: true
label:
en_US: Query string
zh_Hans: 查询字符串
human_description:
en_US: The Arxiv ID or author's name used for searching.
zh_Hans: 用于搜索的Arxiv ID或作者姓名。
llm_description: The Arxiv ID or author's name used for searching.
form: llm
...@@ -54,4 +54,4 @@ class GaodeRepositoriesTool(BuiltinTool): ...@@ -54,4 +54,4 @@ class GaodeRepositoriesTool(BuiltinTool):
s.close() s.close()
return self.create_text_message(f'No weather information for {city} was found.') return self.create_text_message(f'No weather information for {city} was found.')
except Exception as e: except Exception as e:
return self.create_text_message("Github API Key and Api Version is invalid. {}".format(e)) return self.create_text_message("Gaode API Key and Api Version is invalid. {}".format(e))
...@@ -70,7 +70,7 @@ class StableDiffusionTool(BuiltinTool): ...@@ -70,7 +70,7 @@ class StableDiffusionTool(BuiltinTool):
if not base_url: if not base_url:
return self.create_text_message('Please input base_url') return self.create_text_message('Please input base_url')
if 'model' in tool_parameters: if 'model' in tool_parameters and tool_parameters['model']:
self.runtime.credentials['model'] = tool_parameters['model'] self.runtime.credentials['model'] = tool_parameters['model']
model = self.runtime.credentials.get('model', None) model = self.runtime.credentials.get('model', None)
......
...@@ -146,7 +146,8 @@ class ApiBasedToolSchemaParser: ...@@ -146,7 +146,8 @@ class ApiBasedToolSchemaParser:
bundles.append(ApiBasedToolBundle( bundles.append(ApiBasedToolBundle(
server_url=server_url + interface['path'], server_url=server_url + interface['path'],
method=interface['method'], method=interface['method'],
summary=interface['operation']['summary'] if 'summary' in interface['operation'] else None, summary=interface['operation']['description'] if 'description' in interface['operation'] else
interface['operation']['summary'] if 'summary' in interface['operation'] else None,
operation_id=interface['operation']['operationId'], operation_id=interface['operation']['operationId'],
parameters=parameters, parameters=parameters,
author='', author='',
...@@ -249,12 +250,10 @@ class ApiBasedToolSchemaParser: ...@@ -249,12 +250,10 @@ class ApiBasedToolSchemaParser:
if 'operationId' not in operation: if 'operationId' not in operation:
raise ToolApiSchemaError(f'No operationId found in operation {method} {path}.') raise ToolApiSchemaError(f'No operationId found in operation {method} {path}.')
if 'summary' not in operation or len(operation['summary']) == 0: if ('summary' not in operation or len(operation['summary']) == 0) and \
warning['missing_summary'] = f'No summary found in operation {method} {path}.' ('description' not in operation or len(operation['description']) == 0):
warning['missing_summary'] = f'No summary or description found in operation {method} {path}.'
if 'description' not in operation or len(operation['description']) == 0:
warning['missing_description'] = f'No description found in operation {method} {path}.'
openapi['paths'][path][method] = { openapi['paths'][path][method] = {
'operationId': operation['operationId'], 'operationId': operation['operationId'],
'summary': operation.get('summary', ''), 'summary': operation.get('summary', ''),
......
...@@ -66,4 +66,5 @@ yfinance~=0.2.35 ...@@ -66,4 +66,5 @@ yfinance~=0.2.35
pydub~=0.25.1 pydub~=0.25.1
gmpy2~=2.1.5 gmpy2~=2.1.5
numexpr~=2.9.0 numexpr~=2.9.0
duckduckgo-search==4.4.3 duckduckgo-search==4.4.3
\ No newline at end of file arxiv==2.1.0
\ No newline at end of file
...@@ -209,8 +209,8 @@ class ToolManageService: ...@@ -209,8 +209,8 @@ class ToolManageService:
# extra info like description will be set here # extra info like description will be set here
tool_bundles, schema_type = ToolManageService.convert_schema_to_tool_bundles(schema, extra_info) tool_bundles, schema_type = ToolManageService.convert_schema_to_tool_bundles(schema, extra_info)
if len(tool_bundles) > 10: if len(tool_bundles) > 100:
raise ValueError('the number of apis should be less than 10') raise ValueError('the number of apis should be less than 100')
# create db provider # create db provider
db_provider = ApiToolProvider( db_provider = ApiToolProvider(
......
...@@ -153,18 +153,18 @@ const AgentTools: FC = () => { ...@@ -153,18 +153,18 @@ const AgentTools: FC = () => {
) )
: ( : (
<div className='hidden group-hover:flex items-center'> <div className='hidden group-hover:flex items-center'>
{item.provider_type === CollectionType.builtIn && ( {/* {item.provider_type === CollectionType.builtIn && ( */}
<TooltipPlus <TooltipPlus
popupContent={t('tools.setBuiltInTools.infoAndSetting')} popupContent={t('tools.setBuiltInTools.infoAndSetting')}
> >
<div className='mr-1 p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { <div className='mr-1 p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => {
setCurrentTool(item) setCurrentTool(item)
setIsShowSettingTool(true) setIsShowSettingTool(true)
}}> }}>
<InfoCircle className='w-4 h-4 text-gray-500' /> <InfoCircle className='w-4 h-4 text-gray-500' />
</div> </div>
</TooltipPlus> </TooltipPlus>
)} {/* )} */}
<div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { <div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => {
const newModelConfig = produce(modelConfig, (draft) => { const newModelConfig = produce(modelConfig, (draft) => {
...@@ -209,6 +209,7 @@ const AgentTools: FC = () => { ...@@ -209,6 +209,7 @@ const AgentTools: FC = () => {
toolName={currentTool?.tool_name as string} toolName={currentTool?.tool_name as string}
setting={currentTool?.tool_parameters as any} setting={currentTool?.tool_parameters as any}
collection={currentTool?.collection as Collection} collection={currentTool?.collection as Collection}
isBuiltIn={currentTool?.collection?.type === CollectionType.builtIn}
onSave={handleToolSettingChange} onSave={handleToolSettingChange}
onHide={() => setIsShowSettingTool(false)} onHide={() => setIsShowSettingTool(false)}
/>) />)
......
...@@ -8,14 +8,17 @@ import Drawer from '@/app/components/base/drawer-plus' ...@@ -8,14 +8,17 @@ import Drawer from '@/app/components/base/drawer-plus'
import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form' import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form'
import { addDefaultValue, toolParametersToFormSchemas } from '@/app/components/tools/utils/to-form-schema' import { addDefaultValue, toolParametersToFormSchemas } from '@/app/components/tools/utils/to-form-schema'
import type { Collection, Tool } from '@/app/components/tools/types' import type { Collection, Tool } from '@/app/components/tools/types'
import { fetchBuiltInToolList } from '@/service/tools' import { fetchBuiltInToolList, fetchCustomToolList } from '@/service/tools'
import I18n from '@/context/i18n' import I18n from '@/context/i18n'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import Loading from '@/app/components/base/loading' import Loading from '@/app/components/base/loading'
import { DiagonalDividingLine } from '@/app/components/base/icons/src/public/common' import { DiagonalDividingLine } from '@/app/components/base/icons/src/public/common'
import { getLanguage } from '@/i18n/language' import { getLanguage } from '@/i18n/language'
import AppIcon from '@/app/components/base/app-icon'
type Props = { type Props = {
collection: Collection collection: Collection
isBuiltIn?: boolean
toolName: string toolName: string
setting?: Record<string, any> setting?: Record<string, any>
readonly?: boolean readonly?: boolean
...@@ -25,6 +28,7 @@ type Props = { ...@@ -25,6 +28,7 @@ type Props = {
const SettingBuiltInTool: FC<Props> = ({ const SettingBuiltInTool: FC<Props> = ({
collection, collection,
isBuiltIn = true,
toolName, toolName,
setting = {}, setting = {},
readonly, readonly,
...@@ -52,7 +56,7 @@ const SettingBuiltInTool: FC<Props> = ({ ...@@ -52,7 +56,7 @@ const SettingBuiltInTool: FC<Props> = ({
(async () => { (async () => {
setIsLoading(true) setIsLoading(true)
try { try {
const list = await fetchBuiltInToolList(collection.name) const list = isBuiltIn ? await fetchBuiltInToolList(collection.name) : await fetchCustomToolList(collection.name)
setTools(list) setTools(list)
const currTool = list.find(tool => tool.name === toolName) const currTool = list.find(tool => tool.name === toolName)
if (currTool) { if (currTool) {
...@@ -135,12 +139,24 @@ const SettingBuiltInTool: FC<Props> = ({ ...@@ -135,12 +139,24 @@ const SettingBuiltInTool: FC<Props> = ({
onHide={onHide} onHide={onHide}
title={( title={(
<div className='flex'> <div className='flex'>
<div {collection.icon === 'string'
className='w-6 h-6 bg-cover bg-center rounded-md' ? (
style={{ <div
backgroundImage: `url(${collection.icon})`, className='w-6 h-6 bg-cover bg-center rounded-md'
}} style={{
></div> backgroundImage: `url(${collection.icon})`,
}}
></div>
)
: (
<AppIcon
className='rounded-md'
size='tiny'
icon={(collection.icon as any)?.content}
background={(collection.icon as any)?.background}
/>
)}
<div className='ml-2 leading-6 text-base font-semibold text-gray-900'>{currTool?.label[language]}</div> <div className='ml-2 leading-6 text-base font-semibold text-gray-900'>{currTool?.label[language]}</div>
{(hasSetting && !readonly) && (<> {(hasSetting && !readonly) && (<>
<DiagonalDividingLine className='mx-4' /> <DiagonalDividingLine className='mx-4' />
......
...@@ -26,7 +26,8 @@ const Apps: FC = () => { ...@@ -26,7 +26,8 @@ const Apps: FC = () => {
const { isCurrentWorkspaceManager } = useAppContext() const { isCurrentWorkspaceManager } = useAppContext()
const router = useRouter() const router = useRouter()
const { hasEditPermission } = useContext(ExploreContext) const { hasEditPermission } = useContext(ExploreContext)
const allCategoriesEn = t('explore.apps.allCategories') const allCategoriesEn = t('explore.apps.allCategories', { lng: 'en' })
const [currCategory, setCurrCategory] = useTabSearchParams({ const [currCategory, setCurrCategory] = useTabSearchParams({
defaultTab: allCategoriesEn, defaultTab: allCategoriesEn,
}) })
...@@ -47,11 +48,10 @@ const Apps: FC = () => { ...@@ -47,11 +48,10 @@ const Apps: FC = () => {
}, },
) )
const currList = (() => { const currList
if (currCategory === allCategoriesEn) = currCategory === allCategoriesEn
return allList ? allList
return allList.filter(item => item.category === currCategory) : allList.filter(item => item.category === currCategory)
})()
const [currApp, setCurrApp] = React.useState<App | null>(null) const [currApp, setCurrApp] = React.useState<App | null>(null)
const [isShowCreateModal, setIsShowCreateModal] = React.useState(false) const [isShowCreateModal, setIsShowCreateModal] = React.useState(false)
...@@ -112,6 +112,7 @@ const Apps: FC = () => { ...@@ -112,6 +112,7 @@ const Apps: FC = () => {
list={categories} list={categories}
value={currCategory} value={currCategory}
onChange={setCurrCategory} onChange={setCurrCategory}
allCategoriesEn={allCategoriesEn}
/> />
<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 <nav
......
...@@ -12,7 +12,11 @@ export type ICategoryProps = { ...@@ -12,7 +12,11 @@ export type ICategoryProps = {
className?: string className?: string
list: AppCategory[] list: AppCategory[]
value: string value: string
onChange: (value: AppCategory | '') => void onChange: (value: AppCategory | string) => void
/**
* default value for searchparam 'category' in en
*/
allCategoriesEn: string
} }
const Category: FC<ICategoryProps> = ({ const Category: FC<ICategoryProps> = ({
...@@ -20,17 +24,24 @@ const Category: FC<ICategoryProps> = ({ ...@@ -20,17 +24,24 @@ const Category: FC<ICategoryProps> = ({
list, list,
value, value,
onChange, onChange,
allCategoriesEn,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const isAllCategories = !list.includes(value)
const itemClassName = (isSelected: boolean) =>
cn(
isSelected
? 'bg-white text-primary-600 border-gray-200 font-semibold shadow-[0px_1px_2px_rgba(16,24,40,0.05)]'
: 'border-transparent font-medium',
'flex items-center h-7 px-3 border cursor-pointer rounded-lg',
)
const itemClassName = (isSelected: boolean) => cn(isSelected ? 'bg-white text-primary-600 border-gray-200 font-semibold' : 'border-transparent font-medium', 'flex items-center h-7 px-3 border cursor-pointer rounded-lg')
const itemStyle = (isSelected: boolean) => isSelected ? { boxShadow: '0px 1px 2px rgba(16, 24, 40, 0.05)' } : {}
return ( return (
<div className={cn(className, 'flex space-x-1 text-[13px] flex-wrap')}> <div className={cn(className, 'flex space-x-1 text-[13px] flex-wrap')}>
<div <div
className={itemClassName(value === '')} className={itemClassName(isAllCategories)}
style={itemStyle(value === '')} onClick={() => onChange(allCategoriesEn)}
onClick={() => onChange('')}
> >
{t('explore.apps.allCategories')} {t('explore.apps.allCategories')}
</div> </div>
...@@ -38,7 +49,6 @@ const Category: FC<ICategoryProps> = ({ ...@@ -38,7 +49,6 @@ const Category: FC<ICategoryProps> = ({
<div <div
key={name} key={name}
className={itemClassName(name === value)} className={itemClassName(name === value)}
style={itemStyle(name === value)}
onClick={() => onChange(name)} onClick={() => onChange(name)}
> >
{categoryI18n[name] ? t(`explore.category.${name}`) : name} {categoryI18n[name] ? t(`explore.category.${name}`) : name}
...@@ -47,4 +57,5 @@ const Category: FC<ICategoryProps> = ({ ...@@ -47,4 +57,5 @@ const Category: FC<ICategoryProps> = ({
</div> </div>
) )
} }
export default React.memo(Category) export default React.memo(Category)
...@@ -2,14 +2,11 @@ ...@@ -2,14 +2,11 @@
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import classNames from 'classnames' import classNames from 'classnames'
import Link from 'next/link' import Link from 'next/link'
import { useContext } from 'use-context-selector'
import s from './index.module.css' import s from './index.module.css'
import Modal from '@/app/components/base/modal' import Modal from '@/app/components/base/modal'
import { XClose } from '@/app/components/base/icons/src/vender/line/general' import { XClose } from '@/app/components/base/icons/src/vender/line/general'
import type { LangGeniusVersionResponse } from '@/models/common' import type { LangGeniusVersionResponse } from '@/models/common'
import { IS_CE_EDITION } from '@/config' import { IS_CE_EDITION } from '@/config'
import I18n from '@/context/i18n'
import { LanguagesSupported } from '@/i18n/language'
import LogoSite from '@/app/components/base/logo/logo-site' import LogoSite from '@/app/components/base/logo/logo-site'
type IAccountSettingProps = { type IAccountSettingProps = {
...@@ -25,7 +22,6 @@ export default function AccountAbout({ ...@@ -25,7 +22,6 @@ export default function AccountAbout({
onCancel, onCancel,
}: IAccountSettingProps) { }: IAccountSettingProps) {
const { t } = useTranslation() const { t } = useTranslation()
const { locale } = useContext(I18n)
const isLatest = langeniusVersionInfo.current_version === langeniusVersionInfo.latest_version const isLatest = langeniusVersionInfo.current_version === langeniusVersionInfo.latest_version
return ( return (
...@@ -48,8 +44,8 @@ export default function AccountAbout({ ...@@ -48,8 +44,8 @@ export default function AccountAbout({
IS_CE_EDITION IS_CE_EDITION
? <Link href={'https://github.com/langgenius/dify/blob/main/LICENSE'} target='_blank' rel='noopener noreferrer'>Open Source License</Link> ? <Link href={'https://github.com/langgenius/dify/blob/main/LICENSE'} target='_blank' rel='noopener noreferrer'>Open Source License</Link>
: <> : <>
<Link href={locale !== LanguagesSupported[1] ? 'https://docs.dify.ai/user-agreement/privacy-policy' : 'https://docs.dify.ai/v/zh-hans/user-agreement/privacy-policy'} target='_blank' rel='noopener noreferrer'>Privacy Policy</Link>, <Link href='https://dify.ai/privacy' target='_blank' rel='noopener noreferrer'>Privacy Policy</Link>,
<Link href={locale !== LanguagesSupported[1] ? 'https://docs.dify.ai/user-agreement/terms-of-service' : 'https://docs.dify.ai/v/zh-hans/user-agreement/terms-of-service'} target='_blank' rel='noopener noreferrer'>Terms of Service</Link> <Link href='https://dify.ai/terms' target='_blank' rel='noopener noreferrer'>Terms of Service</Link>
</> </>
} }
</div> </div>
......
...@@ -23,9 +23,9 @@ export const AppInfo: FC<{ siteInfo: SiteInfo }> = ({ siteInfo }) => { ...@@ -23,9 +23,9 @@ export const AppInfo: FC<{ siteInfo: SiteInfo }> = ({ siteInfo }) => {
export const PromptTemplate: FC<{ html: string }> = ({ html }) => { export const PromptTemplate: FC<{ html: string }> = ({ html }) => {
return ( return (
<div <div
className={' box-border text-sm text-gray-700'} className={'box-border text-sm text-gray-700'}
dangerouslySetInnerHTML={{ __html: html }} dangerouslySetInnerHTML={{ __html: html }}
></div> />
) )
} }
......
...@@ -69,9 +69,22 @@ const Tools: FC<Props> = ({ ...@@ -69,9 +69,22 @@ const Tools: FC<Props> = ({
})() })()
const [query, setQuery] = useState('') const [query, setQuery] = useState('')
const [collectionType, setCollectionType] = useTabSearchParams({ const [toolPageCollectionType, setToolPageCollectionType] = useTabSearchParams({
defaultTab: collectionTypeOptions[0].value, defaultTab: collectionTypeOptions[0].value,
}) })
const [appPageCollectionType, setAppPageCollectionType] = useState(collectionTypeOptions[0].value)
const { collectionType, setCollectionType } = (() => {
if (isInToolsPage) {
return {
collectionType: toolPageCollectionType,
setCollectionType: setToolPageCollectionType,
}
}
return {
collectionType: appPageCollectionType,
setCollectionType: setAppPageCollectionType,
}
})()
const showCollectionList = (() => { const showCollectionList = (() => {
let typeFilteredList: Collection[] = [] let typeFilteredList: Collection[] = []
......
...@@ -35,9 +35,10 @@ const Item: FC<Props> = ({ ...@@ -35,9 +35,10 @@ const Item: FC<Props> = ({
const language = getLanguage(locale) const language = getLanguage(locale)
const isBuiltIn = collection.type === CollectionType.builtIn const isBuiltIn = collection.type === CollectionType.builtIn
const canShowDetail = !isBuiltIn || (isBuiltIn && isInToolsPage) const canShowDetail = isInToolsPage
const [showDetail, setShowDetail] = useState(false) const [showDetail, setShowDetail] = useState(false)
const addBtn = <Button className='shrink-0 flex items-center h-7 !px-3 !text-xs !font-medium !text-gray-700' disabled={added || !collection.is_team_authorization} onClick={() => onAdd?.(payload)}>{t(`common.operation.${added ? 'added' : 'add'}`)}</Button> const addBtn = <Button className='shrink-0 flex items-center h-7 !px-3 !text-xs !font-medium !text-gray-700' disabled={added || !collection.is_team_authorization} onClick={() => onAdd?.(payload)}>{t(`common.operation.${added ? 'added' : 'add'}`)}</Button>
return ( return (
<> <>
<div <div
...@@ -63,7 +64,7 @@ const Item: FC<Props> = ({ ...@@ -63,7 +64,7 @@ const Item: FC<Props> = ({
)} )}
</div> </div>
</div> </div>
{showDetail && isBuiltIn && ( {showDetail && (
<SettingBuiltInTool <SettingBuiltInTool
collection={collection} collection={collection}
toolName={payload.name} toolName={payload.name}
...@@ -71,6 +72,7 @@ const Item: FC<Props> = ({ ...@@ -71,6 +72,7 @@ const Item: FC<Props> = ({
onHide={() => { onHide={() => {
setShowDetail(false) setShowDetail(false)
}} }}
isBuiltIn={isBuiltIn}
/> />
)} )}
</> </>
......
...@@ -12,7 +12,6 @@ import { IS_CE_EDITION, apiPrefix } from '@/config' ...@@ -12,7 +12,6 @@ import { IS_CE_EDITION, apiPrefix } from '@/config'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import { login, oauth } from '@/service/common' import { login, oauth } from '@/service/common'
import I18n from '@/context/i18n' import I18n from '@/context/i18n'
import { LanguagesSupported } from '@/i18n/language'
import { getPurifyHref } from '@/utils' import { getPurifyHref } from '@/utils'
const validEmailReg = /^[\w\.-]+@([\w-]+\.)+[\w-]{2,}$/ const validEmailReg = /^[\w\.-]+@([\w-]+\.)+[\w-]{2,}$/
...@@ -282,13 +281,13 @@ const NormalForm = () => { ...@@ -282,13 +281,13 @@ const NormalForm = () => {
<Link <Link
className='text-primary-600' className='text-primary-600'
target='_blank' rel='noopener noreferrer' target='_blank' rel='noopener noreferrer'
href={locale !== LanguagesSupported[1] ? 'https://docs.dify.ai/user-agreement/terms-of-service' : 'https://docs.dify.ai/v/zh-hans/user-agreement/terms-of-service'} href='https://dify.ai/terms'
>{t('login.tos')}</Link> >{t('login.tos')}</Link>
&nbsp;&&nbsp; &nbsp;&&nbsp;
<Link <Link
className='text-primary-600' className='text-primary-600'
target='_blank' rel='noopener noreferrer' target='_blank' rel='noopener noreferrer'
href={locale !== LanguagesSupported[1] ? 'https://docs.dify.ai/user-agreement/privacy-policy' : 'https://docs.dify.ai/v/zh-hans/user-agreement/privacy-policy'} href='https://dify.ai/privacy'
>{t('login.pp')}</Link> >{t('login.pp')}</Link>
</div> </div>
......
const translation = {
title: '注釈',
name: '注釈の返信',
editBy: '{{author}} によって編集された回答',
noData: {
title: '注釈がありません',
description: 'ここではアプリのデバッグ中に注釈を編集したり、一括で注釈をインポートしたりして高品質の応答を行うことができます。',
},
table: {
header: {
question: '質問',
answer: '回答',
createdAt: '作成日時',
hits: 'ヒット数',
actions: 'アクション',
addAnnotation: '注釈を追加',
bulkImport: '一括インポート',
bulkExport: '一括エクスポート',
clearAll: 'すべての注釈をクリア',
},
},
editModal: {
title: '注釈の返信を編集',
queryName: 'ユーザーのクエリ',
answerName: 'ストーリーテラーボット',
yourAnswer: 'あなたの回答',
answerPlaceholder: 'ここに回答を入力してください',
yourQuery: 'あなたのクエリ',
queryPlaceholder: 'ここにクエリを入力してください',
removeThisCache: 'この注釈を削除',
createdAt: '作成日時',
},
addModal: {
title: '注釈の返信を追加',
queryName: '質問',
answerName: '回答',
answerPlaceholder: 'ここに回答を入力してください',
queryPlaceholder: 'ここに質問を入力してください',
createNext: '別の注釈付きの応答を追加',
},
batchModal: {
title: '一括インポート',
csvUploadTitle: 'CSVファイルをここにドラッグ&ドロップするか、',
browse: '参照',
tip: 'CSVファイルは以下の構造に準拠する必要があります:',
question: '質問',
answer: '回答',
contentTitle: 'チャンクの内容',
content: '内容',
template: 'テンプレートをここからダウンロード',
cancel: 'キャンセル',
run: '一括実行',
runError: '一括実行に失敗しました',
processing: '一括処理中',
completed: 'インポートが完了しました',
error: 'インポートエラー',
ok: 'OK',
},
errorMessage: {
answerRequired: '回答は必須です',
queryRequired: '質問は必須です',
},
viewModal: {
annotatedResponse: '注釈の返信',
hitHistory: 'ヒット履歴',
hit: 'ヒット',
hits: 'ヒット数',
noHitHistory: 'ヒット履歴はありません',
},
hitHistoryTable: {
query: 'クエリ',
match: '一致',
response: '応答',
source: 'ソース',
score: 'スコア',
time: '時間',
},
initSetup: {
title: '注釈の返信の初期設定',
configTitle: '注釈の返信の設定',
confirmBtn: '保存して有効にする',
configConfirmBtn: '保存',
},
embeddingModelSwitchTip: '注釈テキストのベクトル化モデルです。モデルを切り替えると再埋め込みが行われ、追加のコストが発生します。',
}
export default translation
const translation = {
apiServer: 'APIサーバー',
apiKey: 'APIキー',
status: 'ステータス',
disabled: '無効',
ok: '稼働中',
copy: 'コピー',
copied: 'コピー済み',
play: '再生',
pause: '一時停止',
playing: '再生中',
merMaind: {
rerender: '再レンダリング',
},
never: 'なし',
apiKeyModal: {
apiSecretKey: 'APIシークレットキー',
apiSecretKeyTips: 'APIの悪用を防ぐために、APIキーを保護してください。フロントエンドのコードで平文として使用しないでください。:)',
createNewSecretKey: '新しいシークレットキーを作成',
secretKey: 'シークレットキー',
created: '作成日時',
lastUsed: '最終使用日時',
generateTips: 'このキーを安全でアクセス可能な場所に保管してください。',
},
actionMsg: {
deleteConfirmTitle: 'このシークレットキーを削除しますか?',
deleteConfirmTips: 'この操作は元に戻すことはできません。',
ok: 'OK',
},
completionMode: {
title: '補完アプリAPI',
info: '記事、要約、翻訳などの高品質なテキスト生成には、ユーザーの入力を使用した補完メッセージAPIを使用します。テキスト生成は、Dify Prompt Engineeringで設定されたモデルパラメータとプロンプトテンプレートに依存しています。',
createCompletionApi: '補完メッセージの作成',
createCompletionApiTip: '質疑応答モードをサポートするために、補完メッセージを作成します。',
inputsTips: '(オプション)Prompt Engの変数に対応するキーと値のペアとしてユーザー入力フィールドを提供します。キーは変数名で、値はパラメータの値です。フィールドのタイプがSelectの場合、送信される値は事前に設定された選択肢のいずれかである必要があります。',
queryTips: 'ユーザーの入力テキスト内容。',
blocking: 'ブロッキングタイプで、実行が完了して結果が返されるまで待機します。(処理が長い場合、リクエストは中断される場合があります)',
streaming: 'ストリーミングの返却。SSE(Server-Sent Events)に基づいたストリーミングの返却の実装。',
messageFeedbackApi: 'メッセージフィードバック(いいね)',
messageFeedbackApiTip: 'エンドユーザーの代わりに受信したメッセージを「いいね」または「いいね」で評価します。このデータはログ&注釈ページで表示され、将来のモデルの微調整に使用されます。',
messageIDTip: 'メッセージID',
ratingTip: 'いいねまたはいいね、nullは元に戻す',
parametersApi: 'アプリケーションパラメータ情報の取得',
parametersApiTip: '変数名、フィールド名、タイプ、デフォルト値を含む設定済みの入力パラメータを取得します。通常、これらのフィールドをフォームに表示したり、クライアントの読み込み後にデフォルト値を入力したりするために使用されます。',
},
chatMode: {
title: 'チャットアプリAPI',
info: '質疑応答形式を使用した多目的の対話型アプリケーションには、チャットメッセージAPIを呼び出して対話を開始します。返されたconversation_idを渡すことで、継続的な会話を維持します。応答パラメータとテンプレートは、Dify Prompt Engの設定に依存します。',
createChatApi: 'チャットメッセージの作成',
createChatApiTip: '新しい会話メッセージを作成するか、既存の対話を継続します。',
inputsTips: '(オプション)Prompt Engの変数に対応するキーと値のペアとしてユーザー入力フィールドを提供します。キーは変数名で、値はパラメータの値です。フィールドのタイプがSelectの場合、送信される値は事前に設定された選択肢のいずれかである必要があります。',
queryTips: 'ユーザーの入力/質問内容',
blocking: 'ブロッキングタイプで、実行が完了して結果が返されるまで待機します。(処理が長い場合、リクエストは中断される場合があります)',
streaming: 'ストリーミングの返却。SSE(Server-Sent Events)に基づいたストリーミングの返却の実装。',
conversationIdTip: '(オプション)会話ID:初回の会話の場合は空白のままにしておき、継続する場合はコンテキストからconversation_idを渡します。',
messageFeedbackApi: 'メッセージ端末ユーザーフィードバック、いいね',
messageFeedbackApiTip: 'エンドユーザーの代わりに受信したメッセージを「いいね」または「いいね」で評価します。このデータはログ&注釈ページで表示され、将来のモデルの微調整に使用されます。',
messageIDTip: 'メッセージID',
ratingTip: 'いいねまたはいいね、nullは元に戻す',
chatMsgHistoryApi: 'チャット履歴メッセージの取得',
chatMsgHistoryApiTip: '最初のページは最新の「limit」バーを返します。逆順です。',
chatMsgHistoryConversationIdTip: '会話ID',
chatMsgHistoryFirstId: '現在のページの最初のチャットレコードのID。デフォルトはなし。',
chatMsgHistoryLimit: '1回のリクエストで返されるチャットの数',
conversationsListApi: '会話リストの取得',
conversationsListApiTip: '現在のユーザーのセッションリストを取得します。デフォルトでは、最後の20のセッションが返されます。',
conversationsListFirstIdTip: '現在のページの最後のレコードのID、デフォルトはなし。',
conversationsListLimitTip: '1回のリクエストで返されるチャットの数',
conversationRenamingApi: '会話の名前変更',
conversationRenamingApiTip: '会話の名前を変更します。名前はマルチセッションクライアントインターフェースに表示されます。',
conversationRenamingNameTip: '新しい名前',
parametersApi: 'アプリケーションパラメータ情報の取得',
parametersApiTip: '変数名、フィールド名、タイプ、デフォルト値を含む設定済みの入力パラメータを取得します。通常、これらのフィールドをフォームに表示したり、クライアントの読み込み後にデフォルト値を入力したりするために使用されます。',
},
develop: {
requestBody: 'リクエストボディ',
pathParams: 'パスパラメータ',
query: 'クエリ',
},
}
export default translation
This diff is collapsed.
const translation = {
title: 'ログ',
description: 'ログは、アプリケーションの実行状態を記録します。ユーザーの入力やAIの応答などが含まれます。',
dateTimeFormat: 'MM/DD/YYYY hh:mm A',
table: {
header: {
time: '時間',
endUser: 'エンドユーザー',
input: '入力',
output: '出力',
summary: 'タイトル',
messageCount: 'メッセージ数',
userRate: 'ユーザー評価',
adminRate: 'オペレータ評価',
},
pagination: {
previous: '前へ',
next: '次へ',
},
empty: {
noChat: 'まだ会話がありません',
noOutput: '出力なし',
element: {
title: '誰かいますか?',
content: 'ここではエンドユーザーとAIアプリケーションの相互作用を観察し、注釈を付けることでAIの精度を継続的に向上させることができます。自分自身でWebアプリを<shareLink>共有</shareLink>したり<testLink>テスト</testLink>したりして、このページに戻ってください。',
},
},
},
detail: {
time: '時間',
conversationId: '会話ID',
promptTemplate: 'プロンプトテンプレート',
promptTemplateBeforeChat: 'チャット前のプロンプトテンプレート · システムメッセージとして',
annotationTip: '{{user}}による改善',
timeConsuming: '',
second: '秒',
tokenCost: 'トークン消費',
loading: '読み込み中',
operation: {
like: 'いいね',
dislike: 'いまいち',
addAnnotation: '改善を追加',
editAnnotation: '改善を編集',
annotationPlaceholder: 'AIが返答することを期待する回答を入力してください。これはモデルの微調整やテキスト生成品質の継続的な改善に使用されます。',
},
variables: '変数',
uploadImages: 'アップロードされた画像',
},
filter: {
period: {
today: '今日',
last7days: '過去7日間',
last4weeks: '過去4週間',
last3months: '過去3ヶ月',
last12months: '過去12ヶ月',
monthToDate: '今月まで',
quarterToDate: '四半期まで',
yearToDate: '今年まで',
allTime: 'すべての期間',
},
annotation: {
all: 'すべて',
annotated: '注釈付きの改善({{count}}件)',
not_annotated: '注釈なし',
},
},
}
export default translation
const translation = {
welcome: {
firstStepTip: '始めるには、',
enterKeyTip: '以下にOpenAI APIキーを入力してください',
getKeyTip: 'OpenAIダッシュボードからAPIキーを取得してください',
placeholder: 'OpenAI APIキー(例:sk-xxxx)',
},
apiKeyInfo: {
cloud: {
trial: {
title: '{{providerName}}のトライアルクオータを使用しています。',
description: 'トライアルクオータはテスト用に提供されています。トライアルクオータの使用回数が尽きる前に、独自のモデルプロバイダを設定するか、追加のクオータを購入してください。',
},
exhausted: {
title: 'トライアルクオータが使い果たされました。APIキーを設定してください。',
description: 'トライアルクオータが使い果たされました。独自のモデルプロバイダを設定するか、追加のクオータを購入してください。',
},
},
selfHost: {
title: {
row1: '始めるには、',
row2: 'まずモデルプロバイダを設定してください。',
},
},
callTimes: '呼び出し回数',
usedToken: '使用済みトークン',
setAPIBtn: 'モデルプロバイダの設定へ',
tryCloud: 'または無料クオートでDifyのクラウドバージョンを試してみてください',
},
overview: {
title: '概要',
appInfo: {
explanation: '使いやすいAI Webアプリ',
accessibleAddress: '公開URL',
preview: 'プレビュー',
regenerate: '再生成',
preUseReminder: '続行する前にWebアプリを有効にしてください。',
settings: {
entry: '設定',
title: 'Webアプリの設定',
webName: 'Webアプリ名',
webDesc: 'Webアプリの説明',
webDescTip: 'このテキストはクライアント側に表示され、アプリの使用方法に関する基本的なガイダンスを提供します。',
webDescPlaceholder: 'Webアプリの説明を入力してください',
language: '言語',
more: {
entry: '詳細設定を表示',
copyright: '著作権',
copyRightPlaceholder: '著作者または組織の名前を入力してください',
privacyPolicy: 'プライバシーポリシー',
privacyPolicyPlaceholder: 'プライバシーポリシーリンクを入力してください',
privacyPolicyTip: '訪問者がアプリが収集するデータを理解するのに役立ちます。Difyの<privacyPolicyLink>プライバシーポリシー</privacyPolicyLink>を参照してください。',
},
},
embedded: {
entry: '埋め込み',
title: 'ウェブサイトに埋め込む',
explanation: 'チャットアプリをウェブサイトに埋め込む方法を選択してください。',
iframe: 'ウェブサイトの任意の場所にチャットアプリを追加するには、このiframeをHTMLコードに追加してください。',
scripts: 'ウェブサイトの右下にチャットアプリを追加するには、このコードをHTMLに追加してください。',
chromePlugin: 'Dify Chatbot Chrome拡張機能をインストール',
copied: 'コピー済み',
copy: 'コピー',
},
qrcode: {
title: '共有用QRコード',
scan: 'アプリを共有するためにスキャン',
download: 'QRコードをダウンロード',
},
customize: {
way: '方法',
entry: 'カスタマイズ',
title: 'AI Webアプリのカスタマイズ',
explanation: 'シナリオとスタイルのニーズに合わせてWebアプリのフロントエンドをカスタマイズできます。',
way1: {
name: 'クライアントコードをフォークして変更し、Vercelにデプロイする(推奨)',
step1: 'クライアントコードをフォークして変更する',
step1Tip: 'ここをクリックしてソースコードをGitHubアカウントにフォークし、コードを変更してください',
step1Operation: 'Dify-WebClient',
step2: 'Vercelにデプロイする',
step2Tip: 'ここをクリックしてリポジトリをVercelにインポートし、デプロイしてください',
step2Operation: 'リポジトリのインポート',
step3: '環境変数を設定する',
step3Tip: 'Vercelに以下の環境変数を追加してください',
},
way2: {
name: 'APIを呼び出すためのクライアントサイドコードを記述し、サーバーにデプロイする',
operation: 'ドキュメント',
},
},
},
apiInfo: {
title: 'バックエンドサービスAPI',
explanation: 'アプリケーションに簡単に統合できます',
accessibleAddress: 'サービスAPIエンドポイント',
doc: 'APIリファレンス',
},
status: {
running: 'サービス中',
disable: '無効化',
},
},
analysis: {
title: '分析',
ms: 'ミリ秒',
tokenPS: 'トークン/秒',
totalMessages: {
title: '総メッセージ数',
explanation: 'AIとのやり取りのうち、プロンプトのエンジニアリングやデバッグを除いた日次の相互作用数です。',
},
activeUsers: {
title: 'アクティブユーザー',
explanation: 'AIとのQ&Aに参加しているユニークなユーザー数です。プロンプトのエンジニアリングやデバッグを除きます。',
},
tokenUsage: {
title: 'トークン使用量',
explanation: 'アプリケーションの言語モデルの日次トークン使用量を反映し、コスト管理の目的に役立ちます。',
consumed: '使用済み',
},
avgSessionInteractions: {
title: '平均セッション相互作用数',
explanation: '会話ベースのアプリケーションの連続したユーザーとAIのコミュニケーション数です。',
},
userSatisfactionRate: {
title: 'ユーザー満足率',
explanation: '1,000メッセージあたりの「いいね」の数です。これは、ユーザーが非常に満足している回答の割合を示します。',
},
avgResponseTime: {
title: '平均応答時間',
explanation: 'AIの処理/応答にかかる時間(ミリ秒)です。テキストベースのアプリケーションに適しています。',
},
tps: {
title: 'トークン出力速度',
explanation: 'LLMのパフォーマンスを測定します。リクエストの開始から出力の完了までのLLMのトークン出力速度をカウントします。',
},
},
}
export default translation
const translation = {
createApp: '新しいアプリを作成する',
types: {
all: 'すべて',
assistant: 'アシスタント',
completion: '補完',
},
modes: {
completion: 'テキスト生成',
chat: '基本アシスタント',
},
createFromConfigFile: '設定ファイルからアプリを作成する',
deleteAppConfirmTitle: 'このアプリを削除しますか?',
deleteAppConfirmContent:
'アプリの削除は元に戻せません。ユーザーはアプリにアクセスできなくなり、プロンプトの設定とログは永久に削除されます。',
appDeleted: 'アプリが削除されました',
appDeleteFailed: 'アプリの削除に失敗しました',
join: 'コミュニティに参加する',
communityIntro:
'チームメンバーや貢献者、開発者とさまざまなチャンネルでディスカッションを行います。',
roadmap: 'ロードマップを見る',
appNamePlaceholder: 'アプリの名前を入力してください',
newApp: {
startToCreate: '新しいアプリを作成しましょう',
captionName: 'アプリアイコンと名前',
captionAppType: 'どのタイプのアプリを作成しますか?',
previewDemo: 'デモをプレビューする',
chatApp: 'アシスタント',
chatAppIntro:
'チャットベースのアプリケーションを構築したいです。このアプリは質問と回答の形式を使用し、複数のラウンドの連続した会話が可能です。',
agentAssistant: '新しいエージェントアシスタント',
completeApp: 'テキスト生成',
completeAppIntro:
'プロンプトに基づいて高品質のテキストを生成するアプリケーションを作成したいです。記事、要約、翻訳などの生成が可能です。',
showTemplates: 'テンプレートから選択したいです',
hideTemplates: 'モード選択に戻る',
Create: '作成',
Cancel: 'キャンセル',
nameNotEmpty: '名前は空にできません',
appTemplateNotSelected: 'テンプレートを選択してください',
appTypeRequired: 'アプリのタイプを選択してください',
appCreated: 'アプリが作成されました',
appCreateFailed: 'アプリの作成に失敗しました',
},
editApp: {
startToEdit: 'アプリを編集する',
},
emoji: {
ok: 'OK',
cancel: 'キャンセル',
},
}
export default translation
const translation = {
currentPlan: '現在のプラン',
upgradeBtn: {
plain: 'プランをアップグレード',
encourage: '今すぐアップグレード',
encourageShort: 'アップグレード',
},
viewBilling: '請求とサブスクリプションの管理',
buyPermissionDeniedTip: 'サブスクリプションするには、エンタープライズ管理者に連絡してください',
plansCommon: {
title: 'あなたに合ったプランを選択してください',
yearlyTip: '年間購読で2か月無料!',
mostPopular: '最も人気のある',
planRange: {
monthly: '月額',
yearly: '年額',
},
month: '月',
year: '年',
save: '節約 ',
free: '無料',
currentPlan: '現在のプラン',
contractSales: '営業に連絡する',
contractOwner: 'チームマネージャーに連絡する',
startForFree: '無料で始める',
getStartedWith: '始める ',
contactSales: '営業に連絡する',
talkToSales: '営業と話す',
modelProviders: 'モデルプロバイダー',
teamMembers: 'チームメンバー',
buildApps: 'アプリを作成する',
vectorSpace: 'ベクトルスペース',
vectorSpaceBillingTooltip: '1MBあたり約120万文字のベクトル化データを保存できます(OpenAI Embeddingsを使用して推定され、モデルによって異なります)。',
vectorSpaceTooltip: 'ベクトルスペースは、LLMがデータを理解するために必要な長期記憶システムです。',
documentProcessingPriority: 'ドキュメント処理の優先度',
documentProcessingPriorityTip: 'より高いドキュメント処理の優先度をご希望の場合は、プランをアップグレードしてください。',
documentProcessingPriorityUpgrade: 'より高い精度と高速な速度でデータを処理します。',
priority: {
'standard': '標準',
'priority': '優先',
'top-priority': '最優先',
},
logsHistory: 'ログ履歴',
customTools: 'カスタムツール',
unavailable: '利用不可',
days: '日',
unlimited: '無制限',
support: 'サポート',
supportItems: {
communityForums: 'コミュニティフォーラム',
emailSupport: 'メールサポート',
priorityEmail: '優先メール&チャットサポート',
logoChange: 'ロゴ変更',
SSOAuthentication: 'SSO認証',
personalizedSupport: '個別サポート',
dedicatedAPISupport: '専用APIサポート',
customIntegration: 'カスタム統合とサポート',
ragAPIRequest: 'RAG APIリクエスト',
agentMode: 'エージェントモード',
workflow: 'ワークフロー',
},
comingSoon: '近日公開',
member: 'メンバー',
memberAfter: 'メンバー',
messageRequest: {
title: 'メッセージクレジット',
tooltip: 'OpenAIモデルを使用したさまざまなプランのメッセージ呼び出しクォータ(gpt4を除く)。制限を超えるメッセージはOpenAI APIキーを使用します。',
},
annotatedResponse: {
title: '注釈クォータ制限',
tooltip: '手動での編集と応答の注釈付けにより、アプリのカスタマイズ可能な高品質な質問応答機能が提供されます(チャットアプリのみ適用)。',
},
ragAPIRequestTooltip: 'Difyのナレッジベース処理機能のみを呼び出すAPI呼び出しの数を指します。',
receiptInfo: 'チームオーナーとチーム管理者のみが購読および請求情報を表示できます',
},
plans: {
sandbox: {
name: 'サンドボックス',
description: 'GPTの無料トライアル200回',
includesTitle: '含まれるもの:',
},
professional: {
name: 'プロフェッショナル',
description: '個人や小規模チーム向けにより多くのパワーを手頃な価格で提供します。',
includesTitle: '無料プランに加えて、次も含まれます:',
},
team: {
name: 'チーム',
description: '制限なく協力し、最高のパフォーマンスを楽しむ。',
includesTitle: 'プロフェッショナルプランに加えて、次も含まれます:',
},
enterprise: {
name: 'エンタープライズ',
description: '大規模なミッションクリティカルシステムのためのフル機能とサポートを提供します。',
includesTitle: 'チームプランに加えて、次も含まれます:',
},
},
vectorSpace: {
fullTip: 'ベクトルスペースがいっぱいです。',
fullSolution: 'より多くのスペースを得るためにプランをアップグレードしてください。',
},
apps: {
fullTipLine1: 'より多くのアプリを作成するには、',
fullTipLine2: 'プランをアップグレードしてください。',
},
annotatedResponse: {
fullTipLine1: 'より多くの会話を注釈するには、',
fullTipLine2: 'プランをアップグレードしてください。',
quotaTitle: '注釈返信クォータ',
},
}
export default translation
This diff is collapsed.
const translation = {
custom: 'カスタマイズ',
upgradeTip: {
prefix: 'プランをアップグレードして',
suffix: 'ブランドをカスタマイズしましょう。',
},
webapp: {
title: 'WebAppブランドのカスタマイズ',
removeBrand: 'Powered by Difyを削除',
changeLogo: 'Powered byブランド画像を変更',
changeLogoTip: '最小サイズ40x40pxのSVGまたはPNG形式',
},
app: {
title: 'アプリヘッダーブランドのカスタマイズ',
changeLogoTip: '最小サイズ80x80pxのSVGまたはPNG形式',
},
upload: 'アップロード',
uploading: 'アップロード中',
uploadedFail: '画像のアップロードに失敗しました。再度アップロードしてください。',
change: '変更',
apply: '適用',
restore: 'デフォルトに戻す',
customize: {
contactUs: 'お問い合わせ',
prefix: 'アプリ内のブランドロゴをカスタマイズするには、',
suffix: 'エンタープライズ版にアップグレードしてください。',
},
}
export default translation
const translation = {
steps: {
header: {
creation: 'ナレッジの作成',
update: 'データの追加',
},
one: 'データソースの選択',
two: 'テキストの前処理とクリーニング',
three: '実行して完了',
},
error: {
unavailable: 'このナレッジは利用できません',
},
stepOne: {
filePreview: 'ファイルプレビュー',
pagePreview: 'ページプレビュー',
dataSourceType: {
file: 'テキストファイルからインポート',
notion: 'Notionから同期',
web: 'ウェブサイトから同期',
},
uploader: {
title: 'テキストファイルをアップロード',
button: 'ファイルをドラッグ&ドロップするか',
browse: '参照',
tip: '{{supportTypes}}をサポートしています。1つあたりの最大サイズは{{size}}MBです。',
validation: {
typeError: 'サポートされていないファイルタイプです',
size: 'ファイルサイズが大きすぎます。最大サイズは{{size}}MBです',
count: '複数のファイルはサポートされていません',
filesNumber: 'バッチアップロードの制限({{filesNumber}}個)に達しました。',
},
cancel: 'キャンセル',
change: '変更',
failed: 'アップロードに失敗しました',
},
notionSyncTitle: 'Notionが接続されていません',
notionSyncTip: 'Notionと同期するには、まずNotionへの接続が必要です。',
connect: '接続する',
button: '次へ',
emptyDatasetCreation: '空のナレッジを作成します',
modal: {
title: '空のナレッジを作成',
tip: '空のナレッジにはドキュメントが含まれず、いつでもドキュメントをアップロードできます。',
input: 'ナレッジ名',
placeholder: '入力してください',
nameNotEmpty: '名前は空にできません',
nameLengthInvaild: '名前は1〜40文字である必要があります',
cancelButton: 'キャンセル',
confirmButton: '作成',
failed: '作成に失敗しました',
},
},
stepTwo: {
segmentation: 'チャンク設定',
auto: '自動',
autoDescription: 'チャンクと前処理ルールを自動的に設定します。初めてのユーザーはこれを選択することをおすすめします。',
custom: 'カスタム',
customDescription: 'チャンクのルール、チャンクの長さ、前処理ルールなどをカスタマイズします。',
separator: 'セグメント識別子',
separatorPlaceholder: '例えば改行(\\\\n)や特殊なセパレータ(例:「***」)',
maxLength: '最大チャンク長',
overlap: 'チャンクのオーバーラップ',
overlapTip: 'チャンクのオーバーラップを設定することで、それらの間の意味的な関連性を維持し、検索効果を向上させることができます。最大チャンクサイズの10%〜25%を設定することをおすすめします。',
overlapCheck: 'チャンクのオーバーラップは最大チャンク長を超えてはいけません',
rules: 'テキストの前処理ルール',
removeExtraSpaces: '連続するスペース、改行、タブを置換する',
removeUrlEmails: 'すべてのURLとメールアドレスを削除する',
removeStopwords: '「a」「an」「the」などのストップワードを削除する',
preview: '確認&プレビュー',
reset: 'リセット',
indexMode: 'インデックスモード',
qualified: '高品質',
recommend: 'おすすめ',
qualifiedTip: 'ユーザーのクエリに対してより高い精度を提供するために、デフォルトのシステム埋め込みインターフェースを呼び出して処理します。',
warning: 'モデルプロバイダのAPIキーを設定してください。',
click: '設定に移動',
economical: '経済的',
economicalTip: 'オフラインのベクトルエンジン、キーワードインデックスなどを使用して、トークンを消費せずに精度を低下させます。',
QATitle: '質問と回答形式でセグメント化',
QATip: 'このオプションを有効にすると、追加のトークンが消費されます',
QALanguage: '使用言語',
emstimateCost: '見積もり',
emstimateSegment: '推定チャンク数',
segmentCount: 'チャンク',
calculating: '計算中...',
fileSource: 'ドキュメントの前処理',
notionSource: 'ページの前処理',
other: 'その他',
fileUnit: 'ファイル',
notionUnit: 'ページ',
lastStep: '最後のステップ',
nextStep: '保存して処理',
save: '保存して処理',
cancel: 'キャンセル',
sideTipTitle: 'なぜチャンクと前処理が必要なのか',
sideTipP1: 'テキストデータを処理する際、チャンクとクリーニングは2つの重要な前処理ステップです。',
sideTipP2: 'セグメンテーションは長いテキストを段落に分割し、モデルがより理解しやすくします。これにより、モデルの結果の品質と関連性が向上します。',
sideTipP3: 'クリーニングは不要な文字や書式を削除し、ナレッジをよりクリーンで解析しやすいものにします。',
sideTipP4: '適切なチャンクとクリーニングはモデルのパフォーマンスを向上させ、より正確で価値のある結果を提供します。',
previewTitle: 'プレビュー',
previewTitleButton: 'プレビュー',
previewButton: 'Q&A形式に切り替える',
previewSwitchTipStart: '現在のチャンクプレビューはテキスト形式です。質問と回答形式のプレビューに切り替えると、',
previewSwitchTipEnd: ' 追加のトークンが消費されます',
characters: '文字',
indexSettedTip: 'インデックス方法を変更するには、',
retrivalSettedTip: 'インデックス方法を変更するには、',
datasetSettingLink: 'ナレッジ設定',
},
stepThree: {
creationTitle: '🎉 ナレッジが作成されました',
creationContent: 'ナレッジの名前は自動的に設定されましたが、いつでも変更できます',
label: 'ナレッジ名',
additionTitle: '🎉 ドキュメントがアップロードされました',
additionP1: 'ドキュメントはナレッジにアップロードされました',
additionP2: '、ナレッジのドキュメントリストで見つけることができます。',
stop: '処理を停止',
resume: '処理を再開',
navTo: 'ドキュメントに移動',
sideTipTitle: '次は何ですか',
sideTipContent: 'ドキュメントのインデックスが完了したら、ナレッジをアプリケーションのコンテキストとして統合することができます。プロンプトオーケストレーションページでコンテキスト設定を見つけることができます。また、独立したChatGPTインデックスプラグインとしてリリースすることもできます。',
modelTitle: '埋め込みを停止してもよろしいですか?',
modelContent: '後で処理を再開する必要がある場合は、中断した場所から続行します。',
modelButtonConfirm: '確認',
modelButtonCancel: 'キャンセル',
},
}
export default translation
This diff is collapsed.
const translation = {
title: '検索テスト',
desc: '与えられたクエリテキストに基づいたナレッジのヒット効果をテストします。',
dateTimeFormat: 'MM/DD/YYYY hh:mm A',
recents: '最近の結果',
table: {
header: {
source: 'ソース',
text: 'テキスト',
time: '時間',
},
},
input: {
title: 'ソーステキスト',
placeholder: 'テキストを入力してください。短い記述文がおすすめです。',
countWarning: '最大200文字まで入力できます。',
indexWarning: '高品質のナレッジのみ。',
testing: 'テスト中',
},
hit: {
title: '検索結果パラグラフ',
emptyTip: '検索テストの結果がここに表示されます。',
},
noRecentTip: '最近のクエリ結果はありません。',
viewChart: 'ベクトルチャートを表示',
}
export default translation
const translation = {
title: 'ナレッジの設定',
desc: 'ここではナレッジのプロパティと動作方法を変更できます。',
form: {
name: 'ナレッジ名',
namePlaceholder: 'ナレッジ名を入力してください',
nameError: '名前は空にできません',
desc: 'ナレッジの説明',
descInfo: 'ナレッジの内容を概説するための明確なテキストの説明を書いてください。この説明は、複数のナレッジから推論を選択する際の基準として使用されます。',
descPlaceholder: 'このナレッジに含まれる内容を説明してください。詳細な説明は、AIがナレッジの内容にタイムリーにアクセスできるようにします。空の場合、Difyはデフォルトのヒット戦略を使用します。',
descWrite: '良いナレッジの説明の書き方を学ぶ。',
permissions: '権限',
permissionsOnlyMe: '自分のみ',
permissionsAllMember: 'すべてのチームメンバー',
indexMethod: 'インデックス方法',
indexMethodHighQuality: '高品質',
indexMethodHighQualityTip: 'ユーザーのクエリ時により高い精度を提供するために、OpenAIの埋め込みインターフェースを呼び出して処理します。',
indexMethodEconomy: '経済的',
indexMethodEconomyTip: 'オフラインのベクトルエンジン、キーワードインデックスなどを使用して精度を低下させることなく、トークンを消費せずに処理します。',
embeddingModel: '埋め込みモデル',
embeddingModelTip: '埋め込みモデルを変更するには、',
embeddingModelTipLink: '設定',
retrievalSetting: {
title: '検索設定',
learnMore: '詳細を学ぶ',
description: ' 検索方法についての詳細',
longDescription: ' 検索方法についての詳細については、いつでもナレッジの設定で変更できます。',
},
save: '保存',
},
}
export default translation
const translation = {
knowledge: '知識',
documentCount: ' ドキュメント',
wordCount: 'k 単語',
appCount: ' リンクされたアプリ',
createDataset: '知識を作成',
createDatasetIntro: '独自のテキストデータをインポートするか、LLMコンテキストの強化のためにWebhookを介してリアルタイムでデータを書き込むことができます。',
deleteDatasetConfirmTitle: 'この知識を削除しますか?',
deleteDatasetConfirmContent:
'知識を削除すると元に戻すことはできません。ユーザーはもはやあなたの知識にアクセスできず、すべてのプロンプトの設定とログが永久に削除されます。',
datasetDeleted: '知識が削除されました',
datasetDeleteFailed: '知識の削除に失敗しました',
didYouKnow: 'ご存知ですか?',
intro1: '知識はDifyアプリケーションに統合することができます',
intro2: 'コンテキストとして',
intro3: '、',
intro4: 'または',
intro5: '作成することができます',
intro6: '単体のChatGPTインデックスプラグインとして公開するために',
unavailable: '利用不可',
unavailableTip: '埋め込みモデルが利用できません。デフォルトの埋め込みモデルを設定する必要があります',
datasets: '知識',
datasetsApi: 'API',
retrieval: {
semantic_search: {
title: 'ベクトル検索',
description: 'クエリの埋め込みを生成し、そのベクトル表現に最も類似したテキストチャンクを検索します。',
},
full_text_search: {
title: '全文検索',
description: 'ドキュメント内のすべての用語をインデックス化し、ユーザーが任意の用語を検索してそれに関連するテキストチャンクを取得できるようにします。',
},
hybrid_search: {
title: 'ハイブリッド検索',
description: '全文検索とベクトル検索を同時に実行し、ユーザーのクエリに最適なマッチを選択するために再ランク付けを行います。再ランクモデルAPIの設定が必要です。',
recommend: 'おすすめ',
},
invertedIndex: {
title: '逆インデックス',
description: '効率的な検索に使用される構造です。各用語が含まれるドキュメントまたはWebページを指すように、用語ごとに整理されています。',
},
change: '変更',
changeRetrievalMethod: '検索方法の変更',
},
}
export default translation
const translation = {
title: '探索する',
sidebar: {
discovery: '探索',
chat: 'チャット',
workspace: 'ワークスペース',
action: {
pin: 'ピン留め',
unpin: 'ピン留め解除',
rename: '名前変更',
delete: '削除',
},
delete: {
title: 'アプリを削除',
content: 'このアプリを削除してもよろしいですか?',
},
},
apps: {
title: 'Difyによるアプリの探索',
description: 'これらのテンプレートアプリを即座に使用するか、テンプレートに基づいて独自のアプリをカスタマイズしてください。',
allCategories: 'すべてのカテゴリ',
},
appCard: {
addToWorkspace: 'ワークスペースに追加',
customize: 'カスタマイズ',
},
appCustomize: {
title: '{{name}}からアプリを作成',
subTitle: 'アプリアイコンと名前',
nameRequired: 'アプリ名は必須です',
},
category: {
Assistant: 'アシスタント',
Writing: '執筆',
Translate: '翻訳',
Programming: 'プログラミング',
HR: '人事',
},
}
export default translation
const translation = {
}
export default translation
const translation = {
pageTitle: 'はじめましょう!👋',
welcome: 'Difyへようこそ。続行するにはログインしてください。',
email: 'メールアドレス',
emailPlaceholder: 'メールアドレスを入力してください',
password: 'パスワード',
passwordPlaceholder: 'パスワードを入力してください',
name: 'ユーザー名',
namePlaceholder: 'ユーザー名を入力してください',
forget: 'パスワードをお忘れですか?',
signBtn: 'サインイン',
installBtn: 'セットアップ',
setAdminAccount: '管理者アカウントの設定',
setAdminAccountDesc: 'アプリケーションの作成やLLMプロバイダの管理など、管理者アカウントの最大権限を設定します。',
createAndSignIn: '作成してサインイン',
oneMoreStep: 'あと一歩',
createSample: 'この情報を基に、サンプルアプリケーションを作成します',
invitationCode: '招待コード',
invitationCodePlaceholder: '招待コードを入力してください',
interfaceLanguage: 'インターフェース言語',
timezone: 'タイムゾーン',
go: 'Difyへ移動',
sendUsMail: '自己紹介をメールで送信し、招待リクエストを処理します。',
acceptPP: 'プライバシーポリシーを読み、同意します',
reset: 'パスワードをリセットするには、次のコマンドを実行してください',
withGitHub: 'GitHubで続行',
withGoogle: 'Googleで続行',
rightTitle: 'LLMのフルポテンシャルを解き放つ',
rightDesc: '魅力的で操作可能で改善可能なAIアプリケーションを簡単に構築します。',
tos: '利用規約',
pp: 'プライバシーポリシー',
tosDesc: 'サインアップすることで、以下に同意するものとします',
donthave: 'お持ちでない場合',
invalidInvitationCode: '無効な招待コード',
accountAlreadyInited: 'アカウントは既に初期化されています',
error: {
emailEmpty: 'メールアドレスは必須です',
emailInValid: '有効なメールアドレスを入力してください',
nameEmpty: '名前は必須です',
passwordEmpty: 'パスワードは必須です',
passwordInvalid: 'パスワードは文字と数字を含み、長さは8以上である必要があります',
},
license: {
tip: 'Dify Community Editionを開始する前に、GitHubの',
link: 'オープンソースライセンス',
},
join: '参加する',
joinTipStart: 'あなたを招待します',
joinTipEnd: 'チームに参加する',
invalid: 'リンクの有効期限が切れています',
explore: 'Difyを探索する',
activatedTipStart: 'あなたは',
activatedTipEnd: 'チームに参加しました',
activated: '今すぐサインイン',
adminInitPassword: '管理者初期化パスワード',
validate: '検証',
}
export default translation
const translation = {
}
export default translation
const translation = {
common: {
welcome: '利用していただきありがとうございます',
appUnavailable: 'アプリが利用できません',
appUnkonwError: 'アプリが利用できません',
},
chat: {
newChat: '新しいチャット',
pinnedTitle: 'ピン留めされた',
unpinnedTitle: 'チャット',
newChatDefaultName: '新しい会話',
resetChat: '会話をリセット',
powerBy: 'Powered by',
prompt: 'プロンプト',
privatePromptConfigTitle: '会話の設定',
publicPromptConfigTitle: '初期プロンプト',
configStatusDes: '開始前に、会話の設定を変更できます',
configDisabled:
'前回のセッションの設定がこのセッションで使用されました。',
startChat: 'チャットを開始',
privacyPolicyLeft:
'アプリ開発者が提供する',
privacyPolicyMiddle:
'プライバシーポリシー',
privacyPolicyRight:
'をお読みください。',
deleteConversation: {
title: '会話を削除する',
content: 'この会話を削除してもよろしいですか?',
},
tryToSolve: '解決しようとしています',
temporarySystemIssue: '申し訳ありません、一時的なシステムの問題が発生しました。',
},
generation: {
tabs: {
create: '一度だけ実行',
batch: '一括実行',
saved: '保存済み',
},
savedNoData: {
title: 'まだ結果が保存されていません!',
description: 'コンテンツの生成を開始し、保存された結果をこちらで見つけてください。',
startCreateContent: 'コンテンツの作成を開始',
},
title: 'AI Completion',
queryTitle: 'コンテンツのクエリ',
completionResult: 'Completion 結果',
queryPlaceholder: 'クエリコンテンツを書いてください...',
run: '実行',
copy: 'コピー',
resultTitle: 'AI Completion',
noData: 'AIはここで必要なものを提供します。',
csvUploadTitle: 'CSVファイルをここにドラッグアンドドロップするか、',
browse: '参照',
csvStructureTitle: 'CSVファイルは以下の構造に準拠する必要があります:',
downloadTemplate: 'こちらからテンプレートをダウンロード',
field: 'フィールド',
batchFailed: {
info: '{{num}} 回の実行が失敗しました',
retry: '再試行',
outputPlaceholder: '出力コンテンツなし',
},
errorMsg: {
empty: 'アップロードされたファイルにコンテンツを入力してください。',
fileStructNotMatch: 'アップロードされたCSVファイルが構造と一致しません。',
emptyLine: '行 {{rowIndex}} が空です',
invalidLine: '行 {{rowIndex}}: {{varName}} の値は空にできません',
moreThanMaxLengthLine: '行 {{rowIndex}}: {{varName}} の値は {{maxLength}} 文字を超えることはできません',
atLeastOne: 'アップロードされたファイルには少なくとも1行の入力が必要です。',
},
},
}
export default translation
const translation = {
title: 'ツール',
createCustomTool: 'カスタムツールを作成する',
type: {
all: 'すべて',
builtIn: '組み込み',
custom: 'カスタム',
},
contribute: {
line1: '私は',
line2: 'Difyへのツールの貢献に興味があります。',
viewGuide: 'ガイドを見る',
},
author: '著者',
auth: {
unauthorized: '認証する',
authorized: '認証済み',
setup: '使用するための認証を設定する',
setupModalTitle: '認証の設定',
setupModalTitleDescription: '資格情報を構成した後、ワークスペース内のすべてのメンバーがアプリケーションのオーケストレーション時にこのツールを使用できます。',
},
includeToolNum: '{{num}}個のツールが含まれています',
addTool: 'ツールを追加する',
createTool: {
title: 'カスタムツールを作成する',
editAction: '設定',
editTitle: 'カスタムツールを編集する',
name: '名前',
toolNamePlaceHolder: 'ツール名を入力してください',
schema: 'スキーマ',
schemaPlaceHolder: 'ここにOpenAPIスキーマを入力してください',
viewSchemaSpec: 'OpenAPI-Swagger仕様を表示する',
importFromUrl: 'URLからインポートする',
importFromUrlPlaceHolder: 'https://...',
urlError: '有効なURLを入力してください',
examples: '例',
exampleOptions: {
json: '天気(JSON)',
yaml: 'ペットストア(YAML)',
blankTemplate: '空白テンプレート',
},
availableTools: {
title: '利用可能なツール',
name: '名前',
description: '説明',
method: 'メソッド',
path: 'パス',
action: 'アクション',
test: 'テスト',
},
authMethod: {
title: '認証方法',
type: '認証タイプ',
keyTooltip: 'HTTPヘッダーキー。アイデアがない場合は "Authorization" として残しておいてもかまいません。またはカスタム値に設定できます。',
types: {
none: 'なし',
api_key: 'APIキー',
apiKeyPlaceholder: 'APIキーのHTTPヘッダー名',
apiValuePlaceholder: 'APIキーを入力してください',
},
key: 'キー',
value: '値',
},
authHeaderPrefix: {
title: '認証タイプ',
types: {
basic: 'ベーシック',
bearer: 'ベアラー',
custom: 'カスタム',
},
},
privacyPolicy: 'プライバシーポリシー',
privacyPolicyPlaceholder: 'プライバシーポリシーを入力してください',
},
test: {
title: 'テスト',
parametersValue: 'パラメーター&値',
parameters: 'パラメーター',
value: '値',
testResult: 'テスト結果',
testResultPlaceholder: 'ここにテスト結果が表示されます',
},
thought: {
using: '使用中',
used: '使用済み',
requestTitle: 'リクエスト先',
responseTitle: 'レスポンス先',
},
setBuiltInTools: {
info: '情報',
setting: '設定',
toolDescription: 'ツールの説明',
parameters: 'パラメーター',
string: '文字列',
number: '数',
required: '必須',
infoAndSetting: '情報と設定',
},
noCustomTool: {
title: 'カスタムツールがありません!',
content: 'AIアプリを構築するためのカスタムツールをここで追加および管理します。',
createTool: 'ツールを作成する',
},
noSearchRes: {
title: '申し訳ありません、結果がありません!',
content: '検索に一致するツールが見つかりませんでした。',
reset: '検索をリセット',
},
builtInPromptTitle: 'プロンプト',
toolRemoved: 'ツールが削除されました',
notAuthorized: 'ツールが認可されていません',
howToGet: '取得方法',
}
export default translation
...@@ -59,7 +59,7 @@ export const languages = [ ...@@ -59,7 +59,7 @@ export const languages = [
value: 'ja-JP', value: 'ja-JP',
name: '日本語(日本)', name: '日本語(日本)',
example: 'こんにちは、Dify!', example: 'こんにちは、Dify!',
supported: false, supported: true,
}, },
{ {
value: 'ko-KR', value: 'ko-KR',
......
// TODO: maybe use faker.js to randomize the data
export const mockApps = {
recommended_apps: [
{
app: {
id: 'b82da4c0-2887-48cc-a7d6-7edc0bdd6002',
name: 'AI 前端面试官',
mode: 'chat',
icon: '🤖',
icon_background: null,
},
app_id: 'b82da4c0-2887-48cc-a7d6-7edc0bdd6002',
description:
'一个模拟的前端面试官,通过提问的方式对前端开发的技能水平进行检验。',
copyright: null,
privacy_policy: null,
category: 'HR',
position: 20,
is_listed: true,
install_count: 0,
installed: false,
editable: true,
is_agent: false,
},
{
app: {
id: '1fa25f89-2883-41ac-877e-c372274020a4',
name: '扁平风插画生成',
mode: 'chat',
icon: '🖼️',
icon_background: '#D5F5F6',
},
app_id: '1fa25f89-2883-41ac-877e-c372274020a4',
description: '输入相关元素,为你生成扁平插画风格的封面图片',
copyright: null,
privacy_policy: null,
category: '绘画',
position: 10,
is_listed: true,
install_count: 0,
installed: false,
editable: true,
is_agent: true,
},
{
app: {
id: '94b509ad-4225-4924-8b50-5c25c2bd7e3c',
name: '文章翻译助理 ',
mode: 'completion',
icon: '🤖',
icon_background: null,
},
app_id: '94b509ad-4225-4924-8b50-5c25c2bd7e3c',
description:
'一个多语言翻译器,提供多种语言翻译能力,输入你需要翻译的文本,选择目标语言即可。提示词来自宝玉。',
copyright: null,
privacy_policy: null,
category: 'Assistant',
position: 10,
is_listed: true,
install_count: 0,
installed: false,
editable: true,
is_agent: false,
},
{
app: {
id: 'c8003ab3-9bb7-4693-9249-e603d48e58a6',
name: 'SQL 生成器',
mode: 'completion',
icon: '🤖',
icon_background: null,
},
app_id: 'c8003ab3-9bb7-4693-9249-e603d48e58a6',
description:
'我将帮助你把自然语言转化成指定的数据库查询 SQL 语句,请在下方输入你需要查询的条件,并选择目标数据库类型。',
copyright: null,
privacy_policy: null,
category: 'Programming',
position: 12,
is_listed: true,
install_count: 3142,
installed: false,
editable: true,
is_agent: false,
},
{
app: {
id: 'dad6a1e0-0fe9-47e1-91a9-e16de48f1276',
name: '代码解释器',
mode: 'chat',
icon: 'eye-in-speech-bubble',
icon_background: '#FFEAD5',
},
app_id: 'dad6a1e0-0fe9-47e1-91a9-e16de48f1276',
description: '阐明代码的语法和语义。',
copyright: 'Copyright 2023 Dify',
privacy_policy: 'https://dify.ai',
category: 'Programming',
position: 2,
is_listed: true,
install_count: 2344,
installed: false,
editable: true,
is_agent: false,
},
{
app: {
id: 'fae3e7ac-8ccc-4d43-8986-7c61d2bdde4f',
name: '赛博朋克插画生成',
mode: 'chat',
icon: '🖼️',
icon_background: '#FFEAD5',
},
app_id: 'fae3e7ac-8ccc-4d43-8986-7c61d2bdde4f',
description: '输入相关元素,为你生成赛博朋克风格的插画',
copyright: null,
privacy_policy: null,
category: '绘画',
position: 10,
is_listed: true,
install_count: 0,
installed: false,
editable: true,
is_agent: true,
},
{
app: {
id: '4e57bc83-ab95-4f8a-a955-70796b4804a0',
name: 'SEO 文章生成专家',
mode: 'completion',
icon: '🤖',
icon_background: '#FFEAD5',
},
app_id: '4e57bc83-ab95-4f8a-a955-70796b4804a0',
description:
'我是一名SEO专家,可以根据您提供的标题、关键词、相关信息来批量生成SEO文章。',
copyright: null,
privacy_policy: null,
category: 'Assistant',
position: 10,
is_listed: true,
install_count: 0,
installed: false,
editable: true,
is_agent: false,
},
{
app: {
id: '6786ce62-fa85-4ea7-a4d1-5dbe3e3ff59f',
name: '会议纪要',
mode: 'chat',
icon: 'clipboard',
icon_background: '#D1E0FF',
},
app_id: '6786ce62-fa85-4ea7-a4d1-5dbe3e3ff59f',
description: '帮你重新组织和输出混乱复杂的会议纪要。',
copyright: 'Copyright 2023 Dify',
privacy_policy: 'https://dify.ai',
category: 'Writing',
position: 6,
is_listed: true,
install_count: 1542,
installed: false,
editable: true,
is_agent: false,
},
{
app: {
id: '73dd96bb-49b7-4791-acbd-9ef2ef506900',
name: '美股投资分析助手',
mode: 'chat',
icon: '🤑',
icon_background: '#E4FBCC',
},
app_id: '73dd96bb-49b7-4791-acbd-9ef2ef506900',
description:
'欢迎使用您的个性化美股投资分析助手,在这里我们深入的进行股票分析,为您提供全面的洞察。',
copyright: 'Dify.AI',
privacy_policy: null,
category: '智能助理',
position: 0,
is_listed: true,
install_count: 2,
installed: false,
editable: true,
is_agent: true,
},
{
app: {
id: '93ca3c2c-3a47-4658-b230-d5a6cc61ff01',
name: 'SVG Logo 设计',
mode: 'chat',
icon: '🎨',
icon_background: '#E4FBCC',
},
app_id: '93ca3c2c-3a47-4658-b230-d5a6cc61ff01',
description:
'您好,我是您的创意伙伴,将帮助您将想法生动地实现!我可以协助您利用DALL·E 3的能力创造出令人惊叹的设计。',
copyright: 'Dify.AI',
privacy_policy: null,
category: '智能助理',
position: 4,
is_listed: true,
install_count: 6,
installed: false,
editable: true,
is_agent: true,
},
{
app: {
id: '59924f26-963f-4b4b-90cf-978bbfcddc49',
name: '中英文互译',
mode: 'chat',
icon: 'speaking_head_in_silhouette',
icon_background: '#FBE8FF',
},
app_id: '59924f26-963f-4b4b-90cf-978bbfcddc49',
description: '翻译专家:提供中英文互译',
copyright: 'Copyright 2023 Dify',
privacy_policy: 'https://dify.ai',
category: 'Translate',
position: 4,
is_listed: true,
install_count: 1662,
installed: false,
editable: true,
is_agent: false,
},
{
app: {
id: '89ad1e65-6711-4c80-b469-a71a434e2dbd',
name: '个人学习导师',
mode: 'chat',
icon: '🤖',
icon_background: '#FFEAD5',
},
app_id: '89ad1e65-6711-4c80-b469-a71a434e2dbd',
description: '您的私人学习导师,帮您制定学习计划并辅导',
copyright: 'Copyright 2023 Dify',
privacy_policy: 'https://dify.ai',
category: 'Assistant',
position: 26,
is_listed: true,
install_count: 1441,
installed: true,
editable: true,
is_agent: false,
},
{
app: {
id: 'ff551444-a3ff-4fd8-b297-f38581c98b4a',
name: '文献综述写作',
mode: 'completion',
icon: 'female-student',
icon_background: '#FBE8FF',
},
app_id: 'ff551444-a3ff-4fd8-b297-f38581c98b4a',
description: '帮你撰写论文文献综述',
copyright: 'Copyright 2023 Dify',
privacy_policy: 'https://dify.ai',
category: 'Writing',
position: 7,
is_listed: true,
install_count: 1651,
installed: false,
editable: true,
is_agent: false,
},
{
app: {
id: '79227a52-11f1-4cf9-8c49-0bd86f9be813',
name: 'Youtube 频道数据分析',
mode: 'chat',
icon: '🔢',
icon_background: '#E4FBCC',
},
app_id: '79227a52-11f1-4cf9-8c49-0bd86f9be813',
description:
'你好,告诉我您想分析的 YouTube 频道,我将为您整理一份完整的数据分析报告。',
copyright: null,
privacy_policy: null,
category: '智能助理',
position: 0,
is_listed: true,
install_count: 2,
installed: false,
editable: true,
is_agent: true,
},
{
app: {
id: '609f4a7f-36f7-4791-96a7-4ccbe6f8dfbb',
name: '旅行规划助手',
mode: 'chat',
icon: '✈️',
icon_background: '#E4FBCC',
},
app_id: '609f4a7f-36f7-4791-96a7-4ccbe6f8dfbb',
description:
'欢迎使用您的个性化旅行服务顾问!🌍✈️ 准备好踏上一段充满冒险与放松的旅程了吗?让我们一起深入打造您难忘的旅行体验吧。',
copyright: null,
privacy_policy: null,
category: '智能助理',
position: 0,
is_listed: true,
install_count: 3,
installed: false,
editable: true,
is_agent: true,
},
],
categories: [
'绘画',
'HR',
'Programming',
'Translate',
'Assistant',
'Writing',
'智能助理',
],
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment