這個 Angular 應用程式展示了如何使用 Firebase AI Logic 處理圖片轉文字(Image-to-text)與文字轉語音(Text-to-speech)任務。
為了實踐單一職責原則(Single Responsibility Principle),VisionService 封裝了圖片轉文字任務,而 TextToSpeechService 則封裝了文字轉語音任務。
在這篇部落格文章中,我們將展示如何使用 Firebase AI Logic 與 Gemini 模型從圖片中生成替代文字、標籤以及建議。接著,該服務會使用 Google Search 工具以及生成的標籤,來找出帶有引用來源的冷門知識。
假設 firebase 相依套件已安裝至專案中
#aiModel = inject(VISION_AI_MODEL);
我們注入 VISION_AI_MODEL 注入權杖來存取生成式模型(Generative Model)。
接著,該服務即可使用該模型為上傳的圖片生成文字回應。
const MIN_SPLIT_PARTS = 2;
const DATA_PART_INDEX = 1;
function getDataPart(fileReaderResult: string) {
const splittedResults = fileReaderResult.split(',');
if (splittedResults.length >= MIN_SPLIT_PARTS) {
return splittedResults[DATA_PART_INDEX];
}
throw new Error('FileReader result is not in expected format');
}
function handleReaderLoadEnd(reader: FileReader, resolve: (value: string) => void, reject: (reason: unknown) => void) {
const fileReaderResult = reader.result;
return resolve(getDataPart(fileReaderResult));
}
export async function fileToGenerativePart(file: File) {
const base64EncodedDataPromise = new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => handleReaderLoadEnd(reader, resolve, reject);
reader.onerror = reject;
reader.readAsDataURL(file);
});
return {
inlineData: { data: await base64EncodedDataPromise, mimeType: file.type },
};
}
fileToGenerativePart 函式接受一張圖片,讀取其二進位資料,並回傳 base64 行內資料。
interface ImageAnalysis {
alternativeText: string;
tags: string[];
recommendations: Recommendation[];
fact: string;
}
async generateAltText(image: File) {
const imagePart = await fileToGenerativePart(image);
const altTextPrompt = `
You are asked to perform four tasks:
Task 1: Generate 1 - 3 sentences of alternative texts for the image provided, max 300 words.
Task 2: Generate at least 3 tags to describe the image.
Task 3: Based on the alternative text and tags, provide some suggestions to make the image more interesting and the reason to support them.
Task 4: Search for a surprising or obscure fact that interconnects the following tags. If a direct link doesn't exist, find a conceptual link between them.
`;
const result = await this.#aiModel.generateContent([altTextPrompt, imagePart]);
if (result?.response) {
const response = result.response;
const text = response.text().replace(/```json\n?|```/g, '');
const parsed: ImageAnalysis = JSON.parse(text);
const citations = this.constructCitations(response.candidates?.[0]?.groundingMetadata);
return {
parsed,
citations,
};
}
throw Error('No text generated.');
}
generateAltText 方法包含一段提示詞,要求 Gemini 為上傳的圖片生成替代文字、建議和標籤。生成式模型被賦予了 GoogleSearch 工具,因此它可以使用該工具來尋找與標籤相關的冷門文字資訊。
文字回應會被轉型為 ImageAnalysis 並回傳給展示型元件(Presentational Component)。
citations 物件會回傳用於尋找該冷門知識的來源。
private constructCitations(groundingMetadata?: GroundingMetadata) {
const supports = groundingMetadata.groundingSupports || [];
const chunks = groundingMetadata.groundingChunks || [];
const citations = supports.flatMap((support) =>
(support.groundingChunkIndices || [])
.map((idx) => chunks[idx]?.web)
.filter((web): web is WebGroundingChunk => !!web),
);
const renderedContent = groundingMetadata.searchEntryPoint?.renderedContent || '';
const searchQueries = (groundingMetadata.webSearchQueries || []).filter((query) => !!query);
return {
citations,
renderedContent,
searchQueries,
};
}
Google 搜尋引擎使用 searchQueries 清單來尋找冷門知識。renderedContent 是一組 HTML/CSS 搜尋建議。當使用者點擊結果元素時,搜尋結果會在獨立的網頁中呈現。citations 會回傳來自網路的 Grounding 區塊(Grounding chunks)清單。
我們可以使用這些數值來驗證協助生成冷門知識的資料。
今天就到這裡。明天我們將使用 Firebase AI Logic 與 Gemini TTS 模型來定義 TextToSpeech 服務。Firebase 團隊在今年 8 月支援了這項新功能。
Firebase AI Logic 官方文件
Firebase Remote Config 官方文件
Firebase App Check 官方文件
在網頁應用程式中使用帶有偵錯提供者的 App Check