From 752e169029ebe25460b242025f83de1db6a8ef85 Mon Sep 17 00:00:00 2001 From: Ayush Khatri Date: Sun, 29 Oct 2023 16:21:27 -0700 Subject: [PATCH 01/13] Setting default model providers --- docs/source/users/index.md | 22 +++++++++++ .../jupyter_ai/tests/test_config_manager.py | 38 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/docs/source/users/index.md b/docs/source/users/index.md index 128ef3b23..b9e5e4452 100644 --- a/docs/source/users/index.md +++ b/docs/source/users/index.md @@ -765,6 +765,28 @@ The `--response-path` option is a [JSONPath](https://goessner.net/articles/JsonP You can specify an allowlist, to only allow only a certain list of providers, or a blocklist, to block some providers. +### Initializing default providers + +This configuration allows for setting a default model, and embedding provider with their corresponding API keys, or related fields configuration. + +Following command line arguments can be used to initialize Jupyter AI extension with default providers: +1. ```--AiExtension.model_provider_id```: Specify the default LLM model. E.g.: ```--AiExtension.model_provider_id="bedrock-chat:anthropic.claude-v2"``` +2. ```--AiExtension.embeddings_provider_id```: Specify default embedding provider. E.g.: ```--AiExtension.embeddings_provider_id="bedrock:amazon.titan-embed-text-v1"``` +3. ```--AiExtension.api_keys```: Specify model provider keys in a JSON format. E.g. ```--AiExtension.api_keys='{"OPENAI_API_KEY": "sk-abcd}'``` +4. ```--AiExtension.fields```: Specify additional configuration required for a LLM, and embedding model. E.g: ```--AiExtension.fields='{"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"},"bedrock:amazon.titan-embed-text-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}}'``` + +#### Initializing model provider with API keys + +``` + jupyter lab --AiExtension.model_provider_id="bedrock-chat:anthropic.claude-v1" --AiExtension.fields='{"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"},"bedrock:amazon.titan-embed-text-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}}' --AiExtension.api_keys='{"OPENAI_API_KEY": "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"} +``` + +#### Initializing model provider which requires additional fields + +``` + jupyter lab --AiExtension.model_provider_id="bedrock-chat:anthropic.claude-v1" --AiExtension.fields='{"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"},"bedrock:amazon.titan-embed-text-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}}' --AiExtension.api_keys='{"OPENAI_API_KEY": "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"} +``` + ### Blocklisting providers This configuration allows for blocking specific providers in the settings panel. diff --git a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py index c238fc448..eeddfff88 100644 --- a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py @@ -183,6 +183,44 @@ def test_init_with_allowlists(cm: ConfigManager, common_cm_kwargs): assert test_cm.lm_gid == None assert test_cm.em_gid == None +def test_init_with_default_values( + cm_with_defaults: ConfigManager, config_path: str, schema_path: str +): + """ + Test that the ConfigManager initializes with the expected default values. + + Args: + cm_with_defaults (ConfigManager): A ConfigManager instance with default values. + config_path (str): The path to the configuration file. + schema_path (str): The path to the schema file. + """ + config_response = cm_with_defaults.get_config() + #assert config response + assert config_response.model_provider_id == "bedrock-chat:anthropic.claude-v1" + assert config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" + assert config_response.api_keys == ["OPENAI_API_KEY"] + assert config_response.fields == {"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}} + + del cm_with_defaults + + log = logging.getLogger() + lm_providers = get_lm_providers() + em_providers = get_em_providers() + cm_with_defaults_override =ConfigManager( + log=log, + lm_providers=lm_providers, + em_providers=em_providers, + config_path=config_path, + schema_path=schema_path, + restrictions={"allowed_providers": None, "blocked_providers": None}, + provider_defaults={"model_provider_id": "bedrock-chat:anthropic.claude-v2"}, + ) + + assert cm_with_defaults_override.get_config().model_provider_id == "bedrock-chat:anthropic.claude-v2" + + + + def test_property_access_on_default_config(cm: ConfigManager): """Asserts that the CM behaves well with an empty, default From d198e11d6b320f30d4821e726d8b2dedb7db8f01 Mon Sep 17 00:00:00 2001 From: Ayush Khatri Date: Sun, 29 Oct 2023 16:21:27 -0700 Subject: [PATCH 02/13] Setting default model providers --- .../jupyter-ai/jupyter_ai/config_manager.py | 22 +++++- packages/jupyter-ai/jupyter_ai/extension.py | 40 +++++++++++ .../jupyter_ai/tests/test_config_manager.py | 67 +++++++++++++++++++ 3 files changed, 127 insertions(+), 2 deletions(-) diff --git a/packages/jupyter-ai/jupyter_ai/config_manager.py b/packages/jupyter-ai/jupyter_ai/config_manager.py index 82ef03126..8d2812510 100644 --- a/packages/jupyter-ai/jupyter_ai/config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/config_manager.py @@ -105,11 +105,21 @@ def __init__( blocked_providers: Optional[List[str]], allowed_models: Optional[List[str]], blocked_models: Optional[List[str]], + restrictions: ProviderRestrictions, + provider_defaults: dict, *args, **kwargs, ): super().__init__(*args, **kwargs) self.log = log + """List of LM providers.""" + self._lm_providers = lm_providers + """List of EM providers.""" + self._em_providers = em_providers + """Provider restrictions.""" + self._restrictions = restrictions + """Provider defaults.""" + self._provider_defaults = provider_defaults self._lm_providers = lm_providers """List of LM providers.""" @@ -146,6 +156,7 @@ def _init_validator(self) -> Validator: self.validator = Validator(schema) def _init_config(self): + default_dict = self._init_defaults() if os.path.exists(self.config_path): self._process_existing_config() else: @@ -195,11 +206,18 @@ def _validate_lm_em_id(self, config): def _create_default_config(self): properties = self.validator.schema.get("properties", {}) field_list = GlobalConfig.__fields__.keys() + properties = self.validator.schema.get("properties", {}) field_dict = { field: properties.get(field).get("default") for field in field_list } - default_config = GlobalConfig(**field_dict) - self._write_config(default_config) + if self._provider_defaults is None: + return field_dict + + for field in field_list: + default_value = self._provider_defaults.get(field) + if default_value is not None: + field_dict[field] = default_value + return field_dict def _read_config(self) -> GlobalConfig: """Returns the user's current configuration as a GlobalConfig object. diff --git a/packages/jupyter-ai/jupyter_ai/extension.py b/packages/jupyter-ai/jupyter_ai/extension.py index e3958fc7b..f4f4ecba3 100644 --- a/packages/jupyter-ai/jupyter_ai/extension.py +++ b/packages/jupyter-ai/jupyter_ai/extension.py @@ -106,6 +106,36 @@ class AiExtension(ExtensionApp): config=True, ) + model_provider_id = Unicode( + default_value=None, + allow_none=True, + help="Default language model provider.", + config=True, + ) + + embeddings_provider_id = Unicode( + default_value=None, + allow_none=True, + help="Default embeddings model provider.", + config=True, + ) + + api_keys = Dict( + Unicode(), + Unicode(), + default_value=None, + allow_none=True, + help="API keys for language model providers.", + config=True, + ) + + fields = Dict( + default_value=None, + allow_none=True, + help="Sub fields required for language model providers.", + config=True, + ) + def initialize_settings(self): start = time.time() @@ -124,6 +154,14 @@ def initialize_settings(self): self.settings["model_parameters"] = self.model_parameters self.log.info(f"Configured model parameters: {self.model_parameters}") + + provider_defaults = { + "model_provider_id": self.model_provider_id, + "embeddings_provider_id": self.embeddings_provider_id, + "api_keys": self.api_keys, + "fields": self.fields, + } + # Fetch LM & EM providers self.settings["lm_providers"] = get_lm_providers( log=self.log, restrictions=restrictions @@ -142,6 +180,8 @@ def initialize_settings(self): blocked_providers=self.blocked_providers, allowed_models=self.allowed_models, blocked_models=self.blocked_models, + restrictions=restrictions, + provider_defaults=provider_defaults, ) self.log.info("Registered providers.") diff --git a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py index eeddfff88..7a0d3544f 100644 --- a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py @@ -41,6 +41,35 @@ def common_cm_kwargs(config_path, schema_path): "blocked_providers": None, "allowed_models": None, "blocked_models": None, + "restrictions": {"allowed_providers": None, "blocked_providers": None}, + "provider_defaults": { + "model_provider_id": None, + "embeddings_provider_id": None, + "api_keys": None, + "fields": None, + } + } + + +@pytest.fixture +def cm_kargs_with_defaults(config_path, schema_path): + """Kwargs that are commonly used when initializing the CM.""" + log = logging.getLogger() + lm_providers = get_lm_providers() + em_providers = get_em_providers() + return { + "log": log, + "lm_providers": lm_providers, + "em_providers": em_providers, + "config_path": config_path, + "schema_path": schema_path, + "restrictions": {"allowed_providers": None, "blocked_providers": None}, + "provider_defaults": { + "model_provider_id": "bedrock-chat:anthropic.claude-v1", + "embeddings_provider_id": "bedrock:amazon.titan-embed-text-v1", + "api_keys": {"OPENAI_API_KEY": "open-ai-key-value"}, + "fields": {"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}}, + } } @@ -69,6 +98,10 @@ def cm_with_allowlists(common_cm_kwargs): } return ConfigManager(**kwargs) +def cm_with_defaults(cm_kargs_with_defaults): + """The default ConfigManager instance, with an empty config and config schema.""" + return ConfigManager(**cm_kargs_with_defaults) + @pytest.fixture(autouse=True) def reset(config_path, schema_path): @@ -183,6 +216,40 @@ def test_init_with_allowlists(cm: ConfigManager, common_cm_kwargs): assert test_cm.lm_gid == None assert test_cm.em_gid == None +def test_init_with_default_values( + cm_with_defaults: ConfigManager, config_path: str, schema_path: str +): + """ + Test that the ConfigManager initializes with the expected default values. + + Args: + cm_with_defaults (ConfigManager): A ConfigManager instance with default values. + config_path (str): The path to the configuration file. + schema_path (str): The path to the schema file. + """ + config_response = cm_with_defaults.get_config() + #assert config response + assert config_response.model_provider_id == "bedrock-chat:anthropic.claude-v1" + assert config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" + assert config_response.api_keys == ["OPENAI_API_KEY"] + assert config_response.fields == {"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}} + + del cm_with_defaults + + log = logging.getLogger() + lm_providers = get_lm_providers() + em_providers = get_em_providers() + cm_with_defaults_override =ConfigManager( + log=log, + lm_providers=lm_providers, + em_providers=em_providers, + config_path=config_path, + schema_path=schema_path, + restrictions={"allowed_providers": None, "blocked_providers": None}, + provider_defaults={"model_provider_id": "bedrock-chat:anthropic.claude-v2"}, + ) + + def test_init_with_default_values( cm_with_defaults: ConfigManager, config_path: str, schema_path: str ): From 8b1924e8ff002179fe81a53966a097f39382ca30 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 05:34:42 +0000 Subject: [PATCH 03/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- packages/jupyter-ai/jupyter_ai/extension.py | 1 - .../jupyter_ai/tests/test_config_manager.py | 55 +++++++++++++------ 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/packages/jupyter-ai/jupyter_ai/extension.py b/packages/jupyter-ai/jupyter_ai/extension.py index f4f4ecba3..e8579c391 100644 --- a/packages/jupyter-ai/jupyter_ai/extension.py +++ b/packages/jupyter-ai/jupyter_ai/extension.py @@ -154,7 +154,6 @@ def initialize_settings(self): self.settings["model_parameters"] = self.model_parameters self.log.info(f"Configured model parameters: {self.model_parameters}") - provider_defaults = { "model_provider_id": self.model_provider_id, "embeddings_provider_id": self.embeddings_provider_id, diff --git a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py index 7a0d3544f..849c04ee5 100644 --- a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py @@ -47,7 +47,7 @@ def common_cm_kwargs(config_path, schema_path): "embeddings_provider_id": None, "api_keys": None, "fields": None, - } + }, } @@ -68,8 +68,13 @@ def cm_kargs_with_defaults(config_path, schema_path): "model_provider_id": "bedrock-chat:anthropic.claude-v1", "embeddings_provider_id": "bedrock:amazon.titan-embed-text-v1", "api_keys": {"OPENAI_API_KEY": "open-ai-key-value"}, - "fields": {"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}}, - } + "fields": { + "bedrock-chat:anthropic.claude-v1": { + "credentials_profile_name": "default", + "region_name": "us-west-2", + } + }, + }, } @@ -98,6 +103,7 @@ def cm_with_allowlists(common_cm_kwargs): } return ConfigManager(**kwargs) + def cm_with_defaults(cm_kargs_with_defaults): """The default ConfigManager instance, with an empty config and config schema.""" return ConfigManager(**cm_kargs_with_defaults) @@ -216,8 +222,9 @@ def test_init_with_allowlists(cm: ConfigManager, common_cm_kwargs): assert test_cm.lm_gid == None assert test_cm.em_gid == None + def test_init_with_default_values( - cm_with_defaults: ConfigManager, config_path: str, schema_path: str + cm_with_defaults: ConfigManager, config_path: str, schema_path: str ): """ Test that the ConfigManager initializes with the expected default values. @@ -228,18 +235,25 @@ def test_init_with_default_values( schema_path (str): The path to the schema file. """ config_response = cm_with_defaults.get_config() - #assert config response + # assert config response assert config_response.model_provider_id == "bedrock-chat:anthropic.claude-v1" - assert config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" + assert ( + config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" + ) assert config_response.api_keys == ["OPENAI_API_KEY"] - assert config_response.fields == {"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}} + assert config_response.fields == { + "bedrock-chat:anthropic.claude-v1": { + "credentials_profile_name": "default", + "region_name": "us-west-2", + } + } del cm_with_defaults log = logging.getLogger() lm_providers = get_lm_providers() em_providers = get_em_providers() - cm_with_defaults_override =ConfigManager( + cm_with_defaults_override = ConfigManager( log=log, lm_providers=lm_providers, em_providers=em_providers, @@ -251,7 +265,7 @@ def test_init_with_default_values( def test_init_with_default_values( - cm_with_defaults: ConfigManager, config_path: str, schema_path: str + cm_with_defaults: ConfigManager, config_path: str, schema_path: str ): """ Test that the ConfigManager initializes with the expected default values. @@ -262,18 +276,25 @@ def test_init_with_default_values( schema_path (str): The path to the schema file. """ config_response = cm_with_defaults.get_config() - #assert config response + # assert config response assert config_response.model_provider_id == "bedrock-chat:anthropic.claude-v1" - assert config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" + assert ( + config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" + ) assert config_response.api_keys == ["OPENAI_API_KEY"] - assert config_response.fields == {"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}} + assert config_response.fields == { + "bedrock-chat:anthropic.claude-v1": { + "credentials_profile_name": "default", + "region_name": "us-west-2", + } + } del cm_with_defaults log = logging.getLogger() lm_providers = get_lm_providers() em_providers = get_em_providers() - cm_with_defaults_override =ConfigManager( + cm_with_defaults_override = ConfigManager( log=log, lm_providers=lm_providers, em_providers=em_providers, @@ -283,10 +304,10 @@ def test_init_with_default_values( provider_defaults={"model_provider_id": "bedrock-chat:anthropic.claude-v2"}, ) - assert cm_with_defaults_override.get_config().model_provider_id == "bedrock-chat:anthropic.claude-v2" - - - + assert ( + cm_with_defaults_override.get_config().model_provider_id + == "bedrock-chat:anthropic.claude-v2" + ) def test_property_access_on_default_config(cm: ConfigManager): From 8ab53f391ffc96d60ca05b785d5d58512da40ba0 Mon Sep 17 00:00:00 2001 From: Ayush Khatri Date: Sun, 29 Oct 2023 16:21:27 -0700 Subject: [PATCH 04/13] Setting default model providers --- docs/source/users/index.md | 16 +--- .../jupyter-ai/jupyter_ai/config_manager.py | 25 ++++--- packages/jupyter-ai/jupyter_ai/extension.py | 28 +++---- .../jupyter_ai/tests/test_config_manager.py | 75 ++++++++++++++++++- 4 files changed, 99 insertions(+), 45 deletions(-) diff --git a/docs/source/users/index.md b/docs/source/users/index.md index b9e5e4452..71a60e994 100644 --- a/docs/source/users/index.md +++ b/docs/source/users/index.md @@ -765,27 +765,15 @@ The `--response-path` option is a [JSONPath](https://goessner.net/articles/JsonP You can specify an allowlist, to only allow only a certain list of providers, or a blocklist, to block some providers. -### Initializing default providers +### Initializing default model providers -This configuration allows for setting a default model, and embedding provider with their corresponding API keys, or related fields configuration. +This configuration allows for setting a default model, and embedding provider with their corresponding API keys. Following command line arguments can be used to initialize Jupyter AI extension with default providers: 1. ```--AiExtension.model_provider_id```: Specify the default LLM model. E.g.: ```--AiExtension.model_provider_id="bedrock-chat:anthropic.claude-v2"``` 2. ```--AiExtension.embeddings_provider_id```: Specify default embedding provider. E.g.: ```--AiExtension.embeddings_provider_id="bedrock:amazon.titan-embed-text-v1"``` 3. ```--AiExtension.api_keys```: Specify model provider keys in a JSON format. E.g. ```--AiExtension.api_keys='{"OPENAI_API_KEY": "sk-abcd}'``` -4. ```--AiExtension.fields```: Specify additional configuration required for a LLM, and embedding model. E.g: ```--AiExtension.fields='{"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"},"bedrock:amazon.titan-embed-text-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}}'``` -#### Initializing model provider with API keys - -``` - jupyter lab --AiExtension.model_provider_id="bedrock-chat:anthropic.claude-v1" --AiExtension.fields='{"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"},"bedrock:amazon.titan-embed-text-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}}' --AiExtension.api_keys='{"OPENAI_API_KEY": "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"} -``` - -#### Initializing model provider which requires additional fields - -``` - jupyter lab --AiExtension.model_provider_id="bedrock-chat:anthropic.claude-v1" --AiExtension.fields='{"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"},"bedrock:amazon.titan-embed-text-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}}' --AiExtension.api_keys='{"OPENAI_API_KEY": "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"} -``` ### Blocklisting providers diff --git a/packages/jupyter-ai/jupyter_ai/config_manager.py b/packages/jupyter-ai/jupyter_ai/config_manager.py index 8d2812510..33e733af9 100644 --- a/packages/jupyter-ai/jupyter_ai/config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/config_manager.py @@ -105,7 +105,6 @@ def __init__( blocked_providers: Optional[List[str]], allowed_models: Optional[List[str]], blocked_models: Optional[List[str]], - restrictions: ProviderRestrictions, provider_defaults: dict, *args, **kwargs, @@ -116,10 +115,6 @@ def __init__( self._lm_providers = lm_providers """List of EM providers.""" self._em_providers = em_providers - """Provider restrictions.""" - self._restrictions = restrictions - """Provider defaults.""" - self._provider_defaults = provider_defaults self._lm_providers = lm_providers """List of LM providers.""" @@ -130,6 +125,8 @@ def __init__( self._blocked_providers = blocked_providers self._allowed_models = allowed_models self._blocked_models = blocked_models + """Provider defaults.""" + self._provider_defaults = provider_defaults self._last_read: Optional[int] = None """When the server last read the config file. If the file was not @@ -156,15 +153,17 @@ def _init_validator(self) -> Validator: self.validator = Validator(schema) def _init_config(self): - default_dict = self._init_defaults() + default_config = self._init_defaults() if os.path.exists(self.config_path): - self._process_existing_config() + self._process_existing_config(default_config) else: - self._create_default_config() + self._create_default_config(default_config) - def _process_existing_config(self): + def _process_existing_config(self, default_config): with open(self.config_path, encoding="utf-8") as f: - config = GlobalConfig(**json.loads(f.read())) + existing_config = json.loads(f.read()) + merged_config = {**existing_config, **default_config} + config = GlobalConfig(**merged_config) validated_config = self._validate_lm_em_id(config) # re-write to the file to validate the config and apply any @@ -203,8 +202,10 @@ def _validate_lm_em_id(self, config): return config - def _create_default_config(self): - properties = self.validator.schema.get("properties", {}) + def _create_default_config(self, default_config): + self._write_config(GlobalConfig(**default_config)) + + def _init_defaults(self): field_list = GlobalConfig.__fields__.keys() properties = self.validator.schema.get("properties", {}) field_dict = { diff --git a/packages/jupyter-ai/jupyter_ai/extension.py b/packages/jupyter-ai/jupyter_ai/extension.py index e8579c391..c0007d876 100644 --- a/packages/jupyter-ai/jupyter_ai/extension.py +++ b/packages/jupyter-ai/jupyter_ai/extension.py @@ -86,6 +86,15 @@ class AiExtension(ExtensionApp): config=True, ) + api_keys = Dict( + key_trait=Unicode(), + value_trait=Unicode(), + default_value=None, + allow_none=True, + help="API keys for language model providers.", + config=True, + ) + model_parameters = Dict( key_trait=Unicode(), value_trait=Dict(), @@ -120,22 +129,6 @@ class AiExtension(ExtensionApp): config=True, ) - api_keys = Dict( - Unicode(), - Unicode(), - default_value=None, - allow_none=True, - help="API keys for language model providers.", - config=True, - ) - - fields = Dict( - default_value=None, - allow_none=True, - help="Sub fields required for language model providers.", - config=True, - ) - def initialize_settings(self): start = time.time() @@ -158,7 +151,7 @@ def initialize_settings(self): "model_provider_id": self.model_provider_id, "embeddings_provider_id": self.embeddings_provider_id, "api_keys": self.api_keys, - "fields": self.fields, + "fields": self.model_parameters, } # Fetch LM & EM providers @@ -179,7 +172,6 @@ def initialize_settings(self): blocked_providers=self.blocked_providers, allowed_models=self.allowed_models, blocked_models=self.blocked_models, - restrictions=restrictions, provider_defaults=provider_defaults, ) diff --git a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py index 849c04ee5..9f0349b1c 100644 --- a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py @@ -47,7 +47,7 @@ def common_cm_kwargs(config_path, schema_path): "embeddings_provider_id": None, "api_keys": None, "fields": None, - }, + } } @@ -103,6 +103,10 @@ def cm_with_allowlists(common_cm_kwargs): } return ConfigManager(**kwargs) +def cm_with_defaults(cm_kargs_with_defaults): + """The default ConfigManager instance, with an empty config and config schema.""" + return ConfigManager(**cm_kargs_with_defaults) + def cm_with_defaults(cm_kargs_with_defaults): """The default ConfigManager instance, with an empty config and config schema.""" @@ -222,6 +226,75 @@ def test_init_with_allowlists(cm: ConfigManager, common_cm_kwargs): assert test_cm.lm_gid == None assert test_cm.em_gid == None +def test_init_with_default_values( + cm_with_defaults: ConfigManager, config_path: str, schema_path: str +): + """ + Test that the ConfigManager initializes with the expected default values. + + Args: + cm_with_defaults (ConfigManager): A ConfigManager instance with default values. + config_path (str): The path to the configuration file. + schema_path (str): The path to the schema file. + """ + config_response = cm_with_defaults.get_config() + #assert config response + assert config_response.model_provider_id == "bedrock-chat:anthropic.claude-v1" + assert config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" + assert config_response.api_keys == ["OPENAI_API_KEY"] + assert config_response.fields == {"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}} + + del cm_with_defaults + + log = logging.getLogger() + lm_providers = get_lm_providers() + em_providers = get_em_providers() + cm_with_defaults_override =ConfigManager( + log=log, + lm_providers=lm_providers, + em_providers=em_providers, + config_path=config_path, + schema_path=schema_path, + restrictions={"allowed_providers": None, "blocked_providers": None}, + provider_defaults={"model_provider_id": "bedrock-chat:anthropic.claude-v2"}, + ) + + +def test_init_with_default_values( + cm_with_defaults: ConfigManager, config_path: str, schema_path: str +): + """ + Test that the ConfigManager initializes with the expected default values. + + Args: + cm_with_defaults (ConfigManager): A ConfigManager instance with default values. + config_path (str): The path to the configuration file. + schema_path (str): The path to the schema file. + """ + config_response = cm_with_defaults.get_config() + #assert config response + assert config_response.model_provider_id == "bedrock-chat:anthropic.claude-v1" + assert config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" + assert config_response.api_keys == ["OPENAI_API_KEY"] + assert config_response.fields == {"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}} + + del cm_with_defaults + + log = logging.getLogger() + lm_providers = get_lm_providers() + em_providers = get_em_providers() + cm_with_defaults_override =ConfigManager( + log=log, + lm_providers=lm_providers, + em_providers=em_providers, + config_path=config_path, + schema_path=schema_path, + restrictions={"allowed_providers": None, "blocked_providers": None}, + provider_defaults={"model_provider_id": "bedrock-chat:anthropic.claude-v2"}, + ) + + assert cm_with_defaults_override.get_config().model_provider_id == "bedrock-chat:anthropic.claude-v2" + def test_init_with_default_values( cm_with_defaults: ConfigManager, config_path: str, schema_path: str From f514ea4cc42c7b8038d15c5650b6a9f591c49552 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 07:48:36 +0000 Subject: [PATCH 05/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../jupyter_ai/tests/test_config_manager.py | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py index 9f0349b1c..ce2ae5786 100644 --- a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py @@ -47,7 +47,7 @@ def common_cm_kwargs(config_path, schema_path): "embeddings_provider_id": None, "api_keys": None, "fields": None, - } + }, } @@ -103,6 +103,7 @@ def cm_with_allowlists(common_cm_kwargs): } return ConfigManager(**kwargs) + def cm_with_defaults(cm_kargs_with_defaults): """The default ConfigManager instance, with an empty config and config schema.""" return ConfigManager(**cm_kargs_with_defaults) @@ -226,8 +227,9 @@ def test_init_with_allowlists(cm: ConfigManager, common_cm_kwargs): assert test_cm.lm_gid == None assert test_cm.em_gid == None + def test_init_with_default_values( - cm_with_defaults: ConfigManager, config_path: str, schema_path: str + cm_with_defaults: ConfigManager, config_path: str, schema_path: str ): """ Test that the ConfigManager initializes with the expected default values. @@ -238,18 +240,25 @@ def test_init_with_default_values( schema_path (str): The path to the schema file. """ config_response = cm_with_defaults.get_config() - #assert config response + # assert config response assert config_response.model_provider_id == "bedrock-chat:anthropic.claude-v1" - assert config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" + assert ( + config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" + ) assert config_response.api_keys == ["OPENAI_API_KEY"] - assert config_response.fields == {"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}} + assert config_response.fields == { + "bedrock-chat:anthropic.claude-v1": { + "credentials_profile_name": "default", + "region_name": "us-west-2", + } + } del cm_with_defaults log = logging.getLogger() lm_providers = get_lm_providers() em_providers = get_em_providers() - cm_with_defaults_override =ConfigManager( + cm_with_defaults_override = ConfigManager( log=log, lm_providers=lm_providers, em_providers=em_providers, @@ -261,7 +270,7 @@ def test_init_with_default_values( def test_init_with_default_values( - cm_with_defaults: ConfigManager, config_path: str, schema_path: str + cm_with_defaults: ConfigManager, config_path: str, schema_path: str ): """ Test that the ConfigManager initializes with the expected default values. @@ -272,18 +281,25 @@ def test_init_with_default_values( schema_path (str): The path to the schema file. """ config_response = cm_with_defaults.get_config() - #assert config response + # assert config response assert config_response.model_provider_id == "bedrock-chat:anthropic.claude-v1" - assert config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" + assert ( + config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" + ) assert config_response.api_keys == ["OPENAI_API_KEY"] - assert config_response.fields == {"bedrock-chat:anthropic.claude-v1":{"credentials_profile_name": "default","region_name": "us-west-2"}} + assert config_response.fields == { + "bedrock-chat:anthropic.claude-v1": { + "credentials_profile_name": "default", + "region_name": "us-west-2", + } + } del cm_with_defaults log = logging.getLogger() lm_providers = get_lm_providers() em_providers = get_em_providers() - cm_with_defaults_override =ConfigManager( + cm_with_defaults_override = ConfigManager( log=log, lm_providers=lm_providers, em_providers=em_providers, @@ -293,7 +309,10 @@ def test_init_with_default_values( provider_defaults={"model_provider_id": "bedrock-chat:anthropic.claude-v2"}, ) - assert cm_with_defaults_override.get_config().model_provider_id == "bedrock-chat:anthropic.claude-v2" + assert ( + cm_with_defaults_override.get_config().model_provider_id + == "bedrock-chat:anthropic.claude-v2" + ) def test_init_with_default_values( From 09a49b8e41dfe10d5194bfd139c0974fd7878c7c Mon Sep 17 00:00:00 2001 From: Ayush Khatri Date: Mon, 22 Jan 2024 23:56:18 -0800 Subject: [PATCH 06/13] Added default_ prefix to new attributes --- packages/jupyter-ai/jupyter_ai/extension.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/jupyter-ai/jupyter_ai/extension.py b/packages/jupyter-ai/jupyter_ai/extension.py index c0007d876..69313f835 100644 --- a/packages/jupyter-ai/jupyter_ai/extension.py +++ b/packages/jupyter-ai/jupyter_ai/extension.py @@ -86,7 +86,7 @@ class AiExtension(ExtensionApp): config=True, ) - api_keys = Dict( + default_api_keys = Dict( key_trait=Unicode(), value_trait=Unicode(), default_value=None, @@ -115,14 +115,14 @@ class AiExtension(ExtensionApp): config=True, ) - model_provider_id = Unicode( + default_model_provider_id = Unicode( default_value=None, allow_none=True, help="Default language model provider.", config=True, ) - embeddings_provider_id = Unicode( + default_embeddings_provider_id = Unicode( default_value=None, allow_none=True, help="Default embeddings model provider.", @@ -148,9 +148,9 @@ def initialize_settings(self): self.log.info(f"Configured model parameters: {self.model_parameters}") provider_defaults = { - "model_provider_id": self.model_provider_id, - "embeddings_provider_id": self.embeddings_provider_id, - "api_keys": self.api_keys, + "model_provider_id": self.default_model_provider_id, + "embeddings_provider_id": self.default_embeddings_provider_id, + "api_keys": self.default_api_keys, "fields": self.model_parameters, } From 00f23aadf105a4044a23a8f37b30dc952554f888 Mon Sep 17 00:00:00 2001 From: Ayush Khatri Date: Mon, 22 Jan 2024 23:57:56 -0800 Subject: [PATCH 07/13] Added default_ prefix to docs as well --- docs/source/users/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/users/index.md b/docs/source/users/index.md index 71a60e994..9c5d325d3 100644 --- a/docs/source/users/index.md +++ b/docs/source/users/index.md @@ -770,9 +770,9 @@ a blocklist, to block some providers. This configuration allows for setting a default model, and embedding provider with their corresponding API keys. Following command line arguments can be used to initialize Jupyter AI extension with default providers: -1. ```--AiExtension.model_provider_id```: Specify the default LLM model. E.g.: ```--AiExtension.model_provider_id="bedrock-chat:anthropic.claude-v2"``` -2. ```--AiExtension.embeddings_provider_id```: Specify default embedding provider. E.g.: ```--AiExtension.embeddings_provider_id="bedrock:amazon.titan-embed-text-v1"``` -3. ```--AiExtension.api_keys```: Specify model provider keys in a JSON format. E.g. ```--AiExtension.api_keys='{"OPENAI_API_KEY": "sk-abcd}'``` +1. ```--AiExtension.default_model_provider_id```: Specify the default LLM model. E.g.: ```--AiExtension.model_provider_id="bedrock-chat:anthropic.claude-v2"``` +2. ```--AiExtension.default_embeddings_provider_id```: Specify default embedding provider. E.g.: ```--AiExtension.embeddings_provider_id="bedrock:amazon.titan-embed-text-v1"``` +3. ```--AiExtension.default_api_keys```: Specify model provider keys in a JSON format. E.g. ```--AiExtension.api_keys='{"OPENAI_API_KEY": "sk-abcd}'``` ### Blocklisting providers From bad649ab600b5d820b868534bcd23a210c403dd2 Mon Sep 17 00:00:00 2001 From: Ayush Khatri Date: Mon, 22 Jan 2024 23:59:03 -0800 Subject: [PATCH 08/13] Fix docs --- docs/source/users/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/users/index.md b/docs/source/users/index.md index 9c5d325d3..02714d3a7 100644 --- a/docs/source/users/index.md +++ b/docs/source/users/index.md @@ -770,9 +770,9 @@ a blocklist, to block some providers. This configuration allows for setting a default model, and embedding provider with their corresponding API keys. Following command line arguments can be used to initialize Jupyter AI extension with default providers: -1. ```--AiExtension.default_model_provider_id```: Specify the default LLM model. E.g.: ```--AiExtension.model_provider_id="bedrock-chat:anthropic.claude-v2"``` -2. ```--AiExtension.default_embeddings_provider_id```: Specify default embedding provider. E.g.: ```--AiExtension.embeddings_provider_id="bedrock:amazon.titan-embed-text-v1"``` -3. ```--AiExtension.default_api_keys```: Specify model provider keys in a JSON format. E.g. ```--AiExtension.api_keys='{"OPENAI_API_KEY": "sk-abcd}'``` +1. ```--AiExtension.default_model_provider_id```: Specify the default LLM model. E.g.: ```--AiExtension.default_model_provider_id="bedrock-chat:anthropic.claude-v2"``` +2. ```--AiExtension.default_embeddings_provider_id```: Specify default embedding provider. E.g.: ```--AiExtension.default_embeddings_provider_id="bedrock:amazon.titan-embed-text-v1"``` +3. ```--AiExtension.default_api_keys```: Specify model provider keys in a JSON format. E.g. ```--AiExtension.default_api_keys='{"OPENAI_API_KEY": "sk-abcd}'``` ### Blocklisting providers From ff73facf604fe1a4653a11a246818cc586b63cf4 Mon Sep 17 00:00:00 2001 From: Ayush Khatri Date: Tue, 23 Jan 2024 00:01:55 -0800 Subject: [PATCH 09/13] Removed redundant code --- packages/jupyter-ai/jupyter_ai/config_manager.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/jupyter-ai/jupyter_ai/config_manager.py b/packages/jupyter-ai/jupyter_ai/config_manager.py index 33e733af9..b093dfd7e 100644 --- a/packages/jupyter-ai/jupyter_ai/config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/config_manager.py @@ -111,10 +111,6 @@ def __init__( ): super().__init__(*args, **kwargs) self.log = log - """List of LM providers.""" - self._lm_providers = lm_providers - """List of EM providers.""" - self._em_providers = em_providers self._lm_providers = lm_providers """List of LM providers.""" @@ -125,8 +121,8 @@ def __init__( self._blocked_providers = blocked_providers self._allowed_models = allowed_models self._blocked_models = blocked_models - """Provider defaults.""" self._provider_defaults = provider_defaults + """Provider defaults.""" self._last_read: Optional[int] = None """When the server last read the config file. If the file was not From 4d57c3198bfbae1f2a34e9f64a88b367e1e5f035 Mon Sep 17 00:00:00 2001 From: Ayush Khatri Date: Thu, 25 Jan 2024 14:57:28 -0800 Subject: [PATCH 10/13] Incorporated naming related comments --- docs/source/users/index.md | 6 +- .../jupyter-ai/jupyter_ai/config_manager.py | 11 +- packages/jupyter-ai/jupyter_ai/extension.py | 25 +-- .../jupyter_ai/tests/test_config_manager.py | 167 ++---------------- .../jupyter_ai/workspace.code-workspace | 7 + 5 files changed, 43 insertions(+), 173 deletions(-) create mode 100644 packages/jupyter-ai/jupyter_ai/workspace.code-workspace diff --git a/docs/source/users/index.md b/docs/source/users/index.md index 02714d3a7..766bee8bd 100644 --- a/docs/source/users/index.md +++ b/docs/source/users/index.md @@ -770,9 +770,9 @@ a blocklist, to block some providers. This configuration allows for setting a default model, and embedding provider with their corresponding API keys. Following command line arguments can be used to initialize Jupyter AI extension with default providers: -1. ```--AiExtension.default_model_provider_id```: Specify the default LLM model. E.g.: ```--AiExtension.default_model_provider_id="bedrock-chat:anthropic.claude-v2"``` -2. ```--AiExtension.default_embeddings_provider_id```: Specify default embedding provider. E.g.: ```--AiExtension.default_embeddings_provider_id="bedrock:amazon.titan-embed-text-v1"``` -3. ```--AiExtension.default_api_keys```: Specify model provider keys in a JSON format. E.g. ```--AiExtension.default_api_keys='{"OPENAI_API_KEY": "sk-abcd}'``` +1. ```--AiExtension.default_language_model```: Specify the default LLM model. Sample value: ```--AiExtension.default_language_model="bedrock-chat:anthropic.claude-v2"``` +2. ```--AiExtension.default_embedding_model```: Specify default embedding model. Sample value: ```--AiExtension.default_embedding_model="bedrock:amazon.titan-embed-text-v1"``` +3. ```--AiExtension.api_keys```: Specify model keys in a JSON format. Sample CLI argument: ```--AiExtension.api_keys='{"OPENAI_API_KEY": "sk-abcd}'``` ### Blocklisting providers diff --git a/packages/jupyter-ai/jupyter_ai/config_manager.py b/packages/jupyter-ai/jupyter_ai/config_manager.py index b093dfd7e..a786419f8 100644 --- a/packages/jupyter-ai/jupyter_ai/config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/config_manager.py @@ -105,7 +105,7 @@ def __init__( blocked_providers: Optional[List[str]], allowed_models: Optional[List[str]], blocked_models: Optional[List[str]], - provider_defaults: dict, + defaults: dict, *args, **kwargs, ): @@ -121,7 +121,7 @@ def __init__( self._blocked_providers = blocked_providers self._allowed_models = allowed_models self._blocked_models = blocked_models - self._provider_defaults = provider_defaults + self._defaults = defaults """Provider defaults.""" self._last_read: Optional[int] = None @@ -158,7 +158,8 @@ def _init_config(self): def _process_existing_config(self, default_config): with open(self.config_path, encoding="utf-8") as f: existing_config = json.loads(f.read()) - merged_config = {**existing_config, **default_config} + merged_config = Merger.merge(default_config, + {k: v for k, v in existing_config.items() if v is not None}) config = GlobalConfig(**merged_config) validated_config = self._validate_lm_em_id(config) @@ -207,11 +208,11 @@ def _init_defaults(self): field_dict = { field: properties.get(field).get("default") for field in field_list } - if self._provider_defaults is None: + if self._defaults is None: return field_dict for field in field_list: - default_value = self._provider_defaults.get(field) + default_value = self._defaults.get(field) if default_value is not None: field_dict[field] = default_value return field_dict diff --git a/packages/jupyter-ai/jupyter_ai/extension.py b/packages/jupyter-ai/jupyter_ai/extension.py index 69313f835..5c5b3bf41 100644 --- a/packages/jupyter-ai/jupyter_ai/extension.py +++ b/packages/jupyter-ai/jupyter_ai/extension.py @@ -86,12 +86,13 @@ class AiExtension(ExtensionApp): config=True, ) - default_api_keys = Dict( + api_keys = Dict( key_trait=Unicode(), value_trait=Unicode(), default_value=None, allow_none=True, - help="API keys for language model providers.", + help="""API keys for model providers, as a dictionary, in the format + `:`. Defaults to None.""", config=True, ) @@ -115,17 +116,19 @@ class AiExtension(ExtensionApp): config=True, ) - default_model_provider_id = Unicode( + default_language_model = Unicode( default_value=None, allow_none=True, - help="Default language model provider.", + help="""Default language model to use, as string in the format + :, defaults to None.""", config=True, ) - default_embeddings_provider_id = Unicode( + default_embedding_model = Unicode( default_value=None, allow_none=True, - help="Default embeddings model provider.", + help="""Default embedding model to use, as string in the format + :, defaults to None.""", config=True, ) @@ -147,10 +150,10 @@ def initialize_settings(self): self.settings["model_parameters"] = self.model_parameters self.log.info(f"Configured model parameters: {self.model_parameters}") - provider_defaults = { - "model_provider_id": self.default_model_provider_id, - "embeddings_provider_id": self.default_embeddings_provider_id, - "api_keys": self.default_api_keys, + defaults = { + "model_provider_id": self.default_language_model, + "embeddings_provider_id": self.default_embedding_model, + "api_keys": self.api_keys, "fields": self.model_parameters, } @@ -172,7 +175,7 @@ def initialize_settings(self): blocked_providers=self.blocked_providers, allowed_models=self.allowed_models, blocked_models=self.blocked_models, - provider_defaults=provider_defaults, + defaults=defaults, ) self.log.info("Registered providers.") diff --git a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py index ce2ae5786..b6587e741 100644 --- a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py @@ -42,7 +42,7 @@ def common_cm_kwargs(config_path, schema_path): "allowed_models": None, "blocked_models": None, "restrictions": {"allowed_providers": None, "blocked_providers": None}, - "provider_defaults": { + "defaults": { "model_provider_id": None, "embeddings_provider_id": None, "api_keys": None, @@ -52,19 +52,14 @@ def common_cm_kwargs(config_path, schema_path): @pytest.fixture -def cm_kargs_with_defaults(config_path, schema_path): +def cm_kargs_with_defaults(config_path, schema_path, common_cm_kwargs): """Kwargs that are commonly used when initializing the CM.""" log = logging.getLogger() lm_providers = get_lm_providers() em_providers = get_em_providers() return { - "log": log, - "lm_providers": lm_providers, - "em_providers": em_providers, - "config_path": config_path, - "schema_path": schema_path, - "restrictions": {"allowed_providers": None, "blocked_providers": None}, - "provider_defaults": { + **common_cm_kwargs, + "defaults": { "model_provider_id": "bedrock-chat:anthropic.claude-v1", "embeddings_provider_id": "bedrock:amazon.titan-embed-text-v1", "api_keys": {"OPENAI_API_KEY": "open-ai-key-value"}, @@ -103,12 +98,7 @@ def cm_with_allowlists(common_cm_kwargs): } return ConfigManager(**kwargs) - -def cm_with_defaults(cm_kargs_with_defaults): - """The default ConfigManager instance, with an empty config and config schema.""" - return ConfigManager(**cm_kargs_with_defaults) - - +@pytest.fixture def cm_with_defaults(cm_kargs_with_defaults): """The default ConfigManager instance, with an empty config and config schema.""" return ConfigManager(**cm_kargs_with_defaults) @@ -229,95 +219,7 @@ def test_init_with_allowlists(cm: ConfigManager, common_cm_kwargs): def test_init_with_default_values( - cm_with_defaults: ConfigManager, config_path: str, schema_path: str -): - """ - Test that the ConfigManager initializes with the expected default values. - - Args: - cm_with_defaults (ConfigManager): A ConfigManager instance with default values. - config_path (str): The path to the configuration file. - schema_path (str): The path to the schema file. - """ - config_response = cm_with_defaults.get_config() - # assert config response - assert config_response.model_provider_id == "bedrock-chat:anthropic.claude-v1" - assert ( - config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" - ) - assert config_response.api_keys == ["OPENAI_API_KEY"] - assert config_response.fields == { - "bedrock-chat:anthropic.claude-v1": { - "credentials_profile_name": "default", - "region_name": "us-west-2", - } - } - - del cm_with_defaults - - log = logging.getLogger() - lm_providers = get_lm_providers() - em_providers = get_em_providers() - cm_with_defaults_override = ConfigManager( - log=log, - lm_providers=lm_providers, - em_providers=em_providers, - config_path=config_path, - schema_path=schema_path, - restrictions={"allowed_providers": None, "blocked_providers": None}, - provider_defaults={"model_provider_id": "bedrock-chat:anthropic.claude-v2"}, - ) - - -def test_init_with_default_values( - cm_with_defaults: ConfigManager, config_path: str, schema_path: str -): - """ - Test that the ConfigManager initializes with the expected default values. - - Args: - cm_with_defaults (ConfigManager): A ConfigManager instance with default values. - config_path (str): The path to the configuration file. - schema_path (str): The path to the schema file. - """ - config_response = cm_with_defaults.get_config() - # assert config response - assert config_response.model_provider_id == "bedrock-chat:anthropic.claude-v1" - assert ( - config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" - ) - assert config_response.api_keys == ["OPENAI_API_KEY"] - assert config_response.fields == { - "bedrock-chat:anthropic.claude-v1": { - "credentials_profile_name": "default", - "region_name": "us-west-2", - } - } - - del cm_with_defaults - - log = logging.getLogger() - lm_providers = get_lm_providers() - em_providers = get_em_providers() - cm_with_defaults_override = ConfigManager( - log=log, - lm_providers=lm_providers, - em_providers=em_providers, - config_path=config_path, - schema_path=schema_path, - restrictions={"allowed_providers": None, "blocked_providers": None}, - provider_defaults={"model_provider_id": "bedrock-chat:anthropic.claude-v2"}, - ) - - assert ( - cm_with_defaults_override.get_config().model_provider_id - == "bedrock-chat:anthropic.claude-v2" - ) - - -def test_init_with_default_values( - cm_with_defaults: ConfigManager, config_path: str, schema_path: str -): + cm_with_defaults: ConfigManager, config_path: str, schema_path: str, common_cm_kwargs): """ Test that the ConfigManager initializes with the expected default values. @@ -345,60 +247,17 @@ def test_init_with_default_values( log = logging.getLogger() lm_providers = get_lm_providers() em_providers = get_em_providers() - cm_with_defaults_override = ConfigManager( - log=log, - lm_providers=lm_providers, - em_providers=em_providers, - config_path=config_path, - schema_path=schema_path, - restrictions={"allowed_providers": None, "blocked_providers": None}, - provider_defaults={"model_provider_id": "bedrock-chat:anthropic.claude-v2"}, - ) - - -def test_init_with_default_values( - cm_with_defaults: ConfigManager, config_path: str, schema_path: str -): - """ - Test that the ConfigManager initializes with the expected default values. - - Args: - cm_with_defaults (ConfigManager): A ConfigManager instance with default values. - config_path (str): The path to the configuration file. - schema_path (str): The path to the schema file. - """ - config_response = cm_with_defaults.get_config() - # assert config response - assert config_response.model_provider_id == "bedrock-chat:anthropic.claude-v1" - assert ( - config_response.embeddings_provider_id == "bedrock:amazon.titan-embed-text-v1" - ) - assert config_response.api_keys == ["OPENAI_API_KEY"] - assert config_response.fields == { - "bedrock-chat:anthropic.claude-v1": { - "credentials_profile_name": "default", - "region_name": "us-west-2", - } + kwargs = { + **common_cm_kwargs, + "defaults" : { + "model_provider_id": "bedrock-chat:anthropic.claude-v2" + }, } - - del cm_with_defaults - - log = logging.getLogger() - lm_providers = get_lm_providers() - em_providers = get_em_providers() - cm_with_defaults_override = ConfigManager( - log=log, - lm_providers=lm_providers, - em_providers=em_providers, - config_path=config_path, - schema_path=schema_path, - restrictions={"allowed_providers": None, "blocked_providers": None}, - provider_defaults={"model_provider_id": "bedrock-chat:anthropic.claude-v2"}, - ) + cm_with_defaults_override = ConfigManager(**kwargs) assert ( cm_with_defaults_override.get_config().model_provider_id - == "bedrock-chat:anthropic.claude-v2" + == "bedrock-chat:anthropic.claude-v1" ) diff --git a/packages/jupyter-ai/jupyter_ai/workspace.code-workspace b/packages/jupyter-ai/jupyter_ai/workspace.code-workspace new file mode 100644 index 000000000..ec89ccf30 --- /dev/null +++ b/packages/jupyter-ai/jupyter_ai/workspace.code-workspace @@ -0,0 +1,7 @@ +{ + "folders": [ + { + "path": "../../.." + } + ] +} \ No newline at end of file From d5d45023e914f74eda590bd88b992dd65efa9627 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 22:57:43 +0000 Subject: [PATCH 11/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- packages/jupyter-ai/jupyter_ai/config_manager.py | 6 ++++-- .../jupyter_ai/tests/test_config_manager.py | 11 +++++++---- .../jupyter-ai/jupyter_ai/workspace.code-workspace | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/jupyter-ai/jupyter_ai/config_manager.py b/packages/jupyter-ai/jupyter_ai/config_manager.py index a786419f8..01d3fe766 100644 --- a/packages/jupyter-ai/jupyter_ai/config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/config_manager.py @@ -158,8 +158,10 @@ def _init_config(self): def _process_existing_config(self, default_config): with open(self.config_path, encoding="utf-8") as f: existing_config = json.loads(f.read()) - merged_config = Merger.merge(default_config, - {k: v for k, v in existing_config.items() if v is not None}) + merged_config = Merger.merge( + default_config, + {k: v for k, v in existing_config.items() if v is not None}, + ) config = GlobalConfig(**merged_config) validated_config = self._validate_lm_em_id(config) diff --git a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py index b6587e741..9aa16d2f8 100644 --- a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py @@ -98,6 +98,7 @@ def cm_with_allowlists(common_cm_kwargs): } return ConfigManager(**kwargs) + @pytest.fixture def cm_with_defaults(cm_kargs_with_defaults): """The default ConfigManager instance, with an empty config and config schema.""" @@ -219,7 +220,11 @@ def test_init_with_allowlists(cm: ConfigManager, common_cm_kwargs): def test_init_with_default_values( - cm_with_defaults: ConfigManager, config_path: str, schema_path: str, common_cm_kwargs): + cm_with_defaults: ConfigManager, + config_path: str, + schema_path: str, + common_cm_kwargs, +): """ Test that the ConfigManager initializes with the expected default values. @@ -249,9 +254,7 @@ def test_init_with_default_values( em_providers = get_em_providers() kwargs = { **common_cm_kwargs, - "defaults" : { - "model_provider_id": "bedrock-chat:anthropic.claude-v2" - }, + "defaults": {"model_provider_id": "bedrock-chat:anthropic.claude-v2"}, } cm_with_defaults_override = ConfigManager(**kwargs) diff --git a/packages/jupyter-ai/jupyter_ai/workspace.code-workspace b/packages/jupyter-ai/jupyter_ai/workspace.code-workspace index ec89ccf30..5f8d35ba8 100644 --- a/packages/jupyter-ai/jupyter_ai/workspace.code-workspace +++ b/packages/jupyter-ai/jupyter_ai/workspace.code-workspace @@ -4,4 +4,4 @@ "path": "../../.." } ] -} \ No newline at end of file +} From 786a9bf6556fdd8dc60396345d04038a14666e48 Mon Sep 17 00:00:00 2001 From: Ayush Khatri Date: Thu, 25 Jan 2024 15:00:30 -0800 Subject: [PATCH 12/13] Removing unnecessary files --- packages/jupyter-ai/jupyter_ai/workspace.code-workspace | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 packages/jupyter-ai/jupyter_ai/workspace.code-workspace diff --git a/packages/jupyter-ai/jupyter_ai/workspace.code-workspace b/packages/jupyter-ai/jupyter_ai/workspace.code-workspace deleted file mode 100644 index 5f8d35ba8..000000000 --- a/packages/jupyter-ai/jupyter_ai/workspace.code-workspace +++ /dev/null @@ -1,7 +0,0 @@ -{ - "folders": [ - { - "path": "../../.." - } - ] -} From 50e038b339c94474f7d9d08a5fad2cfc1ffe3581 Mon Sep 17 00:00:00 2001 From: Piyush Jain Date: Thu, 25 Jan 2024 19:25:24 -0800 Subject: [PATCH 13/13] Corrected config names, simplified docs. --- docs/source/users/index.md | 24 +++++++++---- packages/jupyter-ai/jupyter_ai/extension.py | 40 ++++++++++++--------- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/docs/source/users/index.md b/docs/source/users/index.md index 766bee8bd..0ec647714 100644 --- a/docs/source/users/index.md +++ b/docs/source/users/index.md @@ -765,14 +765,26 @@ The `--response-path` option is a [JSONPath](https://goessner.net/articles/JsonP You can specify an allowlist, to only allow only a certain list of providers, or a blocklist, to block some providers. -### Initializing default model providers +### Configuring default models and API keys -This configuration allows for setting a default model, and embedding provider with their corresponding API keys. +This configuration allows for setting a default language and embedding models, and their corresponding API keys. +These values are offered as a starting point for users, so they don't have to select the models and API keys, however, +the selections they make in the settings panel will take precedence over these values. -Following command line arguments can be used to initialize Jupyter AI extension with default providers: -1. ```--AiExtension.default_language_model```: Specify the default LLM model. Sample value: ```--AiExtension.default_language_model="bedrock-chat:anthropic.claude-v2"``` -2. ```--AiExtension.default_embedding_model```: Specify default embedding model. Sample value: ```--AiExtension.default_embedding_model="bedrock:amazon.titan-embed-text-v1"``` -3. ```--AiExtension.api_keys```: Specify model keys in a JSON format. Sample CLI argument: ```--AiExtension.api_keys='{"OPENAI_API_KEY": "sk-abcd}'``` +Specify default language model +``` +jupyter lab --AiExtension.default_language_model=bedrock-chat:anthropic.claude-v2 +``` + +Specify default embedding model +``` +jupyter lab --AiExtension.default_embedding_model=bedrock:amazon.titan-embed-text-v1 +``` + +Specify default API keys +``` +jupyter lab --AiExtension.default_api_keys={'OPENAI_API_KEY': 'sk-abcd'} +``` ### Blocklisting providers diff --git a/packages/jupyter-ai/jupyter_ai/extension.py b/packages/jupyter-ai/jupyter_ai/extension.py index 5c5b3bf41..800c91932 100644 --- a/packages/jupyter-ai/jupyter_ai/extension.py +++ b/packages/jupyter-ai/jupyter_ai/extension.py @@ -86,16 +86,6 @@ class AiExtension(ExtensionApp): config=True, ) - api_keys = Dict( - key_trait=Unicode(), - value_trait=Unicode(), - default_value=None, - allow_none=True, - help="""API keys for model providers, as a dictionary, in the format - `:`. Defaults to None.""", - config=True, - ) - model_parameters = Dict( key_trait=Unicode(), value_trait=Dict(), @@ -119,16 +109,32 @@ class AiExtension(ExtensionApp): default_language_model = Unicode( default_value=None, allow_none=True, - help="""Default language model to use, as string in the format - :, defaults to None.""", + help=""" + Default language model to use, as string in the format + :, defaults to None. + """, + config=True, + ) + + default_embeddings_model = Unicode( + default_value=None, + allow_none=True, + help=""" + Default embeddings model to use, as string in the format + :, defaults to None. + """, config=True, ) - default_embedding_model = Unicode( + default_api_keys = Dict( + key_trait=Unicode(), + value_trait=Unicode(), default_value=None, allow_none=True, - help="""Default embedding model to use, as string in the format - :, defaults to None.""", + help=""" + Default API keys for model providers, as a dictionary, + in the format `:`. Defaults to None. + """, config=True, ) @@ -152,8 +158,8 @@ def initialize_settings(self): defaults = { "model_provider_id": self.default_language_model, - "embeddings_provider_id": self.default_embedding_model, - "api_keys": self.api_keys, + "embeddings_provider_id": self.default_embeddings_model, + "api_keys": self.default_api_keys, "fields": self.model_parameters, }