Feature/dmxapi painting add model (#7851)

* 新增图片模型

* 新增图片生成模型

* 新增模型和调整提示语
This commit is contained in:
Caelan 2025-07-13 21:59:35 +08:00 committed by GitHub
parent e5956d4039
commit 53600175b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 135 additions and 46 deletions

View File

@ -1029,7 +1029,7 @@
"turbo": "Turbo"
},
"req_error_no_balance": "Please check the validity of the token",
"req_error_text": "Operation failed. Please try again. Avoid using 'copyrighted' or 'sensitive' words in your prompt.",
"req_error_text": "The server is busy or the prompt contains \"copyrighted\" or \"sensitive\" terms. Please try again.",
"req_error_token": "Please check the validity of the token",
"required_field": "Required field",
"seed": "Seed",

View File

@ -1029,7 +1029,7 @@
"turbo": "高速"
},
"req_error_no_balance": "トークンの有効性を確認してください",
"req_error_text": "実行に失敗しました。もう一度お試しください。プロンプトに「著作権用語」や「センシティブな用語」を含めないでください。",
"req_error_text": "サーバーが混雑しているか、プロンプトに「著作権用語」または「敏感な用語」が含まれています。もう一度お試しください。",
"req_error_token": "トークンの有効性を確認してください",
"required_field": "必須項目",
"seed": "シード",

View File

@ -1029,7 +1029,7 @@
"turbo": "Быстро"
},
"req_error_no_balance": "Пожалуйста, проверьте действительность токена",
"req_error_text": "Операция не удалась, повторите попытку. Пожалуйста, избегайте защищенных авторским правом терминов и конфиденциальных слов в запросах.",
"req_error_text": "Сервер перегружен или в запросе обнаружены «авторские» либо «чувствительные» слова. Пожалуйста, повторите попытку.",
"req_error_token": "Пожалуйста, проверьте действительность токена",
"required_field": "Обязательное поле",
"seed": "Ключ генерации",

View File

@ -1029,7 +1029,7 @@
"turbo": "快速"
},
"req_error_no_balance": "请检查令牌有效性",
"req_error_text": "运行失败,请重试。提示词避免 \"版权词\" 和 \"敏感词\" 哦。",
"req_error_text": "服务器繁忙或提示词出现 \"版权词\" 和 \"敏感词\" ,请重试。",
"req_error_token": "请检查令牌有效性",
"required_field": "必填项",
"seed": "随机种子",

View File

@ -1029,7 +1029,7 @@
"turbo": "快速"
},
"req_error_no_balance": "請檢查令牌的有效性",
"req_error_text": "运行失败,请重试。提示词避免 “版权词” 和” 敏感词” 哦。",
"req_error_text": "伺服器繁忙或提示詞中出現「版權詞」或「敏感詞」,請重試。",
"req_error_token": "請檢查令牌的有效性",
"required_field": "必填欄位",
"seed": "隨機種子",

View File

