山东大学项目实训-基于LLM的中文法律文书生成系统(八)- 前端(1) - gradio

模型展示工具Gradio

安装与配置

  • 环境要求:Gradio 需要Python 3.8 或更高版本的Python版本
  • 操作系统:Gradio可以在Windows、MacOS和Linux等主流操作系统上运行。
  • 安装步骤:使用pip安装,即打开你的终端或命令提示符,输入pip install gradio来安装Gradio

1. 初识Gradio

  • Gradio简介:Gradio是一个开源的Python库,用于创建机器学习模型的交互式界面。它使得展示和测试模型变得简单快捷,无需深入了解复杂的前端技术。
  • 使用场景:Gradio广泛应用于数据科学、教育、研究和软件开发领域,尤其适合于快速原型设计、模型验证、演示和教学。

2. 核心组件

  • 界面(Interface):Gradio的核心是Interface类,它允许用户定义输入和输出类型,创建交互式的Web界面。
  • 输入类型:Gradio支持多种输入类型,如gr.Text用于文本输入,gr.Image用于图像上传,gr.Audio用于音频输入等。
  • 输出类型:输出类型与输入类型相对应,包括gr.Textgr.Imagegr.Audio等,用于展示模型的输出结果。

Gradio “Hello World”

import gradio as gr

def greet(name):
    return "Hello " + name + "!"
iface = gr.Interface(fn=greet, inputs=gr.Textbox(), outputs=gr.Textbox())
iface.launch()
  1. 设置开发环境: 首先,确保你的Python环境中已经安装了Gradio。如果尚未安装,可以通过以下命令安装:
    pip install gradio
  2. 编写Python脚本: 打开一个新的Python脚本文件,比如命名为gradio_hello_world.py
  3. 导入Gradio库: 在脚本的开始处导入Gradio库:
    import gradio as gr
  4. 定义处理函数: 接下来,定义一个处理用户输入的函数。这个函数将接收一个字符串参数(用户的名字),并返回一个问候语。
    def``greet(name): return``f"Hello {name}!"
  5. 创建Gradio界面: 使用Gradio的Interface类来创建一个交互式界面。这个界面将有一个文本输入框和一个文本输出框。
    iface = gr.Interface(fn=greet, inputs="text", outputs="text")
  6. 运行应用: 最后,使用launch()方法启动你的应用。
    iface.launch()
  7. 尝试你的应用: 运行脚本后,你的默认Web浏览器会打开一个新的页面,显示你的Gradio应用。在文本框中输入你的名字,点击提交,你会看到问候语出现在下方。
import gradio as gr

def greet(name, intensity):
    return "Hello, " + name + "!" * int(intensity)

demo = gr.Interface(
    fn=greet,
    inputs=["text", "slider"],
    outputs=["text"],
)

demo.launch()

接口类 gr.InterfaceInterface

该类有三个核心参数:Interface

fn:将用户界面 (UI) 包裹起来的函数

inputs:用于输入的 Gradio 组件。组件数应与函数中的参数数匹配。

outputs:用于输出的 Gradio 组件。组件数应与函数的返回值数匹配。

该参数非常灵活 -- 您可以传递任何要用 UI 包装的 Python 函数。在上面的例子中,我们看到了一个相对简单的函数,但该函数可以是任何东西,从音乐生成器到税收计算器,再到预训练机器学习模型的预测函数。fn

界面元素介绍:详解不同的输入输出组件

Gradio提供了多种输入和输出组件,适应不同的数据类型和展示需求。了解这些组件对于设计有效的Gradio界面至关重要。

输入组件 (Inputs)

  1. Audio:允许用户上传音频文件或直接录音。参数:source: 指定音频来源(如麦克风)、type: 指定返回类型。 示例:gr.Audio(source="microphone", type="filepath")
  2. Checkbox:提供复选框,用于布尔值输入。参数:label: 显示在复选框旁边的文本标签。 示例:gr.Checkbox(label="同意条款")
  3. CheckboxGroup:允许用户从一组选项中选择多个。参数:choices: 字符串数组,表示复选框的选项、label: 标签文本。示例:gr.CheckboxGroup(["选项1", "选项2", "选项3"], label="选择你的兴趣")
  4. Dropdown:下拉菜单,用户可以从中选择一个选项。参数:choices: 字符串数组,表示下拉菜单的选项、label: 标签文本。示例:gr.Dropdown(["选项1", "选项2", "选项3"], label="选择一个选项")
  5. File:用于上传任意文件,支持多种文件格式。参数:file_count: 允许上传的文件数量,如"single""multiple"、type: 返回的数据类型,如"file""auto"。示例:gr.File(file_count="single", type="file")
  6. Image:用于上传图片,支持多种图像格式。参数:type图像类型,如pil。示例:gr.Image(type='pil')
  7. Number:数字输入框,适用于整数和浮点数。参数:default: 默认数字、label: 标签文本。示例:gr.Number(default=0, label="输入一个数字")
  8. Radio:单选按钮组,用户从中选择一个选项。参数:choices: 字符串数组,表示单选按钮的选项、label: 标签文本。示例:gr.Radio(["选项1", "选项2", "选项3"], label="选择一个选项")
  9. Slider:滑动条,用于选择一定范围内的数值。参数:minimum: 最小值、maximum: 最大值、step: 步长、label: 标签文本。示例:gr.Slider(minimum=0, maximum=10, step=1, label="调整数值")
  10. Textbox:单行文本输入框,适用于简短文本。参数:default: 默认文本、placeholder: 占位符文本。示例:gr.Textbox(default="默认文本", placeholder="输入文本")
  11. Textarea:多行文本输入区域,适合较长的文本输入。参数:lines: 显示行数、placeholder: 占位符文本。示例:gr.Textarea(lines=4, placeholder="输入长文本")

