diff --git a/docs/source/users/index.md b/docs/source/users/index.md
index 128ef3b23..50420f716 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.
+### Configuring default models and 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.
+
+Specify default language model
+```bash
+jupyter lab --AiExtension.default_language_model=bedrock-chat:anthropic.claude-v2
+```
+
+Specify default embedding model
+```bash
+jupyter lab --AiExtension.default_embeddings_model=bedrock:amazon.titan-embed-text-v1
+```
+
+Specify default API keys
+```bash
+jupyter lab --AiExtension.default_api_keys={'OPENAI_API_KEY': 'sk-abcd'}
+```
+
+
### Blocklisting providers
This configuration allows for blocking specific providers in the settings panel.
diff --git a/examples/commands.ipynb b/examples/commands.ipynb
index b640a7001..0b0c6816c 100644
--- a/examples/commands.ipynb
+++ b/examples/commands.ipynb
@@ -146,8 +146,8 @@
"| `gpt4all` | Not applicable. | N/A | `gpt4all:ggml-gpt4all-j-v1.2-jazzy`, `gpt4all:ggml-gpt4all-j-v1.3-groovy`, `gpt4all:ggml-gpt4all-l13b-snoozy`, `gpt4all:mistral-7b-openorca.Q4_0`, `gpt4all:mistral-7b-instruct-v0.1.Q4_0`, `gpt4all:gpt4all-falcon-q4_0`, `gpt4all:wizardlm-13b-v1.2.Q4_0`, `gpt4all:nous-hermes-llama2-13b.Q4_0`, `gpt4all:gpt4all-13b-snoozy-q4_0`, `gpt4all:mpt-7b-chat-merges-q4_0`, `gpt4all:orca-mini-3b-gguf2-q4_0`, `gpt4all:starcoder-q4_0`, `gpt4all:rift-coder-v0-7b-q4_0`, `gpt4all:em_german_mistral_v01.Q4_0` |\n",
"| `huggingface_hub` | `HUGGINGFACEHUB_API_TOKEN` | ✅ | See [https://huggingface.co/models](https://huggingface.co/models) for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`. |\n",
"| `openai` | `OPENAI_API_KEY` | ✅ | `openai:babbage-002`, `openai:davinci-002`, `openai:gpt-3.5-turbo-instruct` |\n",
- "| `openai-chat` | `OPENAI_API_KEY` | ✅ | `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-1106`, `openai-chat:gpt-3.5-turbo-16k`, `openai-chat:gpt-3.5-turbo-0301`, `openai-chat:gpt-3.5-turbo-0613`, `openai-chat:gpt-3.5-turbo-16k-0613`, `openai-chat:gpt-4`, `openai-chat:gpt-4-0613`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0613`, `openai-chat:gpt-4-1106-preview` |\n",
- "| `qianfan` | `QIANFAN_AK`, `QIANFAN_SK` | ✅ | `qianfan:ERNIE-Bot`, `qianfan:ERNIE-Bot-4` |\n",
+ "| `openai-chat` | `OPENAI_API_KEY` | ✅ | `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-0301`, `openai-chat:gpt-3.5-turbo-0613`, `openai-chat:gpt-3.5-turbo-1106`, `openai-chat:gpt-3.5-turbo-16k`, `openai-chat:gpt-3.5-turbo-16k-0613`, `openai-chat:gpt-4`, `openai-chat:gpt-4-0613`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0613`, `openai-chat:gpt-4-1106-preview` |\n",
+ "| `qianfan` | `QIANFAN_AK`, `QIANFAN_SK` | ❌ | `qianfan:ERNIE-Bot`, `qianfan:ERNIE-Bot-4` |\n",
"| `sagemaker-endpoint` | Not applicable. | N/A | Specify an endpoint name as the model ID. In addition, you must specify a region name, request schema, and response path. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints). |\n",
"\n",
"Aliases and custom commands:\n",
@@ -252,10 +252,10 @@
"openai-chat\n",
"Requires environment variable: OPENAI_API_KEY (set)\n",
"* openai-chat:gpt-3.5-turbo\n",
- "* openai-chat:gpt-3.5-turbo-1106\n",
- "* openai-chat:gpt-3.5-turbo-16k\n",
"* openai-chat:gpt-3.5-turbo-0301\n",
"* openai-chat:gpt-3.5-turbo-0613\n",
+ "* openai-chat:gpt-3.5-turbo-1106\n",
+ "* openai-chat:gpt-3.5-turbo-16k\n",
"* openai-chat:gpt-3.5-turbo-16k-0613\n",
"* openai-chat:gpt-4\n",
"* openai-chat:gpt-4-0613\n",
@@ -264,7 +264,7 @@
"* openai-chat:gpt-4-1106-preview\n",
"\n",
"qianfan\n",
- "Requires environment variables: QIANFAN_AK (set), QIANFAN_SK (set)\n",
+ "Requires environment variables: QIANFAN_AK (not set), QIANFAN_SK (not set)\n",
"* qianfan:ERNIE-Bot\n",
"* qianfan:ERNIE-Bot-4\n",
"\n",
@@ -379,8 +379,8 @@
"| `gpt4all` | Not applicable. | N/A | `gpt4all:ggml-gpt4all-j-v1.2-jazzy`, `gpt4all:ggml-gpt4all-j-v1.3-groovy`, `gpt4all:ggml-gpt4all-l13b-snoozy`, `gpt4all:mistral-7b-openorca.Q4_0`, `gpt4all:mistral-7b-instruct-v0.1.Q4_0`, `gpt4all:gpt4all-falcon-q4_0`, `gpt4all:wizardlm-13b-v1.2.Q4_0`, `gpt4all:nous-hermes-llama2-13b.Q4_0`, `gpt4all:gpt4all-13b-snoozy-q4_0`, `gpt4all:mpt-7b-chat-merges-q4_0`, `gpt4all:orca-mini-3b-gguf2-q4_0`, `gpt4all:starcoder-q4_0`, `gpt4all:rift-coder-v0-7b-q4_0`, `gpt4all:em_german_mistral_v01.Q4_0` |\n",
"| `huggingface_hub` | `HUGGINGFACEHUB_API_TOKEN` | ✅ | See [https://huggingface.co/models](https://huggingface.co/models) for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`. |\n",
"| `openai` | `OPENAI_API_KEY` | ✅ | `openai:babbage-002`, `openai:davinci-002`, `openai:gpt-3.5-turbo-instruct` |\n",
- "| `openai-chat` | `OPENAI_API_KEY` | ✅ | `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-1106`, `openai-chat:gpt-3.5-turbo-16k`, `openai-chat:gpt-3.5-turbo-0301`, `openai-chat:gpt-3.5-turbo-0613`, `openai-chat:gpt-3.5-turbo-16k-0613`, `openai-chat:gpt-4`, `openai-chat:gpt-4-0613`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0613`, `openai-chat:gpt-4-1106-preview` |\n",
- "| `qianfan` | `QIANFAN_AK`, `QIANFAN_SK` | ✅ | `qianfan:ERNIE-Bot`, `qianfan:ERNIE-Bot-4` |\n",
+ "| `openai-chat` | `OPENAI_API_KEY` | ✅ | `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-0301`, `openai-chat:gpt-3.5-turbo-0613`, `openai-chat:gpt-3.5-turbo-1106`, `openai-chat:gpt-3.5-turbo-16k`, `openai-chat:gpt-3.5-turbo-16k-0613`, `openai-chat:gpt-4`, `openai-chat:gpt-4-0613`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0613`, `openai-chat:gpt-4-1106-preview` |\n",
+ "| `qianfan` | `QIANFAN_AK`, `QIANFAN_SK` | ❌ | `qianfan:ERNIE-Bot`, `qianfan:ERNIE-Bot-4` |\n",
"| `sagemaker-endpoint` | Not applicable. | N/A | Specify an endpoint name as the model ID. In addition, you must specify a region name, request schema, and response path. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints). |\n",
"\n",
"Aliases and custom commands:\n",
@@ -486,10 +486,10 @@
"openai-chat\n",
"Requires environment variable: OPENAI_API_KEY (set)\n",
"* openai-chat:gpt-3.5-turbo\n",
- "* openai-chat:gpt-3.5-turbo-1106\n",
- "* openai-chat:gpt-3.5-turbo-16k\n",
"* openai-chat:gpt-3.5-turbo-0301\n",
"* openai-chat:gpt-3.5-turbo-0613\n",
+ "* openai-chat:gpt-3.5-turbo-1106\n",
+ "* openai-chat:gpt-3.5-turbo-16k\n",
"* openai-chat:gpt-3.5-turbo-16k-0613\n",
"* openai-chat:gpt-4\n",
"* openai-chat:gpt-4-0613\n",
@@ -498,7 +498,7 @@
"* openai-chat:gpt-4-1106-preview\n",
"\n",
"qianfan\n",
- "Requires environment variables: QIANFAN_AK (set), QIANFAN_SK (set)\n",
+ "Requires environment variables: QIANFAN_AK (not set), QIANFAN_SK (not set)\n",
"* qianfan:ERNIE-Bot\n",
"* qianfan:ERNIE-Bot-4\n",
"\n",
@@ -537,7 +537,7 @@
{
"data": {
"text/markdown": [
- "As an AI developed by OpenAI, I'm sorry but I can't provide the information you're asking for because your instruction lacks specific details. Could you please provide more context or details?"
+ "Sorry, I can't provide the information you're asking for because your question lacks specific details. Could you please provide more context or information?"
],
"text/plain": [
""
@@ -595,27 +595,15 @@
{
"data": {
"text/markdown": [
- " This means no HTML, tables, images or other formatting. If you generate output, you must use Markdown. See the Markdown Syntax for more information.\n",
+ " I need someone to enter data from a pdf into excel.\n",
"\n",
- "What do you mean by a programming language?\n",
+ "We are looking for an experienced freelancer with very high attention to detail to assist us with a number of tasks. Work includes entering data from a pdf into excel, setting up email template, uploading documents, and general administrative support, such as updating excel sheets with current prices. This is a long-term position. Please provide samples of your work. Please note that we will only accept ...\n",
"\n",
- "A programming language is a formal, scripted language used in a computer system to program subroutines for the system. Programming languages are often used because it is more convenient to program a computer in the programming language than in the programming language itself.\n",
+ "I have a PDF form which I want to extract the text from the forms fields and place it in a word file. The form is in French and the extracted text must be translated to English.\n",
"\n",
- "What is the difference between a programming language and a scripting language?\n",
+ "I have a PDF file which I want to extract the text from the forms fields and place it in a word file. The form is in French and the extracted text must be translated to English.\n",
"\n",
- "A scripting language is a programming language designed to enable a user to create applications that are specific to a particular application, such as a web browser or word processing application. … Languages designed for general use are called scripting languages, and they are also known as a scripting languages.\n",
- "\n",
- "Can you use Python to program?\n",
- "\n",
- "Python is a high-level programming language. … Many developers and programmers use Python to create applications and make use of its functionality. By building applications in Python, you can also become more familiar with the language.\n",
- "\n",
- "What are the 2 types of programming languages?\n",
- "\n",
- "A programming language is a set of rules that can be used to write a computer program. The two most common classification systems for computer languages are procedural and object-oriented.\n",
- "\n",
- "What is the difference between Python and C?\n",
- "\n",
- "C is"
+ "I have a PDF form which I want to extract the text from the forms fields and place it in a word file. The form is in French and the extracted text must be translated to English."
],
"text/plain": [
""
@@ -661,8 +649,8 @@
"| `gpt4all` | Not applicable. | N/A | `gpt4all:ggml-gpt4all-j-v1.2-jazzy`, `gpt4all:ggml-gpt4all-j-v1.3-groovy`, `gpt4all:ggml-gpt4all-l13b-snoozy`, `gpt4all:mistral-7b-openorca.Q4_0`, `gpt4all:mistral-7b-instruct-v0.1.Q4_0`, `gpt4all:gpt4all-falcon-q4_0`, `gpt4all:wizardlm-13b-v1.2.Q4_0`, `gpt4all:nous-hermes-llama2-13b.Q4_0`, `gpt4all:gpt4all-13b-snoozy-q4_0`, `gpt4all:mpt-7b-chat-merges-q4_0`, `gpt4all:orca-mini-3b-gguf2-q4_0`, `gpt4all:starcoder-q4_0`, `gpt4all:rift-coder-v0-7b-q4_0`, `gpt4all:em_german_mistral_v01.Q4_0` |\n",
"| `huggingface_hub` | `HUGGINGFACEHUB_API_TOKEN` | ✅ | See [https://huggingface.co/models](https://huggingface.co/models) for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`. |\n",
"| `openai` | `OPENAI_API_KEY` | ✅ | `openai:babbage-002`, `openai:davinci-002`, `openai:gpt-3.5-turbo-instruct` |\n",
- "| `openai-chat` | `OPENAI_API_KEY` | ✅ | `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-1106`, `openai-chat:gpt-3.5-turbo-16k`, `openai-chat:gpt-3.5-turbo-0301`, `openai-chat:gpt-3.5-turbo-0613`, `openai-chat:gpt-3.5-turbo-16k-0613`, `openai-chat:gpt-4`, `openai-chat:gpt-4-0613`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0613`, `openai-chat:gpt-4-1106-preview` |\n",
- "| `qianfan` | `QIANFAN_AK`, `QIANFAN_SK` | ✅ | `qianfan:ERNIE-Bot`, `qianfan:ERNIE-Bot-4` |\n",
+ "| `openai-chat` | `OPENAI_API_KEY` | ✅ | `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-0301`, `openai-chat:gpt-3.5-turbo-0613`, `openai-chat:gpt-3.5-turbo-1106`, `openai-chat:gpt-3.5-turbo-16k`, `openai-chat:gpt-3.5-turbo-16k-0613`, `openai-chat:gpt-4`, `openai-chat:gpt-4-0613`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0613`, `openai-chat:gpt-4-1106-preview` |\n",
+ "| `qianfan` | `QIANFAN_AK`, `QIANFAN_SK` | ❌ | `qianfan:ERNIE-Bot`, `qianfan:ERNIE-Bot-4` |\n",
"| `sagemaker-endpoint` | Not applicable. | N/A | Specify an endpoint name as the model ID. In addition, you must specify a region name, request schema, and response path. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints). |\n",
"\n",
"Aliases and custom commands:\n",
@@ -768,10 +756,10 @@
"openai-chat\n",
"Requires environment variable: OPENAI_API_KEY (set)\n",
"* openai-chat:gpt-3.5-turbo\n",
- "* openai-chat:gpt-3.5-turbo-1106\n",
- "* openai-chat:gpt-3.5-turbo-16k\n",
"* openai-chat:gpt-3.5-turbo-0301\n",
"* openai-chat:gpt-3.5-turbo-0613\n",
+ "* openai-chat:gpt-3.5-turbo-1106\n",
+ "* openai-chat:gpt-3.5-turbo-16k\n",
"* openai-chat:gpt-3.5-turbo-16k-0613\n",
"* openai-chat:gpt-4\n",
"* openai-chat:gpt-4-0613\n",
@@ -780,7 +768,7 @@
"* openai-chat:gpt-4-1106-preview\n",
"\n",
"qianfan\n",
- "Requires environment variables: QIANFAN_AK (set), QIANFAN_SK (set)\n",
+ "Requires environment variables: QIANFAN_AK (not set), QIANFAN_SK (not set)\n",
"* qianfan:ERNIE-Bot\n",
"* qianfan:ERNIE-Bot-4\n",
"\n",
@@ -857,8 +845,8 @@
"| `gpt4all` | Not applicable. | N/A | `gpt4all:ggml-gpt4all-j-v1.2-jazzy`, `gpt4all:ggml-gpt4all-j-v1.3-groovy`, `gpt4all:ggml-gpt4all-l13b-snoozy`, `gpt4all:mistral-7b-openorca.Q4_0`, `gpt4all:mistral-7b-instruct-v0.1.Q4_0`, `gpt4all:gpt4all-falcon-q4_0`, `gpt4all:wizardlm-13b-v1.2.Q4_0`, `gpt4all:nous-hermes-llama2-13b.Q4_0`, `gpt4all:gpt4all-13b-snoozy-q4_0`, `gpt4all:mpt-7b-chat-merges-q4_0`, `gpt4all:orca-mini-3b-gguf2-q4_0`, `gpt4all:starcoder-q4_0`, `gpt4all:rift-coder-v0-7b-q4_0`, `gpt4all:em_german_mistral_v01.Q4_0` |\n",
"| `huggingface_hub` | `HUGGINGFACEHUB_API_TOKEN` | ✅ | See [https://huggingface.co/models](https://huggingface.co/models) for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`. |\n",
"| `openai` | `OPENAI_API_KEY` | ✅ | `openai:babbage-002`, `openai:davinci-002`, `openai:gpt-3.5-turbo-instruct` |\n",
- "| `openai-chat` | `OPENAI_API_KEY` | ✅ | `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-1106`, `openai-chat:gpt-3.5-turbo-16k`, `openai-chat:gpt-3.5-turbo-0301`, `openai-chat:gpt-3.5-turbo-0613`, `openai-chat:gpt-3.5-turbo-16k-0613`, `openai-chat:gpt-4`, `openai-chat:gpt-4-0613`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0613`, `openai-chat:gpt-4-1106-preview` |\n",
- "| `qianfan` | `QIANFAN_AK`, `QIANFAN_SK` | ✅ | `qianfan:ERNIE-Bot`, `qianfan:ERNIE-Bot-4` |\n",
+ "| `openai-chat` | `OPENAI_API_KEY` | ✅ | `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-0301`, `openai-chat:gpt-3.5-turbo-0613`, `openai-chat:gpt-3.5-turbo-1106`, `openai-chat:gpt-3.5-turbo-16k`, `openai-chat:gpt-3.5-turbo-16k-0613`, `openai-chat:gpt-4`, `openai-chat:gpt-4-0613`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0613`, `openai-chat:gpt-4-1106-preview` |\n",
+ "| `qianfan` | `QIANFAN_AK`, `QIANFAN_SK` | ❌ | `qianfan:ERNIE-Bot`, `qianfan:ERNIE-Bot-4` |\n",
"| `sagemaker-endpoint` | Not applicable. | N/A | Specify an endpoint name as the model ID. In addition, you must specify a region name, request schema, and response path. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints). |\n",
"\n",
"Aliases and custom commands:\n",
@@ -963,10 +951,10 @@
"openai-chat\n",
"Requires environment variable: OPENAI_API_KEY (set)\n",
"* openai-chat:gpt-3.5-turbo\n",
- "* openai-chat:gpt-3.5-turbo-1106\n",
- "* openai-chat:gpt-3.5-turbo-16k\n",
"* openai-chat:gpt-3.5-turbo-0301\n",
"* openai-chat:gpt-3.5-turbo-0613\n",
+ "* openai-chat:gpt-3.5-turbo-1106\n",
+ "* openai-chat:gpt-3.5-turbo-16k\n",
"* openai-chat:gpt-3.5-turbo-16k-0613\n",
"* openai-chat:gpt-4\n",
"* openai-chat:gpt-4-0613\n",
@@ -975,7 +963,7 @@
"* openai-chat:gpt-4-1106-preview\n",
"\n",
"qianfan\n",
- "Requires environment variables: QIANFAN_AK (set), QIANFAN_SK (set)\n",
+ "Requires environment variables: QIANFAN_AK (not set), QIANFAN_SK (not set)\n",
"* qianfan:ERNIE-Bot\n",
"* qianfan:ERNIE-Bot-4\n",
"\n",
@@ -1045,7 +1033,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "{'product': 'colorful socks', 'text': ' Chroma Sox'}\n"
+ "{'product': 'colorful socks', 'text': ' Chroma Socks '}\n"
]
}
],
@@ -1103,8 +1091,8 @@
"| `gpt4all` | Not applicable. | N/A | `gpt4all:ggml-gpt4all-j-v1.2-jazzy`, `gpt4all:ggml-gpt4all-j-v1.3-groovy`, `gpt4all:ggml-gpt4all-l13b-snoozy`, `gpt4all:mistral-7b-openorca.Q4_0`, `gpt4all:mistral-7b-instruct-v0.1.Q4_0`, `gpt4all:gpt4all-falcon-q4_0`, `gpt4all:wizardlm-13b-v1.2.Q4_0`, `gpt4all:nous-hermes-llama2-13b.Q4_0`, `gpt4all:gpt4all-13b-snoozy-q4_0`, `gpt4all:mpt-7b-chat-merges-q4_0`, `gpt4all:orca-mini-3b-gguf2-q4_0`, `gpt4all:starcoder-q4_0`, `gpt4all:rift-coder-v0-7b-q4_0`, `gpt4all:em_german_mistral_v01.Q4_0` |\n",
"| `huggingface_hub` | `HUGGINGFACEHUB_API_TOKEN` | ✅ | See [https://huggingface.co/models](https://huggingface.co/models) for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`. |\n",
"| `openai` | `OPENAI_API_KEY` | ✅ | `openai:babbage-002`, `openai:davinci-002`, `openai:gpt-3.5-turbo-instruct` |\n",
- "| `openai-chat` | `OPENAI_API_KEY` | ✅ | `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-1106`, `openai-chat:gpt-3.5-turbo-16k`, `openai-chat:gpt-3.5-turbo-0301`, `openai-chat:gpt-3.5-turbo-0613`, `openai-chat:gpt-3.5-turbo-16k-0613`, `openai-chat:gpt-4`, `openai-chat:gpt-4-0613`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0613`, `openai-chat:gpt-4-1106-preview` |\n",
- "| `qianfan` | `QIANFAN_AK`, `QIANFAN_SK` | ✅ | `qianfan:ERNIE-Bot`, `qianfan:ERNIE-Bot-4` |\n",
+ "| `openai-chat` | `OPENAI_API_KEY` | ✅ | `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-0301`, `openai-chat:gpt-3.5-turbo-0613`, `openai-chat:gpt-3.5-turbo-1106`, `openai-chat:gpt-3.5-turbo-16k`, `openai-chat:gpt-3.5-turbo-16k-0613`, `openai-chat:gpt-4`, `openai-chat:gpt-4-0613`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0613`, `openai-chat:gpt-4-1106-preview` |\n",
+ "| `qianfan` | `QIANFAN_AK`, `QIANFAN_SK` | ❌ | `qianfan:ERNIE-Bot`, `qianfan:ERNIE-Bot-4` |\n",
"| `sagemaker-endpoint` | Not applicable. | N/A | Specify an endpoint name as the model ID. In addition, you must specify a region name, request schema, and response path. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints). |\n",
"\n",
"Aliases and custom commands:\n",
@@ -1210,10 +1198,10 @@
"openai-chat\n",
"Requires environment variable: OPENAI_API_KEY (set)\n",
"* openai-chat:gpt-3.5-turbo\n",
- "* openai-chat:gpt-3.5-turbo-1106\n",
- "* openai-chat:gpt-3.5-turbo-16k\n",
"* openai-chat:gpt-3.5-turbo-0301\n",
"* openai-chat:gpt-3.5-turbo-0613\n",
+ "* openai-chat:gpt-3.5-turbo-1106\n",
+ "* openai-chat:gpt-3.5-turbo-16k\n",
"* openai-chat:gpt-3.5-turbo-16k-0613\n",
"* openai-chat:gpt-4\n",
"* openai-chat:gpt-4-0613\n",
@@ -1222,7 +1210,7 @@
"* openai-chat:gpt-4-1106-preview\n",
"\n",
"qianfan\n",
- "Requires environment variables: QIANFAN_AK (set), QIANFAN_SK (set)\n",
+ "Requires environment variables: QIANFAN_AK (not set), QIANFAN_SK (not set)\n",
"* qianfan:ERNIE-Bot\n",
"* qianfan:ERNIE-Bot-4\n",
"\n",
@@ -1256,18 +1244,12 @@
"id": "cfef0fee-a7c6-49e4-8d90-9aa12f7b91d1",
"metadata": {},
"outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "/opt/miniconda3/envs/jupyter-ai-jl4/lib/python3.11/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The function `run` was deprecated in LangChain 0.1.0 and will be removed in 0.2.0. Use invoke instead.\n",
- " warn_deprecated(\n"
- ]
- },
{
"data": {
"text/markdown": [
- " Chroma Socks "
+ " Chroma Sox \n",
+ "\n",
+ "Let me know if you would like me to provide any other suggestions! "
],
"text/plain": [
""
@@ -1298,7 +1280,7 @@
{
"data": {
"text/plain": [
- " Chroma Socks "
+ " Punch Up Colorful Fashions"
]
},
"execution_count": 19,
diff --git a/packages/jupyter-ai-magics/jupyter_ai_magics/magics.py b/packages/jupyter-ai-magics/jupyter_ai_magics/magics.py
index f6239fbdf..51b1f3bb9 100644
--- a/packages/jupyter-ai-magics/jupyter_ai_magics/magics.py
+++ b/packages/jupyter-ai-magics/jupyter_ai_magics/magics.py
@@ -481,8 +481,13 @@ def run_ai_cell(self, args: CellArgs, prompt: str):
if args.model_id in self.custom_model_registry and isinstance(
self.custom_model_registry[args.model_id], LLMChain
):
+ # Get the output, either as raw text or as the contents of the 'text' key of a dict
+ invoke_output = self.custom_model_registry[args.model_id].invoke(prompt)
+ if isinstance(invoke_output, dict):
+ invoke_output = invoke_output.get("text")
+
return self.display_output(
- self.custom_model_registry[args.model_id].run(prompt),
+ invoke_output,
args.format,
{"jupyter_ai": {"custom_chain_id": args.model_id}},
)
diff --git a/packages/jupyter-ai-magics/jupyter_ai_magics/providers.py b/packages/jupyter-ai-magics/jupyter_ai_magics/providers.py
index 5762f2560..850e24a99 100644
--- a/packages/jupyter-ai-magics/jupyter_ai_magics/providers.py
+++ b/packages/jupyter-ai-magics/jupyter_ai_magics/providers.py
@@ -11,7 +11,13 @@
from langchain.chat_models.base import BaseChatModel
from langchain.llms.sagemaker_endpoint import LLMContentHandler
from langchain.llms.utils import enforce_stop_tokens
-from langchain.prompts import PromptTemplate
+from langchain.prompts import (
+ ChatPromptTemplate,
+ HumanMessagePromptTemplate,
+ MessagesPlaceholder,
+ PromptTemplate,
+ SystemMessagePromptTemplate,
+)
from langchain.pydantic_v1 import BaseModel, Extra, root_validator
from langchain.schema import LLMResult
from langchain.utils import get_from_dict_or_env
@@ -42,6 +48,49 @@
from pydantic.main import ModelMetaclass
+CHAT_SYSTEM_PROMPT = """
+You are Jupyternaut, a conversational assistant living in JupyterLab to help users.
+You are not a language model, but rather an application built on a foundation model from {provider_name} called {local_model_id}.
+You are talkative and you provide lots of specific details from the foundation model's context.
+You may use Markdown to format your response.
+Code blocks must be formatted in Markdown.
+Math should be rendered with inline TeX markup, surrounded by $.
+If you do not know the answer to a question, answer truthfully by responding that you do not know.
+The following is a friendly conversation between you and a human.
+""".strip()
+
+CHAT_DEFAULT_TEMPLATE = """Current conversation:
+{history}
+Human: {input}
+AI:"""
+
+
+COMPLETION_SYSTEM_PROMPT = """
+You are an application built to provide helpful code completion suggestions.
+You should only produce code. Keep comments to minimum, use the
+programming language comment syntax. Produce clean code.
+The code is written in JupyterLab, a data analysis and code development
+environment which can execute code extended with additional syntax for
+interactive features, such as magics.
+""".strip()
+
+# only add the suffix bit if present to save input tokens/computation time
+COMPLETION_DEFAULT_TEMPLATE = """
+The document is called `{{filename}}` and written in {{language}}.
+{% if suffix %}
+The code after the completion request is:
+
+```
+{{suffix}}
+```
+{% endif %}
+
+Complete the following code:
+
+```
+{{prefix}}"""
+
+
class EnvAuthStrategy(BaseModel):
"""Require one auth token via an environment variable."""
@@ -265,6 +314,55 @@ def get_prompt_template(self, format) -> PromptTemplate:
else:
return self.prompt_templates["text"] # Default to plain format
+ def get_chat_prompt_template(self) -> PromptTemplate:
+ """
+ Produce a prompt template optimised for chat conversation.
+ The template should take two variables: history and input.
+ """
+ name = self.__class__.name
+ if self.is_chat_provider:
+ return ChatPromptTemplate.from_messages(
+ [
+ SystemMessagePromptTemplate.from_template(
+ CHAT_SYSTEM_PROMPT
+ ).format(provider_name=name, local_model_id=self.model_id),
+ MessagesPlaceholder(variable_name="history"),
+ HumanMessagePromptTemplate.from_template("{input}"),
+ ]
+ )
+ else:
+ return PromptTemplate(
+ input_variables=["history", "input"],
+ template=CHAT_SYSTEM_PROMPT.format(
+ provider_name=name, local_model_id=self.model_id
+ )
+ + "\n\n"
+ + CHAT_DEFAULT_TEMPLATE,
+ )
+
+ def get_completion_prompt_template(self) -> PromptTemplate:
+ """
+ Produce a prompt template optimised for inline code or text completion.
+ The template should take variables: prefix, suffix, language, filename.
+ """
+ if self.is_chat_provider:
+ return ChatPromptTemplate.from_messages(
+ [
+ SystemMessagePromptTemplate.from_template(COMPLETION_SYSTEM_PROMPT),
+ HumanMessagePromptTemplate.from_template(
+ COMPLETION_DEFAULT_TEMPLATE, template_format="jinja2"
+ ),
+ ]
+ )
+ else:
+ return PromptTemplate(
+ input_variables=["prefix", "suffix", "language", "filename"],
+ template=COMPLETION_SYSTEM_PROMPT
+ + "\n\n"
+ + COMPLETION_DEFAULT_TEMPLATE,
+ template_format="jinja2",
+ )
+
@property
def is_chat_provider(self):
return isinstance(self, BaseChatModel)
diff --git a/packages/jupyter-ai/jupyter_ai/chat_handlers/default.py b/packages/jupyter-ai/jupyter_ai/chat_handlers/default.py
index 0db83afdd..584f0b33f 100644
--- a/packages/jupyter-ai/jupyter_ai/chat_handlers/default.py
+++ b/packages/jupyter-ai/jupyter_ai/chat_handlers/default.py
@@ -4,32 +4,9 @@
from jupyter_ai_magics.providers import BaseProvider
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferWindowMemory
-from langchain.prompts import (
- ChatPromptTemplate,
- HumanMessagePromptTemplate,
- MessagesPlaceholder,
- PromptTemplate,
- SystemMessagePromptTemplate,
-)
from .base import BaseChatHandler, SlashCommandRoutingType
-SYSTEM_PROMPT = """
-You are Jupyternaut, a conversational assistant living in JupyterLab to help users.
-You are not a language model, but rather an application built on a foundation model from {provider_name} called {local_model_id}.
-You are talkative and you provide lots of specific details from the foundation model's context.
-You may use Markdown to format your response.
-Code blocks must be formatted in Markdown.
-Math should be rendered with inline TeX markup, surrounded by $.
-If you do not know the answer to a question, answer truthfully by responding that you do not know.
-The following is a friendly conversation between you and a human.
-""".strip()
-
-DEFAULT_TEMPLATE = """Current conversation:
-{history}
-Human: {input}
-AI:"""
-
class DefaultChatHandler(BaseChatHandler):
id = "default"
@@ -49,27 +26,10 @@ def create_llm_chain(
model_parameters = self.get_model_parameters(provider, provider_params)
llm = provider(**provider_params, **model_parameters)
- if llm.is_chat_provider:
- prompt_template = ChatPromptTemplate.from_messages(
- [
- SystemMessagePromptTemplate.from_template(SYSTEM_PROMPT).format(
- provider_name=provider.name, local_model_id=llm.model_id
- ),
- MessagesPlaceholder(variable_name="history"),
- HumanMessagePromptTemplate.from_template("{input}"),
- ]
- )
- self.memory = ConversationBufferWindowMemory(return_messages=True, k=2)
- else:
- prompt_template = PromptTemplate(
- input_variables=["history", "input"],
- template=SYSTEM_PROMPT.format(
- provider_name=provider.name, local_model_id=llm.model_id
- )
- + "\n\n"
- + DEFAULT_TEMPLATE,
- )
- self.memory = ConversationBufferWindowMemory(k=2)
+ prompt_template = llm.get_chat_prompt_template()
+ self.memory = ConversationBufferWindowMemory(
+ return_messages=llm.is_chat_provider, k=2
+ )
self.llm = llm
self.llm_chain = ConversationChain(
diff --git a/packages/jupyter-ai/jupyter_ai/completions/handlers/default.py b/packages/jupyter-ai/jupyter_ai/completions/handlers/default.py
index 687e41fed..552d23791 100644
--- a/packages/jupyter-ai/jupyter_ai/completions/handlers/default.py
+++ b/packages/jupyter-ai/jupyter_ai/completions/handlers/default.py
@@ -18,32 +18,6 @@
)
from .base import BaseInlineCompletionHandler
-SYSTEM_PROMPT = """
-You are an application built to provide helpful code completion suggestions.
-You should only produce code. Keep comments to minimum, use the
-programming language comment syntax. Produce clean code.
-The code is written in JupyterLab, a data analysis and code development
-environment which can execute code extended with additional syntax for
-interactive features, such as magics.
-""".strip()
-
-AFTER_TEMPLATE = """
-The code after the completion request is:
-
-```
-{suffix}
-```
-""".strip()
-
-DEFAULT_TEMPLATE = """
-The document is called `{filename}` and written in {language}.
-{after}
-
-Complete the following code:
-
-```
-{prefix}"""
-
class DefaultInlineCompletionHandler(BaseInlineCompletionHandler):
llm_chain: Runnable
@@ -57,18 +31,7 @@ def create_llm_chain(
model_parameters = self.get_model_parameters(provider, provider_params)
llm = provider(**provider_params, **model_parameters)
- if llm.is_chat_provider:
- prompt_template = ChatPromptTemplate.from_messages(
- [
- SystemMessagePromptTemplate.from_template(SYSTEM_PROMPT),
- HumanMessagePromptTemplate.from_template(DEFAULT_TEMPLATE),
- ]
- )
- else:
- prompt_template = PromptTemplate(
- input_variables=["prefix", "suffix", "language", "filename"],
- template=SYSTEM_PROMPT + "\n\n" + DEFAULT_TEMPLATE,
- )
+ prompt_template = llm.get_completion_prompt_template()
self.llm = llm
self.llm_chain = prompt_template | llm | StrOutputParser()
@@ -151,13 +114,11 @@ def _token_from_request(self, request: InlineCompletionRequest, suggestion: int)
def _template_inputs_from_request(self, request: InlineCompletionRequest) -> Dict:
suffix = request.suffix.strip()
- # only add the suffix template if the suffix is there to save input tokens/computation time
- after = AFTER_TEMPLATE.format(suffix=suffix) if suffix else ""
filename = request.path.split("/")[-1] if request.path else "untitled"
return {
"prefix": request.prefix,
- "after": after,
+ "suffix": suffix,
"language": request.language,
"filename": filename,
"stop": ["\n```"],
diff --git a/packages/jupyter-ai/jupyter_ai/config_manager.py b/packages/jupyter-ai/jupyter_ai/config_manager.py
index 82ef03126..01d3fe766 100644
--- a/packages/jupyter-ai/jupyter_ai/config_manager.py
+++ b/packages/jupyter-ai/jupyter_ai/config_manager.py
@@ -105,6 +105,7 @@ def __init__(
blocked_providers: Optional[List[str]],
allowed_models: Optional[List[str]],
blocked_models: Optional[List[str]],
+ defaults: dict,
*args,
**kwargs,
):
@@ -120,6 +121,8 @@ def __init__(
self._blocked_providers = blocked_providers
self._allowed_models = allowed_models
self._blocked_models = blocked_models
+ self._defaults = defaults
+ """Provider defaults."""
self._last_read: Optional[int] = None
"""When the server last read the config file. If the file was not
@@ -146,14 +149,20 @@ def _init_validator(self) -> Validator:
self.validator = Validator(schema)
def _init_config(self):
+ 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 = 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)
# re-write to the file to validate the config and apply any
@@ -192,14 +201,23 @@ 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 = {
field: properties.get(field).get("default") for field in field_list
}
- default_config = GlobalConfig(**field_dict)
- self._write_config(default_config)
+ if self._defaults is None:
+ return field_dict
+
+ for field in field_list:
+ default_value = self._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..800c91932 100644
--- a/packages/jupyter-ai/jupyter_ai/extension.py
+++ b/packages/jupyter-ai/jupyter_ai/extension.py
@@ -106,6 +106,38 @@ class AiExtension(ExtensionApp):
config=True,
)
+ default_language_model = Unicode(
+ default_value=None,
+ allow_none=True,
+ 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_api_keys = Dict(
+ key_trait=Unicode(),
+ value_trait=Unicode(),
+ default_value=None,
+ allow_none=True,
+ help="""
+ Default API keys for model providers, as a dictionary,
+ in the format `:`. Defaults to None.
+ """,
+ config=True,
+ )
+
def initialize_settings(self):
start = time.time()
@@ -124,6 +156,13 @@ def initialize_settings(self):
self.settings["model_parameters"] = self.model_parameters
self.log.info(f"Configured model parameters: {self.model_parameters}")
+ defaults = {
+ "model_provider_id": self.default_language_model,
+ "embeddings_provider_id": self.default_embeddings_model,
+ "api_keys": self.default_api_keys,
+ "fields": self.model_parameters,
+ }
+
# Fetch LM & EM providers
self.settings["lm_providers"] = get_lm_providers(
log=self.log, restrictions=restrictions
@@ -142,6 +181,7 @@ def initialize_settings(self):
blocked_providers=self.blocked_providers,
allowed_models=self.allowed_models,
blocked_models=self.blocked_models,
+ 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 c238fc448..9aa16d2f8 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},
+ "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, 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 {
+ **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"},
+ "fields": {
+ "bedrock-chat:anthropic.claude-v1": {
+ "credentials_profile_name": "default",
+ "region_name": "us-west-2",
+ }
+ },
+ },
}
@@ -70,6 +99,12 @@ 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."""
+ return ConfigManager(**cm_kargs_with_defaults)
+
+
@pytest.fixture(autouse=True)
def reset(config_path, schema_path):
"""Fixture that deletes the config and config schema after each test."""
@@ -184,6 +219,51 @@ def test_init_with_allowlists(cm: ConfigManager, common_cm_kwargs):
assert test_cm.em_gid == None
+def test_init_with_default_values(
+ cm_with_defaults: ConfigManager,
+ config_path: str,
+ schema_path: str,
+ common_cm_kwargs,
+):
+ """
+ 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()
+ kwargs = {
+ **common_cm_kwargs,
+ "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-v1"
+ )
+
+
def test_property_access_on_default_config(cm: ConfigManager):
"""Asserts that the CM behaves well with an empty, default
configuration."""