feat: Added partial prompt messages (#7900)
Some checks failed
SonarCloud Scan / SonarCloud (push) Failing after -6s

This commit is contained in:
zhengkunwang 2025-02-18 18:08:52 +08:00 committed by GitHub
parent 0c68f16a66
commit ea1261b48e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 101 additions and 25 deletions

View file

@ -95,6 +95,7 @@ type AppDetail struct {
Website string `json:"website"` Website string `json:"website"`
Document string `json:"document"` Document string `json:"document"`
Github string `json:"github"` Github string `json:"github"`
GpuSupport bool `json:"gpuSupport"`
} }
type AppInstallDTO struct { type AppInstallDTO struct {

View file

@ -750,6 +750,7 @@ func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) {
} }
res.AppContainerConfig = config res.AppContainerConfig = config
res.HostMode = isHostModel(install.DockerCompose) res.HostMode = isHostModel(install.DockerCompose)
res.GpuConfig = isGpuConfig(install.DockerCompose)
return &res, nil return &res, nil
} }

View file

@ -1341,6 +1341,7 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool)
Github: installed.App.Github, Github: installed.App.Github,
Website: installed.App.Website, Website: installed.App.Website,
Document: installed.App.Document, Document: installed.App.Document,
GpuSupport: installed.App.GpuSupport,
}, },
} }
if updated { if updated {
@ -1509,6 +1510,8 @@ func addDockerComposeCommonParam(composeMap map[string]interface{}, serviceName
}, },
}, },
} }
} else {
delete(resource, "reservations")
} }
ports, ok := serviceValue["ports"].([]interface{}) ports, ok := serviceValue["ports"].([]interface{})
@ -1612,6 +1615,33 @@ func isHostModel(dockerCompose string) bool {
return false return false
} }
func isGpuConfig(dockerCompose string) bool {
composeMap := make(map[string]interface{})
_ = yaml.Unmarshal([]byte(dockerCompose), &composeMap)
services, serviceValid := composeMap["services"].(map[string]interface{})
if !serviceValid {
return false
}
for _, service := range services {
serviceValue := service.(map[string]interface{})
deploy := map[string]interface{}{}
if de, ok := serviceValue["deploy"]; ok {
deploy = de.(map[string]interface{})
}
resource := map[string]interface{}{}
if res, ok := deploy["resources"]; ok {
resource = res.(map[string]interface{})
}
if reservations, ok := resource["reservations"]; ok {
reservationsMap := reservations.(map[string]interface{})
if _, dOk := reservationsMap["devices"]; dOk {
return true
}
}
}
return false
}
func RequestDownloadCallBack(downloadCallBackUrl string) { func RequestDownloadCallBack(downloadCallBackUrl string) {
if downloadCallBackUrl == "" { if downloadCallBackUrl == "" {
return return

View file

@ -242,6 +242,7 @@ export namespace App {
allowPort: boolean; allowPort: boolean;
dockerCompose: string; dockerCompose: string;
hostMode?: boolean; hostMode?: boolean;
gpuConfig?: boolean;
} }
export interface IgnoredApp { export interface IgnoredApp {

View file

@ -1979,8 +1979,7 @@ const message = {
pullImage: 'Pull Image', pullImage: 'Pull Image',
pullImageHelper: 'Execute docker pull to pull the image before the application starts', pullImageHelper: 'Execute docker pull to pull the image before the application starts',
gpuConfig: 'GPU Acceleration', gpuConfig: 'GPU Acceleration',
gpuConfigHelper: gpuConfigHelper: 'Please ensure that the server has NVIDIA drivers and NVIDIA Container Toolkit installed',
'Please ensure that the server has NVIDIA drivers and NVIDIA Container Toolkit installed',
}, },
website: { website: {
website: 'Website | Websites', website: 'Website | Websites',
@ -2591,6 +2590,7 @@ const message = {
proxyHelper4: 'Once created, you can view and manage it in the website list', proxyHelper4: 'Once created, you can view and manage it in the website list',
proxyHelper5: proxyHelper5:
'After enabling, you can disable external access to the port in the App Store - Installed - Ollama - Parameters to improve security.', 'After enabling, you can disable external access to the port in the App Store - Installed - Ollama - Parameters to improve security.',
proxyHelper6: 'To disable proxy configuration, you can delete it from the website list.',
}, },
}; };

View file

@ -2559,6 +2559,7 @@ const message = {
proxyHelper4: '作成後ウェブサイトリストで確認および管理できます', proxyHelper4: '作成後ウェブサイトリストで確認および管理できます',
proxyHelper5: proxyHelper5:
'有効にするとアプリストア - インストール済み - Ollama - パラメータでポートの外部アクセスを無効にしセキュリティを向上させることができます', '有効にするとアプリストア - インストール済み - Ollama - パラメータでポートの外部アクセスを無効にしセキュリティを向上させることができます',
proxyHelper6: 'プロキシ設定を無効にするにはウェブサイトリストから削除できます',
}, },
}; };
export default { export default {

View file

@ -1920,8 +1920,7 @@ const message = {
pullImage: '이미지 ', pullImage: '이미지 ',
pullImageHelper: '애플리케이션 시작 전에 docker pull 실행하여 이미지를 다운로드하세요.', pullImageHelper: '애플리케이션 시작 전에 docker pull 실행하여 이미지를 다운로드하세요.',
gpuConfig: 'GPU 가속', gpuConfig: 'GPU 가속',
gpuConfigHelper: gpuConfigHelper: '서버에 NVIDIA 드라이버와 NVIDIA Container Toolkit이 설치되어 있는지 확인하십시오',
'서버에 NVIDIA 드라이버와 NVIDIA Container Toolkit이 설치되어 있는지 확인하십시오',
}, },
website: { website: {
website: '웹사이트 | 웹사이트들', website: '웹사이트 | 웹사이트들',
@ -2521,6 +2520,7 @@ const message = {
proxyHelper4: '생성 , 웹사이트 목록에서 이를 보고 관리할 있습니다', proxyHelper4: '생성 , 웹사이트 목록에서 이를 보고 관리할 있습니다',
proxyHelper5: proxyHelper5:
'활성화한 , 스토어 - 설치됨 - Ollama - 매개변수에서 포트 외부 접근을 비활성화하여 보안을 강화할 있습니다.', '활성화한 , 스토어 - 설치됨 - Ollama - 매개변수에서 포트 외부 접근을 비활성화하여 보안을 강화할 있습니다.',
proxyHelper6: '프록시 구성을 비활성화하려면 웹사이트 목록에서 삭제할 있습니다.',
}, },
}; };

