Skip to content

Commit

Permalink
improvements and added initial spotify plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
n3d1117 committed Jun 19, 2023
1 parent d86cd38 commit c1bfda4
Show file tree
Hide file tree
Showing 13 changed files with 475 additions and 129 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ __pycache__
.DS_Store
/usage_logs
venv
/.cache
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,18 @@ Check out the [Budget Manual](https://github.com/n3d1117/chatgpt-telegram-bot/di
| `PLUGINS` | List of plugins to enable (see below for a full list), e.g: `PLUGINS=wolfram,weather` | `-` |
| `SHOW_PLUGINS_USED` | Whether to show which plugins were used for a response | `false` |
| `WOLFRAM_APP_ID` | Wolfram Alpha APP ID (required for the `wolfram` plugin, you can get one [here](https://products.wolframalpha.com/simple-api/documentation)) | `-` |
| `SPOTIFY_CLIENT_ID` | Spotify app Client ID (required for the `spotify` plugin, you can find it on the [dashboard](https://developer.spotify.com/dashboard/)) | `-` |
| `SPOTIFY_CLIENT_SECRET` | Spotify app Client Secret (required for the `spotify` plugin, you can find it on the [dashboard](https://developer.spotify.com/dashboard/)) | `-` |
| `SPOTIFY_REDIRECT_URI` | Spotify app Redirect URI (required for the `spotify` plugin, you can find it on the [dashboard](https://developer.spotify.com/dashboard/)) | `-` |

#### Available plugins
| Name | Description | Required API key |
|--------------|---------------------------------------------------------------------------------------------------------------------|------------------|
| `weather` | Daily weather and 7-day forecast for any location (powered by [Open-Meteo](https://open-meteo.com)) | `-` |
| `wolfram` | WolframAlpha queries (powered by [WolframAlpha](https://www.wolframalpha.com)) | `WOLFRAM_APP_ID` |
| `web_search` | Web search (powered by [DuckDuckGo](https://duckduckgo.com)) | `-` |
| `crypto` | Live cryptocurrencies rate (powered by [CoinCap](https://coincap.io)) - by [@stumpyfr](https://github.com/stumpyfr) | `-` |
| Name | Description | Required API key(s) |
|--------------|-------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------|
| `weather` | Daily weather and 7-day forecast for any location (powered by [Open-Meteo](https://open-meteo.com)) | `-` |
| `wolfram` | WolframAlpha queries (powered by [WolframAlpha](https://www.wolframalpha.com)) | `WOLFRAM_APP_ID` |
| `web_search` | Web search (powered by [DuckDuckGo](https://duckduckgo.com)) | `-` |
| `crypto` | Live cryptocurrencies rate (powered by [CoinCap](https://coincap.io)) - by [@stumpyfr](https://github.com/stumpyfr) | `-` |
| `spotify` | Spotify top tracks/artists and currently playing song (powered by [Spotify](https://spotify.com)). Requires one-time auth approval. | `SPOTIFY_CLIENT_ID`, `SPOTIFY_CLIENT_SECRET`, `SPOTIFY_REDIRECT_URI` |

Check out the [official API reference](https://platform.openai.com/docs/api-reference/chat) for more details.

Expand Down
2 changes: 1 addition & 1 deletion bot/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from dotenv import load_dotenv

from functions import PluginManager
from plugin_manager import PluginManager
from openai_helper import OpenAIHelper, default_max_tokens, are_functions_available
from telegram_bot import ChatGPTTelegramBot

Expand Down
2 changes: 1 addition & 1 deletion bot/openai_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from tenacity import retry, stop_after_attempt, wait_fixed, retry_if_exception_type

from functions import PluginManager
from plugin_manager import PluginManager

# Models can be found here: https://platform.openai.com/docs/models/overview
GPT_3_MODELS = ("gpt-3.5-turbo", "gpt-3.5-turbo-0301", "gpt-3.5-turbo-0613")
Expand Down
22 changes: 13 additions & 9 deletions bot/functions.py → bot/plugin_manager.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import json

from plugins.python import PythonPlugin
from plugins.spotify import SpotifyPlugin
from plugins.crypto import CryptoPlugin
from plugins.weather import WeatherPlugin
from plugins.web_search import WebSearchPlugin
Expand All @@ -12,19 +14,20 @@ class PluginManager:
"""
def __init__(self, config):
enabled_plugins = config.get('plugins', [])
plugins = [
WolframAlphaPlugin() if 'wolfram' in enabled_plugins else None,
WeatherPlugin() if 'weather' in enabled_plugins else None,
CryptoPlugin() if 'crypto' in enabled_plugins else None,
WebSearchPlugin() if 'web_search' in enabled_plugins else None,
]
self.plugins = [plugin for plugin in plugins if plugin is not None]
plugin_mapping = {
'wolfram': WolframAlphaPlugin(),
'weather': WeatherPlugin(),
'crypto': CryptoPlugin(),
'web_search': WebSearchPlugin(),
'spotify': SpotifyPlugin(),
}
self.plugins = [plugin_mapping[plugin] for plugin in enabled_plugins]

def get_functions_specs(self):
"""
Return the list of function specs that can be called by the model
"""
return [plugin.get_spec() for plugin in self.plugins]
return [spec for specs in map(lambda plugin: plugin.get_spec(), self.plugins) for spec in specs]

async def call_function(self, function_name, arguments):
"""
Expand All @@ -45,4 +48,5 @@ def get_plugin_source_name(self, function_name) -> str:
return plugin.get_source_name()

def __get_plugin_by_function_name(self, function_name):
return next((plugin for plugin in self.plugins if plugin.get_spec().get('name') == function_name), None)
return next((plugin for plugin in self.plugins
if function_name in map(lambda spec: spec.get('name'), plugin.get_spec())), None)
8 changes: 4 additions & 4 deletions bot/plugins/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class CryptoPlugin(Plugin):
def get_source_name(self) -> str:
return "CoinCap"

def get_spec(self) -> Dict:
return {
def get_spec(self) -> [Dict]:
return [{
"name": "get_crypto_rate",
"description": "Get the current rate of various crypto currencies",
"parameters": {
Expand All @@ -24,7 +24,7 @@ def get_spec(self) -> Dict:
},
"required": ["asset"],
},
}
}]

async def execute(self, **kwargs) -> Dict:
async def execute(self, function_name, **kwargs) -> Dict:
return requests.get(f"https://api.coincap.io/v2/rates/{kwargs['asset']}").json()
6 changes: 3 additions & 3 deletions bot/plugins/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ def get_source_name(self) -> str:
pass

@abstractmethod
def get_spec(self) -> Dict:
def get_spec(self) -> [Dict]:
"""
Function spec in the form of JSON schema as specified in the OpenAI documentation:
Function specs in the form of JSON schema as specified in the OpenAI documentation:
https://platform.openai.com/docs/api-reference/chat/create#chat/create-functions
"""
pass

@abstractmethod
async def execute(self, **kwargs) -> Dict:
async def execute(self, function_name, **kwargs) -> Dict:
"""
Execute the plugin and return a JSON serializable response
"""
Expand Down
Loading

0 comments on commit c1bfda4

Please sign in to comment.