Skip to content

Commit

Permalink
Merge pull request #11 from nozomi-koborinai/feature/web-browsing
Browse files Browse the repository at this point in the history
Feature/web browsing
  • Loading branch information
nozomi-koborinai authored Oct 17, 2024
2 parents 30a860f + 7cba59a commit dfb2b8f
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 36 deletions.
15 changes: 15 additions & 0 deletions functions/prompts/analyze.prompt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
model: googleai/gemini-1.5-flash-latest
config:
temperature: 1.0
input:
schema:
storageFileUrl: string
output:
format: json
schema:
analysis: string
---

この画像の内容を詳しく説明し、その主要な特徴を要約してください。
{{media url=storageFileUrl}}
13 changes: 13 additions & 0 deletions functions/prompts/generateImage.prompt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
model: vertexai/imagen3
config:
temperature: 0.7
input:
schema:
prompt: string
output:
format: media
---

あなたは世界一のイラストレーターです。
{{prompt}} の画像を生成してください。
27 changes: 27 additions & 0 deletions functions/src/genkit-functions/analyzeStorageImage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { prompt } from '@genkit-ai/dotprompt'
import * as genkitFunctions from '@genkit-ai/firebase/functions'
import * as z from 'zod'
import { analyzeStorageInputSchema } from '../schemas/analyzeStorageInputSchema'
import { analyzeStorageOutputSchema } from '../schemas/analyzeStorageOutputSchema'
import { isGenkitEnabled } from '../utils/genkitUtils'

// Cloud Storage からファイルを読み込み、Gemini Flash 1.5 で要約する関数
export const analyzeStorageImage = genkitFunctions.onFlow(
{
name: `analyzeStorageImage`,
httpsOptions: {
cors: true,
},
inputSchema: analyzeStorageInputSchema,
outputSchema: analyzeStorageOutputSchema,
authPolicy: genkitFunctions.noAuth(),
},
async (input) => {
if (!(await isGenkitEnabled())) throw new Error(`Genkit が無効になっています。`)

const analyzeFilePrompt = await prompt<z.infer<typeof analyzeStorageInputSchema>>(`analyze`)
const result = await analyzeFilePrompt.generate({ input })

return result.output()
}
)
32 changes: 32 additions & 0 deletions functions/src/genkit-functions/analyzeWebContents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { generate } from '@genkit-ai/ai'
import * as genkitFunctions from '@genkit-ai/firebase/functions'
import { gemini15Flash } from '@genkit-ai/googleai'
import * as config from '../config/firebase'
import { analyzeWebInputSchema } from '../schemas/analyzeWebInputSchema'
import { analyzeWebOutputSchema } from '../schemas/analyzeWebOutputSchema'
import { webLoader } from '../utils/genkitUtils'

export const analyzeWebContents = genkitFunctions.onFlow(
{
name: `analyzeWebContents`,
httpsOptions: {
cors: true,
secrets: [config.googleAIapiKey],
},
inputSchema: analyzeWebInputSchema,
outputSchema: analyzeWebOutputSchema,
authPolicy: genkitFunctions.noAuth(),
},
async (input) => {
const result = await generate({
model: gemini15Flash,
prompt: `以下のウェブページの内容を分析してください。:${input}`,
tools: [webLoader],
output: {
format: `text`,
},
})

return result.output()
}
)
36 changes: 1 addition & 35 deletions functions/src/genkit-functions/anonymousFirestoreChatbot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as config from '../config/firebase'
import { db } from '../config/firebase'
import { chatbotInputSchema } from '../schemas/chatbotInputSchema'
import { chatbotOutputSchema } from '../schemas/chatbotOutputSchema'
import { isGenkitEnabled } from '../utils/genkitUtils'
import { createChatbotInput, isGenkitEnabled } from '../utils/genkitUtils'

export const anonymousFirestoreChatbot = genkitFunctions.onFlow(
{
Expand Down Expand Up @@ -53,37 +53,3 @@ export const anonymousFirestoreChatbot = genkitFunctions.onFlow(
}
}
)

function createChatbotInput(
userId: string,
currentQuery: string,
userData: any,
chatData: any,
productData: any
): z.infer<typeof chatbotInputSchema> {
return {
userId,
currentQuery,
chatHistory:
chatData?.messages?.map((message: any) => ({
role: message.role as `user` | `assistant`,
content: message.content,
timestamp: message.timestamp,
})) || [],
userProfile: {
name: userData?.userProfile?.name || ``,
preferredLanguage: userData?.userProfile?.preferredLanguage || ``,
accountType: userData?.userProfile?.accountType || ``,
},
productCatalog: productData
? [
{
id: productData.id || ``,
name: productData.name || ``,
details: productData.details || ``,
price: productData.price || 0,
},
]
: [],
}
}
23 changes: 23 additions & 0 deletions functions/src/genkit-functions/generateImage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { prompt } from '@genkit-ai/dotprompt'
import * as genkitFunctions from '@genkit-ai/firebase/functions'
import * as z from 'zod'
import { googleAIapiKey } from '../config/firebase'
import { generateImageInputSchema } from '../schemas/generateImageInputSchema'