View file

@ -2004,8 +2004,7 @@ const message = {
pullImage: 'Tarik Imej', pullImage: 'Tarik Imej',
pullImageHelper: 'Laksanakan docker pull untuk menarik imej sebelum aplikasi dimulakan.', pullImageHelper: 'Laksanakan docker pull untuk menarik imej sebelum aplikasi dimulakan.',
gpuConfig: 'Pecutan GPU', gpuConfig: 'Pecutan GPU',
gpuConfigHelper: gpuConfigHelper: 'Sila pastikan bahawa pelayan telah dipasang pemacu NVIDIA dan NVIDIA Container Toolkit',
'Sila pastikan bahawa pelayan telah dipasang pemacu NVIDIA dan NVIDIA Container Toolkit',
}, },
website: { website: {
website: 'Laman Web | Laman Web', website: 'Laman Web | Laman Web',
@ -2620,6 +2619,7 @@ const message = {
proxyHelper4: 'Setelah selesai, anda boleh melihat dan mengurusnya dalam senarai laman web', proxyHelper4: 'Setelah selesai, anda boleh melihat dan mengurusnya dalam senarai laman web',
proxyHelper5: proxyHelper5:
'Selepas diaktifkan, anda boleh melumpuhkan akses luaran ke port dalam App Store - Dipasang - Ollama - Parameter untuk meningkatkan keselamatan.', 'Selepas diaktifkan, anda boleh melumpuhkan akses luaran ke port dalam App Store - Dipasang - Ollama - Parameter untuk meningkatkan keselamatan.',
proxyHelper6: 'Untuk melumpuhkan konfigurasi proksi, anda boleh memadamnya dari senarai laman web.',
}, },
}; };

View file

