feat: 支持 huanke-gemini 图片生成 provider
- 将 huanke-gemini 加入 Gemini 图片生成处理流程 - 禁用 Base64 图片传输,统一使用 URL 格式 - gemini-image 和 huanke-gemini 内部会自行处理图片上传到 S3 - 添加 huanke-gemini 模型调试日志
This commit is contained in:
parent
4267ac42bf
commit
e631cc45f3
@ -2553,9 +2553,9 @@ export function AdminSettingsClient() {
|
||||
</div>
|
||||
{siteSettings.bannerEnabled && (
|
||||
<>
|
||||
<div className="space-y-2">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="bannerText">横幅文字</Label>
|
||||
<Input
|
||||
<Input
|
||||
id="bannerText"
|
||||
value={siteSettings.bannerText}
|
||||
onChange={(e) => setSiteSettings({ ...siteSettings, bannerText: e.target.value })}
|
||||
@ -2963,11 +2963,11 @@ export function AdminSettingsClient() {
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<div className="space-y-2">
|
||||
<Label>视频链接 *</Label>
|
||||
<Input
|
||||
<Input
|
||||
value={tutorialVideoForm.videoUrl}
|
||||
onChange={(e) => setTutorialVideoForm({ ...tutorialVideoForm, videoUrl: e.target.value })}
|
||||
placeholder="视频URL(上传后自动填充或手动输入)"
|
||||
@ -3020,7 +3020,7 @@ export function AdminSettingsClient() {
|
||||
</Button>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label>视频描述</Label>
|
||||
@ -3067,7 +3067,7 @@ export function AdminSettingsClient() {
|
||||
<Button variant="outline" onClick={() => setShowTutorialVideoDialog(false)}>取消</Button>
|
||||
<Button onClick={handleSaveTutorialVideo} disabled={!tutorialVideoForm.title || !tutorialVideoForm.videoUrl}>
|
||||
保存
|
||||
</Button>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
@ -3130,8 +3130,8 @@ export function AdminSettingsClient() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* 导航链接列表 */}
|
||||
|
||||
@ -105,11 +105,14 @@ function hasAnnotatedImage(messages: ChatMessage[]): boolean {
|
||||
const ANNOTATION_SYSTEM_PROMPT = "【重要】用户提供的图片上有标注线条(如箭头、圆圈、画笔痕迹或文字说明),这些标注是用户用来指示需要修改的区域或方向。请仔细理解标注的含义,按照标注指示进行编辑,但在生成的新图片中不要保留这些标注线条,输出干净的编辑结果。";
|
||||
|
||||
/**
|
||||
* 自定义消息转换函数,支持将图片 URL 转换为 base64(仅用于 Gemini)
|
||||
* 自定义消息转换函数
|
||||
* 注意:gemini-image 和 huanke-gemini 都需要 URL 格式(不是 Base64)
|
||||
* 因为这些 provider 内部会自行处理图片上传到 S3
|
||||
*/
|
||||
async function convertMessagesWithImages(messages: ChatMessage[], providerType: string) {
|
||||
// 千问视频需要真实的 HTTP URL,不能用 base64
|
||||
// 只有 Gemini 需要 base64
|
||||
// 所有 provider 都使用 URL 格式传输图片
|
||||
// gemini-image 和 huanke-gemini 内部会将 Base64 转换为 S3 URL
|
||||
// 这里不再进行 Base64 转换,直接返回标准格式
|
||||
if (providerType !== "gemini") {
|
||||
return convertToModelMessages(messages);
|
||||
}
|
||||
@ -146,26 +149,15 @@ async function convertMessagesWithImages(messages: ChatMessage[], providerType:
|
||||
text: textContent,
|
||||
});
|
||||
} else if (part.type === "file" && part.url) {
|
||||
// 将图片 URL 转换为 base64
|
||||
try {
|
||||
const base64Data = await convertImageUrlToBase64(part.url);
|
||||
content.push({
|
||||
type: "image_url",
|
||||
image_url: {
|
||||
url: base64Data,
|
||||
},
|
||||
});
|
||||
console.log("[Message Convert] Image converted to base64 and formatted as image_url");
|
||||
} catch (error) {
|
||||
console.error("[Message Convert] Failed to convert image, using URL:", error);
|
||||
// 失败时仍然尝试使用 URL
|
||||
content.push({
|
||||
type: "image_url",
|
||||
image_url: {
|
||||
url: part.url,
|
||||
},
|
||||
});
|
||||
}
|
||||
// 直接使用 URL 格式(不再转换为 Base64)
|
||||
// gemini-image 和 huanke-gemini provider 内部会处理图片上传
|
||||
content.push({
|
||||
type: "image_url",
|
||||
image_url: {
|
||||
url: part.url,
|
||||
},
|
||||
});
|
||||
console.log("[Message Convert] Image kept as URL format:", part.url.substring(0, 80) + "...");
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,8 +736,10 @@ export async function POST(request: Request) {
|
||||
}
|
||||
|
||||
// ========== Gemini 图片生成独立处理 ==========
|
||||
if ((languageModel as any).provider === "gemini-image" && typeof (languageModel as any).doGenerate === "function") {
|
||||
console.log("[Chat API] Using Gemini image generation");
|
||||
// 支持 gemini-image 和 huanke-gemini 两种图片生成 provider
|
||||
const isGeminiImageProvider = ["gemini-image", "huanke-gemini"].includes((languageModel as any).provider);
|
||||
if (isGeminiImageProvider && typeof (languageModel as any).doGenerate === "function") {
|
||||
console.log("[Chat API] Using Gemini image generation, provider:", (languageModel as any).provider);
|
||||
console.log("[Chat API] Image params:", requestBody.imageParams);
|
||||
|
||||
// 🆕 获取备用模型配置
|
||||
@ -767,8 +761,10 @@ export async function POST(request: Request) {
|
||||
const messagesForGemini = lastUserMessage ? [lastUserMessage] : uiMessages;
|
||||
console.log("[Chat API] Gemini: Using only last user message (no history context)");
|
||||
|
||||
// 转换消息,Gemini 需要 base64 格式的图片
|
||||
const modelMessages = await convertMessagesWithImages(messagesForGemini, "gemini");
|
||||
// 转换消息:gemini-image 需要 base64 格式,huanke-gemini 需要 URL 格式
|
||||
const providerForConvert = (languageModel as any).provider === "huanke-gemini" ? "huanke-gemini" : "gemini";
|
||||
const modelMessages = await convertMessagesWithImages(messagesForGemini, providerForConvert);
|
||||
console.log("[Chat API] Message conversion provider:", providerForConvert);
|
||||
|
||||
// 调用 doGenerate 获取图片(如果是备用模型,传入 overrideModelId)
|
||||
const result = await (languageModel as any).doGenerate({
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user