{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "import time\n", "import panel as pn\n", "\n", "pn.extension()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `ChatStep` opens up the possibility to display / hide intermediate steps prior to the final result.\n", "\n", "Check out the [panel-chat-examples](https://holoviz-topics.github.io/panel-chat-examples/) docs to see applicable examples related to [LangChain](https://python.langchain.com/docs/get_started/introduction), [OpenAI](https://openai.com/blog/chatgpt), [Mistral](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwjZtP35yvSBAxU00wIHHerUDZAQFnoECBEQAQ&url=https%3A%2F%2Fdocs.mistral.ai%2F&usg=AOvVaw2qpx09O_zOzSksgjBKiJY_&opi=89978449), [Llama](https://ai.meta.com/llama/), etc. If you have an example to demo, we'd love to add it to the panel-chat-examples gallery!\n", "\n", "#### Parameters:\n", "\n", "##### Core\n", "\n", "* **`collapsed_on_success`** (`bool`): Whether to collapse the card on completion. Defaults to `True`.\n", "* **`context_exception`** (`str`): How to handle exceptions raised upon exiting the context manager. If \"raise\", the exception will be raised. If \"summary\", a summary will be sent to the chat step. If \"verbose\", the full traceback will be sent to the chat step. If \"ignore\", the exception will be ignored.\n", "* **`success_title`** (`str`): Title to display when status is success; if not provided and `collapsed_on_success` uses the last object's string. Defaults to `None`.\n", "* **`default_title`** (`str`): The default title to display if the other title params are unset. Defaults to an empty string `\"\"`.\n", "* **`failed_title`** (`str`): Title to display when status is failed. Defaults to `None`.\n", "* **`margin`** (`tuple`): Allows creating additional space around the component. May be specified as a two-tuple of the form (vertical, horizontal) or a four-tuple (top, right, bottom, left). Defaults to `(5, 5, 5, 10)`.\n", "* **``objects``** (list): The list of objects to display in the `ChatStep`, which will be formatted like a `Column`. Should not generally be modified directly except when replaced in its entirety.\n", "* **`pending_title`** (`str`): Title to display when status is pending. Defaults to `None`.\n", "* **`running_title`** (`str`): Title to display when status is running. Defaults to `None`.\n", "* **`status`** (`str`): The status of the chat step. Must be one of [\"pending\", \"running\", \"success\", \"failed\"]. Defaults to `\"pending\"`.\n", "\n", "##### Styling\n", "\n", "* **`collapsed`** (`bool`): Whether the contents of the `ChatStep` are collapsed. Defaults to `False`.\n", "* **`default_badges`** (`dict`): Mapping from status to default status badge. Defaults to `DEFAULT_STATUS_BADGES`; keys must be one of 'pending', 'running', 'success', 'failed'.\n", "\n", "#### Methods\n", "\n", "##### Core\n", "\n", "* **`stream`**: Stream a token to the last available string-like object.\n", "* **`stream_title`**: Stream a token to the title header.\n", "* **`serialize`**: Format the object to a string.\n", "\n", "___" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Basics" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`ChatStep` can be initialized without any arguments." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step = pn.chat.ChatStep()\n", "chat_step" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Append `Markdown` objects to the chat step by calling `stream`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step.stream(\"Just thinking...\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Calling it again will concatenate the text to the last available `Markdown` pane." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step.stream(\" about `ChatStep`!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, setting `replace=True` will override the existing message." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step.stream(\"`ChatStep` can do a lot of things!\", replace=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It's possible to also append any objects, like images." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step.append(pn.pane.Image(\"https://assets.holoviz.org/panel/samples/png_sample.png\", width=50, height=50))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Calling `stream` afterwards will append a new `Markdown` pane below it." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step.stream(\"Like it can support images too! Above is a picture of dices.\")\n", "print(chat_step.objects)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To convert the objects into a string, call `serialize`, or simply use `str()`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step.serialize()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Badges\n", "\n", "The default avatars are `BooleanStatus`, but can be changed by providing `default_badges`. The values can be emojis, images, text, or Panel objects." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step = pn.chat.ChatStep(\n", " default_badges={\n", " \"pending\": \"🤔\",\n", " \"running\": \"🏃\",\n", " \"success\": \"🎉\",\n", " \"failed\": \"😞\",\n", " },\n", " status=\"success\",\n", ")\n", "chat_step" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Status" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To show that the step is processing, you can set the status to `running` and provide a `running_title`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step = pn.chat.ChatStep(status=\"running\", running_title=\"Processing this step...\")\n", "chat_step.stream(\"Pretending to do something.\")\n", "chat_step" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Upon completion, set the status to `success` and it'll automatically collapse the contents." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step.status = \"success\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To have the title update on success, either provide the `success_title` or `default_title`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step = pn.chat.ChatStep(status=\"running\", running_title=\"Processing this step...\", success_title=\"Pretend job done!\")\n", "chat_step.stream(\"Pretending to do something.\")\n", "chat_step.status = \"success\"\n", "chat_step" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To streamline this process, `ChatStep` may be used as a context manager.\n", "\n", "Upon entry, the status will be changed from the default `pending` to `running`.\n", "\n", "Exiting will change the status from `running` to `completed` if successful." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step = pn.chat.ChatStep(running_title=\"Processing this step...\", success_title=\"Pretend job done!\")\n", "with chat_step:\n", " chat_step.stream(\"Pretending to do something.\")\n", "\n", "chat_step" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However, if an exception occurs, the status will be set to \"failed\" and the error message will be displayed on the title." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step = pn.chat.ChatStep(running_title=\"Processing this step...\", success_title=\"Pretend job done!\")\n", "chat_step" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "try:\n", " with chat_step:\n", " chat_step.stream(\"Breaking something\")\n", " raise RuntimeError(\"Just demoing!\")\n", "except RuntimeError as e:\n", " print(\"Comment this try/except to see what happens!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The title can also be streamed." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step = pn.chat.ChatStep()\n", "chat_step" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step.status = \"running\"\n", "for char in \"It's streaming a title!\":\n", " time.sleep(0.02)\n", " chat_step.stream_title(char)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It can be used with any `status`, like setting `status=\"pending\"`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step = pn.chat.ChatStep()\n", "chat_step" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for char in \"I'm deciding on a title... how about this one?\":\n", " time.sleep(0.01)\n", " chat_step.stream_title(char, status=\"pending\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The title can also be completely replaced--equivalent to setting `chat_step.pending_title = \"Nevermind!`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chat_step.stream_title(\"Nevermind!\", replace=True, status=\"pending\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Be sure to check out [ChatFeed](ChatFeed.ipynb) to see it works with a `ChatFeed` or `ChatInterface`!" ] } ], "metadata": { "language_info": { "name": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 4 }