@ -2614,6 +2614,7 @@ const message = {
proxyHelper2: 'Limite o acesso por IP para evitar exposição na internet pública', proxyHelper2: 'Limite o acesso por IP para evitar exposição na internet pública',
proxyHelper3: 'Habilite a transmissão em fluxo', proxyHelper3: 'Habilite a transmissão em fluxo',
proxyHelper4: 'Após a criação, você pode visualizar e gerenciar no lista de sites', proxyHelper4: 'Após a criação, você pode visualizar e gerenciar no lista de sites',
proxyHelper6: 'Para desativar a configuração de proxy, você pode excluí-la da lista de sites.',
}, },
}; };

View file

@ -1997,8 +1997,7 @@ const message = {
pullImage: 'Загрузить образ', pullImage: 'Загрузить образ',
pullImageHelper: 'Выполнить docker pull для загрузки образа перед запуском приложения', pullImageHelper: 'Выполнить docker pull для загрузки образа перед запуском приложения',
gpuConfig: 'GPU Hızlandırma', gpuConfig: 'GPU Hızlandırma',
gpuConfigHelper: gpuConfigHelper: 'Пожалуйста, убедитесь, что на сервере установлены драйверы NVIDIA и NVIDIA Container Toolkit',
'Пожалуйста, убедитесь, что на сервере установлены драйверы NVIDIA и NVIDIA Container Toolkit',
}, },
website: { website: {
website: 'Веб-сайт | Веб-сайты', website: 'Веб-сайт | Веб-сайты',
@ -2613,6 +2612,7 @@ const message = {
proxyHelper4: 'После создания вы можете просматривать и управлять этим в списке сайтов', proxyHelper4: 'После создания вы можете просматривать и управлять этим в списке сайтов',
proxyHelper5: proxyHelper5:
'После включения вы можете отключить внешний доступ к порту в Магазине приложений - Установленные - Ollama - Параметры для повышения безопасности.', 'После включения вы можете отключить внешний доступ к порту в Магазине приложений - Установленные - Ollama - Параметры для повышения безопасности.',
proxyHelper6: 'Чтобы отключить настройку прокси, вы можете удалить её из списка сайтов.',
}, },
}; };

View file

@ -2427,6 +2427,7 @@ const message = {
proxyHelper3: '啟用流式傳輸', proxyHelper3: '啟用流式傳輸',
proxyHelper4: '創建後您可以在網站列表中查看並管理', proxyHelper4: '創建後您可以在網站列表中查看並管理',
proxyHelper5: '啟用後您可以在應用商店 - 已安裝 - Ollama - 參數中取消端口外部訪問以提高安全性', proxyHelper5: '啟用後您可以在應用商店 - 已安裝 - Ollama - 參數中取消端口外部訪問以提高安全性',
proxyHelper6: '如需關閉代理配置可以在網站列表中刪除',
}, },
}; };
export default { export default {

View file

@ -2066,7 +2066,7 @@ const message = {
ipv6: '监听 IPV6', ipv6: '监听 IPV6',
leechReturnError: '请填写 HTTP 状态码', leechReturnError: '请填写 HTTP 状态码',
selectAcme: '选择 acme 账号', selectAcme: '选择 acme 账号',
imported: '手动创建', imported: '存量/自签证书',
importType: '导入方式', importType: '导入方式',
pasteSSL: '粘贴代码', pasteSSL: '粘贴代码',
localSSL: '选择服务器文件', localSSL: '选择服务器文件',
@ -2424,11 +2424,12 @@ const message = {
}, },
aitool: { aitool: {
proxy: 'AI 代理增强', proxy: 'AI 代理增强',
proxyHelper1: '绑定域名并开启 HTTPS增强传输安全性', proxyHelper1: '绑定域名并开启 HTTPS增强传输安全性',
proxyHelper2: '限制 IP 访问防止在公网暴露', proxyHelper2: '限制 IP 访问防止在公网暴露',
proxyHelper3: '开启流式传输', proxyHelper3: '开启流式传输',
proxyHelper4: '创建完成之后可以在网站列表中查看并管理', proxyHelper4: '创建完成之后可以在网站列表中查看并管理',
proxyHelper5: '开启之后可以在应用商店 - 已安装 - ollama - 参数中取消端口外部访问以提高安全性', proxyHelper5: '创建完成之后可以在应用商店 - 已安装 - ollama - 参数中取消端口外部访问以提高安全性',
proxyHelper6: '如需关闭代理配置可以在网站列表中删除',
}, },
}; };
export default { export default {

View file

@ -25,7 +25,18 @@
<el-form-item :label="$t('website.domain')" prop="domain"> <el-form-item :label="$t('website.domain')" prop="domain">
<el-input v-model.trim="req.domain" :disabled="operate === 'update'" /> <el-input v-model.trim="req.domain" :disabled="operate === 'update'" />
<span class="input-help"> <span class="input-help">
{{ $t('aitool.proxyHelper4') }} {{ $t('aitool.proxyHelper4') + ' ' }}
<el-link
class="pageRoute"
icon="Position"
@click="toWebsite(req.websiteID)"
type="primary"
>
{{ $t('firewall.quickJump') }}
</el-link>
</span>
<span class="input-help">
{{ $t('aitool.proxyHelper6') }}
</span> </span>
</el-form-item> </el-form-item>
<el-form-item :label="$t('firewall.address')" prop="ipList"> <el-form-item :label="$t('firewall.address')" prop="ipList">
@ -52,6 +63,7 @@
:placeholder="$t('website.selectAcme')" :placeholder="$t('website.selectAcme')"
@change="listSSL" @change="listSSL"
> >
<el-option :key="0" :label="$t('website.imported')" :value="0"></el-option>
<el-option <el-option
v-for="(acme, index) in acmeAccounts" v-for="(acme, index) in acmeAccounts"
:key="index" :key="index"
@ -190,8 +202,8 @@ const listAcmeAccount = () => {
acmeAccounts.value = res.data.items || []; acmeAccounts.value = res.data.items || [];
if (acmeAccounts.value.length > 0) { if (acmeAccounts.value.length > 0) {
req.value.acmeAccountID = acmeAccounts.value[0].id; req.value.acmeAccountID = acmeAccounts.value[0].id;
listSSL();
} }
listSSL();
}); });
}; };
@ -230,7 +242,22 @@ const search = async (appInstallID: number) => {
} catch (e) {} } catch (e) {}
}; };
const toWebsite = (websiteID: number) => {
if (websiteID != undefined && websiteID > 0) {
window.location.href = `/websites/${websiteID}/config/basic`;
} else {
window.location.href = '/websites';
}
};
defineExpose({ defineExpose({
acceptParams, acceptParams,
}); });
</script> </script>
<style lang="scss" scoped>
.pageRoute {
font-size: 12px;
margin-left: 5px;
}
</style>

