Skip to content

Commit

Permalink
feature: max_active_requests front end
Browse files Browse the repository at this point in the history
  • Loading branch information
liuzhenghua-jk committed Jul 5, 2024
1 parent c340bc8 commit 96d78a7
Show file tree
Hide file tree
Showing 19 changed files with 82 additions and 6 deletions.
4 changes: 4 additions & 0 deletions api/controllers/console/app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def post(self):
"""Create app"""
parser = reqparse.RequestParser()
parser.add_argument('name', type=str, required=True, location='json')
parser.add_argument('max_active_requests', type=int, location='json')
parser.add_argument('description', type=str, location='json')
parser.add_argument('mode', type=str, choices=ALLOW_CREATE_APP_MODES, location='json')
parser.add_argument('icon', type=str, location='json')
Expand All @@ -70,6 +71,8 @@ def post(self):

if 'mode' not in args or args['mode'] is None:
raise BadRequest("mode is required")
if 'max_active_requests' in args and args['max_active_requests'] is not None and args['max_active_requests'] < 0:
raise BadRequest("max active requests should be a non-negative integer")

app_service = AppService()
app = app_service.create_app(current_user.current_tenant_id, args, current_user)
Expand Down Expand Up @@ -134,6 +137,7 @@ def put(self, app_model):
parser.add_argument('description', type=str, location='json')
parser.add_argument('icon', type=str, location='json')
parser.add_argument('icon_background', type=str, location='json')
parser.add_argument('max_active_requests', type=int, location='json')
args = parser.parse_args()

