mirror of
https://github.com/gradio-app/gradio.git
synced 2025-03-19 12:00:39 +08:00
Fix some documentation-related issues in Guides (#3903)
* client doc fixes * simplify demo * added guides * chatbot guide * notebooks * format
This commit is contained in:
parent
f81b8235c7
commit
7a04ebe7fd
@ -35,7 +35,7 @@ from gradio_client.utils import Communicator, JobStatus, Status, StatusUpdate
|
||||
set_documentation_group("py-client")
|
||||
|
||||
|
||||
@document("predict", "submit", "view_api")
|
||||
@document("predict", "submit", "view_api", "duplicate")
|
||||
class Client:
|
||||
"""
|
||||
The main Client class for the Python client. This class is used to connect to a remote Gradio app and call its API endpoints.
|
||||
@ -51,7 +51,6 @@ class Client:
|
||||
job = client.submit("hello", api_name="/predict") # runs the prediction in a background thread
|
||||
job.result()
|
||||
>> 49 # returns the result of the remote API call (blocking call)
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -160,6 +159,13 @@ class Client:
|
||||
sleep_timeout: The number of minutes after which the duplicate Space will be puased if no requests are made to it (to minimize billing charges). Defaults to 5 minutes.
|
||||
max_workers: The maximum number of thread workers that can be used to make requests to the remote Gradio app simultaneously.
|
||||
verbose: Whether the client should print statements to the console.
|
||||
Example:
|
||||
import os
|
||||
from gradio_client import Client
|
||||
HF_TOKEN = os.environ.get("HF_TOKEN")
|
||||
client = Client.duplicate("abidlabs/whisper", hf_token=HF_TOKEN)
|
||||
client.predict("audio_sample.wav")
|
||||
>> "This is a test of the whisper speech recognition model."
|
||||
"""
|
||||
try:
|
||||
original_info = huggingface_hub.get_space_runtime(from_id, token=hf_token)
|
||||
|
@ -1 +1 @@
|
||||
{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: chatbot_simple"]}, {"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", "import random\n", "import time\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot()\n", " msg = gr.Textbox()\n", " clear = gr.Button(\"Clear\")\n", "\n", " def user(user_message, history):\n", " return \"\", history + [[user_message, None]]\n", "\n", " def bot(history):\n", " bot_message = random.choice([\"Yes\", \"No\"])\n", " history[-1][1] = bot_message\n", " time.sleep(1)\n", " return history\n", "\n", " msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", " clear.click(lambda: None, None, chatbot, queue=False)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
||||
{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: chatbot_simple"]}, {"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", "import random\n", "import time\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot()\n", " msg = gr.Textbox()\n", " clear = gr.Button(\"Clear\")\n", "\n", " def respond(message, chat_history):\n", " bot_message = random.choice([\"How are you?\", \"I love you\", \"I'm very hungry\"])\n", " chat_history.append((message, bot_message))\n", " time.sleep(1)\n", " return \"\", chat_history\n", "\n", " msg.submit(respond, [msg, chatbot], [msg, chatbot])\n", " clear.click(lambda: None, None, chatbot, queue=False)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
@ -7,18 +7,13 @@ with gr.Blocks() as demo:
|
||||
msg = gr.Textbox()
|
||||
clear = gr.Button("Clear")
|
||||
|
||||
def user(user_message, history):
|
||||
return "", history + [[user_message, None]]
|
||||
|
||||
def bot(history):
|
||||
bot_message = random.choice(["Yes", "No"])
|
||||
history[-1][1] = bot_message
|
||||
def respond(message, chat_history):
|
||||
bot_message = random.choice(["How are you?", "I love you", "I'm very hungry"])
|
||||
chat_history.append((message, bot_message))
|
||||
time.sleep(1)
|
||||
return history
|
||||
return "", chat_history
|
||||
|
||||
msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
|
||||
bot, chatbot, chatbot
|
||||
)
|
||||
msg.submit(respond, [msg, chatbot], [msg, chatbot])
|
||||
clear.click(lambda: None, None, chatbot, queue=False)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
1
demo/chatbot_streaming/run.ipynb
Normal file
1
demo/chatbot_streaming/run.ipynb
Normal file
@ -0,0 +1 @@
|
||||
{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: chatbot_streaming"]}, {"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", "import random\n", "import time\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot()\n", " msg = gr.Textbox()\n", " clear = gr.Button(\"Clear\")\n", "\n", " def user(user_message, history):\n", " return \"\", history + [[user_message, None]]\n", "\n", " def bot(history):\n", " bot_message = random.choice([\"How are you?\", \"I love you\", \"I'm very hungry\"])\n", " history[-1][1] = \"\"\n", " for character in bot_message:\n", " history[-1][1] += character\n", " time.sleep(0.05)\n", " yield history\n", "\n", " msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", " clear.click(lambda: None, None, chatbot, queue=False)\n", " \n", "demo.queue()\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
28
demo/chatbot_streaming/run.py
Normal file
28
demo/chatbot_streaming/run.py
Normal file
@ -0,0 +1,28 @@
|
||||
import gradio as gr
|
||||
import random
|
||||
import time
|
||||
|
||||
with gr.Blocks() as demo:
|
||||
chatbot = gr.Chatbot()
|
||||
msg = gr.Textbox()
|
||||
clear = gr.Button("Clear")
|
||||
|
||||
def user(user_message, history):
|
||||
return "", history + [[user_message, None]]
|
||||
|
||||
def bot(history):
|
||||
bot_message = random.choice(["How are you?", "I love you", "I'm very hungry"])
|
||||
history[-1][1] = ""
|
||||
for character in bot_message:
|
||||
history[-1][1] += character
|
||||
time.sleep(0.05)
|
||||
yield history
|
||||
|
||||
msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
|
||||
bot, chatbot, chatbot
|
||||
)
|
||||
clear.click(lambda: None, None, chatbot, queue=False)
|
||||
|
||||
demo.queue()
|
||||
if __name__ == "__main__":
|
||||
demo.launch()
|
@ -603,7 +603,7 @@ class Blocks(BlockContext):
|
||||
|
||||
demo.launch()
|
||||
Demos: blocks_hello, blocks_flipper, blocks_speech_text_sentiment, generate_english_german, sound_alert
|
||||
Guides: blocks_and_event_listeners, controlling_layout, state_in_blocks, custom_CSS_and_JS, custom_interpretations_with_blocks, using_blocks_like_functions
|
||||
Guides: blocks-and-event-listeners, controlling-layout, state-in-blocks, custom-CSS-and-JS, custom-interpretations-with-blocks, using-blocks-like-functions
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
@ -385,7 +385,7 @@ class Textbox(
|
||||
Examples-format: a {str} representing the textbox input.
|
||||
|
||||
Demos: hello_world, diff_texts, sentence_builder
|
||||
Guides: creating_a_chatbot, real_time_speech_recognition
|
||||
Guides: creating-a-chatbot, real-time-speech-recognition
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -780,7 +780,7 @@ class Slider(
|
||||
Examples-format: A {float} or {int} representing the slider's value.
|
||||
|
||||
Demos: sentence_builder, slider_release, generate_tone, titanic_survival, interface_random_slider, blocks_random_slider
|
||||
Guides: create_your_own_friends_with_a_gan
|
||||
Guides: create-your-own-friends-with-a-gan
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -1621,7 +1621,7 @@ class Image(
|
||||
Postprocessing: expects a {numpy.array}, {PIL.Image} or {str} or {pathlib.Path} filepath to an image and displays the image.
|
||||
Examples-format: a {str} filepath to a local file that contains the image.
|
||||
Demos: image_mod, image_mod_default_image
|
||||
Guides: Gradio_and_ONNX_on_Hugging_Face, image_classification_in_pytorch, image_classification_in_tensorflow, image_classification_with_vision_transformers, building_a_pictionary_app, create_your_own_friends_with_a_gan
|
||||
Guides: image-classification-in-pytorch, image-classification-in-tensorflow, image-classification-with-vision-transformers, building-a-pictionary_app, create-your-own-friends-with-a-gan
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -2300,7 +2300,7 @@ class Audio(
|
||||
Postprocessing: expects a {Tuple(int, numpy.array)} corresponding to (sample rate in Hz, audio data as a float or int numpy array) or as a {str} filepath or URL to an audio file, which gets displayed
|
||||
Examples-format: a {str} filepath to a local file that contains audio.
|
||||
Demos: main_note, generate_tone, reverse_audio
|
||||
Guides: real_time_speech_recognition
|
||||
Guides: real-time-speech-recognition
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -3224,7 +3224,7 @@ class State(IOComponent, SimpleSerializable):
|
||||
Preprocessing: No preprocessing is performed
|
||||
Postprocessing: No postprocessing is performed
|
||||
Demos: blocks_simple_squares
|
||||
Guides: creating_a_chatbot, real_time_speech_recognition
|
||||
Guides: real-time-speech-recognition
|
||||
"""
|
||||
|
||||
allow_string_shortcut = False
|
||||
@ -3618,7 +3618,7 @@ class Label(Changeable, Selectable, IOComponent, JSONSerializable):
|
||||
Postprocessing: expects a {Dict[str, float]} of classes and confidences, or {str} with just the class or an {int}/{float} for regression outputs, or a {str} path to a .json file containing a json dictionary in the structure produced by Label.postprocess().
|
||||
|
||||
Demos: main_note, titanic_survival
|
||||
Guides: Gradio_and_ONNX_on_Hugging_Face, image_classification_in_pytorch, image_classification_in_tensorflow, image_classification_with_vision_transformers, building_a_pictionary_app
|
||||
Guides: image-classification-in-pytorch, image-classification-in-tensorflow, image-classification-with-vision-transformers, building-a-pictionary-app
|
||||
"""
|
||||
|
||||
CONFIDENCES_KEY = "confidences"
|
||||
@ -3763,7 +3763,7 @@ class HighlightedText(Changeable, Selectable, IOComponent, JSONSerializable):
|
||||
Postprocessing: expects a {List[Tuple[str, float | str]]]} consisting of spans of text and their associated labels, or a {Dict} with two keys: (1) "text" whose value is the complete text, and "entities", which is a list of dictionaries, each of which have the keys: "entity" (consisting of the entity label), "start" (the character index where the label starts), and "end" (the character index where the label ends). Entities should not overlap.
|
||||
|
||||
Demos: diff_texts, text_analysis
|
||||
Guides: named_entity_recognition
|
||||
Guides: named-entity-recognition
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -4218,7 +4218,7 @@ class HTML(Changeable, IOComponent, StringSerializable):
|
||||
Postprocessing: expects a valid HTML {str}.
|
||||
|
||||
Demos: text_analysis
|
||||
Guides: key_features
|
||||
Guides: key-features
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -4463,6 +4463,7 @@ class Chatbot(Changeable, Selectable, IOComponent, JSONSerializable):
|
||||
Postprocessing: expects function to return a {List[List[str | None | Tuple]]}, a list of lists. The inner list should have 2 elements: the user message and the response message. Messages should be strings, tuples, or Nones. If the message is a string, it can include Markdown. If it is a tuple, it should consist of (string filepath to image/video/audio, [optional string alt text]). Messages that are `None` are not displayed.
|
||||
|
||||
Demos: chatbot_simple, chatbot_multimodal
|
||||
Guides: creating-a-chatbot
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -4652,7 +4653,7 @@ class Model3D(Changeable, Editable, Clearable, IOComponent, FileSerializable):
|
||||
Postprocessing: expects function to return a {str} path to a file of type (.obj, glb, or .gltf)
|
||||
|
||||
Demos: model3D
|
||||
Guides: how_to_use_3D_model_component
|
||||
Guides: how-to-use-3D-model-component
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -4780,7 +4781,7 @@ class Plot(Changeable, Clearable, IOComponent, JSONSerializable):
|
||||
Postprocessing: expects either a {matplotlib.figure.Figure}, a {plotly.graph_objects._figure.Figure}, or a {dict} corresponding to a bokeh plot (json_item format)
|
||||
|
||||
Demos: altair_plot, outbreak_forecast, blocks_kinematics, stock_forecast, map_airbnb
|
||||
Guides: plot_component_for_maps
|
||||
Guides: plot-component-for-maps
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -4905,7 +4906,7 @@ class ScatterPlot(Plot):
|
||||
Postprocessing: expects a pandas dataframe with the data to plot.
|
||||
|
||||
Demos: native_plots
|
||||
Guides: creating_a_dashboard_from_bigquery_data
|
||||
Guides: creating-a-dashboard-from-bigquery-data
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -5905,7 +5906,7 @@ class Markdown(IOComponent, Changeable, StringSerializable):
|
||||
Postprocessing: expects a valid {str} that can be rendered as Markdown.
|
||||
|
||||
Demos: blocks_hello, blocks_kinematics
|
||||
Guides: key_features
|
||||
Guides: key-features
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -6199,7 +6200,7 @@ class Interpretation(Component, SimpleSerializable):
|
||||
Preprocessing: this component does *not* accept input.
|
||||
Postprocessing: expects a {dict} with keys "original" and "interpretation".
|
||||
|
||||
Guides: custom_interpretations_with_blocks
|
||||
Guides: custom-interpretations-with-blocks
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
@ -171,7 +171,7 @@ class CSVLogger(FlaggingCallback):
|
||||
return {'cat': 0.3, 'dog': 0.7}
|
||||
demo = gr.Interface(fn=image_classifier, inputs="image", outputs="label",
|
||||
flagging_callback=CSVLogger())
|
||||
Guides: using_flagging
|
||||
Guides: using-flagging
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
@ -246,7 +246,7 @@ class HuggingFaceDatasetSaver(FlaggingCallback):
|
||||
return {'cat': 0.3, 'dog': 0.7}
|
||||
demo = gr.Interface(fn=image_classifier, inputs="image", outputs="label",
|
||||
allow_flagging="manual", flagging_callback=hf_writer)
|
||||
Guides: using_flagging
|
||||
Guides: using-flagging
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -382,7 +382,7 @@ class HuggingFaceDatasetJSONSaver(FlaggingCallback):
|
||||
return {'cat': 0.3, 'dog': 0.7}
|
||||
demo = gr.Interface(fn=image_classifier, inputs="image", outputs="label",
|
||||
allow_flagging="manual", flagging_callback=hf_writer)
|
||||
Guides: using_flagging
|
||||
Guides: using-flagging
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
@ -81,7 +81,7 @@ class Examples:
|
||||
components. Optionally handles example caching for fast inference.
|
||||
|
||||
Demos: blocks_inputs, fake_gan
|
||||
Guides: more_on_examples_and_flagging, using_hugging_face_integrations, image_classification_in_pytorch, image_classification_in_tensorflow, image_classification_with_vision_transformers, create_your_own_friends_with_a_gan
|
||||
Guides: more-on-examples-and-flagging, using-hugging-face-integrations, image-classification-in-pytorch, image-classification-in-tensorflow, image-classification-with-vision-transformers, create-your-own-friends-with-a-gan
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
@ -56,7 +56,7 @@ class Interface(Blocks):
|
||||
demo = gr.Interface(fn=image_classifier, inputs="image", outputs="label")
|
||||
demo.launch()
|
||||
Demos: hello_world, hello_world_3, gpt_j
|
||||
Guides: quickstart, key_features, sharing_your_app, interface_state, reactive_interfaces, advanced_interface_features, setting_up_a_gradio_demo_for_maximum_performance
|
||||
Guides: quickstart, key-features, sharing-your-app, interface-state, reactive-interfaces, advanced-interface-features, setting-up-a-gradio-demo-for-maximum-performance
|
||||
"""
|
||||
|
||||
# stores references to all currently existing Interface instances
|
||||
|
@ -21,7 +21,7 @@ class Row(BlockContext):
|
||||
gr.Image("lion.jpg")
|
||||
gr.Image("tiger.jpg")
|
||||
demo.launch()
|
||||
Guides: controlling_layout
|
||||
Guides: controlling-layout
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -89,7 +89,7 @@ class Column(BlockContext):
|
||||
with gradio.Column(scale=4):
|
||||
btn1 = gr.Button("Button 1")
|
||||
btn2 = gr.Button("Button 2")
|
||||
Guides: controlling_layout
|
||||
Guides: controlling-layout
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@ -187,7 +187,7 @@ class Tab(BlockContext, Selectable):
|
||||
with gradio.Tab("Tiger"):
|
||||
gr.Image("tiger.jpg")
|
||||
gr.Button("New Tiger")
|
||||
Guides: controlling_layout
|
||||
Guides: controlling-layout
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
@ -18,7 +18,7 @@ class Parallel(gradio.Interface):
|
||||
The Interfaces to put in Parallel must share the same input components (but can have different output components).
|
||||
|
||||
Demos: interface_parallel, interface_parallel_load
|
||||
Guides: advanced_interface_features
|
||||
Guides: advanced-interface-features
|
||||
"""
|
||||
|
||||
def __init__(self, *interfaces: gradio.Interface, **options):
|
||||
@ -72,7 +72,7 @@ class Series(gradio.Interface):
|
||||
and so the input and output components must agree between the interfaces).
|
||||
|
||||
Demos: interface_series, interface_series_load
|
||||
Guides: advanced_interface_features
|
||||
Guides: advanced-interface-features
|
||||
"""
|
||||
|
||||
def __init__(self, *interfaces: gradio.Interface, **options):
|
||||
|
@ -186,7 +186,7 @@ demo2.launch()
|
||||
|
||||
## Iterative Outputs
|
||||
|
||||
In some cases, you may want to show a sequence of outputs rather than a single output. For example, you might have an image generation model and you want to show the image that is generated at each step, leading up to the final image.
|
||||
In some cases, you may want to stream a sequence of outputs rather than show a single output at once. For example, you might have an image generation model and you want to show the image that is generated at each step, leading up to the final image. Or you might have a chatbot which streams its response one word at a time instead of returning it all at once.
|
||||
|
||||
In such cases, you can supply a **generator** function into Gradio instead of a regular function. Creating generators in Python is very simple: instead of a single `return` value, a function should `yield` a series of values instead. Usually the `yield` statement is put in some kind of loop. Here's an example of an generator that simply counts up to a given number:
|
||||
|
||||
|
@ -56,17 +56,20 @@ client = Client("abidlabs/my-private-space", hf_token="...")
|
||||
```
|
||||
|
||||
|
||||
## Duplicating a Space for private use**
|
||||
## Duplicating a Space for private use
|
||||
|
||||
While you can use any public Space as an API, you may get rate limited by Hugging Face if you make too many requests. For unlimited usage of a Space, simply duplicate the Space to create a private Space,
|
||||
and then use it to make as many requests as you'd like!
|
||||
and then use it to make as many requests as you'd like!
|
||||
|
||||
The `gradio_client` includes a class method: `Client.duplicate()` to make this process simple:
|
||||
The `gradio_client` includes a class method: `Client.duplicate()` to make this process simple (you'll need to pass in your [Hugging Face token](https://huggingface.co/settings/tokens) or be logged in using the Hugging Face CLI):
|
||||
|
||||
```python
|
||||
import os
|
||||
from gradio_client import Client
|
||||
|
||||
client = Client.duplicate("abidlabs/whisper")
|
||||
HF_TOKEN = os.environ.get("HF_TOKEN")
|
||||
|
||||
client = Client.duplicate("abidlabs/whisper", hf_token=HF_TOKEN)
|
||||
client.predict("audio_sample.wav")
|
||||
|
||||
>> "This is a test of the whisper speech recognition model."
|
||||
|
@ -6,38 +6,52 @@ Tags: NLP, TEXT, CHAT
|
||||
|
||||
Chatbots are widely used in natural language processing (NLP) research and industry. Because chatbots are designed to be used directly by customers and end users, it is important to validate that chatbots are behaving as expected when confronted with a wide variety of input prompts.
|
||||
|
||||
Using `gradio`, you can easily build a demo of your chatbot model and share that with a testing team, or test it yourself using an intuitive chatbot GUI.
|
||||
Using `gradio`, you can easily build a demo of your chatbot model and share that with your users, or try it yourself using an intuitive chatbot GUI.
|
||||
|
||||
This tutorial will show how to make two kinds of chatbot UIs with Gradio: a simple one to display text and a more sophisticated one that can handle media files as well. The simple chatbot interface that we create will look something like this:
|
||||
This tutorial will show how to make several kinds of chatbot UIs with Gradio: first a simple one to display text, second one to stream text responses, and finally a chatbot that can handle media files as well. The chatbot interface that we create will look something like this:
|
||||
|
||||
$demo_chatbot_simple
|
||||
$demo_chatbot_streaming
|
||||
|
||||
**Prerequisite**: We'll be using the `gradio.Blocks` class to build our Chatbot demo.
|
||||
You can [read the Guide to Blocks first](https://gradio.app/quickstart/#blocks-more-flexibility-and-control) if you are not already familiar with it.
|
||||
|
||||
## A Simple Chatbot Demo
|
||||
|
||||
Let's start with recreating the simple demo above. As you may have noticed, our bot simply randomly responds "yes" or "no" to any input. Here's the code to create this with Gradio:
|
||||
Let's start with recreating the simple demo above. As you may have noticed, our bot simply randomly responds "How are you?", "I love you", or "I'm very hungry" to any input. Here's the code to create this with Gradio:
|
||||
|
||||
$code_chatbot_simple
|
||||
|
||||
There are three Gradio components here:
|
||||
|
||||
* A `Chatbot`, whose value stores the entire history of the conversation, as a list of response pairs between the user and bot.
|
||||
* A `Textbox` where the user can type their message, and then hit enter/submit to trigger the chatbot response
|
||||
* A `Clear` button to clear the entire Chatbot history
|
||||
|
||||
Note that when a user submits their message, we chain two event events with `.then`:
|
||||
We have a single function, `respond()`, which takes in the entire history of the chatbot, appends a random message, waits 1 second, and then returns the updated chat history. The `respond()` function also clears the textbox when it returns.
|
||||
|
||||
Of course, in practice, you would replace `respond()` with your own more complex function, which might call a pretrained model or an API, to generate a response.
|
||||
|
||||
Finally, when the `Clear` button is clicked, we assign `None` to the value of the `Chatbot` to clear its entire history. Try out this chatbot here:
|
||||
|
||||
$demo_chatbot_simple
|
||||
|
||||
|
||||
## Add Streaming to your Chatbot
|
||||
|
||||
There are several ways we can improve the user experience of the chatbot above. First, we can stream responses so the user doesn't have to wait as long for a message to be generated. Second, we can have the user message appear immediately in the chat history, while the chatbot's response is being generated. Here's the code to achieve that:
|
||||
|
||||
$code_chatbot_streaming
|
||||
|
||||
|
||||
You'll notice that when a user submits their message, we now *chain* two event events with `.then()`:
|
||||
|
||||
1. The first method `user()` updates the chatbot with the user message and clears the input field. Because we want this to happen instantly, we set `queue=False`, which would skip any queue if it had been enabled. The chatbot's history is appended with `(user_message, None)`, the `None` signifying that the bot has not responded.
|
||||
|
||||
2. The second method, `bot()` waits for the bot to respond, and then updates the chatbot with the bot's response. Instead of creating a new message, we just replace the previous `None` message with the bot's response. We add a `time.sleep` to simulate the bot's processing time.
|
||||
|
||||
The reason we split these events is so that the user can see their message appear in the chatbot immediately before the bot responds, which can take some time to process.
|
||||
|
||||
Note we pass the entire history of the chatbot to these functions and back to the component. To clear the chatbot, we pass it `None`.
|
||||
2. The second method, `bot()` updates the chatbot history with the bot's response. Instead of creating a new message, we just replace the previously-created `None` message with the bot's response. Finally, we construct the message character by character and `yield` the intermediate outputs as they are being constructed. Gradio automatically turns any function with the `yield` keyword [into a streaming output interface](/key-features/#iterative-outputs).
|
||||
|
||||
Of course, in practice, you would replace `bot()` with your own more complex function, which might call a pretrained model or an API, to generate a response.
|
||||
|
||||
Finally, we enable queuing by running `demo.queue()`, which is required for streaming intermediate outputs. You can try the improved chatbot by scrolling to the demo at the top of this page.
|
||||
|
||||
## Adding Markdown, Images, Audio, or Videos
|
||||
|
||||
@ -60,7 +74,6 @@ def add_file(history, file):
|
||||
|
||||
Putting this together, we can create a *multimodal* chatbot with a textbox for a user to submit text and an file upload button to submit images / audio / video files. The rest of the code looks pretty much the same as before:
|
||||
|
||||
|
||||
$code_chatbot_multimodal
|
||||
$demo_chatbot_multimodal
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user