fix: @google/generative-ai local compilation issue #682

close #682
This commit is contained in:
kangfenmao 2025-01-07 23:16:58 +08:00
parent c9813bb1e2
commit 1fbd727a7b
6 changed files with 22 additions and 21 deletions

View File

@ -173,4 +173,6 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
ipcMain.handle('gemini:upload-file', GeminiService.uploadFile) ipcMain.handle('gemini:upload-file', GeminiService.uploadFile)
ipcMain.handle('gemini:base64-file', GeminiService.base64File) ipcMain.handle('gemini:base64-file', GeminiService.base64File)
ipcMain.handle('gemini:retrieve-file', GeminiService.retrieveFile) ipcMain.handle('gemini:retrieve-file', GeminiService.retrieveFile)
ipcMain.handle('gemini:list-files', GeminiService.listFiles)
ipcMain.handle('gemini:delete-file', GeminiService.deleteFile)
} }

View File

@ -50,4 +50,14 @@ export class GeminiService {
} }
return undefined return undefined
} }
static async listFiles(_: Electron.IpcMainInvokeEvent, apiKey: string) {
const fileManager = new GoogleAIFileManager(apiKey)
return await fileManager.listFiles()
}
static async deleteFile(_: Electron.IpcMainInvokeEvent, apiKey: string, fileId: string) {
const fileManager = new GoogleAIFileManager(apiKey)
await fileManager.deleteFile(fileId)
}
} }

View File

@ -1,6 +1,5 @@
import { ElectronAPI } from '@electron-toolkit/preload' import { ElectronAPI } from '@electron-toolkit/preload'
import type { FileMetadataResponse } from '@google/generative-ai/server' import type { FileMetadataResponse, ListFilesResponse, UploadFileResponse } from '@google/generative-ai/server'
import { UploadFileResponse } from '@google/generative-ai/server'
import { AddLoaderReturn, ExtractChunkData } from '@llm-tools/embedjs-interfaces' import { AddLoaderReturn, ExtractChunkData } from '@llm-tools/embedjs-interfaces'
import { FileType } from '@renderer/types' import { FileType } from '@renderer/types'
import { WebDavConfig } from '@renderer/types' import { WebDavConfig } from '@renderer/types'
@ -86,6 +85,8 @@ declare global {
uploadFile: (file: FileType, apiKey: string) => Promise<UploadFileResponse> uploadFile: (file: FileType, apiKey: string) => Promise<UploadFileResponse>
retrieveFile: (file: FileType, apiKey: string) => Promise<FileMetadataResponse | undefined> retrieveFile: (file: FileType, apiKey: string) => Promise<FileMetadataResponse | undefined>
base64File: (file: FileType) => Promise<{ data: string; mimeType: string }> base64File: (file: FileType) => Promise<{ data: string; mimeType: string }>
listFiles: (apiKey: string) => Promise<ListFilesResponse>
deleteFile: (apiKey: string, fileId: string) => Promise<void>
} }
} }
} }

View File

@ -78,7 +78,9 @@ const api = {
gemini: { gemini: {
uploadFile: (file: FileType, apiKey: string) => ipcRenderer.invoke('gemini:upload-file', file, apiKey), uploadFile: (file: FileType, apiKey: string) => ipcRenderer.invoke('gemini:upload-file', file, apiKey),
base64File: (file: FileType) => ipcRenderer.invoke('gemini:base64-file', file), base64File: (file: FileType) => ipcRenderer.invoke('gemini:base64-file', file),
retrieveFile: (file: FileType, apiKey: string) => ipcRenderer.invoke('gemini:retrieve-file', file, apiKey) retrieveFile: (file: FileType, apiKey: string) => ipcRenderer.invoke('gemini:retrieve-file', file, apiKey),
listFiles: (apiKey: string) => ipcRenderer.invoke('gemini:list-files', apiKey),
deleteFile: (apiKey: string, fileId: string) => ipcRenderer.invoke('gemini:delete-file', apiKey, fileId)
} }
} }