输出组件 (Outputs)

  1. Audio:播放音频文件。参数:type 指定输出格式。示例:gr.Audio(type="auto")
  2. HTML:展示HTML内容,适用于富文本或网页布局。
  3. Image:展示图像。参数:type 指定图像格式。 示例:gr.Image(type="pil")
  4. JSON:以JSON格式展示数据,便于查看结构化数据。
  5. KeyValues:以键值对形式展示数据。
  6. Label:展示文本标签,适用于简单的文本输出。
  7. Markdown:支持Markdown格式的文本展示。
  8. Plot:展示图表,如matplotlib生成的图表。
  9. Text:用于显示文本,适合较长的输出。
  10. Video:播放视频文件。

项目前端代码(已废弃)

import os
import gradio as gr
import torch
from threading import Thread

from typing import Union, Annotated
from pathlib import Path
from peft import AutoPeftModelForCausalLM, PeftModelForCausalLM
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    PreTrainedModel,
    PreTrainedTokenizer,
    PreTrainedTokenizerFast,
    StoppingCriteria,
    StoppingCriteriaList,
    TextIteratorStreamer
)

ModelType = Union[PreTrainedModel, PeftModelForCausalLM]
TokenizerType = Union[PreTrainedTokenizer, PreTrainedTokenizerFast]

MODEL_PATH = os.environ.get('MODEL_PATH', 'THUDM/chatglm3-6b')
TOKENIZER_PATH = os.environ.get("TOKENIZER_PATH", MODEL_PATH)

# 将字符串路径转换为Path对象,并自动扩展用户路径。
def _resolve_path(path: Union[str, Path]) -> Path:
    return Path(path).expanduser().resolve()

# 加载模型和分词器
def load_model_and_tokenizer(
        model_dir: Union[str, Path], trust_remote_code: bool = True
) -> tuple[ModelType, TokenizerType]:
    model_dir = _resolve_path(model_dir)
    if (model_dir / 'adapter_config.json').exists():
        model = AutoPeftModelForCausalLM.from_pretrained(
            model_dir, trust_remote_code=trust_remote_code, device_map='auto'
        )
        tokenizer_dir = model.peft_config['default'].base_model_name_or_path
    else:
        model = AutoModelForCausalLM.from_pretrained(
            model_dir, trust_remote_code=trust_remote_code, device_map='auto'
        )
        tokenizer_dir = model_dir
    tokenizer = AutoTokenizer.from_pretrained(
        tokenizer_dir, trust_remote_code=trust_remote_code
    )
    return model, tokenizer


model, tokenizer = load_model_and_tokenizer(MODEL_PATH, trust_remote_code=True)


class StopOnTokens(StoppingCriteria):
    def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
        stop_ids = [0, 2]
        for stop_id in stop_ids:
            if input_ids[0][-1] == stop_id:
                return True
        return False

# 解析输入文本,将代码块转换为 HTML 代码
def parse_text(text):
    lines = text.split("\n")
    lines = [line for line in lines if line != ""]
    count = 0
    for i, line in enumerate(lines):
        if "```" in line:
            count += 1
            items = line.split('`')
            if count % 2 == 1:
                lines[i] = f'<pre><code class="language-{items[-1]}">'
            else:
                lines[i] = f'<br></code></pre>'
        else:
            if i > 0:
                if count % 2 == 1:
                    line = line.replace("`", "\`")
                    line = line.replace("<", "&lt;")
                    line = line.replace(">", "&gt;")
                    line = line.replace(" ", "&nbsp;")
                    line = line.replace("*", "&ast;")
                    line = line.replace("_", "&lowbar;")
                    line = line.replace("-", "&#45;")
                    line = line.replace(".", "&#46;")
                    line = line.replace("!", "&#33;")
                    line = line.replace("(", "&#40;")
                    line = line.replace(")", "&#41;")
                    line = line.replace("$", "&#36;")
                lines[i] = "<br>" + line
    text = "".join(lines)
    return text