@ -1,8 +1,7 @@
import { PlusOutlined, RedoOutlined } from '@ant-design/icons'
import DMXAPIToImg from '@renderer/assets/images/providers/DMXAPI-to-img.webp'
import { Navbar, NavbarCenter, NavbarRight } from '@renderer/components/app/Navbar'
import { VStack } from '@renderer/components/Layout'
import { HStack } from '@renderer/components/Layout'
import { HStack, VStack } from '@renderer/components/Layout'
import Scrollbar from '@renderer/components/Scrollbar'
import { isMac } from '@renderer/config/constant'
import { getProviderLogo } from '@renderer/config/providers'
@ -19,8 +18,7 @@ import { DmxapiPainting } from '@types'
import { Avatar, Button, Input, Radio, Segmented, Select, Switch, Tooltip } from 'antd'
import TextArea from 'antd/es/input/TextArea'
import { Info } from 'lucide-react'
import React, { FC } from 'react'
import { useEffect, useRef, useState } from 'react'
import React, { FC, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
@ -32,14 +30,13 @@ import Artboard from './components/Artboard'
import ImageUploader from './components/ImageUploader'
import PaintingsList from './components/PaintingsList'
import {
ALL_MODELS,
COURSE_URL,
DEFAULT_PAINTING,
IMAGE_EDIT_MODELS,
IMAGE_MERGE_MODELS,
IMAGE_SIZES,
MODEL_GROUPS,
MODEOPTIONS,
STYLE_TYPE_OPTIONS,
TEXT_TO_IMAGES_MODELS
STYLE_TYPE_OPTIONS
} from './config/DmxapiConfig'
const generateRandomSeed = () => Math.floor(Math.random() * 1000000).toString()
@ -88,24 +85,15 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
const getModelOptions = (mode: generationModeType) => {
if (mode === generationModeType.EDIT) {
return IMAGE_EDIT_MODELS.map((model) => ({
label: model.name,
value: model.id
}))
return MODEL_GROUPS.IMAGE_EDIT
}
if (mode === generationModeType.MERGE) {
return IMAGE_MERGE_MODELS.map((model) => ({
label: model.name,
value: model.id
}))
return MODEL_GROUPS.IMAGE_MERGE
}
// 默认情况或其它模式下的选项
return TEXT_TO_IMAGES_MODELS.map((model) => ({
label: model.name,
value: model.id
}))
return MODEL_GROUPS.TEXT_TO_IMAGES
}
const [modelOptions, setModelOptions] = useState(() => {
@ -126,13 +114,22 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
const getNewPainting = (params?: Partial<DmxapiPainting>) => {
clearImages()
const generationMode = params?.generationMode || painting?.generationMode || MODEOPTIONS[0].value
const modelOptionsList = getModelOptions(generationMode as generationModeType)
const modelGroups = getModelOptions(generationMode as generationModeType)
// 获取第一个非空分组的第一个模型
let firstModel = ''
for (const provider of Object.keys(modelGroups)) {
if (modelGroups[provider].length > 0) {
firstModel = modelGroups[provider][0].id
break
}
}
return {
...DEFAULT_PAINTING,
id: uuid(),
seed: generateRandomSeed(),
generationMode,
model: modelOptionsList[0]?.value,
model: firstModel,
...params
}
}
@ -148,7 +145,7 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
}
const onSelectModel = (modelId: string) => {
const model = TEXT_TO_IMAGES_MODELS.find((m) => m.id === modelId)
const model = ALL_MODELS.find((m) => m.id === modelId)
if (model) {
updatePaintingState({ model: modelId })
}
@ -222,9 +219,17 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
const onGenerationModeChange = (v: generationModeType) => {
clearImages()
const newModelOptions = getModelOptions(v)
setModelOptions(newModelOptions)
const firstModel = newModelOptions[0]?.value
const newModelGroups = getModelOptions(v)
setModelOptions(newModelGroups)
// 获取第一个非空分组的第一个模型
let firstModel = ''
for (const provider of Object.keys(newModelGroups)) {
if (newModelGroups[provider].length > 0) {
firstModel = newModelGroups[provider][0].id
break
}
}
// 如果有urls创建新的painting
if (Array.isArray(painting.urls) && painting.urls.length > 0) {
@ -376,13 +381,25 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
const data = await response.json()
if (
painting.generationMode &&
[generationModeType.EDIT, generationModeType.MERGE].includes(painting.generationMode)
) {
return data.data.map((item: { b64_json: string }) => 'data:image/png;base64,' + item.b64_json)
}
return data.data.map((item: { url: string }) => item.url)
// if (
// painting.generationMode &&
// [generationModeType.EDIT, generationModeType.MERGE].includes(painting.generationMode)
// ) {
// return data.data.map((item: { b64_json: string }) => 'data:image/png;base64,' + item.b64_json)
// }
// return data.data.map((item: { url: string }) => item.url)
return data.data.map((item: { url: string; b64_json: string }) => {
if (item.b64_json) {
return 'data:image/png;base64,' + item.b64_json
}
if (item.url) {
return item.url
}
return ''
})
}
// 下载图像函数
@ -603,11 +620,11 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
return (
<LoadTextWrap>
<div>
OpenAI gpt-image-1
使
<br />
2~5
<br />
DMIAPI后台日志查看
DMXAPI后台日志查看
</div>
</LoadTextWrap>
)
@ -699,7 +716,20 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
)}
<SettingTitle style={{ marginBottom: 5, marginTop: 15 }}>{t('common.model')}</SettingTitle>
<Select value={painting.model} options={modelOptions} onChange={onSelectModel} />
<Select value={painting.model} onChange={onSelectModel} style={{ width: '100%' }}>
{Object.entries(modelOptions).map(([provider, models]) => {
if (models.length === 0) return null
return (
<Select.OptGroup label={provider} key={provider}>
{models.map((model) => (
<Select.Option key={model.id} value={model.id}>
{model.name}
</Select.Option>
))}
</Select.OptGroup>
)
})}
</Select>
{painting.generationMode === generationModeType.GENERATION && (
<>

View File

@ -42,27 +42,64 @@ export const STYLE_TYPE_OPTIONS = [
export const TEXT_TO_IMAGES_MODELS = [
{
id: 'seedream-3.0',
provider: 'DMXAPI',
provider: 'doubao',
name: ' 即梦 seedream-3.0'
},
{
id: 'flux-kontext-pro',
provider: 'Black Forest Labs',
name: 'flux-kontext-pro'
},
{
id: 'flux-kontext-max',
provider: 'Black Forest Labs',
name: 'flux-kontext-max'
},
{
id: 'imagen4',
provider: 'Google',
name: 'imagen4'
}
]
export const IMAGE_EDIT_MODELS = [
{
id: 'gpt-image-1',
provider: 'DMXAPI',
name: 'OpenAIgpt-image-1'
provider: 'OpenAI',
name: 'gpt-image-1'
},
{
id: 'flux-kontext-pro',
provider: 'Black Forest Labs',
name: 'flux-kontext-pro'
},
{
id: 'flux-kontext-max',
provider: 'Black Forest Labs',
name: 'flux-kontext-max'
}
]
export const IMAGE_MERGE_MODELS = [
{
id: 'gpt-image-1',
provider: 'DMXAPI',
name: 'OpenAIgpt-image-1'
provider: 'OpenAI',
name: 'gpt-image-1'
},
{
id: 'flux-kontext-pro',
provider: 'Black Forest Labs',
name: 'flux-kontext-pro'
},
{
id: 'flux-kontext-max',
provider: 'Black Forest Labs',
name: 'flux-kontext-max'
}
]
export const ALL_MODELS = [...TEXT_TO_IMAGES_MODELS, ...IMAGE_EDIT_MODELS, ...IMAGE_MERGE_MODELS]
export const IMAGE_SIZES = [
{
label: '1:1',
@ -118,3 +155,25 @@ export const MODEOPTIONS = [
{ label: '改图', value: generationModeType.EDIT },
{ label: '合并图', value: generationModeType.MERGE }
]
// 按品牌分组的模型配置
export const MODEL_GROUPS = {
TEXT_TO_IMAGES: {
Doubao: TEXT_TO_IMAGES_MODELS.filter((model) => model.provider === 'doubao'),
OpenAI: TEXT_TO_IMAGES_MODELS.filter((model) => model.provider === 'OpenAI'),
'Black Forest Labs': IMAGE_EDIT_MODELS.filter((model) => model.provider === 'Black Forest Labs'),
Google: TEXT_TO_IMAGES_MODELS.filter((model) => model.provider === 'Google')
},
IMAGE_EDIT: {
Doubao: IMAGE_EDIT_MODELS.filter((model) => model.provider === 'doubao'),
OpenAI: IMAGE_EDIT_MODELS.filter((model) => model.provider === 'OpenAI'),
'Black Forest Labs': IMAGE_EDIT_MODELS.filter((model) => model.provider === 'Black Forest Labs'),
Google: IMAGE_EDIT_MODELS.filter((model) => model.provider === 'Google')
},
IMAGE_MERGE: {
Doubao: IMAGE_MERGE_MODELS.filter((model) => model.provider === 'doubao'),
OpenAI: IMAGE_MERGE_MODELS.filter((model) => model.provider === 'OpenAI'),
'Black Forest Labs': IMAGE_MERGE_MODELS.filter((model) => model.provider === 'Black Forest Labs'),
Google: IMAGE_MERGE_MODELS.filter((model) => model.provider === 'Google')
}
}