View file

@ -33,6 +33,9 @@
<el-button :disabled="modelInfo.status !== 'Running'" type="primary" @click="onCreate()"> <el-button :disabled="modelInfo.status !== 'Running'" type="primary" @click="onCreate()">
{{ $t('ai_tools.model.create') }} {{ $t('ai_tools.model.create') }}
</el-button> </el-button>
<el-button plain type="primary" :disabled="modelInfo.status !== 'Running'" @click="bindDomain">
{{ $t('aitool.proxy') }}
</el-button>
<el-button :disabled="modelInfo.status !== 'Running'" @click="onLoadConn" type="primary" plain> <el-button :disabled="modelInfo.status !== 'Running'" @click="onLoadConn" type="primary" plain>
{{ $t('database.databaseConnInfo') }} {{ $t('database.databaseConnInfo') }}
</el-button> </el-button>
@ -48,9 +51,7 @@
> >
OpenWebUI OpenWebUI
</el-button> </el-button>
<el-button plain type="primary" :disabled="modelInfo.status !== 'Running'" @click="bindDomain">
{{ $t('aitool.proxy') }}
</el-button>
<el-button plain :disabled="selects.length === 0" type="primary" @click="onDelete(null)"> <el-button plain :disabled="selects.length === 0" type="primary" @click="onDelete(null)">
{{ $t('commons.button.delete') }} {{ $t('commons.button.delete') }}
</el-button> </el-button>

View file

