diff --git a/packages/jupyter-ai/jupyter_ai/chat_handlers/__init__.py b/packages/jupyter-ai/jupyter_ai/chat_handlers/__init__.py index 463369244..3e7e45aa8 100644 --- a/packages/jupyter-ai/jupyter_ai/chat_handlers/__init__.py +++ b/packages/jupyter-ai/jupyter_ai/chat_handlers/__init__.py @@ -5,10 +5,7 @@ from .ask import AskChatHandler from .base import BaseChatHandler, SlashCommandRoutingType -from .clear import ClearChatHandler from .default import DefaultChatHandler -from .export import ExportChatHandler -from .fix import FixChatHandler from .generate import GenerateChatHandler from .help import HelpChatHandler from .learn import LearnChatHandler diff --git a/packages/jupyter-ai/jupyter_ai/chat_handlers/clear.py b/packages/jupyter-ai/jupyter_ai/chat_handlers/clear.py deleted file mode 100644 index d5b0ab6c7..000000000 --- a/packages/jupyter-ai/jupyter_ai/chat_handlers/clear.py +++ /dev/null @@ -1,26 +0,0 @@ -from jupyter_ai.models import ClearRequest - -from .base import BaseChatHandler, SlashCommandRoutingType - - -class ClearChatHandler(BaseChatHandler): - """Clear the chat panel and show the help menu""" - - id = "clear" - name = "Clear chat messages" - help = "Clear the chat window" - routing_type = SlashCommandRoutingType(slash_id="clear") - - uses_llm = False - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - async def process_message(self, _): - # Clear chat by triggering `RootChatHandler.on_clear_request()`. - for handler in self._root_chat_handlers.values(): - if not handler: - continue - - handler.on_clear_request(ClearRequest()) - break diff --git a/packages/jupyter-ai/jupyter_ai/chat_handlers/export.py b/packages/jupyter-ai/jupyter_ai/chat_handlers/export.py deleted file mode 100644 index 7323d81c1..000000000 --- a/packages/jupyter-ai/jupyter_ai/chat_handlers/export.py +++ /dev/null @@ -1,49 +0,0 @@ -import argparse -import os -from datetime import datetime -from typing import List - -from jupyter_ai.models import AgentChatMessage, AgentStreamMessage, HumanChatMessage - -from .base import BaseChatHandler, SlashCommandRoutingType - - -class ExportChatHandler(BaseChatHandler): - id = "export" - name = "Export chat history" - help = "Export chat history to a Markdown file" - routing_type = SlashCommandRoutingType(slash_id="export") - - uses_llm = False - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.parser.prog = "/export" - self.parser.add_argument("path", nargs=argparse.REMAINDER) - - def chat_message_to_markdown(self, message): - if isinstance(message, (AgentChatMessage, AgentStreamMessage)): - agent = self.config_manager.persona.name - return f"**{agent}**: {message.body}" - elif isinstance(message, HumanChatMessage): - return f"**{message.client.display_name}**: {message.body}" - else: - return "" - - # Write the chat history to a markdown file with a timestamp - async def process_message(self, message: HumanChatMessage): - markdown_content = "\n\n".join( - self.chat_message_to_markdown(msg) for msg in self._chat_history - ) - args = self.parse_args(message) - chat_filename = ( # if no filename, use "chat_history" + timestamp - args.path[0] - if (args.path and args.path[0] != "") - else f"chat_history-{datetime.now():%Y-%m-%d-%H-%M-%S}.md" - ) # Handles both empty args and double tap key - chat_file = os.path.join( - self.output_dir, chat_filename - ) # Do not use timestamp if filename is entered as argument - with open(chat_file, "w") as chat_history: - chat_history.write(markdown_content) - self.reply(f"File saved to `{chat_file}`") diff --git a/packages/jupyter-ai/jupyter_ai/chat_handlers/fix.py b/packages/jupyter-ai/jupyter_ai/chat_handlers/fix.py deleted file mode 100644 index 390b93cf6..000000000 --- a/packages/jupyter-ai/jupyter_ai/chat_handlers/fix.py +++ /dev/null @@ -1,106 +0,0 @@ -from typing import Dict, Type - -from jupyter_ai.models import CellWithErrorSelection, HumanChatMessage -from jupyter_ai_magics.providers import BaseProvider -from langchain.prompts import PromptTemplate - -from .base import BaseChatHandler, SlashCommandRoutingType - -FIX_STRING_TEMPLATE = """ -You are Jupyternaut, a conversational assistant living in JupyterLab. Please fix -the notebook cell described below. - -Additional instructions: - -{extra_instructions} - -Input cell: - -``` -{cell_content} -``` - -Output error: - -``` -{traceback} - -{error_name}: {error_value} -``` -""".strip() - -FIX_PROMPT_TEMPLATE = PromptTemplate( - input_variables=[ - "extra_instructions", - "cell_content", - "traceback", - "error_name", - "error_value", - ], - template=FIX_STRING_TEMPLATE, -) - - -class FixChatHandler(BaseChatHandler): - """ - Accepts a `HumanChatMessage` that includes a cell with error output and - recommends a fix as a reply. If a cell with error output is not included, - this chat handler does nothing. - - `/fix` also accepts additional instructions in natural language as an - arbitrary number of arguments, e.g. - - ``` - /fix use the numpy library to implement this function instead. - ``` - """ - - id = "fix" - name = "Fix error cell" - help = "Fix an error cell selected in your notebook" - routing_type = SlashCommandRoutingType(slash_id="fix") - uses_llm = True - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.prompt_template = None - - def create_llm_chain( - self, provider: Type[BaseProvider], provider_params: Dict[str, str] - ): - unified_parameters = { - **provider_params, - **(self.get_model_parameters(provider, provider_params)), - } - llm = provider(**unified_parameters) - self.llm = llm - prompt_template = FIX_PROMPT_TEMPLATE - - runnable = prompt_template | llm # type:ignore - self.llm_chain = runnable - - async def process_message(self, message: HumanChatMessage): - if not (message.selection and message.selection.type == "cell-with-error"): - self.reply( - "`/fix` requires an active code cell with error output. Please click on a cell with error output and retry.", - message, - ) - return - - # hint type of selection - selection: CellWithErrorSelection = message.selection - - # parse additional instructions specified after `/fix` - extra_instructions = message.prompt[4:].strip() or "None." - - self.get_llm_chain() - assert self.llm_chain - - inputs = { - "extra_instructions": extra_instructions, - "cell_content": selection.source, - "traceback": "\n".join(selection.error.traceback), - "error_name": selection.error.name, - "error_value": selection.error.value, - } - await self.stream_reply(inputs, message, pending_msg="Analyzing error") diff --git a/packages/jupyter-ai/jupyter_ai/extension.py b/packages/jupyter-ai/jupyter_ai/extension.py index 31a2e4fe0..7c02b9e40 100644 --- a/packages/jupyter-ai/jupyter_ai/extension.py +++ b/packages/jupyter-ai/jupyter_ai/extension.py @@ -2,7 +2,6 @@ import re import time import types -import uuid from functools import partial from typing import Dict, Optional @@ -24,10 +23,7 @@ from .chat_handlers import ( AskChatHandler, BaseChatHandler, - ClearChatHandler, DefaultChatHandler, - ExportChatHandler, - FixChatHandler, GenerateChatHandler, HelpChatHandler, LearnChatHandler, @@ -533,7 +529,6 @@ def _init_chat_handlers( "ychat": ychat, } default_chat_handler = DefaultChatHandler(**chat_handler_kwargs) - clear_chat_handler = ClearChatHandler(**chat_handler_kwargs) generate_chat_handler = GenerateChatHandler( **chat_handler_kwargs, log_dir=self.error_logs_dir, @@ -542,17 +537,10 @@ def _init_chat_handlers( retriever = Retriever(learn_chat_handler=learn_chat_handler) ask_chat_handler = AskChatHandler(**chat_handler_kwargs, retriever=retriever) - export_chat_handler = ExportChatHandler(**chat_handler_kwargs) - - fix_chat_handler = FixChatHandler(**chat_handler_kwargs) - chat_handlers["default"] = default_chat_handler chat_handlers["/ask"] = ask_chat_handler - chat_handlers["/clear"] = clear_chat_handler chat_handlers["/generate"] = generate_chat_handler chat_handlers["/learn"] = learn_chat_handler - chat_handlers["/export"] = export_chat_handler - chat_handlers["/fix"] = fix_chat_handler slash_command_pattern = r"^[a-zA-Z0-9_]+$" for chat_handler_ep in chat_handler_eps: