mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-10-20 05:20: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 '
|
||||
'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 os
|
||||
|
||||
from calibre.ai.open_router import OpenRouterAI
|
||||
from calibre.constants import numeric_version
|
||||
from calibre.customize import FileTypePlugin, InterfaceActionBase, MetadataReaderPlugin, MetadataWriterPlugin, PreferencesPlugin, StoreBase
|
||||
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 {{{
|
||||
|
||||
|
||||
class EPUBMetadataWriter(MetadataWriterPlugin):
|
||||
|
||||
name = 'Set EPUB metadata'
|
||||
@ -851,9 +852,9 @@ plugins += [GoogleBooks, GoogleImages, Amazon, Edelweiss, OpenLibrary, BigBookSe
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
# Interface Actions {{{
|
||||
|
||||
|
||||
class ActionAdd(InterfaceActionBase):
|
||||
name = 'Add Books'
|
||||
actual_plugin = 'calibre.gui2.actions.add:AddAction'
|
||||
@ -1191,9 +1192,9 @@ plugins += [ActionAdd, ActionAllActions, ActionColumnTooltip, ActionFetchAnnotat
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
# Preferences Plugins {{{
|
||||
|
||||
|
||||
class LookAndFeel(PreferencesPlugin):
|
||||
name = 'Look & Feel'
|
||||
icon = 'lookfeel.png'
|
||||
@ -1468,9 +1469,9 @@ plugins += [LookAndFeel, Behavior, Columns, Toolbar, Search, InputOptions,
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
# Store plugins {{{
|
||||
|
||||
|
||||
class StoreAmazonKindleStore(StoreBase):
|
||||
name = 'Amazon Kindle'
|
||||
description = 'Kindle books from Amazon.'
|
||||
@ -1976,6 +1977,8 @@ plugins += [
|
||||
|
||||
# }}}
|
||||
|
||||
plugins.extend((OpenRouterAI,))
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Test load speed
|
||||
import subprocess
|
||||
|
@ -7,10 +7,12 @@ import shutil
|
||||
import sys
|
||||
import traceback
|
||||
from collections import defaultdict
|
||||
from collections.abc import Iterator
|
||||
from itertools import chain, repeat
|
||||
|
||||
from calibre.constants import DEBUG, ismacos, numeric_version, system_plugins_loc
|
||||
from calibre.customize import (
|
||||
AIProviderPlugin,
|
||||
CatalogPlugin,
|
||||
EditBookToolPlugin,
|
||||
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 # {{{
|
||||
|
||||
def store_plugins():
|
||||
|
Loading…
x
Reference in New Issue
Block a user