@ -107,7 +107,10 @@
{{ $t('container.limitHelper', [limits.memory]) }} {{ paramModel.memoryUnit }}B {{ $t('container.limitHelper', [limits.memory]) }} {{ paramModel.memoryUnit }}B
</span> </span>
</el-form-item> </el-form-item>
<el-form-item pro="gpuConfig" v-if="gpuSupport">
<el-checkbox v-model="paramModel.gpuConfig" :label="$t('app.gpuConfig')" size="large" />
<span class="input-help">{{ $t('app.gpuConfigHelper') }}</span>
</el-form-item>
<el-form-item prop="editCompose"> <el-form-item prop="editCompose">
<el-checkbox v-model="paramModel.editCompose" :label="$t('app.editCompose')" size="large" /> <el-checkbox v-model="paramModel.editCompose" :label="$t('app.editCompose')" size="large" />
<span class="input-help">{{ $t('app.editComposeHelper') }}</span> <span class="input-help">{{ $t('app.editComposeHelper') }}</span>
@ -162,10 +165,12 @@ const extensions = [yaml(), oneDark];
interface ParamProps { interface ParamProps {
id: Number; id: Number;
app: any; app: any;
gpuSupport?: boolean;
} }
const paramData = ref<ParamProps>({ const paramData = ref<ParamProps>({
id: 0, id: 0,
app: {}, app: {},
gpuSupport: false,
}); });
interface EditForm extends App.InstallParams { interface EditForm extends App.InstallParams {
@ -190,6 +195,8 @@ const limits = ref<Container.ResourceLimit>({
cpu: null as number, cpu: null as number,
memory: null as number, memory: null as number,
}); });
const gpuSupport = ref(false);
const em = defineEmits(['close']);
const changeUnit = () => { const changeUnit = () => {
if (paramModel.value.memoryUnit == 'M') { if (paramModel.value.memoryUnit == 'M') {
@ -212,6 +219,7 @@ const acceptParams = async (props: ParamProps) => {
params.value = []; params.value = [];
paramData.value.id = props.id; paramData.value.id = props.id;
paramModel.value.params = {}; paramModel.value.params = {};
gpuSupport.value = props.gpuSupport;
edit.value = false; edit.value = false;
await get(); await get();
open.value = true; open.value = true;
@ -219,6 +227,7 @@ const acceptParams = async (props: ParamProps) => {
const handleClose = () => { const handleClose = () => {
open.value = false; open.value = false;
em('close', open);
}; };
const editParam = () => { const editParam = () => {
params.value.forEach((param: EditForm) => { params.value.forEach((param: EditForm) => {
@ -265,6 +274,7 @@ const get = async () => {
paramModel.value.advanced = false; paramModel.value.advanced = false;
paramModel.value.dockerCompose = res.data.dockerCompose; paramModel.value.dockerCompose = res.data.dockerCompose;
paramModel.value.isHostMode = res.data.hostMode; paramModel.value.isHostMode = res.data.hostMode;
paramModel.value.gpuConfig = res.data.gpuConfig;
} catch (error) { } catch (error) {
} finally { } finally {
loading.value = false; loading.value = false;
@ -303,6 +313,7 @@ const submit = async (formEl: FormInstance) => {
submitModel.value.editCompose = paramModel.value.editCompose; submitModel.value.editCompose = paramModel.value.editCompose;
submitModel.value.dockerCompose = paramModel.value.dockerCompose; submitModel.value.dockerCompose = paramModel.value.dockerCompose;
} }
submitModel.value.gpuConfig = paramModel.value.gpuConfig;
} }
try { try {
loading.value = true; loading.value = true;

View file

@ -302,7 +302,7 @@
<Uploads ref="uploadRef" /> <Uploads ref="uploadRef" />
<AppResources ref="checkRef" @close="search" /> <AppResources ref="checkRef" @close="search" />
<AppDelete ref="deleteRef" @close="search" /> <AppDelete ref="deleteRef" @close="search" />
<AppParams ref="appParamRef" /> <AppParams ref="appParamRef" @close="search" />
<AppUpgrade ref="upgradeRef" @close="search" /> <AppUpgrade ref="upgradeRef" @close="search" />
<PortJumpDialog ref="dialogPortJumpRef" /> <PortJumpDialog ref="dialogPortJumpRef" />
<AppIgnore ref="ignoreRef" @close="search" /> <AppIgnore ref="ignoreRef" @close="search" />
@ -605,7 +605,7 @@ const openUploads = (key: string, name: string) => {
}; };
const openParam = (row: any) => { const openParam = (row: any) => {
appParamRef.value.acceptParams({ id: row.id }); appParamRef.value.acceptParams({ id: row.id, gpuSupport: row.app.gpuSupport });
}; };
const isAppErr = (row: any) => { const isAppErr = (row: any) => {