View File

@ -1,7 +1,6 @@
import { DeleteOutlined } from '@ant-design/icons' import { DeleteOutlined } from '@ant-design/icons'
import { FileMetadataResponse, FileState } from '@google/generative-ai/server' import type { FileMetadataResponse } from '@google/generative-ai/server'
import { useProvider } from '@renderer/hooks/useProvider' import { useProvider } from '@renderer/hooks/useProvider'
import GeminiProvider from '@renderer/providers/GeminiProvider'
import { runAsyncFunction } from '@renderer/utils' import { runAsyncFunction } from '@renderer/utils'
import { Table } from 'antd' import { Table } from 'antd'
import type { ColumnsType } from 'antd/es/table' import type { ColumnsType } from 'antd/es/table'
@ -20,9 +19,8 @@ const GeminiFiles: FC<GeminiFilesProps> = ({ id }) => {
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const fetchFiles = useCallback(async () => { const fetchFiles = useCallback(async () => {
const geminiProvider = new GeminiProvider(provider) const { files } = await window.api.gemini.listFiles(provider.apiKey)
const { files } = await geminiProvider.listFiles() files && setFiles(files.filter((file) => file.state === 'ACTIVE'))
files && setFiles(files.filter((file) => file.state === FileState.ACTIVE))
}, [provider]) }, [provider])
const columns: ColumnsType<FileMetadataResponse> = [ const columns: ColumnsType<FileMetadataResponse> = [
@ -54,13 +52,12 @@ const GeminiFiles: FC<GeminiFilesProps> = ({ id }) => {
key: 'actions', key: 'actions',
align: 'center', align: 'center',
render: (_, record) => { render: (_, record) => {
const geminiProvider = new GeminiProvider(provider)
return ( return (
<DeleteOutlined <DeleteOutlined
style={{ cursor: 'pointer', color: 'var(--color-error)' }} style={{ cursor: 'pointer', color: 'var(--color-error)' }}
onClick={() => { onClick={() => {
setFiles(files.filter((file) => file.name !== record.name)) setFiles(files.filter((file) => file.name !== record.name))
geminiProvider.deleteFile(record.name).catch((error) => { window.api.gemini.deleteFile(provider.apiKey, record.name).catch((error) => {
console.error('Failed to delete file:', error) console.error('Failed to delete file:', error)
setFiles((prev) => [...prev, record]) setFiles((prev) => [...prev, record])
}) })

View File

@ -9,7 +9,6 @@ import {
RequestOptions, RequestOptions,
TextPart TextPart
} from '@google/generative-ai' } from '@google/generative-ai'
import { GoogleAIFileManager, ListFilesResponse } from '@google/generative-ai/server'
import { isEmbeddingModel, isWebSearchModel } from '@renderer/config/models' import { isEmbeddingModel, isWebSearchModel } from '@renderer/config/models'
import { getStoreSetting } from '@renderer/hooks/useSettings' import { getStoreSetting } from '@renderer/hooks/useSettings'
import i18n from '@renderer/i18n' import i18n from '@renderer/i18n'
@ -345,14 +344,4 @@ export default class GeminiProvider extends BaseProvider {
const data = await this.sdk.getGenerativeModel({ model: model.id }, this.requestOptions).embedContent('hi') const data = await this.sdk.getGenerativeModel({ model: model.id }, this.requestOptions).embedContent('hi')
return data.embedding.values.length return data.embedding.values.length
} }
public async listFiles(): Promise<ListFilesResponse> {
const fileManager = new GoogleAIFileManager(this.apiKey)
return await fileManager.listFiles()
}
public async deleteFile(fileId: string): Promise<void> {
const fileManager = new GoogleAIFileManager(this.apiKey)
await fileManager.deleteFile(fileId)
}
} }