Skip to content

Commit 2302463

Browse files
dlqqqjonahjung22srdas
authored
Migrate from LangChain to LiteLLM (major upgrade) (#1426)
* [litellm] Initial migration to LiteLLM (#1425) * add new /api/ai/models endpoint * add litellm dependency * add new model ID input component * fix custom model ID input * update ConfigManager to accept litellm model IDs * update Jupyternaut to use litellm * remove LangChain partner packages from dependencies * remove LangChain provider entry points * pre-commit * rename /api/ai/models => /api/ai/models/chat * simplify model settings UI * [litellm] Remove LangChain from source code (#1435) * remove LangChain from jupyter_ai_magics * remove unused useServerInfo() hook in frontend * remove LangChain references from jupyter_ai * remove langchain from test & cookiecutter packages * move all completions code to jupyter_ai.completions * remove LangChain provider code from ConfigManager * minor fixes to allow JAI to start * Implementing model parameters input * Implement new Secrets UI and REST API (#1439) * add EnvSecretsManager and secrets REST API * make ListSecrets endpoint more generic * fix UpdateSecretsRequest type * fix bug where last secret cannot be deleted * remove error log used in dev * add new <SecretsSection /> component * tweak UI appearance * make settings page scrollable, fix #1409 * show no static secrets by default * show something when no secrets are present * adjust language * fix success & error alerts on updating secrets * fix lint * fix bug when .gitignore and .env do not exist * bump to 2s poll interval in EnvSecretsManager * disable model parameters input for now, fix merge conflicts * Adding `magics` functionality to the `litellm` implementation (#1437) * Adding `magics` functionality to the `litellm` implementation * updates for initializing aliases and resolving types, mypy * Update magics.py * init alias * Update test_magics.py * Update magics.py * Changed `error` to `fix` in magics * Update index.md * Update test_magics.py * Update magics.py * streamlining magics * removed update command * initial_chat_model * magics pre-commit * Update magics.py * missing model id in magics (#1457) Thanks David for approving this. * Added sublists for providers using %ai (#1458) * Fix `litellm` branch CI, add `EnvSecretsManager` tests (#1459) * update prettier ignore file * fix prettier errors & warnings * fix mypy errors in jupyter_ai * skip ConfigManager and inline completion tests until fixed in v3 * add tests for secrets manager * fix mypy error * run minimum dependency tests on Python 3.10 * comment out precommit job to be added in future * updated test_magics.py --------- Co-authored-by: Sanjiv Das <[email protected]> * [litellm] Display model IDs to match search string (#1445) * Enable the use of API Keys in magics from the `.env` file (#1465) * magics to use dotenv * Update magics.py * Update magics.py * Add model parameters input (#1456) * start of backend implementation * fixes api code * implemented type mapping * integrating api with ui * Working prototype of the model parameter input component with correct model parameters and dropdown feature! * added api to save parameters to config and removed old model-fields * code debugging, changing UI, and adding success error message * latest changes * fix type safety issues in model-parameters-input * fix frontend lint checks, update comment * fix mypy errors, add comments * small type fix * Updated coercion typing, improved code functionality, removed unnecessary code * pass chat model arguments to Jupyternaut * delete/update existing parameter * hide params controlling tool usage from frontend --------- Co-authored-by: David L. Qiu <[email protected]> * Clean up AI settings page (#1468) * Clean up AI settings page * remove debug line added by accident * Move LiteLLM model list to `jupyter_ai_magics` (#1469) * move model list to jupyter_ai_magics * fix mypy --------- Co-authored-by: Jonah Jung <[email protected]> Co-authored-by: Sanjiv Das <[email protected]> Co-authored-by: Jonah Jung <[email protected]>
1 parent f749896 commit 2302463

File tree

88 files changed

+4155
-4814
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+4155
-4814
lines changed

.github/workflows/lint.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ on:
33
- pull_request
44

55
jobs:
6-
lint_ts:
7-
name: Lint TypeScript source
6+
lint_frontend:
7+
name: Stylelint, Prettier, ESLint
88
runs-on: ubuntu-latest
99
steps:
1010
- uses: actions/checkout@v4
@@ -17,3 +17,7 @@ jobs:
1717
run: jlpm
1818
- name: Lint TypeScript source
1919
run: jlpm lerna run lint:check
20+
21+
# TODO
22+
# precommit:
23+
# name: pre-commit check

.github/workflows/unit-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
matrix:
2020
include:
2121
- dependency-type: minimum
22-
python-version: "3.9"
22+
python-version: "3.10"
2323
- dependency-type: standard
2424
python-version: "3.12"
2525
steps:

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,6 @@ packages/**/_version.py
142142
# Ignore local chat files & local .jupyter/ dir
143143
*.chat
144144
.jupyter/
145+
146+
# Ignore secrets in '.env'
147+
.env

conftest.py

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
1+
from __future__ import annotations
2+
import asyncio
13
from pathlib import Path
2-
34
import pytest
5+
from traitlets.config import Config, LoggingConfigurable
6+
import logging
7+
from jupyter_server.services.contents.filemanager import AsyncFileContentsManager
8+
from typing import TYPE_CHECKING
49

5-
pytest_plugins = ("jupyter_server.pytest_plugin",)
10+
if TYPE_CHECKING:
11+
from jupyter_server.serverapp import ServerApp
612

13+
pytest_plugins = ("jupyter_server.pytest_plugin",)
714

815
@pytest.fixture
9-
def jp_server_config(jp_server_config):
10-
return {"ServerApp": {"jpserver_extensions": {"jupyter_ai": True}}}
16+
def jp_server_config(jp_server_config, tmp_path):
17+
return Config({"ServerApp": {"jpserver_extensions": {"jupyter_ai": True}}, "ContentsManager": {"root_dir": str(tmp_path)}})
1118

1219

1320
@pytest.fixture(scope="session")
@@ -21,9 +28,45 @@ def static_test_files_dir() -> Path:
2128
/ "static"
2229
)
2330

31+
class MockAiExtension(LoggingConfigurable):
32+
"""Mock AiExtension class for testing purposes."""
33+
34+
serverapp: ServerApp
35+
36+
def __init__(self, *args, serverapp: ServerApp, **kwargs):
37+
super().__init__(*args, **kwargs)
38+
self.serverapp = serverapp
39+
self._log = None
40+
41+
@property
42+
def log(self) -> logging.Logger:
43+
return self.serverapp.log
44+
45+
@property
46+
def event_loop(self) -> asyncio.AbstractEventLoop:
47+
return self.serverapp.io_loop.asyncio_loop
48+
49+
@property
50+
def contents_manager(self) -> AsyncFileContentsManager:
51+
return self.serverapp.contents_manager
52+
2453

2554
@pytest.fixture
26-
def jp_ai_staging_dir(jp_data_dir: Path) -> Path:
27-
staging_area = jp_data_dir / "scheduler_staging_area"
28-
staging_area.mkdir()
29-
return staging_area
55+
def mock_ai_extension(jp_server_config, jp_configurable_serverapp) -> MockAiExtension:
56+
"""
57+
Returns a mocked `AiExtension` object that can be passed as the `parent`
58+
argument to objects normally initialized by `AiExtension`. This should be
59+
passed to most of the "manager singletons" like `ConfigManager`,
60+
`PersonaManager`, and `EnvSecretsManager`.
61+
62+
See `MockAiExtension` in `conftest.py` for a complete description of the
63+
attributes, properties, and methods available. If something is missing,
64+
please feel free to add to it in your PR.
65+
66+
Returns:
67+
A `MockAiExtension` instance that can be passed as the `parent` argument
68+
to objects normally initialized by `AiExtension`.
69+
"""
70+
serverapp = jp_configurable_serverapp()
71+
return MockAiExtension(config=jp_server_config, serverapp=serverapp)
72+

docs/source/users/index.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ We currently support the following language model providers:
762762
To configure a default model you can use the IPython `%config` magic:
763763

764764
```python
765-
%config AiMagics.default_language_model = "anthropic:claude-v1.2"
765+
%config AiMagics.initial_language_model = "anthropic:claude-v1.2"
766766
```
767767

768768
Then subsequent magics can be invoked without typing in the model:
@@ -772,10 +772,10 @@ Then subsequent magics can be invoked without typing in the model:
772772
Write a poem about C++.
773773
```
774774

775-
You can configure the default model for all notebooks by specifying `c.AiMagics.default_language_model` tratilet in `ipython_config.py`, for example:
775+
You can configure the default model for all notebooks by specifying `c.AiMagics.initial_language_model` tratilet in `ipython_config.py`, for example:
776776

777777
```python
778-
c.AiMagics.default_language_model = "anthropic:claude-v1.2"
778+
c.AiMagics.initial_language_model = "anthropic:claude-v1.2"
779779
```
780780

781781
The location of `ipython_config.py` file is documented in [IPython configuration reference](https://ipython.readthedocs.io/en/stable/config/intro.html).
@@ -965,18 +965,18 @@ produced the following Python error:
965965
Write a new version of this code that does not produce that error.
966966
```
967967

968-
As a shortcut for explaining errors, you can use the `%ai error` command, which will explain the most recent error using the model of your choice.
968+
As a shortcut for explaining and fixing errors, you can use the `%ai fix` command, which will explain the most recent error using the model of your choice.
969969

970970
```
971-
%ai error anthropic:claude-v1.2
971+
%ai fix anthropic:claude-v1.2
972972
```
973973

974974
### Creating and managing aliases
975975

976-
You can create an alias for a model using the `%ai register` command. For example, the command:
976+
You can create an alias for a model using the `%ai alias` command. For example, the command:
977977

978978
```
979-
%ai register claude anthropic:claude-v1.2
979+
%ai alias claude anthropic:claude-v1.2
980980
```
981981

982982
will register the alias `claude` as pointing to the `anthropic` provider's `claude-v1.2` model. You can then use this alias as you would use any other model name:
@@ -1001,10 +1001,10 @@ prompt = PromptTemplate(
10011001
chain = LLMChain(llm=llm, prompt=prompt)
10021002
```
10031003

1004-
… and then use `%ai register` to give it a name:
1004+
… and then use `%ai alias` to give it a name:
10051005

10061006
```
1007-
%ai register companyname chain
1007+
%ai alias companyname chain
10081008
```
10091009

10101010
You can change an alias's target using the `%ai update` command:
@@ -1013,10 +1013,10 @@ You can change an alias's target using the `%ai update` command:
10131013
%ai update claude anthropic:claude-instant-v1.0
10141014
```
10151015

1016-
You can delete an alias using the `%ai delete` command:
1016+
You can delete an alias using the `%ai dealias` command:
10171017

10181018
```
1019-
%ai delete claude
1019+
%ai dealias claude
10201020
```
10211021

10221022
You can see a list of all aliases by running the `%ai list` command.
@@ -1103,7 +1103,7 @@ the selections they make in the settings panel will take precedence over these v
11031103

11041104
Specify default language model
11051105
```bash
1106-
jupyter lab --AiExtension.default_language_model=bedrock-chat:anthropic.claude-v2
1106+
jupyter lab --AiExtension.initial_language_model=bedrock-chat:anthropic.claude-v2
11071107
```
11081108

11091109
Specify default embedding model
Lines changed: 9 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,20 @@
1+
from __future__ import annotations
2+
13
from typing import TYPE_CHECKING
24

3-
from ._import_utils import import_attr as _import_attr
45
from ._version import __version__
56

67
if TYPE_CHECKING:
7-
# same as dynamic imports but understood by mypy
8-
from .embedding_providers import (
9-
BaseEmbeddingsProvider,
10-
GPT4AllEmbeddingsProvider,
11-
HfHubEmbeddingsProvider,
12-
QianfanEmbeddingsEndpointProvider,
13-
)
14-
from .exception import store_exception
15-
from .magics import AiMagics
16-
from .providers import (
17-
AI21Provider,
18-
BaseProvider,
19-
GPT4AllProvider,
20-
HfHubProvider,
21-
QianfanProvider,
22-
TogetherAIProvider,
23-
)
24-
else:
25-
_exports_by_module = {
26-
"embedding_providers": [
27-
"BaseEmbeddingsProvider",
28-
"GPT4AllEmbeddingsProvider",
29-
"HfHubEmbeddingsProvider",
30-
"QianfanEmbeddingsEndpointProvider",
31-
],
32-
"exception": ["store_exception"],
33-
"magics": ["AiMagics"],
34-
# expose model providers on the package root
35-
"providers": [
36-
"AI21Provider",
37-
"BaseProvider",
38-
"GPT4AllProvider",
39-
"HfHubProvider",
40-
"QianfanProvider",
41-
"TogetherAIProvider",
42-
],
43-
}
8+
from IPython.core.interactiveshell import InteractiveShell
449

45-
_modules_by_export = {
46-
import_name: module
47-
for module, imports in _exports_by_module.items()
48-
for import_name in imports
49-
}
50-
51-
def __getattr__(export_name: str) -> object:
52-
module_name = _modules_by_export.get(export_name)
53-
result = _import_attr(export_name, module_name, __spec__.parent)
54-
globals()[export_name] = result
55-
return result
5610

11+
def load_ipython_extension(ipython: InteractiveShell):
12+
from .exception import store_exception
13+
from .magics import AiMagics
5714

58-
def load_ipython_extension(ipython):
59-
ipython.register_magics(__getattr__("AiMagics"))
60-
ipython.set_custom_exc((BaseException,), __getattr__("store_exception"))
15+
ipython.register_magics(AiMagics)
16+
ipython.set_custom_exc((BaseException,), store_exception)
6117

6218

63-
def unload_ipython_extension(ipython):
19+
def unload_ipython_extension(ipython: InteractiveShell):
6420
ipython.set_custom_exc((BaseException,), ipython.CustomTB)
65-
66-
67-
# required to preserve backward compatibility with `from jupyter_ai_magics import *`
68-
__all__ = [
69-
"__version__",
70-
"load_ipython_extension",
71-
"unload_ipython_extension",
72-
"BaseEmbeddingsProvider",
73-
"GPT4AllEmbeddingsProvider",
74-
"HfHubEmbeddingsProvider",
75-
"QianfanEmbeddingsEndpointProvider",
76-
"store_exception",
77-
"AiMagics",
78-
"AI21Provider",
79-
"BaseProvider",
80-
"GPT4AllProvider",
81-
"HfHubProvider",
82-
"QianfanProvider",
83-
"TogetherAIProvider",
84-
]
85-
86-
87-
def __dir__():
88-
# Allows more editors (e.g. IPython) to complete on `jupyter_ai_magics.<tab>`
89-
return list(__all__)

packages/jupyter-ai-magics/jupyter_ai_magics/_import_utils.py

Lines changed: 0 additions & 58 deletions
This file was deleted.

packages/jupyter-ai-magics/jupyter_ai_magics/aliases.py

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)