LM或矢量数据库,并支持多用户管理和权限。 AnythingLLM将您的文档划分为称为工作区的对象。工作区的功能很像线程,但增加了文 ...

逼谇叭掏一、摘要

构建AI应用的前端方案有很多,这里介绍一个开源前端库---Gradio,通过它可以使用简短的代码就可以快速的实现简单的AI应用前端。这里我们选择的场景为做RAG召回测试,通过调用先前封装好的LangChain代码,来快速的搭建这个前端页面。

二、AI项目前端方案的对比

可以做AI的前端方案很多,这里主要介绍比较热门的三个方案:

Gradio 是一款开源的 Python 库,核心定位是快速构建机器学习 / 深度学习模型的交互式 Web 演示界面,无需前端开发经验,一行代码即可将模型(或任意 Python 函数)转化为可通过浏览器访问的交互页面,方便开发者、研究者快速展示、测试和分享模型。

Streamlit 是一款开源的 Python 库,主打快速构建数据科学 / 机器学习领域的交互式 Web 应用,无需前端开发经验,以 "脚本即应用" 为核心理念 ------ 普通的 Python 脚本只需添加少量 Streamlit 语法,就能一键转化为可交互的 Web 应用,是数据分析师、算法工程师快速落地可视化 / 分析工具的首选。

Vue(读音 /vju?/,类似 view)是一款渐进式 JavaScript 框架,核心聚焦于前端视图层(UI)开发,由尤雨溪开发并开源,是目前最主流的前端框架之一(与 React、Angular 并称)。

相对三种方案,Gradio是直接被设计成AI的前端的,Streamlit适合做数据科学的前端。而Vue是一个更专业的前端框架。

这里我们介绍的就是Gradio。所以我们使用Gradio构建了一个RAG(检索增强生成)召回测试系统界面,主要功能是通过调用LC_RAG_02_RecallTest.py中的recall函数实现相似度检索,用户可以输入查询文本并设置返回结果数量,系统会展示检索到的最相似文档。

三、环境介绍

这里基于我另外一篇笔记:

https://www.cnblogs.com/aspnetx/p/19173914

在这个笔记中,介绍了如何使用python构建RAG系统,使用的是LangChain1.0的库。

整个项目可以在以下仓库中找到:

https://github.com/microsoftbi/Langchain_DEMO/tree/main/RAG

我会用到在其中的一个文件中封装好的做RAG召回测试的代码,来构建前端应用,借此展示Gradio环境中如何快速的搭建前端页面。

本文创建的代码文件名为:LC_RAG_07b_Gradio.py

调用先前召回测试的代码文件为:LC_RAG_02_RecallTest.py

四、主要功能模块

  1. 召回测试函数 run_recall_test

功能:调用LC_RAG_02_RecallTest.py文件中封装好的recall函数执行检索并捕获输出结果。

def run_recall_test(query, top_k):

"""运行召回测试并返回结果"""

try:

调用recall函数,但需要捕获其输出

import io

from contextlib import redirect_stdout

创建一个字符串IO对象来捕获输出

f = io.StringIO()

with redirect_stdout(f):

recall(

query=query,

top_k=top_k,

vectorstore_dir="./RAG/chroma_db",

embedding_model="text-embedding-v4"

)

获取捕获的输出

output = f.getvalue()

return output

except Exception as e:

return f"错误: {str(e)}"

实现要点:

使用io.StringIO()创建字符串缓冲区

通过redirect_stdout上下文管理器捕获recall函数的打印输出

调用recall函数时指定参数:查询文本、返回数量、向量存储目录和嵌入模型

因为在先前封装好的代码中并没有返回值,而是直接通过print来输出结果,所以这里需要调用相关的包来读取这些输出。

  1. Gradio界面构建

首先需要确保Gradio的库已经被安装:

pip install gradio

然后在代码中引入这个库。

import gradio as gr

随后使用gr.Blocks创建结构化界面,在其下再通过gr.Row()以及gr.Column(),就可以往这个框架下分割出来不同的行和列来堆放需要的组件。

顺便说一下,Gradid有两种方式的布局,一个是interface, 通过绑定的函数自动生成界面,另一个就是Block,通过行列的方式自己组织界面。这里用到的就是Blocks方式。

以下是几种常用的设置前端界面的方法:

(1)页面标题与说明

直接做markdown格式的输出:

gr.Markdown("# RAG召回测试系统")

gr.Markdown("使用Gradio构建的RAG召回测试界面,调用LC_RAG_02_RecallTest.py实现相似度检索")

(2)输入区域(左侧)

也就是在gr.Row()的第一个gr.Column()

with gr.Column(scale=1):

gr.Markdown("## 查询设置")

查询文本输入

query_input = gr.Textbox(

label="查询文本",

placeholder="请输入您要检索的问题或关键词",

lines=3,

info="例如: '什么是未成年?' 或 '哪些节假日应该安排休假?'"

)

Top-K设置

top_k_slider = gr.Slider(

label="Top-K检索数量",

minimum=1,

maximum=10,

value=5,

step=1,

info="设置返回的最相似文档数量"

)

提交按钮

submit_btn = gr.Button(

"执行召回测试",

variant="primary",

size="lg"

)

重置按钮

clear_btn = gr.Button("重置", variant="secondary")

这段代码包括创建以下界面:

查询文本输入框:gr.Textbox,支持多行输入

Top-K设置滑块:gr.Slider,范围1-10,默认值5

操作按钮:"执行召回测试"(主按钮)和"重置"(次要按钮)

可以看到通过gr.对应的方法,就可以创建不同的组件。

(3)输出区域(右侧)

gr.Row()的第二个gr.Column()

右侧:输出区域

with gr.Column(scale=2):

gr.Markdown("## 召回结果")

结果输出

result_output = gr.Textbox(

label="相似度检索结果",

lines=20,

interactive=False,

placeholder="召回结果将显示在这里..."

)

状态信息

status_info = gr.Markdown("状态: 就绪")

结果输出框:gr.Textbox,展示检索结果

状态信息:gr.Markdown,显示系统当前状态

  1. 按钮事件

这里主要是调用前面定义的方法:run_recall_test

然后下面封装了一个响应按钮的方法:

按钮事件

def on_submit(query, top_k):

if not query:

return "请输入查询文本", "状态: 错误 - 查询文本不能为空"

status_info.value = "状态: 正在执行召回测试..."

result = run_recall_test(query, top_k)

return result, "状态: 测试完成"

最后挂载按钮的click方法:

绑定事件

submit_btn.click(

fn=lambda query, top_k: on_submit(query, top_k),

inputs=[query_input, top_k_slider],

outputs=[result_output, status_info]

需要留意的是这里的事件响应的方法跟其它编程语言的会有些不同。

  1. 应用启动

demo.launch(

server_name="0.0.0.0", # 允许外部访问

server_port=7860, # 端口号

share=False, # 不生成公共链接

debug=False # 非调试模式

)

指定端口号和其它信息,直接运行这个代码就可以在浏览器里访问了。

以下是代码所构建的界面。

img

可以看到相比用Vue来封装,代码量就少了很多,尤其是不需要创建,构建项目,以及为前端去专门写API。

所以对于快速的开发来说,Gradio是非常合适的。但是对于企业级的专业开发,还是建议选择Vue。

还有一种建议就是,通过Gradio来做快速的原型开发,然后用Vue来做生产开发。