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."""