使用Gradio构建AI前端 - RAG召回测试
使用Gradio构建AI前端 - RAG召回测试
一、摘要
构建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来输出结果,所以这里需要调用相关的包来读取这些输出。
- 使用
2. 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,显示系统当前状态
3. 按钮事件
这里主要是调用前面定义的方法: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]
需要留意的是这里的事件响应的方法跟其它编程语言的会有些不同。
5. 应用启动
demo.launch(
server_name="0.0.0.0", # 允许外部访问
server_port=7860, # 端口号
share=False, # 不生成公共链接
debug=False # 非调试模式
)
指定端口号和其它信息,直接运行这个代码就可以在浏览器里访问了。
以下是代码所构建的界面。

可以看到相比用Vue来封装,代码量就少了很多,尤其是不需要创建,构建项目,以及为前端去专门写API。
所以对于快速的开发来说,Gradio是非常合适的。但是对于企业级的专业开发,还是建议选择Vue。
还有一种建议就是,通过Gradio来做快速的原型开发,然后用Vue来做生产开发。
以下是代码的全部内容,点击展开。
import os
import gradio as gr
from dotenv import load_dotenv
from LC_RAG_02_RecallTest import recall
# 加载环境变量
load_dotenv()
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)}"
# 创建界面
with gr.Blocks(title="RAG召回测试系统", theme=gr.themes.Soft()) as demo:
# 页面标题
gr.Markdown("# RAG召回测试系统")
gr.Markdown("使用Gradio构建的RAG召回测试界面,调用LC_RAG_02_RecallTest.py实现相似度检索")
with gr.Row():
# 左侧:输入区域
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")
# 右侧:输出区域
with gr.Column(scale=2):
gr.Markdown("## 召回结果")
# 结果输出
result_output = gr.Textbox(
label="相似度检索结果",
lines=20,
interactive=False,
placeholder="召回结果将显示在这里..."
)
# 状态信息
status_info = gr.Markdown("状态: 就绪")
# 按钮事件
def on_submit(query, top_k):
if not query:
return "请输入查询文本", "状态: 错误 - 查询文本不能为空"
status_info.value = "状态: 正在执行召回测试..."
result = run_recall_test(query, top_k)
return result, "状态: 测试完成"
def on_clear():
return "", 5, "", "状态: 已重置"
# 绑定事件
submit_btn.click(
fn=lambda query, top_k: on_submit(query, top_k),
inputs=[query_input, top_k_slider],
outputs=[result_output, status_info]
)
clear_btn.click(
fn=on_clear,
inputs=[],
outputs=[query_input, top_k_slider, result_output, status_info]
)
# 示例查询
gr.Markdown("## 示例查询")
with gr.Row():
example1 = gr.Button("什么是未成年?")
example2 = gr.Button("哪些节假日应该安排休假?")
example3 = gr.Button("足球比赛的基本规则是什么?")
def set_example(example_text):
return example_text, 5, "", "状态: 就绪"
example1.click(fn=lambda: set_example("什么是未成年?"), inputs=[], outputs=[query_input, top_k_slider, result_output, status_info])
example2.click(fn=lambda: set_example("哪些节假日应该安排休假?"), inputs=[], outputs=[query_input, top_k_slider, result_output, status_info])
example3.click(fn=lambda: set_example("足球比赛的基本规则是什么?"), inputs=[], outputs=[query_input, top_k_slider, result_output, status_info])
# 启动应用
if __name__ == "__main__":
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
debug=False
)
---------------------------------------------------------------
aspnetx的BI笔记系列索引:
使用SQL Server Analysis Services数据挖掘的关联规则实现商品推荐功能
---------------------------------------------------------------

浙公网安备 33010602011771号