UNPKG

@lobehub/chat

Version:

Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.

140 lines (116 loc) 4.08 kB
import { imageUrlToBase64 } from '@lobechat/utils'; import createDebug from 'debug'; import { RuntimeImageGenParamsValue } from 'model-bank'; import { CreateImageOptions } from '../../core/openaiCompatibleFactory'; import { CreateImagePayload, CreateImageResponse } from '../../types'; import { AgentRuntimeErrorType } from '../../types/error'; import { AgentRuntimeError } from '../../utils/createError'; import { parseDataUri } from '../../utils/uriParser'; const log = createDebug('lobe-image:siliconcloud'); interface SiliconCloudImageResponse { images: { url: string }[]; seed: number; timings: { inference: number }; } async function convertToDataURI(imageUrl: string): Promise<string> { const { type, base64, mimeType } = parseDataUri(imageUrl); if (type === 'base64') { if (!base64) { throw new TypeError("Image URL doesn't contain base64 data"); } return `data:${mimeType || 'image/png'};base64,${base64}`; } if (type === 'url') { const { base64: urlBase64, mimeType: urlMimeType } = await imageUrlToBase64(imageUrl); return `data:${urlMimeType};base64,${urlBase64}`; } throw new TypeError(`Unsupported image url: ${imageUrl}`); } export async function createSiliconCloudImage( payload: CreateImagePayload, options: CreateImageOptions, ): Promise<CreateImageResponse> { const { model, params } = payload; const { apiKey, baseURL, provider } = options; log('Creating image with SiliconCloud model: %s, params: %O', model, params); const endpoint = `${baseURL}/images/generations`; const paramsMap = new Map<RuntimeImageGenParamsValue, string>([ ['negativePrompt', 'negative_prompt'], ['size', 'image_size'], ['n', 'batch_size'], ['steps', 'num_inference_steps'], ]); const body: Record<string, any> = { model, prompt: params.prompt, }; for (const [p, value] of Object.entries(params)) { const key = p as RuntimeImageGenParamsValue; if (value === undefined || value === null) continue; if (key === 'cfg') { if (model.toLowerCase().includes('kolors')) { body['guidance_scale'] = value; } else { body['cfg'] = value; } continue; } if (key === 'imageUrl') { if (typeof value === 'string') { body['image'] = await convertToDataURI(value); } continue; } if (key === 'imageUrls') { if (Array.isArray(value) && value.length > 0) { body['image'] = await convertToDataURI(value[0]); if (model === 'Qwen/Qwen-Image-Edit-2509') { if (value.length > 1) body['image2'] = await convertToDataURI(value[1]); if (value.length > 2) body['image3'] = await convertToDataURI(value[2]); } } continue; } const mappedKey = paramsMap.get(key) || p; body[mappedKey] = value; } log('Request body: %O', body); const response = await fetch(endpoint, { body: JSON.stringify(body), headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json', }, method: 'POST', }); if (!response.ok) { const errorData = await response.json().catch(() => null); log('Error response from SiliconCloud API: %O', { errorData, status: response.status, statusText: response.statusText, }); throw AgentRuntimeError.createImage({ error: { ...errorData, status: response.status, statusText: response.statusText, }, errorType: AgentRuntimeErrorType.ProviderBizError, provider, }); } const data: SiliconCloudImageResponse = await response.json(); log('SiliconCloud API response: %O', data); if (!data.images || data.images.length === 0 || !data.images[0].url) { log('Invalid response from SiliconCloud API: no images generated. Response data: %O', data); throw AgentRuntimeError.createImage({ error: { data, message: 'No images generated' }, errorType: AgentRuntimeErrorType.ProviderBizError, provider, }); } return { imageUrl: data.images[0].url, }; }