From 3aaf8979a0658bc69d71dd209f0f7b9baef547d8 Mon Sep 17 00:00:00 2001 From: Shotaro Nakamura Date: Sat, 9 Nov 2024 07:19:48 +0000 Subject: [PATCH] feat --- .../note/components/notes/TextNote/AI.tsx | 244 +++++++++++++----- 1 file changed, 182 insertions(+), 62 deletions(-) diff --git a/src/islands/note/components/notes/TextNote/AI.tsx b/src/islands/note/components/notes/TextNote/AI.tsx index fc41180..3cc9ce5 100644 --- a/src/islands/note/components/notes/TextNote/AI.tsx +++ b/src/islands/note/components/notes/TextNote/AI.tsx @@ -1,10 +1,15 @@ -import type { - GenerateContentStreamResult, - GoogleGenerativeAI, +import { + type GenerateContentStreamResult, + type GoogleGenerativeAI, + GoogleGenerativeAIResponseError, + type GenerateContentResponse, + GoogleGenerativeAIFetchError, } from '@google/generative-ai' import markdownIt from 'markdown-it' import { + Match, Show, + Switch, createComputed, createEffect, createMemo, @@ -20,6 +25,9 @@ import { Spinner } from '../../utils/Spinner' const markdownParser = markdownIt() type Mode = 'text' | 'image' +type Generate = { + generate: () => Promise +} const renderMarkdown = (markdown: string) => markdownParser @@ -85,7 +93,7 @@ const getGemini = (): GoogleGenerativeAI => { return ai } export const FromText = (props: { - setStream(stream: GenerateContentStreamResult): void + setStream(stream: Generate): void initPrompt?: string }) => { const [getCurrentPlaceholder, setCurrentPlaceholder] = createSignal({ @@ -157,20 +165,21 @@ export const FromText = (props: { const model = gemini.getGenerativeModel({ model: 'gemini-1.5-flash', }) - props.setStream( - await model - .startChat({ - systemInstruction: { - role: 'model', - parts: [ - { - text: 'ユーザーの指示に基づき、暗記の手助けになる赤シート用文章を生成しなさい。赤シートで隠すべき単語は、Markdownの太字機能で表現しなさい。隠す必要がない場所には太字は使わないでください。太字の場所はユーザーに見えません。また、単語の一覧を箇条書きにすることはしないでください。', - }, - ], - }, - }) - .sendMessageStream(getPrompt()), - ) + props.setStream({ + generate: () => + model + .startChat({ + systemInstruction: { + role: 'model', + parts: [ + { + text: 'ユーザーの指示に基づき、暗記の手助けになる赤シート用文章を生成しなさい。赤シートで隠すべき単語は、Markdownの太字機能で表現しなさい。隠す必要がない場所には太字は使わないでください。太字の場所はユーザーに見えません。また、単語の一覧を箇条書きにすることはしないでください。', + }, + ], + }, + }) + .sendMessageStream(getPrompt()), + }) setIsPreprocessing(false) } @@ -192,7 +201,7 @@ export const FromText = (props: { disabled={!getPrompt() || getIsPreprocessing()} type="button" > - + 準備中... @@ -202,7 +211,7 @@ export const FromText = (props: { ) } export const FromImage = (props: { - setStream(stream: GenerateContentStreamResult): void + setStream(stream: Generate): void }) => { const [getImageFile, setImageFile] = createSignal() const [getScanedImageURL, setScanedImageURL] = createSignal() @@ -236,29 +245,30 @@ export const FromImage = (props: { reader.readAsDataURL(file) }) - const stream = await model - .startChat({ - systemInstruction: { - role: 'model', - parts: [ - { - text: '画像を抽出し、そっくりそのまま書き出しなさい。省略せずに画像の文字全てを書き出すこと。画像に書いていないことは書かないこと。また、ユーザーからの指示があれば、条件を満たす場所をMarkdownの太字で表現しなさい。', + const generate = () => + model + .startChat({ + systemInstruction: { + role: 'model', + parts: [ + { + text: '画像を抽出し、そっくりそのまま書き出しなさい。省略せずに画像の文字全てを書き出すこと。画像に書いていないことは書かないこと。また、ユーザーからの指示があれば、条件を満たす場所をMarkdownの太字で表現しなさい。', + }, + ], + }, + }) + .sendMessageStream([ + { + text: '', + }, + { + inlineData: { + mimeType: file.type, + data: b64, }, - ], - }, - }) - .sendMessageStream([ - { - text: '', - }, - { - inlineData: { - mimeType: file.type, - data: b64, }, - }, - ]) - props.setStream(stream) + ]) + props.setStream({ generate }) setIsPreprocessing(false) } @@ -284,7 +294,12 @@ export const FromImage = (props: {