Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feat: support gemini image output in chat #6956

Merged
merged 7 commits into from
Mar 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions locales/ar/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash يقدم ميزات وتحسينات من الجيل التالي، بما في ذلك سرعة فائقة، واستخدام أدوات أصلية، وتوليد متعدد الوسائط، ونافذة سياق تصل إلى 1M توكن."
},
"gemini-2.0-flash-exp": {
"description": "نموذج جمنيس 2.0 فلاش، تم تحسينه لتحقيق أهداف مثل الكفاءة من حيث التكلفة وانخفاض الكمون."
},
"gemini-2.0-flash-lite": {
"description": "نموذج جمنّي 2.0 فلاش هو نسخة معدلة، تم تحسينها لتحقيق الكفاءة من حيث التكلفة والحد من التأخير."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/bg-BG/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash предлага следващо поколение функции и подобрения, включително изключителна скорост, нативна употреба на инструменти, многомодално генериране и контекстен прозорец от 1M токена."
},
"gemini-2.0-flash-exp": {
"description": "Gemini 2.0 Flash моделна вариация, оптимизирана за икономичност и ниска латентност."
},
"gemini-2.0-flash-lite": {
"description": "Gemini 2.0 Flash е вариант на модела, оптимизиран за икономичност и ниска латентност."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/de-DE/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash bietet nächste Generation Funktionen und Verbesserungen, einschließlich außergewöhnlicher Geschwindigkeit, nativer Werkzeugnutzung, multimodaler Generierung und einem Kontextfenster von 1M Tokens."
},
"gemini-2.0-flash-exp": {
"description": "Gemini 2.0 Flash-Modellvariante, die auf Kosteneffizienz und niedrige Latenz optimiert ist."
},
"gemini-2.0-flash-lite": {
"description": "Gemini 2.0 Flash ist eine Modellvariante, die auf Kosteneffizienz und niedrige Latenz optimiert ist."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/en-US/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash offers next-generation features and improvements, including exceptional speed, native tool usage, multimodal generation, and a 1M token context window."
},
"gemini-2.0-flash-exp": {
"description": "Gemini 2.0 Flash model variant optimized for cost-effectiveness and low latency."
},
"gemini-2.0-flash-lite": {
"description": "Gemini 2.0 Flash is a variant of the model optimized for cost-effectiveness and low latency."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/es-ES/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash ofrece funciones y mejoras de próxima generación, incluyendo velocidad excepcional, uso de herramientas nativas, generación multimodal y una ventana de contexto de 1M tokens."
},
"gemini-2.0-flash-exp": {
"description": "Variante del modelo Gemini 2.0 Flash, optimizada para objetivos como la rentabilidad y la baja latencia."
},
"gemini-2.0-flash-lite": {
"description": "Variante del modelo Gemini 2.0 Flash, optimizada para objetivos como la rentabilidad y la baja latencia."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/fa-IR/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash ویژگی‌ها و بهبودهای نسل بعدی را ارائه می‌دهد، از جمله سرعت عالی، استفاده از ابزارهای بومی، تولید چندرسانه‌ای و پنجره متن 1M توکن."
},
"gemini-2.0-flash-exp": {
"description": "مدل متغیر Gemini 2.0 Flash که برای بهینه‌سازی هزینه و تأخیر کم طراحی شده است."
},
"gemini-2.0-flash-lite": {
"description": "مدل متغیر Gemini 2.0 Flash برای بهینه‌سازی هزینه و تأخیر کم طراحی شده است."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/fr-FR/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash propose des fonctionnalités et des améliorations de nouvelle génération, y compris une vitesse exceptionnelle, l'utilisation d'outils natifs, la génération multimodale et une fenêtre de contexte de 1M tokens."
},
"gemini-2.0-flash-exp": {
"description": "Modèle variant Gemini 2.0 Flash, optimisé pour des objectifs tels que le rapport coût-efficacité et la faible latence."
},
"gemini-2.0-flash-lite": {
"description": "Une variante du modèle Gemini 2.0 Flash, optimisée pour des objectifs tels que le rapport coût-efficacité et la faible latence."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/it-IT/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash offre funzionalità e miglioramenti di nuova generazione, tra cui velocità eccezionale, utilizzo di strumenti nativi, generazione multimodale e una finestra di contesto di 1M token."
},
"gemini-2.0-flash-exp": {
"description": "Gemini 2.0 Flash è una variante del modello ottimizzata per obiettivi come il rapporto costo-efficacia e la bassa latenza."
},
"gemini-2.0-flash-lite": {
"description": "Gemini 2.0 Flash è una variante del modello Flash, ottimizzata per obiettivi come il rapporto costo-efficacia e la bassa latenza."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/ja-JP/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flashは、卓越した速度、ネイティブツールの使用、マルチモーダル生成、1Mトークンのコンテキストウィンドウを含む次世代の機能と改善を提供します。"
},
"gemini-2.0-flash-exp": {
"description": "Gemini 2.0 Flash モデルのバリアントで、コスト効率と低遅延などの目標に最適化されています。"
},
"gemini-2.0-flash-lite": {
"description": "Gemini 2.0 Flashモデルのバリアントで、コスト効率と低遅延などの目標に最適化されています。"
},
Expand Down
3 changes: 3 additions & 0 deletions locales/ko-KR/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash는 뛰어난 속도, 원주율 도구 사용, 다중 모달 생성 및 1M 토큰 문맥 창을 포함한 차세대 기능과 개선 사항을 제공합니다."
},
"gemini-2.0-flash-exp": {
"description": "Gemini 2.0 Flash 모델 변형으로, 비용 효율성과 저지연 등의 목표를 위해 최적화되었습니다."
},
"gemini-2.0-flash-lite": {
"description": "Gemini 2.0 플래시 모델 변형으로, 비용 효율성과 낮은 지연 시간 등의 목표를 위해 최적화되었습니다."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/nl-NL/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash biedt next-gen functies en verbeteringen, waaronder uitstekende snelheid, native toolgebruik, multimodale generatie en een contextvenster van 1M tokens."
},
"gemini-2.0-flash-exp": {
"description": "Gemini 2.0 Flash modelvariant, geoptimaliseerd voor kosteneffectiviteit en lage latentie."
},
"gemini-2.0-flash-lite": {
"description": "Gemini 2.0 Flash is een modelvariant die is geoptimaliseerd voor kosteneffectiviteit en lage latentie."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/pl-PL/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash oferuje funkcje i ulepszenia nowej generacji, w tym doskonałą prędkość, natywne korzystanie z narzędzi, generowanie multimodalne oraz okno kontekstowe o długości 1M tokenów."
},
"gemini-2.0-flash-exp": {
"description": "Gemini 2.0 Flash to wariant modelu, zoptymalizowany pod kątem efektywności kosztowej i niskiego opóźnienia."
},
"gemini-2.0-flash-lite": {
"description": "Gemini 2.0 Flash to wariant modelu, zoptymalizowany pod kątem efektywności kosztowej i niskiego opóźnienia."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/pt-BR/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash oferece funcionalidades e melhorias de próxima geração, incluindo velocidade excepcional, uso nativo de ferramentas, geração multimodal e uma janela de contexto de 1M tokens."
},
"gemini-2.0-flash-exp": {
"description": "Variante do modelo Gemini 2.0 Flash, otimizada para custo-benefício e baixa latência."
},
"gemini-2.0-flash-lite": {
"description": "Variante do modelo Gemini 2.0 Flash, otimizada para custo-benefício e baixa latência."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/ru-RU/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash предлагает функции следующего поколения и улучшения, включая выдающуюся скорость, использование встроенных инструментов, многомодальную генерацию и контекстное окно на 1M токенов."
},
"gemini-2.0-flash-exp": {
"description": "Модельный вариант Gemini 2.0 Flash, оптимизированный для достижения таких целей, как экономическая эффективность и низкая задержка."
},
"gemini-2.0-flash-lite": {
"description": "Модельный вариант Gemini 2.0 Flash, оптимизированный для достижения таких целей, как экономическая эффективность и низкая задержка."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/tr-TR/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash, mükemmel hız, yerel araç kullanımı, çok modlu üretim ve 1M token bağlam penceresi dahil olmak üzere bir sonraki nesil özellikler ve iyileştirmeler sunar."
},
"gemini-2.0-flash-exp": {
"description": "Gemini 2.0 Flash modeli varyantı, maliyet etkinliği ve düşük gecikme gibi hedefler için optimize edilmiştir."
},
"gemini-2.0-flash-lite": {
"description": "Gemini 2.0 Flash model varyantı, maliyet etkinliği ve düşük gecikme gibi hedefler için optimize edilmiştir."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/vi-VN/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash cung cấp các tính năng và cải tiến thế hệ tiếp theo, bao gồm tốc độ vượt trội, sử dụng công cụ bản địa, tạo đa phương tiện và cửa sổ ngữ cảnh 1M token."
},
"gemini-2.0-flash-exp": {
"description": "Biến thể mô hình Gemini 2.0 Flash, được tối ưu hóa cho hiệu quả chi phí và độ trễ thấp."
},
"gemini-2.0-flash-lite": {
"description": "Biến thể mô hình Gemini 2.0 Flash được tối ưu hóa cho hiệu quả chi phí và độ trễ thấp."
},
Expand Down
3 changes: 3 additions & 0 deletions locales/zh-CN/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash 提供下一代功能和改进,包括卓越的速度、原生工具使用、多模态生成和1M令牌上下文窗口。"
},
"gemini-2.0-flash-exp": {
"description": "Gemini 2.0 Flash 模型变体,针对成本效益和低延迟等目标进行了优化。"
},
"gemini-2.0-flash-lite": {
"description": "Gemini 2.0 Flash 模型变体,针对成本效益和低延迟等目标进行了优化。"
},
Expand Down
3 changes: 3 additions & 0 deletions locales/zh-TW/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,9 @@
"gemini-2.0-flash-001": {
"description": "Gemini 2.0 Flash 提供下一代功能和改進,包括卓越的速度、原生工具使用、多模態生成和1M令牌上下文窗口。"
},
"gemini-2.0-flash-exp": {
"description": "Gemini 2.0 Flash 模型變體,針對成本效益和低延遲等目標進行了優化。"
},
"gemini-2.0-flash-lite": {
"description": "Gemini 2.0 Flash 模型變體,針對成本效益和低延遲等目標進行了優化。"
},
Expand Down
17 changes: 17 additions & 0 deletions src/config/aiModels/google.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@ const googleChatModels: AIChatModelCard[] = [
releasedAt: '2025-02-05',
type: 'chat',
},
{
abilities: {
vision: true,
},
contextWindowTokens: 32_768,
description: 'Gemini 2.0 Flash 模型变体,针对成本效益和低延迟等目标进行了优化。',
displayName: 'Gemini 2.0 Flash Exp',
enabled: true,
id: 'gemini-2.0-flash-exp',
maxOutput: 8192,
pricing: {
input: 0,
output: 0,
},
releasedAt: '2025-02-05',
type: 'chat',
},
{
abilities: {
vision: true,
Expand Down
29 changes: 20 additions & 9 deletions src/database/server/models/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
CreateMessageParams,
MessageItem,
ModelRankItem,
UpdateMessageParams,
} from '@/types/message';
import { merge } from '@/utils/merge';
import { today } from '@/utils/time';
Expand Down Expand Up @@ -497,15 +498,25 @@ export class MessageModel {
};
// **************** Update *************** //

update = async (id: string, message: Partial<MessageItem>) => {
return this.db
.update(messages)
.set({
...message,
// TODO: need a better way to handle this
role: message.role as any,
})
.where(and(eq(messages.id, id), eq(messages.userId, this.userId)));
update = async (id: string, { imageList, ...message }: Partial<UpdateMessageParams>) => {
return this.db.transaction(async (trx) => {
// 1. insert message files
if (imageList && imageList.length > 0) {
await trx
.insert(messagesFiles)
.values(imageList.map((file) => ({ fileId: file.id, messageId: id })));
}

return trx
.update(messages)
.set({
...message,
// TODO: need a better way to handle this
// TODO: but I forget why 🤡
role: message.role as any,
})
.where(and(eq(messages.id, id), eq(messages.userId, this.userId)));
});
};

updatePluginState = async (id: string, state: Record<string, any>) => {
Expand Down
2 changes: 1 addition & 1 deletion src/features/AlertBanner/CloudBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const CloudBanner = memo<{ mobile?: boolean }>(({ mobile }) => {
<b>{t('alert.cloud.title', { name: LOBE_CHAT_CLOUD })}:</b>
<span>
{t(mobile ? 'alert.cloud.descOnMobile' : 'alert.cloud.desc', {
credit: new Intl.NumberFormat('en-US').format(450_000),
credit: new Intl.NumberFormat('en-US').format(500_000),
name: LOBE_CHAT_CLOUD,
})}
</span>
Expand Down
5 changes: 4 additions & 1 deletion src/features/Conversation/Messages/Assistant/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ReactNode, memo } from 'react';
import { Flexbox } from 'react-layout-kit';

import { LOADING_FLAT } from '@/const/message';
import ImageFileListViewer from '@/features/Conversation/Messages/User/ImageFileListViewer';
import { useChatStore } from '@/store/chat';
import { aiChatSelectors, chatSelectors } from '@/store/chat/selectors';
import { ChatMessage } from '@/types/message';
Expand All @@ -17,7 +18,7 @@ export const AssistantMessage = memo<
ChatMessage & {
editableContent: ReactNode;
}
>(({ id, tools, content, chunksList, search, ...props }) => {
>(({ id, tools, content, chunksList, search, imageList, ...props }) => {
const editing = useChatStore(chatSelectors.isMessageEditing(id));
const generating = useChatStore(chatSelectors.isMessageGenerating(id));

Expand All @@ -28,6 +29,7 @@ export const AssistantMessage = memo<
const isIntentUnderstanding = useChatStore(aiChatSelectors.isIntentUnderstanding(id));

const showSearch = !!search && !!search.citations?.length;
const showImageItems = !!imageList && imageList.length > 0;

// remove \n to avoid empty content
// refs: https://github.com/lobehub/lobe-chat/pull/6153
Expand Down Expand Up @@ -64,6 +66,7 @@ export const AssistantMessage = memo<
/>
)
)}
{showImageItems && <ImageFileListViewer items={imageList} />}
{tools && (
<Flexbox gap={8}>
{tools.map((toolCall, index) => (
Expand Down
8 changes: 4 additions & 4 deletions src/features/Conversation/Messages/User/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ export const UserMessage = memo<
ChatMessage & {
editableContent: ReactNode;
}
>(({ id, editableContent, content, ...res }) => {
>(({ id, editableContent, content, imageList, fileList }) => {
if (content === LOADING_FLAT) return <BubblesLoading />;

return (
<Flexbox gap={8} id={id}>
{editableContent}
{res.imageList && res.imageList?.length > 0 && <ImageFileListViewer items={res.imageList} />}
{res.fileList && res.fileList?.length > 0 && (
{imageList && imageList?.length > 0 && <ImageFileListViewer items={imageList} />}
{fileList && fileList?.length > 0 && (
<div style={{ marginTop: 8 }}>
<FileListViewer items={res.fileList} />
<FileListViewer items={fileList} />
</div>
)}
</Flexbox>
Expand Down
10 changes: 8 additions & 2 deletions src/libs/agent-runtime/google/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ import { StreamingResponse } from '../utils/response';
import { GoogleGenerativeAIStream, convertIterableToStream } from '../utils/streams';
import { parseDataUri } from '../utils/uriParser';

const modelsOffSafetySettings = new Set(['gemini-2.0-flash-exp']);
const modelsWithModalities = new Set(['gemini-2.0-flash-exp']);

export interface GoogleModelCard {
displayName: string;
inputTokenLimit: number;
Expand All @@ -50,8 +53,7 @@ enum HarmBlockThreshold {
}

function getThreshold(model: string): HarmBlockThreshold {
const useOFF = ['gemini-2.0-flash-exp'];
if (useOFF.includes(model)) {
if (modelsOffSafetySettings.has(model)) {
return 'OFF' as HarmBlockThreshold; // https://discuss.ai.google.dev/t/59352
}
return HarmBlockThreshold.BLOCK_NONE;
Expand Down Expand Up @@ -94,6 +96,10 @@ export class LobeGoogleAI implements LobeRuntimeAI {
{
generationConfig: {
maxOutputTokens: payload.max_tokens,
// @ts-expect-error - Google SDK 0.24.0 doesn't have this property for now with
response_modalities: modelsWithModalities.has(model)
? ['Text', 'Image']
: undefined,
temperature: payload.temperature,
topP: payload.top_p,
},
Expand Down
Loading