mirror of
https://github.com/gradio-app/gradio.git
synced 2025-04-24 13:01:18 +08:00
Add Markdown support in chatbots (#2731)
* started working on this * demo * added markdown support * notebook * changelog * tests * chatbot * formatting
This commit is contained in:
parent
d79039beb1
commit
5c8e7887dc
22
CHANGELOG.md
22
CHANGELOG.md
@ -2,6 +2,28 @@
|
||||
|
||||
## New Features:
|
||||
|
||||
### The `Chatbot` component now supports a subset of Markdown (including bold, italics, code, images)
|
||||
|
||||
You can now pass in some Markdown to the Chatbot component and it will show up,
|
||||
meaning that you can pass in images as well! by [@abidlabs](https://github.com/abidlabs) in [PR 2731](https://github.com/gradio-app/gradio/pull/2731)
|
||||
|
||||
Here's a simple example that references a local image `lion.jpg` that is in the same
|
||||
folder as the Python script:
|
||||
|
||||
```py
|
||||
import gradio as gr
|
||||
|
||||
with gr.Blocks() as demo:
|
||||
gr.Chatbot([("hi", "hello **abubakar**"), ("", "cool pic")])
|
||||
|
||||
demo.launch()
|
||||
```
|
||||
|
||||

|
||||
|
||||
To see a more realistic example, see the new demo `/demo/chatbot_multimodal/run.py`.
|
||||
|
||||
|
||||
### Latex support
|
||||
Added mathtext (a subset of latex) support to gr.Markdown. Added by [@kashif](https://github.com/kashif) and [@aliabid94](https://github.com/aliabid94) in [PR 2696](https://github.com/gradio-app/gradio/pull/2696).
|
||||
|
||||
|
1
demo/chatbot_multimodal/run.ipynb
Normal file
1
demo/chatbot_multimodal/run.ipynb
Normal file
@ -0,0 +1 @@
|
||||
{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: chatbot_multimodal"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def add_text(state, text):\n", " state = state + [(text, text + \"?\")]\n", " return state, state\n", "\n", "def add_image(state, image):\n", " state = state + [(f\"\", \"Cool pic!\")]\n", " return state, state\n", "\n", "\n", "with gr.Blocks(css=\"#chatbot .overflow-y-auto{height:500px}\") as demo:\n", " chatbot = gr.Chatbot(elem_id=\"chatbot\")\n", " state = gr.State([])\n", " \n", " with gr.Row():\n", " with gr.Column(scale=0.85):\n", " txt = gr.Textbox(show_label=False, placeholder=\"Enter text and press enter, or upload an image\").style(container=False)\n", " with gr.Column(scale=0.15, min_width=0):\n", " btn = gr.UploadButton(\"\ud83d\uddbc\ufe0f\", file_types=[\"image\"])\n", " \n", " txt.submit(add_text, [state, txt], [state, chatbot])\n", " txt.submit(lambda :\"\", None, txt)\n", " btn.upload(add_image, [state, btn], [state, chatbot])\n", " \n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
27
demo/chatbot_multimodal/run.py
Normal file
27
demo/chatbot_multimodal/run.py
Normal file
@ -0,0 +1,27 @@
|
||||
import gradio as gr
|
||||
|
||||
def add_text(state, text):
|
||||
state = state + [(text, text + "?")]
|
||||
return state, state
|
||||
|
||||
def add_image(state, image):
|
||||
state = state + [(f"", "Cool pic!")]
|
||||
return state, state
|
||||
|
||||
|
||||
with gr.Blocks(css="#chatbot .overflow-y-auto{height:500px}") as demo:
|
||||
chatbot = gr.Chatbot(elem_id="chatbot")
|
||||
state = gr.State([])
|
||||
|
||||
with gr.Row():
|
||||
with gr.Column(scale=0.85):
|
||||
txt = gr.Textbox(show_label=False, placeholder="Enter text and press enter, or upload an image").style(container=False)
|
||||
with gr.Column(scale=0.15, min_width=0):
|
||||
btn = gr.UploadButton("🖼️", file_types=["image"])
|
||||
|
||||
txt.submit(add_text, [state, txt], [state, chatbot])
|
||||
txt.submit(lambda :"", None, txt)
|
||||
btn.upload(add_image, [state, btn], [state, chatbot])
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo.launch()
|
@ -2862,11 +2862,13 @@ class UploadButton(Clickable, Uploadable, IOComponent, SimpleSerializable):
|
||||
)
|
||||
if self.type == "file":
|
||||
if is_file:
|
||||
file = processing_utils.create_tmp_copy_of_file(file_name)
|
||||
file = processing_utils.create_tmp_copy_of_file(
|
||||
file_name, dir=self.temp_dir
|
||||
)
|
||||
file.orig_name = file_name
|
||||
else:
|
||||
file = processing_utils.decode_base64_to_file(
|
||||
data, file_path=file_name
|
||||
data, file_path=file_name, dir=self.temp_dir
|
||||
)
|
||||
file.orig_name = file_name
|
||||
return file
|
||||
@ -3615,9 +3617,9 @@ class Carousel(IOComponent, Changeable, SimpleSerializable):
|
||||
@document("change", "style")
|
||||
class Chatbot(Changeable, IOComponent, JSONSerializable):
|
||||
"""
|
||||
Displays a chatbot output showing both user submitted messages and responses
|
||||
Displays a chatbot output showing both user submitted messages and responses. Supports a subset of Markdown including bold, italics, code, and images.
|
||||
Preprocessing: this component does *not* accept input.
|
||||
Postprocessing: expects a {List[Tuple[str, str]]}, a list of tuples with user inputs and responses.
|
||||
Postprocessing: expects a {List[Tuple[str, str]]}, a list of tuples with user inputs and responses as strings of HTML.
|
||||
|
||||
Demos: chatbot_demo
|
||||
"""
|
||||
@ -3646,6 +3648,7 @@ class Chatbot(Changeable, IOComponent, JSONSerializable):
|
||||
"The 'color_map' parameter has been moved from the constructor to `Chatbot.style()` ",
|
||||
)
|
||||
self.color_map = color_map
|
||||
self.md = MarkdownIt()
|
||||
|
||||
IOComponent.__init__(
|
||||
self,
|
||||
@ -3685,11 +3688,15 @@ class Chatbot(Changeable, IOComponent, JSONSerializable):
|
||||
def postprocess(self, y: List[Tuple[str, str]]) -> List[Tuple[str, str]]:
|
||||
"""
|
||||
Parameters:
|
||||
y: List of tuples representing the message and response
|
||||
y: List of tuples representing the message and response pairs. Each message and response should be a string, which may be in Markdown format.
|
||||
Returns:
|
||||
List of tuples representing the message and response
|
||||
List of tuples representing the message and response. Each message and response will be a string of HTML.
|
||||
"""
|
||||
return [] if y is None else y
|
||||
if y is None:
|
||||
return []
|
||||
for i, (message, response) in enumerate(y):
|
||||
y[i] = (self.md.render(message), self.md.render(response))
|
||||
return y
|
||||
|
||||
def style(self, *, color_map: Optional[List[str, str]] = None, **kwargs):
|
||||
"""
|
||||
|
@ -1479,6 +1479,29 @@ class TestHighlightedText:
|
||||
]
|
||||
|
||||
|
||||
class TestChatbot:
|
||||
def test_component_functions(self):
|
||||
"""
|
||||
Postprocess, get_config
|
||||
"""
|
||||
chatbot = gr.Chatbot()
|
||||
assert chatbot.postprocess([("You are **cool**", "so are *you*")]) == [
|
||||
("<p>You are <strong>cool</strong></p>\n", "<p>so are <em>you</em></p>\n")
|
||||
]
|
||||
assert chatbot.get_config() == {
|
||||
"value": [],
|
||||
"color_map": None,
|
||||
"label": None,
|
||||
"show_label": True,
|
||||
"interactive": None,
|
||||
"name": "chatbot",
|
||||
"visible": True,
|
||||
"elem_id": None,
|
||||
"style": {},
|
||||
"root_url": None,
|
||||
}
|
||||
|
||||
|
||||
class TestJSON:
|
||||
def test_component_functions(self):
|
||||
"""
|
||||
|
@ -46,18 +46,24 @@
|
||||
{#each value as message}
|
||||
<div
|
||||
data-testid="user"
|
||||
class="px-3 py-2 rounded-[22px] rounded-br-none text-white text-sm"
|
||||
class="px-3 py-2 rounded-[22px] rounded-br-none text-white text-sm chat-message"
|
||||
style={"background-color:" + _colors[0]}
|
||||
>
|
||||
{message[0]}
|
||||
{@html message[0]}
|
||||
</div>
|
||||
<div
|
||||
data-testid="bot"
|
||||
class="px-3 py-2 rounded-[22px] rounded-bl-none place-self-start text-white text-sm"
|
||||
class="px-3 py-2 rounded-[22px] rounded-bl-none place-self-start text-white text-sm chat-message"
|
||||
style={"background-color:" + _colors[1]}
|
||||
>
|
||||
{message[1]}
|
||||
{@html message[1]}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.chat-message :global(img) {
|
||||
border-radius: 13px;
|
||||
}
|
||||
</style>
|
||||
|
Loading…
x
Reference in New Issue
Block a user