#
Hiểu lớp Interface

Trong phần này, chúng ta sẽ xem xét kỹ hơn về lớp `Interface` và hiểu các tham số chính được sử dụng để tạo ra nó.

##
Cách tạo một Interface

Bạn sẽ nhận thấy rằng lớp `Interface` có 3 tham số bắt buộc:

`Interface(fn, inputs, outputs, ...)`

Các tham số này là:

- `fn`: hàm dự đoán được bao bọc bởi giao diện Gradio. Hàm này có thể nhận một hoặc nhiều tham số và trả về một hoặc nhiều giá trị
- `inputs`: (các) loại thành phần đầu vào. Gradio cung cấp nhiều thành phần được tạo sẵn như`"image"` hay `"mic"`.
- `outputs`: (các) loại thành phần đầu ra. Một lần nữa, Gradio cung cấp nhiều thành phần được tạo sẵn, ví dụ: `"image"` hay `"label"`.

Để có danh sách đầy đủ các thành phần, xem tài liệu Gradio. Mỗi thành phần được tạo sẵn có thể được tùy chỉnh bằng cách khởi tạo lớp tương ứng với thành phần.

Ví dụ: như chúng ta đã thấy trong phần trước, thay vì truyền tham số `input` vào trong `"textbox"`, bạn có thể truyền vào `Textbox(lines=7, label="Prompt")` để tạo một hộp văn bản có 7 dòng và một nhãn.

Hãy xem một ví dụ khác, lần này với thành phần `Audio`.

##
Một ví dụ đơn giản với âm thanh

Như đã đề cập trước đó, Gradio cung cấp nhiều đầu vào và đầu ra khác nhau. Vì vậy, hãy xây dựng một `Interface` hoạt động với âm thanh.

Trong ví dụ này, chúng tôi sẽ xây dựng một hàm chuyển đổi âm thanh sang âm thanh mà nhận tập tin âm thanh và chỉ cần đảo ngược nó.

Chúng ta sẽ sử dụng thành phần `Audio` cho đầu vào. Khi sử dụng thành phần `Audio`, bạn có thể chỉ định xem bạn có muốn `source` của âm thanh là một tệp mà người dùng tải lên hoặc micrô mà người dùng ghi lại giọng nói của họ. Trong trường hợp này, hãy đặt nó thành `"microphone"`. Chỉ cho vui thôi, chúng ta sẽ thêm một nhãn vào phần `Audio` của mình có nội dung “Speak here…”, nghĩa là “Nói ở đây …“.

Ngoài ra, chúng ta muốn nhận âm thanh dưới dạng mảng numpy để ta có thể dễ dàng “đảo ngược” nó lại. Vì vậy, chúng ta sẽ đặt `"type"` là `"numpy"`, chuyển đầu vào dữ liệu dưới dạng một bộ (`sample_rate`, `data`) trong hàm của chúng ta.

Chúng ta cũng sẽ sử dụng thành phần đầu ra `Audio` có thể tự động hiển thị một bộ tuple với tốc độ mẫu và mảng dữ liệu phức tạp dưới dạng tệp âm thanh có thể phát. Trong trường hợp này, chúng ta không cần thực hiện bất kỳ tùy chỉnh nào, vì vậy cta sẽ sử dụng chuỗi phím tắt `"audio"`.

    import numpy as np
    import gradio as gr

    def reverse_audio(audio):
        sr, data = audio
        reversed_audio = (sr, np.flipud(data))
        return reversed_audio

    mic = gr.Audio(source="microphone", type="numpy", label="Speak here...")
    gr.Interface(reverse_audio, mic, "audio").launch()

Đoạn mã trên sẽ tạo ra một giao diện giống như bên dưới (nếu trình duyệt của bạn không yêu cầu bạn cấp quyền đối với micrô, mở bản demo sang một tab khác.)

Bây giờ bạn có thể ghi lại giọng nói của mình và nghe thấy chính mình đang nói ngược lại - thật ma quái 👻!

##
Xử lý nhiều đầu vào và đầu ra

Giả sử chúng ta có một hàm phức tạp hơn, với nhiều đầu vào và đầu ra. Trong ví dụ dưới đây, chúng ta có một hàm lấy chỉ mục thả xuống, giá trị thanh trượt và số, và trả về một mẫu âm thanh của một giai điệu âm nhạc.

Hãy xem cách chúng ta chuyển danh sách các thành phần đầu vào và đầu ra, và xem liệu bạn có thể theo dõi những gì đang xảy ra không.

