@@ -93,7 +93,7 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
|
||||
const getNewPainting = useCallback(() => {
|
||||
return {
|
||||
...DEFAULT_PAINTING,
|
||||
model: mode === 'aihubmix_image_generate' ? 'gpt-image-1' : 'V_3',
|
||||
model: mode === 'aihubmix_image_generate' ? 'gemini-3-pro-image-preview' : 'V_3',
|
||||
id: uuid()
|
||||
}
|
||||
}, [mode])
|
||||
@@ -201,6 +201,74 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
|
||||
updatePaintingState({ files: validFiles, urls: validFiles.map((file) => file.name) })
|
||||
}
|
||||
return
|
||||
} else if (painting.model === 'gemini-3-pro-image-preview') {
|
||||
const geminiUrl = `${aihubmixProvider.apiHost}/gemini/v1beta/models/gemini-3-pro-image-preview:streamGenerateContent`
|
||||
const geminiHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
'x-goog-api-key': aihubmixProvider.apiKey
|
||||
}
|
||||
|
||||
const requestBody = {
|
||||
contents: [
|
||||
{
|
||||
parts: [
|
||||
{
|
||||
text: prompt
|
||||
}
|
||||
],
|
||||
role: 'user'
|
||||
}
|
||||
],
|
||||
generationConfig: {
|
||||
responseModalities: ['TEXT', 'IMAGE'],
|
||||
imageConfig: {
|
||||
aspectRatio: painting.aspectRatio?.replace('ASPECT_', '').replace('_', ':') || '1:1',
|
||||
imageSize: painting.imageSize || '1k'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.silly(`Gemini Request: ${JSON.stringify(requestBody)}`)
|
||||
|
||||
const response = await fetch(geminiUrl, {
|
||||
method: 'POST',
|
||||
headers: geminiHeaders,
|
||||
body: JSON.stringify(requestBody)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json()
|
||||
logger.error('Gemini API Error:', errorData)
|
||||
throw new Error(errorData.error?.message || '生成图像失败')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
logger.silly(`Gemini API Response: ${JSON.stringify(data)}`)
|
||||
|
||||
// Handle array response (stream) or single object
|
||||
const responseItems = Array.isArray(data) ? data : [data]
|
||||
const base64s: string[] = []
|
||||
|
||||
responseItems.forEach((item) => {
|
||||
item.candidates?.forEach((candidate: any) => {
|
||||
candidate.content?.parts?.forEach((part: any) => {
|
||||
if (part.inlineData?.data) {
|
||||
base64s.push(part.inlineData.data)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
if (base64s.length > 0) {
|
||||
const validFiles = await Promise.all(
|
||||
base64s.map(async (base64: string) => {
|
||||
return await window.api.file.saveBase64Image(base64)
|
||||
})
|
||||
)
|
||||
await FileManager.addFiles(validFiles)
|
||||
updatePaintingState({ files: validFiles, urls: validFiles.map((file) => file.name) })
|
||||
}
|
||||
return
|
||||
} else if (painting.model === 'V_3') {
|
||||
// V3 API uses different endpoint and parameters format
|
||||
const formData = new FormData()
|
||||
|
||||
@@ -72,6 +72,7 @@ export const createModeConfigs = (): Record<AihubmixMode, ConfigItem[]> => {
|
||||
label: 'Gemini',
|
||||
title: 'Gemini',
|
||||
options: [
|
||||
{ label: 'Nano Banana Pro', value: 'gemini-3-pro-image-preview' },
|
||||
{ label: 'imagen-4.0-preview', value: 'imagen-4.0-generate-preview-06-06' },
|
||||
{ label: 'imagen-4.0-ultra', value: 'imagen-4.0-ultra-generate-preview-06-06' }
|
||||
]
|
||||
@@ -224,7 +225,20 @@ export const createModeConfigs = (): Record<AihubmixMode, ConfigItem[]> => {
|
||||
{ label: '16:9', value: 'ASPECT_16_9' }
|
||||
],
|
||||
initialValue: 'ASPECT_1_1',
|
||||
condition: (painting) => Boolean(painting.model?.startsWith('imagen-'))
|
||||
condition: (painting) =>
|
||||
Boolean(painting.model?.startsWith('imagen-') || painting.model === 'gemini-3-pro-image-preview')
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
key: 'imageSize',
|
||||
title: 'paintings.image.size',
|
||||
options: [
|
||||
{ label: '1K', value: '1K' },
|
||||
{ label: '2K', value: '2K' },
|
||||
{ label: '4K', value: '4K' }
|
||||
],
|
||||
initialValue: '1K',
|
||||
condition: (painting) => painting.model === 'gemini-3-pro-image-preview'
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
@@ -398,7 +412,7 @@ export const createModeConfigs = (): Record<AihubmixMode, ConfigItem[]> => {
|
||||
// 几种默认的绘画配置
|
||||
export const DEFAULT_PAINTING: PaintingAction = {
|
||||
id: 'aihubmix_1',
|
||||
model: 'gpt-image-1',
|
||||
model: 'gemini-3-pro-image-preview',
|
||||
aspectRatio: 'ASPECT_1_1',
|
||||
numImages: 1,
|
||||
styleType: 'AUTO',
|
||||
@@ -420,5 +434,6 @@ export const DEFAULT_PAINTING: PaintingAction = {
|
||||
moderation: 'auto',
|
||||
n: 1,
|
||||
numberOfImages: 4,
|
||||
safetyTolerance: 6
|
||||
safetyTolerance: 6,
|
||||
imageSize: '1K'
|
||||
}
|
||||
|
||||
@@ -320,6 +320,7 @@ export interface GeneratePainting extends PaintingParams {
|
||||
safetyTolerance?: number
|
||||
width?: number
|
||||
height?: number
|
||||
imageSize?: string
|
||||
}
|
||||
|
||||
export interface EditPainting extends PaintingParams {
|
||||
|
||||
Reference in New Issue
Block a user