mirror of
https://github.com/langgenius/webapp-conversation.git
synced 2025-12-08 17:32:27 +08:00
chore: enchance app config
This commit is contained in:
19
README.md
19
README.md
@ -1,11 +1,24 @@
|
|||||||
# Conversion Web App Template
|
# Conversion Web App Template
|
||||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||||
|
|
||||||
## Set App Info
|
## Config App
|
||||||
Set app info in `config/index.ts`. Includes:
|
Config app in `config/index.ts`.Please config:
|
||||||
- APP_ID
|
- APP_ID
|
||||||
- API_KEY
|
- API_KEY
|
||||||
- APP_INFO
|
|
||||||
|
More config:
|
||||||
|
```js
|
||||||
|
export const APP_INFO: AppInfo = {
|
||||||
|
"title": 'Chat APP',
|
||||||
|
"description": '',
|
||||||
|
"copyright": '',
|
||||||
|
"privacy_policy": '',
|
||||||
|
"default_language": 'zh-Hans'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isShowPrompt = true
|
||||||
|
export const promptTemplate = ''
|
||||||
|
```
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
First, install dependencies:
|
First, install dependencies:
|
||||||
|
|||||||
@ -9,26 +9,18 @@ import Toast from '@/app/components/base/toast'
|
|||||||
import Sidebar from '@/app/components/sidebar'
|
import Sidebar from '@/app/components/sidebar'
|
||||||
import ConfigSence from '@/app/components/config-scence'
|
import ConfigSence from '@/app/components/config-scence'
|
||||||
import Header from '@/app/components/header'
|
import Header from '@/app/components/header'
|
||||||
import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, sendChatMessage, updateFeedback } from '@/service'
|
import { fetchAppParams, fetchChatList, fetchConversations, sendChatMessage, updateFeedback } from '@/service'
|
||||||
import type { ConversationItem, Feedbacktype, IChatItem, PromptConfig, SiteInfo } from '@/types/app'
|
import type { ConversationItem, Feedbacktype, IChatItem, PromptConfig, AppInfo } from '@/types/app'
|
||||||
import Chat from '@/app/components/chat'
|
import Chat from '@/app/components/chat'
|
||||||
import { setLocaleOnClient } from '@/i18n/client'
|
import { setLocaleOnClient } from '@/i18n/client'
|
||||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||||
import Loading from '@/app/components/base/loading'
|
import Loading from '@/app/components/base/loading'
|
||||||
import { replaceVarWithValues } from '@/utils/prompt'
|
import { replaceVarWithValues } from '@/utils/prompt'
|
||||||
import AppUnavailable from '@/app/components/app-unavailable'
|
import AppUnavailable from '@/app/components/app-unavailable'
|
||||||
import { APP_ID, API_KEY } from '@/config'
|
import { APP_ID, API_KEY, APP_INFO, isShowPrompt, promptTemplate } from '@/config'
|
||||||
|
|
||||||
export type IMainProps = {
|
|
||||||
params: {
|
|
||||||
locale: string
|
|
||||||
appId: string
|
|
||||||
conversationId: string
|
|
||||||
token: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Main: FC<IMainProps> = () => {
|
const Main: FC = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const media = useBreakpoints()
|
const media = useBreakpoints()
|
||||||
const isMobile = media === MediaType.mobile
|
const isMobile = media === MediaType.mobile
|
||||||
@ -39,23 +31,16 @@ const Main: FC<IMainProps> = () => {
|
|||||||
*/
|
*/
|
||||||
const [appUnavailable, setAppUnavailable] = useState<boolean>(false)
|
const [appUnavailable, setAppUnavailable] = useState<boolean>(false)
|
||||||
const [isUnknwonReason, setIsUnknwonReason] = useState<boolean>(false)
|
const [isUnknwonReason, setIsUnknwonReason] = useState<boolean>(false)
|
||||||
const [appId, setAppId] = useState<string>('')
|
|
||||||
const [isPublicVersion, setIsPublicVersion] = useState<boolean>(true)
|
|
||||||
const [siteInfo, setSiteInfo] = useState<SiteInfo | null>()
|
|
||||||
const [promptConfig, setPromptConfig] = useState<PromptConfig | null>(null)
|
const [promptConfig, setPromptConfig] = useState<PromptConfig | null>(null)
|
||||||
const [inited, setInited] = useState<boolean>(false)
|
const [inited, setInited] = useState<boolean>(false)
|
||||||
const [plan, setPlan] = useState<string>('basic') // basic/plus/pro
|
|
||||||
// in mobile, show sidebar by click button
|
// in mobile, show sidebar by click button
|
||||||
const [isShowSidebar, { setTrue: showSidebar, setFalse: hideSidebar }] = useBoolean(false)
|
const [isShowSidebar, { setTrue: showSidebar, setFalse: hideSidebar }] = useBoolean(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (siteInfo?.title) {
|
if (APP_INFO?.title) {
|
||||||
if (plan !== 'basic')
|
document.title = `${APP_INFO.title} - Powered by LangGenius`
|
||||||
document.title = `${siteInfo.title}`
|
|
||||||
else
|
|
||||||
document.title = `${siteInfo.title} - Powered by LangGenius`
|
|
||||||
}
|
}
|
||||||
}, [siteInfo?.title, plan])
|
}, [APP_INFO?.title])
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* conversation info
|
* conversation info
|
||||||
@ -97,11 +82,6 @@ const Main: FC<IMainProps> = () => {
|
|||||||
const handleConversationSwitch = () => {
|
const handleConversationSwitch = () => {
|
||||||
if (!inited)
|
if (!inited)
|
||||||
return
|
return
|
||||||
if (!appId) {
|
|
||||||
// wait for appId
|
|
||||||
setTimeout(handleConversationSwitch, 100)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// update inputs of current conversation
|
// update inputs of current conversation
|
||||||
let notSyncToStateIntroduction = ''
|
let notSyncToStateIntroduction = ''
|
||||||
@ -160,7 +140,7 @@ const Main: FC<IMainProps> = () => {
|
|||||||
setConversationIdChangeBecauseOfNew(false)
|
setConversationIdChangeBecauseOfNew(false)
|
||||||
}
|
}
|
||||||
// trigger handleConversationSwitch
|
// trigger handleConversationSwitch
|
||||||
setCurrConversationId(id, appId)
|
setCurrConversationId(id, APP_ID)
|
||||||
hideSidebar()
|
hideSidebar()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +183,7 @@ const Main: FC<IMainProps> = () => {
|
|||||||
content: caculatedIntroduction,
|
content: caculatedIntroduction,
|
||||||
isAnswer: true,
|
isAnswer: true,
|
||||||
feedbackDisabled: true,
|
feedbackDisabled: true,
|
||||||
isOpeningStatement: isPublicVersion,
|
isOpeningStatement: isShowPrompt,
|
||||||
}
|
}
|
||||||
if (caculatedIntroduction)
|
if (caculatedIntroduction)
|
||||||
return [openstatement]
|
return [openstatement]
|
||||||
@ -219,37 +199,30 @@ const Main: FC<IMainProps> = () => {
|
|||||||
}
|
}
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const [appData, conversationData, appParams] = await Promise.all([fetchAppInfo(), fetchConversations(), fetchAppParams()])
|
const [conversationData, appParams] = await Promise.all([fetchConversations(), fetchAppParams()])
|
||||||
const { app_id: appId, site: siteInfo, prompt_config, plan }: any = appData
|
|
||||||
setAppId(appId)
|
|
||||||
setPlan(plan)
|
|
||||||
const tempIsPublicVersion = !!prompt_config
|
|
||||||
setIsPublicVersion(tempIsPublicVersion)
|
|
||||||
const prompt_template = tempIsPublicVersion ? prompt_config.prompt_template : ''
|
|
||||||
|
|
||||||
// handle current conversation id
|
// handle current conversation id
|
||||||
const { data: conversations } = conversationData as { data: ConversationItem[] }
|
const { data: conversations } = conversationData as { data: ConversationItem[] }
|
||||||
const _conversationId = getConversationIdFromStorage(appId)
|
const _conversationId = getConversationIdFromStorage(APP_ID)
|
||||||
const isNotNewConversation = conversations.some(item => item.id === _conversationId)
|
const isNotNewConversation = conversations.some(item => item.id === _conversationId)
|
||||||
|
|
||||||
// fetch new conversation info
|
// fetch new conversation info
|
||||||
const { variables: prompt_variables, introduction }: any = appParams
|
const { variables: prompt_variables, introduction }: any = appParams
|
||||||
|
|
||||||
setLocaleOnClient(siteInfo.default_language, true)
|
setLocaleOnClient(APP_INFO.default_language, true)
|
||||||
setNewConversationInfo({
|
setNewConversationInfo({
|
||||||
name: t('app.chat.newChatDefaultName'),
|
name: t('app.chat.newChatDefaultName'),
|
||||||
introduction,
|
introduction,
|
||||||
})
|
})
|
||||||
setSiteInfo(siteInfo as SiteInfo)
|
|
||||||
setPromptConfig({
|
setPromptConfig({
|
||||||
prompt_template,
|
prompt_template: promptTemplate,
|
||||||
prompt_variables,
|
prompt_variables,
|
||||||
} as PromptConfig)
|
} as PromptConfig)
|
||||||
|
|
||||||
setConversationList(conversations as ConversationItem[])
|
setConversationList(conversations as ConversationItem[])
|
||||||
|
|
||||||
if (isNotNewConversation)
|
if (isNotNewConversation)
|
||||||
setCurrConversationId(_conversationId, appId, false)
|
setCurrConversationId(_conversationId, APP_ID, false)
|
||||||
|
|
||||||
setInited(true)
|
setInited(true)
|
||||||
}
|
}
|
||||||
@ -355,7 +328,7 @@ const Main: FC<IMainProps> = () => {
|
|||||||
setConversationIdChangeBecauseOfNew(false)
|
setConversationIdChangeBecauseOfNew(false)
|
||||||
resetNewConversationInputs()
|
resetNewConversationInputs()
|
||||||
setChatNotStarted()
|
setChatNotStarted()
|
||||||
setCurrConversationId(tempNewConversationId, appId, true)
|
setCurrConversationId(tempNewConversationId, APP_ID, true)
|
||||||
},
|
},
|
||||||
onError() {
|
onError() {
|
||||||
setResponsingFalse()
|
setResponsingFalse()
|
||||||
@ -383,28 +356,28 @@ const Main: FC<IMainProps> = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const renderSidebar = () => {
|
const renderSidebar = () => {
|
||||||
if (!appId || !siteInfo || !promptConfig)
|
if (!APP_ID || !APP_INFO || !promptConfig)
|
||||||
return null
|
return null
|
||||||
return (
|
return (
|
||||||
<Sidebar
|
<Sidebar
|
||||||
list={conversationList}
|
list={conversationList}
|
||||||
onCurrentIdChange={handleConversationIdChange}
|
onCurrentIdChange={handleConversationIdChange}
|
||||||
currentId={currConversationId}
|
currentId={currConversationId}
|
||||||
copyRight={siteInfo.copyright || siteInfo.title}
|
copyRight={APP_INFO.copyright || APP_INFO.title}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appUnavailable)
|
if (appUnavailable)
|
||||||
return <AppUnavailable isUnknwonReason={isUnknwonReason} errMessage={!hasSetAppConfig && 'Please set APP_ID and API_KEY in config/index.tsx'} />
|
return <AppUnavailable isUnknwonReason={isUnknwonReason} errMessage={!hasSetAppConfig ? 'Please set APP_ID and API_KEY in config/index.tsx' : ''} />
|
||||||
|
|
||||||
if (!appId || !siteInfo || !promptConfig)
|
if (!APP_ID || !APP_INFO || !promptConfig)
|
||||||
return <Loading type='app' />
|
return <Loading type='app' />
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='bg-gray-100'>
|
<div className='bg-gray-100'>
|
||||||
<Header
|
<Header
|
||||||
title={siteInfo.title}
|
title={APP_INFO.title}
|
||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
onShowSideBar={showSidebar}
|
onShowSideBar={showSidebar}
|
||||||
onCreateNewChat={() => handleConversationIdChange('-1')}
|
onCreateNewChat={() => handleConversationIdChange('-1')}
|
||||||
@ -427,14 +400,13 @@ const Main: FC<IMainProps> = () => {
|
|||||||
<ConfigSence
|
<ConfigSence
|
||||||
conversationName={conversationName}
|
conversationName={conversationName}
|
||||||
hasSetInputs={hasSetInputs}
|
hasSetInputs={hasSetInputs}
|
||||||
isPublicVersion={isPublicVersion}
|
isPublicVersion={isShowPrompt}
|
||||||
siteInfo={siteInfo}
|
siteInfo={APP_INFO}
|
||||||
promptConfig={promptConfig}
|
promptConfig={promptConfig}
|
||||||
onStartChat={handleStartChat}
|
onStartChat={handleStartChat}
|
||||||
canEidtInpus={canEditInpus}
|
canEidtInpus={canEditInpus}
|
||||||
savedInputs={currInputs as Record<string, any>}
|
savedInputs={currInputs as Record<string, any>}
|
||||||
onInputsChange={setCurrInputs}
|
onInputsChange={setCurrInputs}
|
||||||
plan={plan}
|
|
||||||
></ConfigSence>
|
></ConfigSence>
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@ -4,8 +4,8 @@ import React, { useEffect, useState } from 'react'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import TemplateVarPanel, { PanelTitle, VarOpBtnGroup } from '../value-panel'
|
import TemplateVarPanel, { PanelTitle, VarOpBtnGroup } from '../value-panel'
|
||||||
import s from './style.module.css'
|
import s from './style.module.css'
|
||||||
import { AppInfo, ChatBtn, EditBtn, FootLogo, PromptTemplate } from './massive-component'
|
import { AppInfoComp, ChatBtn, EditBtn, FootLogo, PromptTemplate } from './massive-component'
|
||||||
import type { PromptConfig, SiteInfo } from '@/types/app'
|
import type { PromptConfig, AppInfo } from '@/types/app'
|
||||||
import Toast from '@/app/components/base/toast'
|
import Toast from '@/app/components/base/toast'
|
||||||
import Select from '@/app/components/base/select'
|
import Select from '@/app/components/base/select'
|
||||||
import { DEFAULT_VALUE_MAX_LEN } from '@/config'
|
import { DEFAULT_VALUE_MAX_LEN } from '@/config'
|
||||||
@ -17,13 +17,12 @@ export type IWelcomeProps = {
|
|||||||
conversationName: string
|
conversationName: string
|
||||||
hasSetInputs: boolean
|
hasSetInputs: boolean
|
||||||
isPublicVersion: boolean
|
isPublicVersion: boolean
|
||||||
siteInfo: SiteInfo
|
siteInfo: AppInfo
|
||||||
promptConfig: PromptConfig
|
promptConfig: PromptConfig
|
||||||
onStartChat: (inputs: Record<string, any>) => void
|
onStartChat: (inputs: Record<string, any>) => void
|
||||||
canEidtInpus: boolean
|
canEidtInpus: boolean
|
||||||
savedInputs: Record<string, any>
|
savedInputs: Record<string, any>
|
||||||
onInputsChange: (inputs: Record<string, any>) => void
|
onInputsChange: (inputs: Record<string, any>) => void
|
||||||
plan: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Welcome: FC<IWelcomeProps> = ({
|
const Welcome: FC<IWelcomeProps> = ({
|
||||||
@ -31,7 +30,6 @@ const Welcome: FC<IWelcomeProps> = ({
|
|||||||
hasSetInputs,
|
hasSetInputs,
|
||||||
isPublicVersion,
|
isPublicVersion,
|
||||||
siteInfo,
|
siteInfo,
|
||||||
plan,
|
|
||||||
promptConfig,
|
promptConfig,
|
||||||
onStartChat,
|
onStartChat,
|
||||||
canEidtInpus,
|
canEidtInpus,
|
||||||
@ -144,7 +142,7 @@ const Welcome: FC<IWelcomeProps> = ({
|
|||||||
if (isPublicVersion) {
|
if (isPublicVersion) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AppInfo siteInfo={siteInfo} />
|
<AppInfoComp siteInfo={siteInfo} />
|
||||||
<TemplateVarPanel
|
<TemplateVarPanel
|
||||||
isFold={false}
|
isFold={false}
|
||||||
header={
|
header={
|
||||||
@ -167,7 +165,7 @@ const Welcome: FC<IWelcomeProps> = ({
|
|||||||
<TemplateVarPanel
|
<TemplateVarPanel
|
||||||
isFold={false}
|
isFold={false}
|
||||||
header={
|
header={
|
||||||
<AppInfo siteInfo={siteInfo} />
|
<AppInfoComp siteInfo={siteInfo} />
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ChatBtn onClick={handleChat} />
|
<ChatBtn onClick={handleChat} />
|
||||||
@ -180,7 +178,7 @@ const Welcome: FC<IWelcomeProps> = ({
|
|||||||
<TemplateVarPanel
|
<TemplateVarPanel
|
||||||
isFold={false}
|
isFold={false}
|
||||||
header={
|
header={
|
||||||
<AppInfo siteInfo={siteInfo} />
|
<AppInfoComp siteInfo={siteInfo} />
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{renderInputs()}
|
{renderInputs()}
|
||||||
@ -325,10 +323,10 @@ const Welcome: FC<IWelcomeProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
: <div>
|
: <div>
|
||||||
</div>}
|
</div>}
|
||||||
{plan === 'basic' && <a className='flex items-center pr-3 space-x-3' href="https://langgenius.ai/" target="_blank">
|
<a className='flex items-center pr-3 space-x-3' href="https://langgenius.ai/" target="_blank">
|
||||||
<span className='uppercase'>{t('app.chat.powerBy')}</span>
|
<span className='uppercase'>{t('app.chat.powerBy')}</span>
|
||||||
<FootLogo />
|
<FootLogo />
|
||||||
</a>}
|
</a>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -7,10 +7,10 @@ import {
|
|||||||
PencilIcon,
|
PencilIcon,
|
||||||
} from '@heroicons/react/24/solid'
|
} from '@heroicons/react/24/solid'
|
||||||
import s from './style.module.css'
|
import s from './style.module.css'
|
||||||
import type { SiteInfo } from '@/types/app'
|
import type { AppInfo } from '@/types/app'
|
||||||
import Button from '@/app/components/base/button'
|
import Button from '@/app/components/base/button'
|
||||||
|
|
||||||
export const AppInfo: FC<{ siteInfo: SiteInfo }> = ({ siteInfo }) => {
|
export const AppInfoComp: FC<{ siteInfo: AppInfo }> = ({ siteInfo }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@ -1,22 +1,17 @@
|
|||||||
|
import { AppInfo } from "@/types/app"
|
||||||
export const APP_ID = ''
|
export const APP_ID = ''
|
||||||
export const API_KEY = ''
|
export const API_KEY = ''
|
||||||
export const APP_INFO = {
|
|
||||||
"app_id": APP_ID,
|
export const APP_INFO: AppInfo = {
|
||||||
"site": {
|
"title": 'Chat APP',
|
||||||
"title": "Chat APP",
|
"description": '',
|
||||||
"description": null,
|
"copyright": '',
|
||||||
"copyright": null,
|
"privacy_policy": '',
|
||||||
"privacy_policy": null,
|
"default_language": 'zh-Hans'
|
||||||
"default_language": "zh-Hans",
|
|
||||||
"prompt_public": true
|
|
||||||
},
|
|
||||||
"prompt_config": {
|
|
||||||
"introduction": "Chat APP",
|
|
||||||
"prompt_template": "{{a}}", "prompt_variables": [{ "key": "a", "name": "a", "type": "string", "max_length": 48 }], "completion_params": { "max_token": 256, "temperature": 1, "top_p": 1, "presence_penalty": 0, "frequency_penalty": 0 }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isShowPrompt = false
|
||||||
|
export const promptTemplate = 'I want you to act as a javascript console.'
|
||||||
|
|
||||||
export const API_PREFIX = '/api';
|
export const API_PREFIX = '/api';
|
||||||
|
|
||||||
|
|||||||
@ -66,7 +66,7 @@ export type ConversationItem = {
|
|||||||
introduction: string,
|
introduction: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SiteInfo = {
|
export type AppInfo = {
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
default_language: Locale
|
default_language: Locale
|
||||||
|
|||||||
Reference in New Issue
Block a user