# 与语言模型交互。这个函数接收历史记录、最大长度、top_p 和温度参数,并使用这些参数来生成新的响应
def predict(history, max_length, top_p, temperature):
    stop = StopOnTokens()
    messages = []
    for idx, (user_msg, model_msg) in enumerate(history):
        if idx == len(history) - 1 and not model_msg:
            messages.append({"role": "user", "content": user_msg})
            break
        if user_msg:
            messages.append({"role": "user", "content": user_msg})
        if model_msg:
            messages.append({"role": "assistant", "content": model_msg})

    print("\n\n====conversation====\n", messages)
    model_inputs = tokenizer.apply_chat_template(messages,
                                                 add_generation_prompt=True,
                                                 tokenize=True,
                                                 return_tensors="pt").to(next(model.parameters()).device)
    streamer = TextIteratorStreamer(tokenizer, timeout=60, skip_prompt=True, skip_special_tokens=True)
    generate_kwargs = {
        "input_ids": model_inputs,
        "streamer": streamer,
        "max_new_tokens": max_length,
        "do_sample": True,
        "top_p": top_p,
        "temperature": temperature,
        "stopping_criteria": StoppingCriteriaList([stop]),
        "repetition_penalty": 1.2,
    }
    t = Thread(target=model.generate, kwargs=generate_kwargs)
    t.start()

    for new_token in streamer:
        if new_token != '':
            history[-1][1] += new_token
            yield history

# 使用 Gradio 创建用户界面
with gr.Blocks() as demo:
    gr.HTML("""<h1 align="center">ChatGLM3-6B Gradio Simple Demo</h1>""")
    chatbot = gr.Chatbot()

    with gr.Row():
        with gr.Column(scale=4):
            with gr.Column(scale=12):
                user_input = gr.Textbox(show_label=False, placeholder="Input...", lines=10, container=False)
            with gr.Column(min_width=32, scale=1):
                submitBtn = gr.Button("Submit")
        with gr.Column(scale=1):
            emptyBtn = gr.Button("Clear History")
            max_length = gr.Slider(0, 32768, value=8192, step=1.0, label="Maximum length", interactive=True)
            top_p = gr.Slider(0, 1, value=0.8, step=0.01, label="Top P", interactive=True)
            temperature = gr.Slider(0.01, 1, value=0.6, step=0.01, label="Temperature", interactive=True)


    def user(query, history):
        return "", history + [[parse_text(query), ""]]


    submitBtn.click(user, [user_input, chatbot], [user_input, chatbot], queue=False).then(
        predict, [chatbot, max_length, top_p, temperature], chatbot
    )
    emptyBtn.click(lambda: None, None, chatbot, queue=False)

demo.queue()
demo.launch(server_name="127.0.0.1", server_port=7870, inbrowser=True, share=False)

使用

ChatGLM3 Demo 拥有三种模式:

  • Chat: 对话模式,在此模式下可以与模型进行对话。
  • Tool: 工具模式,模型除了对话外,还可以通过工具进行其他操作。
  • Code Interpreter: 代码解释器模式,模型可以在一个 Jupyter 环境中执行代码并获取结果,以完成复杂任务。

对话模式

对话模式下,用户可以直接在侧边栏修改 top_p, temperature, System Prompt 等参数来调整模型的行为。

工具模式

可以通过在 tool_registry.py 中注册新的工具来增强模型的能力。只需要使用 @register_tool 装饰函数即可完成注册。对于工具声明,函数名称即为工具的名称,函数 docstring 即为工具的说明;对于工具的参数,使用 Annotated[typ: type, description: str, required: bool] 标注参数的类型、描述和是否必须。

例如,get_weather 工具的注册如下:

@register_tool
def get_weather(
    city_name: Annotated[str, 'The name of the city to be queried', True],
) -> str:
    """
    Get the weather for `city_name` in the following week
    """
    ...

此外,你也可以在页面中通过 Manual mode 进入手动模式,在这一模式下你可以通过 YAML 来直接指定工具列表,但你需要手动将工具的输出反馈给模型。

image-20240624074903919

代码解释器模式

由于拥有代码执行环境,此模式下的模型能够执行更为复杂的任务,例如绘制图表、执行符号运算等等。模型会根据对任务完成情况的理解自动地连续执行多个代码块,直到任务完成。因此,在这一模式下,你只需要指明希望模型执行的任务即可。

image-20240624074839780

官网地址:Gradio

posted @ 2024-05-31 08:30  H1S96  阅读(296)  评论(0)    收藏  举报