mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-10-20 21:40:29 -04:00
Start work on supporting multiple AI providers via plugins
This commit is contained in:
parent
21aa23eba4
commit
adb85e2569
13
src/calibre/ai/open_router/__init__.py
Normal file
13
src/calibre/ai/open_router/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# License: GPLv3 Copyright: 2025, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
|
||||||
|
from calibre.customize import AIProviderPlugin
|
||||||
|
|
||||||
|
|
||||||
|
class OpenRouterAI(AIProviderPlugin):
|
||||||
|
name = 'OpenRouter'
|
||||||
|
version = (1, 0, 0)
|
||||||
|
description = _('AI services from OpenRouter.ai. Allows choosing from hundreds of different AI models to query.')
|
||||||
|
author = 'Kovid Goyal'
|
||||||
|
builtin_live_module_name = 'calibre.ai.open_router.backend'
|
5
src/calibre/ai/open_router/backend.py
Normal file
5
src/calibre/ai/open_router/backend.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# License: GPLv3 Copyright: 2025, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
|
||||||
|
module_version = 1 # needed for live updates
|
@ -817,3 +817,32 @@ class LibraryClosedPlugin(Plugin): # {{{
|
|||||||
raise NotImplementedError('LibraryClosedPlugin '
|
raise NotImplementedError('LibraryClosedPlugin '
|
||||||
'run method must be overridden in subclass')
|
'run method must be overridden in subclass')
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
class AIProviderPlugin(Plugin): # {{{
|
||||||
|
'''
|
||||||
|
AIProvider plugins abstract AI services that can be used by the rest of calibre.
|
||||||
|
'''
|
||||||
|
type = _('AI provider')
|
||||||
|
|
||||||
|
# minimum version when support for this plugin type was added
|
||||||
|
minimum_calibre_version = (8, 10, 0)
|
||||||
|
|
||||||
|
# Used by builtin AI Provider plugins to live load the backend code
|
||||||
|
builtin_live_module_name = ''
|
||||||
|
|
||||||
|
@property
|
||||||
|
def builtin_live_module(self):
|
||||||
|
if not self.builtin_live_module_name:
|
||||||
|
return None
|
||||||
|
if (ans := self._builtin_live_module) is None:
|
||||||
|
from calibre.live import Strategy, load_module
|
||||||
|
ans = self._builtin_live_module = load_module(self.builtin_live_module_name, strategy=Strategy.fast)
|
||||||
|
return ans
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
self._builtin_live_module = None
|
||||||
|
|
||||||
|
def customization_help(self):
|
||||||
|
return ''
|
||||||
|
# }}}
|
||||||
|
@ -4,6 +4,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from calibre.ai.open_router import OpenRouterAI
|
||||||
from calibre.constants import numeric_version
|
from calibre.constants import numeric_version
|
||||||
from calibre.customize import FileTypePlugin, InterfaceActionBase, MetadataReaderPlugin, MetadataWriterPlugin, PreferencesPlugin, StoreBase
|
from calibre.customize import FileTypePlugin, InterfaceActionBase, MetadataReaderPlugin, MetadataWriterPlugin, PreferencesPlugin, StoreBase
|
||||||
from calibre.ebooks.html.to_zip import HTML2ZIP
|
from calibre.ebooks.html.to_zip import HTML2ZIP
|
||||||
@ -434,9 +435,9 @@ plugins += [x for x in list(locals().values()) if isinstance(x, type) and
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
# Metadata writer plugins {{{
|
# Metadata writer plugins {{{
|
||||||
|
|
||||||
|
|
||||||
class EPUBMetadataWriter(MetadataWriterPlugin):
|
class EPUBMetadataWriter(MetadataWriterPlugin):
|
||||||
|
|
||||||
name = 'Set EPUB metadata'
|
name = 'Set EPUB metadata'
|
||||||
@ -851,9 +852,9 @@ plugins += [GoogleBooks, GoogleImages, Amazon, Edelweiss, OpenLibrary, BigBookSe
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
# Interface Actions {{{
|
# Interface Actions {{{
|
||||||
|
|
||||||
|
|
||||||
class ActionAdd(InterfaceActionBase):
|
class ActionAdd(InterfaceActionBase):
|
||||||
name = 'Add Books'
|
name = 'Add Books'
|
||||||
actual_plugin = 'calibre.gui2.actions.add:AddAction'
|
actual_plugin = 'calibre.gui2.actions.add:AddAction'
|
||||||
@ -1191,9 +1192,9 @@ plugins += [ActionAdd, ActionAllActions, ActionColumnTooltip, ActionFetchAnnotat
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
# Preferences Plugins {{{
|
# Preferences Plugins {{{
|
||||||
|
|
||||||
|
|
||||||
class LookAndFeel(PreferencesPlugin):
|
class LookAndFeel(PreferencesPlugin):
|
||||||
name = 'Look & Feel'
|
name = 'Look & Feel'
|
||||||
icon = 'lookfeel.png'
|
icon = 'lookfeel.png'
|
||||||
@ -1468,9 +1469,9 @@ plugins += [LookAndFeel, Behavior, Columns, Toolbar, Search, InputOptions,
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
# Store plugins {{{
|
# Store plugins {{{
|
||||||
|
|
||||||
|
|
||||||
class StoreAmazonKindleStore(StoreBase):
|
class StoreAmazonKindleStore(StoreBase):
|
||||||
name = 'Amazon Kindle'
|
name = 'Amazon Kindle'
|
||||||
description = 'Kindle books from Amazon.'
|
description = 'Kindle books from Amazon.'
|
||||||
@ -1976,6 +1977,8 @@ plugins += [
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
plugins.extend((OpenRouterAI,))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Test load speed
|
# Test load speed
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -7,10 +7,12 @@ import shutil
|
|||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from collections.abc import Iterator
|
||||||
from itertools import chain, repeat
|
from itertools import chain, repeat
|
||||||
|
|
||||||
from calibre.constants import DEBUG, ismacos, numeric_version, system_plugins_loc
|
from calibre.constants import DEBUG, ismacos, numeric_version, system_plugins_loc
|
||||||
from calibre.customize import (
|
from calibre.customize import (
|
||||||
|
AIProviderPlugin,
|
||||||
CatalogPlugin,
|
CatalogPlugin,
|
||||||
EditBookToolPlugin,
|
EditBookToolPlugin,
|
||||||
FileTypePlugin,
|
FileTypePlugin,
|
||||||
@ -357,6 +359,18 @@ def has_library_closed_plugins():
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
# AI Provider Plugins {{{
|
||||||
|
def available_ai_provider_plugins() -> Iterator[AIProviderPlugin]:
|
||||||
|
customization = config['plugin_customization']
|
||||||
|
for plugin in _initialized_plugins:
|
||||||
|
if isinstance(plugin, AIProviderPlugin):
|
||||||
|
if not is_disabled(plugin):
|
||||||
|
plugin.site_customization = customization.get(plugin.name, '')
|
||||||
|
yield plugin
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
# Store Plugins # {{{
|
# Store Plugins # {{{
|
||||||
|
|
||||||
def store_plugins():
|
def store_plugins():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user