Chìa khóa ở đây là khi bạn truyền vào:

- danh sách các thành phần đầu vào, mỗi thành phần tương ứng với một tham số theo thứ tự.
- danh sách các thành phần đầu ra, mỗi thành phần tương ứng với một giá trị trả về.

Đoạn mã bên dưới cho thấy cách ba thành phần đầu vào xếp hàng với ba tham số của hàm `generate_tone()`:

    import numpy as np
    import gradio as gr

    notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]

    def generate_tone(note, octave, duration):
        sr = 48000
        a4_freq, tones_from_a4 = 440, 12 * (octave - 4) + (note - 9)
        frequency = a4_freq * 2 ** (tones_from_a4 / 12)
        duration = int(duration)
        audio = np.linspace(0, duration, duration * sr)
        audio = (20000 * np.sin(audio * (2 * np.pi * frequency))).astype(np.int16)
        return (sr, audio)

    gr.Interface(
        generate_tone,
        [
            gr.Dropdown(notes, type="index"),
            gr.Slider(minimum=4, maximum=6, step=1),
            gr.Textbox(type="number", value=1, label="Duration in seconds"),
        ],
        "audio",
    ).launch()

###
Phương thức `launch()`

Cho đến nay, chúng tôi đã sử dụng phương thức `launch()` để khởi chạy giao diện, nhưng chúng ta chưa thực sự thảo luận về những gì nó làm.

Theo mặc định, phương thức `launch()` sẽ khởi chạy bản demo trong một máy chủ web đang chạy cục bộ. Nếu bạn đang chạy mã của mình trong notebook Jupyter hoặc Colab, thì Gradio sẽ nhúng GUI demo vào notebook để bạn có thể dễ dàng sử dụng.

Bạn có thể tùy chỉnh hành vi của `launch()` thông qua các tham số khác nhau:

- `inline` - có hiển thị giao diện nội tuyến trên notebook Python hay không.
- `inbrowser` - có tự động khởi chạy giao diện trong tab mới trên trình duyệt mặc định hay không.
- `share` - có tạo một liên kết có thể chia sẻ công khai từ máy tính của bạn cho giao diện hay không. Giống như một liên kết Google Drive!

Chúng tôi sẽ trình bày chi tiết hơn về tham số `share` trong phần tiếp theo!

##
✏️ Hãy áp dụng nó!

Hãy xây dựng một giao diện cho phép bạn giới thiệu mô hình nhận dạng giọng nói. Để làm cho nó thú vị, chúng ta sẽ chấp nhận hoặc đầu vào micrô hoặc một tệp đã tải lên.

Như thường lệ, chúng ta sẽ tải mô hình nhận dạng giọng nói của mình bằng cách sử dụng hàm `pipeline()` từ 🤗 Transformers. Nếu bạn cần cập nhật nhanh, bạn có thể quay lại phần đó trong Chương 1. Tiếp theo, chúng ta sẽ triển khai một hàm `transcribe_audio()` để xử lý âm thanh và trả về phiên âm. Cuối cùng, chúng ta sẽ gói hàm này trong một `Interface` với các thành phần `Audio` cho đầu vào và chỉ văn bản cho đầu ra. Nhìn chung, mã cho ứng dụng này như sau:

    from transformers import pipeline
    import gradio as gr

    model = pipeline("automatic-speech-recognition")

    def transcribe_audio(mic=None, file=None):
        if mic is not None:
            audio = mic
        elif file is not None:
            audio = file
        else:
            return "You must either provide a mic recording or a file"
        transcription = model(audio)["text"]
        return transcription

    gr.Interface(
        fn=transcribe_audio,
        inputs=[
            gr.Audio(source="microphone", type="filepath", optional=True),
            gr.Audio(source="upload", type="filepath", optional=True),
        ],
        outputs="text",
    ).launch()

Nếu trình duyệt của bạn không yêu cầu bạn cấp quyền đối với micrô, hãy mở bản demo trong một tab riêng.

Nó đó! Bây giờ bạn có thể sử dụng giao diện này để phiên âm âm thanh. Chú ý ở đây rằng bằng cách đặt tham số `option` là `True`, chúng ta cho phép người dùng cung cấp micrô hoặc tệp âm thanh (hoặc không, nhưng điều đó sẽ trả lại thông báo lỗi).

Tiếp tục xem cách chia sẻ giao diện của bạn với những người khác!