// 画像出力の Genkit Functions
export const generateImage = genkitFunctions.onFlow(
{
name: `generateImage`,
httpsOptions: {
cors: true,
secrets: [googleAIapiKey],
},
inputSchema: generateImageInputSchema,
authPolicy: genkitFunctions.noAuth(),
},
async (input) => {
const generateImagePrompt = await prompt<z.infer<typeof generateImageInputSchema>>(`generateImage`)
const result = await generateImagePrompt.generate({ input })
return result.media()
}
)
5 changes: 4 additions & 1 deletion functions/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export { noAuthFunction } from './genkit-functions/noAuthFunction'
export { analyzeStorageImage } from './genkit-functions/analyzeStorageImage'
export { analyzeWebContents } from './genkit-functions/analyzeWebContents'
export { anonymousFirestoreChatbot } from './genkit-functions/anonymousFirestoreChatbot'
export { generateImage } from './genkit-functions/generateImage'
export { noAuthFunction } from './genkit-functions/noAuthFunction'
5 changes: 5 additions & 0 deletions functions/src/schemas/analyzeStorageInputSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as z from 'zod'

export const analyzeStorageInputSchema = z.object({
storageFileUrl: z.string(),
})
5 changes: 5 additions & 0 deletions functions/src/schemas/analyzeStorageOutputSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as z from 'zod'

export const analyzeStorageOutputSchema = z.object({
analysis: z.string(),
})
5 changes: 5 additions & 0 deletions functions/src/schemas/analyzeWebInputSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as z from 'zod'

export const analyzeWebInputSchema = z.object({
contentsUrl: z.string(),
})
5 changes: 5 additions & 0 deletions functions/src/schemas/analyzeWebOutputSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as z from 'zod'

export const analyzeWebOutputSchema = z.object({
analysis: z.string(),
})
5 changes: 5 additions & 0 deletions functions/src/schemas/generateImageInputSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as z from 'zod'

export const generateImageInputSchema = z.object({
prompt: z.string(),
})
57 changes: 57 additions & 0 deletions functions/src/utils/genkitUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,63 @@
import { defineTool } from '@genkit-ai/ai'
import * as cheerio from 'cheerio'
import * as z from 'zod'
import { db } from '../config/firebase'
import { chatbotInputSchema } from '../schemas/chatbotInputSchema'

export async function isGenkitEnabled(): Promise<boolean> {
const appConfDoc = await db.collection(`appConf`).doc(`config`).get()
return appConfDoc.data()?.genkitEnabled ?? false
}

export const webLoader = defineTool(
{
name: `webLoader`,
description: `指定されたURLにアクセスし、ウェブページの内容を取得します。`,
inputSchema: z.object({ url: z.string().url() }),
outputSchema: z.string(),
},
async ({ url }) => {
const res = await fetch(url)
const html = await res.text()
const $ = cheerio.load(html)
$(`script, style, noscript`).remove()
if ($(`article`).length) {
return $(`article`).text()
}
return $(`body`).text()
}
)

export function createChatbotInput(
userId: string,
currentQuery: string,
userData: any,

Check warning on line 34 in functions/src/utils/genkitUtils.ts

View workflow job for this annotation

GitHub Actions / Deploy Functions

Unexpected any. Specify a different type
chatData: any,

Check warning on line 35 in functions/src/utils/genkitUtils.ts

View workflow job for this annotation

GitHub Actions / Deploy Functions

Unexpected any. Specify a different type
productData: any

Check warning on line 36 in functions/src/utils/genkitUtils.ts

View workflow job for this annotation

GitHub Actions / Deploy Functions

Unexpected any. Specify a different type
): z.infer<typeof chatbotInputSchema> {
return {
userId,
currentQuery,
chatHistory:
chatData?.messages?.map((message: any) => ({

Check warning on line 42 in functions/src/utils/genkitUtils.ts

View workflow job for this annotation

GitHub Actions / Deploy Functions

Unexpected any. Specify a different type
role: message.role as `user` | `assistant`,
content: message.content,
timestamp: message.timestamp,
})) || [],
userProfile: {
name: userData?.userProfile?.name || ``,
preferredLanguage: userData?.userProfile?.preferredLanguage || ``,
accountType: userData?.userProfile?.accountType || ``,
},
productCatalog: productData
? [
{
id: productData.id || ``,
name: productData.name || ``,
details: productData.details || ``,
price: productData.price || 0,
},
]
: [],
}
}

0 comments on commit dfb2b8f

Please sign in to comment.