Skip to content

Commit 0a38783

Browse files
authored
Revert "Introduce AI persona framework (#1324)" (#1340)
This reverts commit 1458af6.
1 parent 1458af6 commit 0a38783

File tree

16 files changed

+197
-805
lines changed

16 files changed

+197
-805
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
"clean:all": "lerna run clean:all",
3131
"dev": "jupyter lab --config playground/config.py",
3232
"dev-install": "lerna run dev-install --stream",
33-
"dev-reinstall": "jlpm dev-uninstall && jlpm dev-install",
3433
"dev-uninstall": "lerna run dev-uninstall --stream",
3534
"install-from-src": "lerna run install-from-src --stream",
3635
"lint": "jlpm && lerna run prettier && lerna run eslint",

packages/jupyter-ai-test/jupyter_ai_test/debug_persona.py

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

packages/jupyter-ai-test/pyproject.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ test-provider-ask-learn-unsupported = "jupyter_ai_test.test_providers:TestProvid
3535
[project.entry-points."jupyter_ai.chat_handlers"]
3636
test-slash-command = "jupyter_ai_test.test_slash_commands:TestSlashCommand"
3737

38-
[project.entry-points."jupyter_ai.personas"]
39-
debug-persona = "jupyter_ai_test.debug_persona:DebugPersona"
40-
4138
[tool.hatch.build.hooks.version]
4239
path = "jupyter_ai_test/_version.py"
4340

packages/jupyter-ai/jupyter_ai/extension.py

Lines changed: 31 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
import re
33
import time
44
import types
5-
from asyncio import get_event_loop_policy
65
from functools import partial
7-
from typing import TYPE_CHECKING, Dict, Optional
6+
from typing import Dict
87

98
import traitlets
109
from dask.distributed import Client as DaskClient
@@ -13,6 +12,7 @@
1312
from jupyter_ai_magics.utils import get_em_providers, get_lm_providers
1413
from jupyter_events import EventLogger
1514
from jupyter_server.extension.application import ExtensionApp
15+
from jupyter_server.utils import url_path_join
1616
from jupyterlab_chat.models import Message
1717
from jupyterlab_chat.ychat import YChat
1818
from pycrdt import ArrayEvent
@@ -22,6 +22,7 @@
2222
from .chat_handlers.base import BaseChatHandler
2323
from .completions.handlers import DefaultInlineCompletionHandler
2424
from .config_manager import ConfigManager
25+
from .constants import BOT
2526
from .context_providers import BaseCommandContextProvider, FileContextProvider
2627
from .handlers import (
2728
ApiKeysHandler,
@@ -32,10 +33,6 @@
3233
SlashCommandsInfoHandler,
3334
)
3435
from .history import YChatHistory
35-
from .personas import PersonaManager
36-
37-
if TYPE_CHECKING:
38-
from asyncio import AbstractEventLoop
3936

4037
from jupyter_collaboration import ( # type:ignore[import-untyped] # isort:skip
4138
__version__ as jupyter_collaboration_version,
@@ -247,13 +244,6 @@ def initialize(self):
247244
schema_id=JUPYTER_COLLABORATION_EVENTS_URI, listener=self.connect_chat
248245
)
249246

250-
@property
251-
def event_loop(self) -> "AbstractEventLoop":
252-
"""
253-
Returns a reference to the asyncio event loop.
254-
"""
255-
return get_event_loop_policy().get_event_loop()
256-
257247
async def connect_chat(
258248
self, logger: EventLogger, schema_id: str, data: dict
259249
) -> None:
@@ -274,19 +264,17 @@ async def connect_chat(
274264
if ychat is None:
275265
return
276266

267+
# Add the bot user to the chat document awareness.
268+
BOT["avatar_url"] = url_path_join(
269+
self.settings.get("base_url", "/"), "api/ai/static/jupyternaut.svg"
270+
)
271+
if ychat.awareness is not None:
272+
ychat.awareness.set_local_state_field("user", BOT)
273+
277274
# initialize chat handlers for new chat
278275
self.chat_handlers_by_room[room_id] = self._init_chat_handlers(ychat)
279276

280-
# initialize persona manager
281-
persona_manager = self._init_persona_manager(ychat)
282-
if not persona_manager:
283-
self.log.error(
284-
"Jupyter AI was unable to initialize its AI personas. They are not available for use in chat until this error is resolved. "
285-
+ "Please verify your configuration and open a new issue on GitHub if this error persists."
286-
)
287-
return
288-
289-
callback = partial(self.on_change, room_id, persona_manager)
277+
callback = partial(self.on_change, room_id)
290278
ychat.ymessages.observe(callback)
291279

292280
async def get_chat(self, room_id: str) -> YChat:
@@ -313,26 +301,21 @@ async def get_chat(self, room_id: str) -> YChat:
313301
self.ychats_by_room[room_id] = document
314302
return document
315303

316-
def on_change(
317-
self, room_id: str, persona_manager: PersonaManager, events: ArrayEvent
318-
) -> None:
304+
def on_change(self, room_id: str, events: ArrayEvent) -> None:
319305
assert self.serverapp
320306

321307
for change in events.delta: # type:ignore[attr-defined]
322308
if not "insert" in change.keys():
323309
continue
310+
messages = change["insert"]
311+
for message_dict in messages:
312+
message = Message(**message_dict)
313+
if message.sender == BOT["username"] or message.raw_time:
314+
continue
324315

325-
# the "if not m['raw_time']" clause is necessary because every new
326-
# message triggers 2 events, one with `raw_time` set to `True` and
327-
# another with `raw_time` set to `False` milliseconds later.
328-
# we should explore fixing this quirk in Jupyter Chat.
329-
#
330-
# Ref: https://github.com/jupyterlab/jupyter-chat/issues/212
331-
new_messages = [
332-
Message(**m) for m in change["insert"] if not m.get("raw_time", False)
333-
]
334-
for new_message in new_messages:
335-
persona_manager.route_message(new_message)
316+
self.serverapp.io_loop.asyncio_loop.create_task( # type:ignore[attr-defined]
317+
self.route_human_message(room_id, message)
318+
)
336319

337320
async def route_human_message(self, room_id: str, message: Message):
338321
"""
@@ -417,15 +400,18 @@ def initialize_settings(self):
417400

418401
self.log.info(f"Registered {self.name} server extension")
419402

420-
self.settings["jai_event_loop"] = self.event_loop
403+
# get reference to event loop
404+
# `asyncio.get_event_loop()` is deprecated in Python 3.11+, in favor of
405+
# the more readable `asyncio.get_event_loop_policy().get_event_loop()`.
406+
# it's easier to just reference the loop directly.
407+
loop = self.serverapp.io_loop.asyncio_loop
408+
self.settings["jai_event_loop"] = loop
421409

422410
# We cannot instantiate the Dask client directly here because it
423411
# requires the event loop to be running on init. So instead we schedule
424412
# this as a task that is run as soon as the loop starts, and pass
425413
# consumers a Future that resolves to the Dask client when awaited.
426-
self.settings["dask_client_future"] = self.event_loop.create_task(
427-
self._get_dask_client()
428-
)
414+
self.settings["dask_client_future"] = loop.create_task(self._get_dask_client())
429415

430416
# Create empty context providers dict to be filled later.
431417
# This is created early to use as kwargs for chat handlers.
@@ -470,7 +456,10 @@ async def _stop_extension(self):
470456

471457
def _init_chat_handlers(self, ychat: YChat) -> Dict[str, BaseChatHandler]:
472458
"""
473-
Initializes a set of chat handlers for a given `YChat` instance.
459+
Initializes a set of chat handlers. May accept a YChat instance for
460+
collaborative chats.
461+
462+
TODO: Make `ychat` required once Jupyter Chat migration is complete.
474463
"""
475464
assert self.serverapp
476465

@@ -617,32 +606,3 @@ def _init_context_providers(self):
617606
**context_providers_kwargs
618607
)
619608
self.log.info(f"Registered context provider `{context_provider.id}`.")
620-
621-
def _init_persona_manager(self, ychat: YChat) -> Optional[PersonaManager]:
622-
"""
623-
Initializes a `PersonaManager` instance scoped to a `YChat`.
624-
625-
This method should not raise an exception. Upon encountering an
626-
exception, this method will catch it, log it, and return `None`.
627-
"""
628-
persona_manager: Optional[PersonaManager]
629-
630-
try:
631-
config_manager = self.settings.get("jai_config_manager", None)
632-
assert config_manager and isinstance(config_manager, ConfigManager)
633-
634-
persona_manager = PersonaManager(
635-
ychat=ychat,
636-
config_manager=config_manager,
637-
event_loop=self.event_loop,
638-
log=self.log,
639-
)
640-
except Exception as e:
641-
# TODO: how to stop the extension when this fails
642-
# also why do uncaught exceptions produce an empty error log in Jupyter Server?
643-
self.log.error(
644-
f"Unable to initialize PersonaManager in YChat with ID '{ychat.get_id()}' due to an exception printed below."
645-
)
646-
self.log.exception(e)
647-
finally:
648-
return persona_manager

packages/jupyter-ai/jupyter_ai/history.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import List, Optional
22

3+
from jupyter_ai.constants import BOT
34
from jupyterlab_chat.models import Message as JChatMessage
45
from jupyterlab_chat.ychat import YChat
56
from langchain_core.chat_history import BaseChatMessageHistory
@@ -45,7 +46,7 @@ def _convert_to_langchain_messages(self, jchat_messages: List[JChatMessage]):
4546
"""
4647
messages: List[BaseMessage] = []
4748
for jchat_message in jchat_messages:
48-
if jchat_message.sender.startswith("jupyter-ai-personas::"):
49+
if jchat_message.sender == BOT["username"]:
4950
messages.append(AIMessage(content=jchat_message.body))
5051
else:
5152
messages.append(HumanMessage(content=jchat_message.body))

packages/jupyter-ai/jupyter_ai/personas/__init__.py

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

0 commit comments

Comments
 (0)