app_service = AppService()
Expand Down
1 change: 1 addition & 0 deletions api/fields/app_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
app_partial_fields = {
'id': fields.String,
'name': fields.String,
'max_active_requests': fields.Integer,
'description': fields.String(attribute='desc_or_prompt'),
'mode': fields.String(attribute='mode_compatible_with_agent'),
'icon': fields.String,
Expand Down
5 changes: 5 additions & 0 deletions api/services/app_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from constants.model_template import default_app_templates
from core.agent.entities import AgentToolEntity
from core.app.features.rate_limiting import RateLimit
from core.errors.error import LLMBadRequestError, ProviderTokenNotInitError
from core.model_manager import ModelManager
from core.model_runtime.entities.model_entities import ModelPropertyKey, ModelType
Expand Down Expand Up @@ -118,6 +119,7 @@ def create_app(self, tenant_id: str, args: dict, account: Account) -> App:

app = App(**app_template['app'])
app.name = args['name']
app.max_active_requests = args['max_active_requests']
app.description = args.get('description', '')
app.mode = args['mode']
app.icon = args['icon']
Expand Down Expand Up @@ -322,11 +324,14 @@ def update_app(self, app: App, args: dict) -> App:
"""
app.name = args.get('name')
app.description = args.get('description', '')
app.max_active_requests = args.get('max_active_requests', 0)
app.icon = args.get('icon')
app.icon_background = args.get('icon_background')
app.updated_at = datetime.now(timezone.utc).replace(tzinfo=None)
db.session.commit()

rate_limit = RateLimit(app.id, app.max_active_requests)
rate_limit.flush_cache(use_local_value=True)
return app

def update_app_name(self, app: App, name: str) -> App:
Expand Down
3 changes: 3 additions & 0 deletions web/app/(commonLayout)/apps/AppCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
name,
icon,
icon_background,
max_active_requests,
description,
}) => {
try {
Expand All @@ -81,6 +82,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
name,
icon,
icon_background,
max_active_requests,
description,
})
setShowEditModal(false)
Expand Down Expand Up @@ -337,6 +339,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
appIcon={app.icon}
appIconBackground={app.icon_background}
appName={app.name}
maxActiveRequests={app.max_active_requests}
appDescription={app.description}
show={showEditModal}
onConfirm={onEdit}
Expand Down
22 changes: 20 additions & 2 deletions web/app/components/app/create-app-modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client'
import type { MouseEventHandler } from 'react'
import type { ChangeEvent, MouseEventHandler } from 'react'
import { useCallback, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import cn from 'classnames'
Expand Down Expand Up @@ -43,6 +43,12 @@ const CreateAppModal = ({ show, onSuccess, onClose }: CreateAppDialogProps) => {
const [emoji, setEmoji] = useState({ icon: '🤖', icon_background: '#FFEAD5' })
const [showEmojiPicker, setShowEmojiPicker] = useState(false)
const [name, setName] = useState('')
const [max_active_requests, setMaxActiveRequests] = useState<number | null>(null)
const handleMaxActiveRequestsChange = (e: ChangeEvent<HTMLInputElement>) => {
const value = e.target.value
if ((parseInt(value) >= 0 && !value.startsWith('-')))
setMaxActiveRequests(parseInt(value))
}
const [description, setDescription] = useState('')

const { plan, enableBilling } = useProviderContext()
Expand All @@ -68,6 +74,7 @@ const CreateAppModal = ({ show, onSuccess, onClose }: CreateAppDialogProps) => {
description,
icon: emoji.icon,
icon_background: emoji.icon_background,
max_active_requests,
mode: appMode,
})
notify({ type: 'success', message: t('app.newApp.appCreated') })
Expand All @@ -81,7 +88,7 @@ const CreateAppModal = ({ show, onSuccess, onClose }: CreateAppDialogProps) => {
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
}
isCreatingRef.current = false
}, [name, notify, t, appMode, emoji.icon, emoji.icon_background, description, onSuccess, onClose, mutateApps, push, isCurrentWorkspaceEditor])
}, [name, notify, t, appMode, emoji.icon, emoji.icon_background, max_active_requests, description, onSuccess, onClose, mutateApps, push, isCurrentWorkspaceEditor])

return (
<Modal
Expand Down Expand Up @@ -288,6 +295,17 @@ const CreateAppModal = ({ show, onSuccess, onClose }: CreateAppDialogProps) => {
}}
/>}
</div>
{/* max active requests */}
<div className='pt-2 px-8'>
<div className='py-2 text-sm font-medium leading-[20px] text-gray-900'>{t('app.newApp.appMaxActiveRequests')}</div>
<input
type="number"
className='w-full h-10 px-3 text-sm font-normal bg-gray-100 rounded-lg border border-transparent outline-none appearance-none caret-primary-600 placeholder:text-gray-400 hover:bg-gray-50 hover:border hover:border-gray-300 focus:bg-gray-50 focus:border focus:border-gray-300 focus:shadow-xs'
placeholder={t('app.newApp.appMaxActiveRequestsPlaceholder') || ''}
value={max_active_requests}
onChange={handleMaxActiveRequestsChange}
/>
</div>
{/* description */}
<div className='pt-2 px-8'>
<div className='py-2 text-sm font-medium leading-[20px] text-gray-900'>{t('app.newApp.captionDescription')}</div>
Expand Down
1 change: 1 addition & 0 deletions web/app/components/explore/app-list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ const Apps = ({
appIcon={currApp?.app.icon || ''}
appIconBackground={currApp?.app.icon_background || ''}
appName={currApp?.app.name || ''}
maxActiveRequests={currApp?.app.max_active_request || 0}
appDescription={currApp?.app.description || ''}
show={isShowCreateModal}
onConfirm={onCreate}
Expand Down
22 changes: 22 additions & 0 deletions web/app/components/explore/create-app-modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use client'
import type { ChangeEvent } from 'react'
import React, { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { RiCloseLine } from '@remixicon/react'
Expand All @@ -14,13 +15,15 @@ export type CreateAppModalProps = {
show: boolean
isEditModal?: boolean
appName: string
maxActiveRequests: number
appDescription: string
appIcon: string
appIconBackground: string
onConfirm: (info: {
name: string
icon: string
icon_background: string
max_active_requests: number
description: string
}) => Promise<void>
onHide: () => void
Expand All @@ -32,13 +35,20 @@ const CreateAppModal = ({
appIcon,
appIconBackground,
appName,
maxActiveRequests,
appDescription,
onConfirm,
onHide,
}: CreateAppModalProps) => {
const { t } = useTranslation()

const [name, setName] = React.useState(appName)
const [max_active_requests, setMaxActiveRequests] = useState(maxActiveRequests)
const handleMaxActiveRequestsChange = (e: ChangeEvent<HTMLInputElement>) => {
const value = e.target.value
if (value === '' || (parseInt(value) >= 0 && !value.startsWith('-')))
setMaxActiveRequests(parseInt(value))
}
const [showEmojiPicker, setShowEmojiPicker] = useState(false)
const [emoji, setEmoji] = useState({ icon: appIcon, icon_background: appIconBackground })
const [description, setDescription] = useState(appDescription || '')
Expand All @@ -54,6 +64,7 @@ const CreateAppModal = ({
onConfirm({
name,
...emoji,
max_active_requests,
description,
})
onHide()
Expand Down Expand Up @@ -89,6 +100,17 @@ const CreateAppModal = ({
/>
</div>
</div>
{/* max active requests */}
<div className='pt-2'>
<div className='py-2 text-sm font-medium leading-[20px] text-gray-900'>{t('app.newApp.appMaxActiveRequests')}</div>
<input
type="number"
className='w-full h-10 px-3 text-sm font-normal bg-gray-100 rounded-lg border border-transparent outline-none appearance-none caret-primary-600 placeholder:text-gray-400 hover:bg-gray-50 hover:border hover:border-gray-300 focus:bg-gray-50 focus:border focus:border-gray-300 focus:shadow-xs'
placeholder={t('app.newApp.appMaxActiveRequestsPlaceholder') || ''}
value={max_active_requests}
onChange={handleMaxActiveRequestsChange}
/>
</div>
{/* description */}
<div className='pt-2'>
<div className='py-2 text-sm font-medium leading-[20px] text-gray-900'>{t('app.newApp.captionDescription')}</div>
Expand Down
2 changes: 2 additions & 0 deletions web/i18n/de-DE/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const translation = {
newApp: {
startToCreate: 'Lassen Sie uns mit Ihrer neuen App beginnen',
captionName: 'App-Symbol & Name',
appMaxActiveRequests: 'Maximale aktive Anfragen',
appMaxActiveRequestsPlaceholder: 'Die maximale Anzahl aktiver Anfragen für die Anwendung, wobei 0 unbegrenzt bedeutet, sollte eine nicht-negative Ganzzahl sein.',
captionAppType: 'Welchen Typ von App möchten Sie erstellen?',
previewDemo: 'Vorschau-Demo',
chatApp: 'Assistent',
Expand Down
2 changes: 2 additions & 0 deletions web/i18n/en-US/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ const translation = {
appNamePlaceholder: 'Give your app a name',
captionDescription: 'Description',
appDescriptionPlaceholder: 'Enter the description of the app',
appMaxActiveRequests: 'Max active requests',
appMaxActiveRequestsPlaceholder: 'The maximum number of active requests for the application, where 0 means unlimited, should be a non-negative integer.',
useTemplate: 'Use this template',
previewDemo: 'Preview demo',
chatApp: 'Assistant',
Expand Down
2 changes: 2 additions & 0 deletions web/i18n/fr-FR/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ const translation = {
advancedDescription: 'L\'orchestration de flux de travail orchestre les Chatbots sous forme de workflows, offrant un haut degré de personnalisation, y compris la possibilité de modifier les invites intégrées. Il convient aux utilisateurs expérimentés.',
captionName: 'Icône et nom de l\'application',
appNamePlaceholder: 'Donnez un nom à votre application',
appMaxActiveRequests: 'Nombre maximal de requêtes actives',
appMaxActiveRequestsPlaceholder: 'Le nombre maximum de requêtes actives pour l\'application, où 0 signifie illimité, doit être un entier non négatif.',
captionDescription: 'Description',
appDescriptionPlaceholder: 'Entrez la description de l\'application',
useTemplate: 'Utiliser ce modèle',
Expand Down
2 changes: 2 additions & 0 deletions web/i18n/ja-JP/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ const translation = {
advancedDescription: 'ワークフロー オーケストレートは、ワークフロー形式でチャットボットをオーケストレートし、組み込みのプロンプトを編集する機能を含む高度なカスタマイズを提供します。経験豊富なユーザー向けです。',
captionName: 'アプリのアイコンと名前',
appNamePlaceholder: 'アプリに名前を付ける',
appMaxActiveRequests: '最大アクティブリクエスト数',
appMaxActiveRequestsPlaceholder: 'アプリケーションの最大アクティブリクエスト数。0は無制限を意味し、非負の整数である必要があります。',
captionDescription: '説明',
appDescriptionPlaceholder: 'アプリの説明を入力してください',
useTemplate: 'このテンプレートを使用する',
Expand Down
2 changes: 2 additions & 0 deletions web/i18n/ko-KR/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ const translation = {
advancedDescription: '워크플로우 오케스트레이션은 워크플로우 형식으로 챗봇을 오케스트레이션하며 내장된 프롬프트를 편집할 수 있는 고급 사용자 정의 기능을 제공합니다. 경험이 많은 사용자용입니다.',
captionName: '앱 아이콘과 이름',
appNamePlaceholder: '앱 이름을 입력하세요',
appMaxActiveRequests: '최대 활성 요청 수',
appMaxActiveRequestsPlaceholder: '애플리케이션의 최대 활성 요청 수. 0은 무제한을 의미하며, 음이 아닌 정수여야 합니다.',
captionDescription: '설명',
appDescriptionPlaceholder: '앱 설명을 입력하세요',
useTemplate: '이 템플릿 사용',
Expand Down
2 changes: 2 additions & 0 deletions web/i18n/pl-PL/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ const translation = {
'Orkiestracja przepływu pracy organizuje Chatboty w formie przepływów pracy, oferując wysoki stopień dostosowania, w tym możliwość edycji wbudowanych monitów. Jest odpowiednia dla doświadczonych użytkowników.',
captionName: 'Ikona i nazwa aplikacji',
appNamePlaceholder: 'Podaj nazwę swojej aplikacji',
appMaxActiveRequests: 'Maksymalna liczba aktywnych żądań',
appMaxActiveRequestsPlaceholder: 'Maksymalna liczba aktywnych żądań dla aplikacji, gdzie 0 oznacza brak limitu, powinna być liczbą nieujemną całkowitą.',
captionDescription: 'Opis',
appDescriptionPlaceholder: 'Wprowadź opis aplikacji',
useTemplate: 'Użyj tego szablonu',
Expand Down
2 changes: 2 additions & 0 deletions web/i18n/pt-BR/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ const translation = {
advancedDescription: 'A Orquestração de Fluxo de Trabalho orquestra Chatbots na forma de fluxos de trabalho, oferecendo um alto grau de personalização, incluindo a capacidade de editar prompts integrados. É adequado para usuários experientes.',
captionName: 'Ícone e nome do aplicativo',
appNamePlaceholder: 'Dê um nome para o seu aplicativo',
appMaxActiveRequests: 'Máximo de requisições ativas',
appMaxActiveRequestsPlaceholder: 'O número máximo de requisições ativas para a aplicação, onde 0 significa ilimitado, deve ser um número inteiro não negativo.',
captionDescription: 'Descrição',
appDescriptionPlaceholder: 'Digite a descrição do aplicativo',
useTemplate: 'Usar este modelo',
Expand Down
2 changes: 2 additions & 0 deletions web/i18n/uk-UA/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ const translation = {
advancedDescription: 'Оркестрування робочого процесу оркеструє чатботи у формі робочих процесів, пропонуючи високий рівень настроювання, включаючи можливість редагувати вбудовані підказки. Він підходить для досвідчених користувачів.',
captionName: 'Іконка та назва додатка',
appNamePlaceholder: 'Дайте назву вашому додатку',
appMaxActiveRequests: 'Максимальна кількість активних запитів',
appMaxActiveRequestsPlaceholder: 'Максимальна кількість активних запитів для додатка, де 0 означає необмежено, повинна бути невід\'ємним цілим числом.',
captionDescription: 'Опис',
appDescriptionPlaceholder: 'Введіть опис додатка',
useTemplate: 'Використовуйте цей шаблон',
Expand Down
2 changes: 2 additions & 0 deletions web/i18n/zh-Hans/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const translation = {
advancedDescription: '工作流编排以工作流的形式编排聊天机器人,提供高度的自定义,包括编辑内置提示的能力。 它适合有经验的用户。',
captionName: '图标 & 名称',
appNamePlaceholder: '给你的应用起个名字',
appMaxActiveRequests: '最大活动请求数',
appMaxActiveRequestsPlaceholder: '应用程序的最大活动请求数,其中 0 表示无限制,应为非负整数。',
captionDescription: '描述',
appDescriptionPlaceholder: '输入应用的描述',
useTemplate: '使用该模板',
Expand Down
2 changes: 2 additions & 0 deletions web/i18n/zh-Hant/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const translation = {
advancedDescription: '工作流編排以工作流的形式編排聊天機器人,提供高度的自定義,包括編輯內建提示的能力。 它適合有經驗的使用者。',
captionName: '圖示 & 名稱',
appNamePlaceholder: '給你的應用起個名字',
appMaxActiveRequests: '最大活動請求數',
appMaxActiveRequestsPlaceholder: '應用程式的最大活動請求數,其中 0 表示無限制,應為非負整數。',
captionDescription: '描述',
appDescriptionPlaceholder: '輸入應用的描述',
useTemplate: '使用該模板',
Expand Down
8 changes: 4 additions & 4 deletions web/service/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ export const fetchAppTemplates: Fetcher<AppTemplatesResponse, { url: string }> =
return get<AppTemplatesResponse>(url)
}

export const createApp: Fetcher<AppDetailResponse, { name: string; icon: string; icon_background: string; mode: AppMode; description?: string; config?: ModelConfig }> = ({ name, icon, icon_background, mode, description, config }) => {
return post<AppDetailResponse>('apps', { body: { name, icon, icon_background, mode, description, model_config: config } })
export const createApp: Fetcher<AppDetailResponse, { name: string; icon: string; icon_background: string; max_active_requests: number | null; mode: AppMode; description?: string; config?: ModelConfig }> = ({ name, icon, icon_background, max_active_requests, mode, description, config }) => {
return post<AppDetailResponse>('apps', { body: { name, icon, icon_background, max_active_requests, mode, description, model_config: config } })
}

export const updateAppInfo: Fetcher<AppDetailResponse, { appID: string; name: string; icon: string; icon_background: string; description: string }> = ({ appID, name, icon, icon_background, description }) => {
return put<AppDetailResponse>(`apps/${appID}`, { body: { name, icon, icon_background, description } })
export const updateAppInfo: Fetcher<AppDetailResponse, { appID: string; name: string; icon: string; icon_background: string; max_active_requests: number; description: string }> = ({ appID, name, icon, icon_background, max_active_requests, description }) => {
return put<AppDetailResponse>(`apps/${appID}`, { body: { name, icon, icon_background, max_active_requests, description } })
}

export const copyApp: Fetcher<AppDetailResponse, { appID: string; name: string; icon: string; icon_background: string; mode: AppMode; description?: string }> = ({ appID, name, icon, icon_background, mode, description }) => {
Expand Down
2 changes: 2 additions & 0 deletions web/types/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@ export type App = {
id: string
/** Name */
name: string
/** Max active requests */
max_active_requests: number
/** Description */
description: string

Expand Down

0 comments on commit 96d78a7

Please sign in to comment.