Gradio 应用接入 LLM Agent:用 gradio_tools 把任意 Gradio 应用封装为大模型工具
大语言模型(LLM)擅长理解与生成语言,但缺乏调用外部能力的手段;如果把模型无法直接完成的任务(如语音转写、图片生成、OCR)封装成"工具",交给 Agent 按需调用,就能显著扩展模型的行动边界。本篇技术指南以官方文档 guides/09_gradio-clients-and-lite/04_gradio-and-llm-agents.md 为骨架,讲解如何借助 gradio_tools 库把任何 Gradio 应用转成一个可供 LLM Agent 使用的工具,并深入封装自建工具所需的 GradioTool 抽象接口与底层 gradio_client 调用链。读完你将掌握:端到端装配一个可自主编排多工具的长链 Agent、为任意 Gradio 应用手写一个 LLM 工具、并理解 create_job / postprocess / fn_index 等关键概念背后的实现原理。
背景:Agent 与 Gradio 为何能互补
什么是 Agent
一个 LangChain Agent,本质上是"一个能够自主决定用哪些工具来完成任务的 LLM":它接收用户输入,从手头可用的一组工具中做选择、调用工具、读取工具返回结果,再继续推理直至产出最终答案。工具的描述(description)就是 Agent 的"目录"——它决定模型在什么场景下该选哪把工具。Gradio 恰好在生态中沉淀了大量开箱即用的机器学习应用,二者结合自然顺理成章。
Gradio 在其中扮演什么角色
Gradio 是构建、分享机器学习 Web 应用的 Python 框架(本仓库即其官方实现)。生态中已部署着大量功能各异的 Gradio Space 与自托管应用——语音识别、图像生成、OCR、视频合成等应有尽有。借助 gradio_client,任何 Gradio 应用都可以被当作 HTTP API 调用(参见 client/python/README.md 与姊妹篇指南 Getting Started with the Gradio Python client)。因此,只要把"调用 Gradio API"这件事封装成一个 Agent 能看懂的工具,LLM 就间接拥有了访问这些外部 AI 能力的手段。
gradio_tools 端到端示例:让 Agent 自主编排多把工具
文档中最核心的演示场景是:Agent 收到一条复合指令——"生成一张狗狗踩滑板的照片,但请先帮我把提示词优化一下;随后请为生成图配上一句说明,再用优化后的提示词生成一段视频"。注意,全程没有显式告诉 Agent 该用哪把工具、按什么顺序用,全靠模型自己编排。
该示例一共用到四把 gradio_tools 内置工具:
StableDiffusionPromptGeneratorTool:为 stable diffusion 优化提示词;StableDiffusionTool:根据提示词生成图片;ImageCaptioningTool:为生成的图片生成文字描述;TextToVideoTool:根据提示词合成视频。
完整代码如下(来自关联文档):
import os
if not os.getenv("OPENAI_API_KEY"):
raise ValueError("OPENAI_API_KEY must be set")
from langchain.agents import initialize_agent
from langchain.llms import OpenAI
from gradio_tools import (StableDiffusionTool, ImageCaptioningTool, StableDiffusionPromptGeneratorTool,
TextToVideoTool)
from langchain.memory import ConversationBufferMemory
llm = OpenAI(temperature=0)
memory = ConversationBufferMemory(memory_key="chat_history")
tools = [StableDiffusionTool().langchain, ImageCaptioningTool().langchain,
StableDiffusionPromptGeneratorTool().langchain, TextToVideoTool().langchain]
agent = initialize_agent(tools, llm, memory=memory, agent="conversational-react-description", verbose=True)
output = agent.run(input=("Please create a photo of a dog riding a skateboard "
"but improve my prompt prior to using an image generator."
"Please caption the generated image and create a video for it using the improved prompt."))
这个示例有几个值得注意的工程细节:
- 环境变量前置校验:代码在导入任何 LLM 相关模块前先检查
OPENAI_API_KEY是否已设置,避免运行中途才报出底层 API 鉴权错误。实际运行前请确保OPENAI_API_KEY已导出,并安装好gradio_tools、langchain及对应 LLM 依赖。 .langchain属性:每把工具实例通过.langchain暴露出可供 LangChain 直接识别的工具形态,再以列表形式交给initialize_agent。模型会在推理中自行决策调用哪把、先调谁后调谁。- 会话记忆:
ConversationBufferMemory(memory_key="chat_history")配合agent="conversational-react-description",让 Agent 能基于多轮对话历史做连续推理,而不是每轮"失忆"。 - 长链协同:PromptGenerator → StableDiffusion → ImageCaptioning/TextToVideo 的级联在本例中由模型自主发起,体现"工具化"的真正价值——模型能力通过工具组合被成倍放大。
指南同时指出,gradio_tools 仓库内置了一批开箱即用的预置工具(完整清单见其仓库 README),并在首章代码中演示了其中四把。若内置工具无法覆盖你的需求,也可以非常容易地封装自己的工具——这正是下一节的核心。
GradioTool 抽象:自定义工具的标准接口
gradio_tools 的核心抽象是 GradioTool。它继承 LangChain 的 BaseTool,只要开发者实现一组标准接口,就能把自己的 Gradio 应用变成一把 LLM 工具。文档给出的骨架如下:
class GradioTool(BaseTool):
def __init__(self, name: str, description: str, src: str) -> None:
@abstractmethod
def create_job(self, query: str) -> Job:
pass
@abstractmethod
def postprocess(self, output: Tuple[Any] | Any) -> str:
pass
按文档的说明,实现一把工具需要满足以下要求(这也是实现层面最值得逐条咀嚼的部分):
name(工具名):LLM 在推理中据以指代这把工具的唯一标识,应简洁、无歧义。description(工具描述)——至关重要:Agent 完全依靠 description 来决定何时调用哪把工具。务必精确定义工具的职责,并且给出输入与输出分别长什么样的示例,例如"输入应是图片内容的文字描述,输出是一个图片文件的路径"。描述含糊,模型就会选错工具或用错参数。src(Gradio 应用地址):既可以是完整 URL,也可以是 Hugging Face Space ID(如freddyaboulton/calculator)。gradio_tools会依据该值创建一个 gradio client 实例,通过其 API 协议与上游应用通信。此前提是:上游 Gradio 应用本身要能被 client 解析并暴露可调用的接口。create_job(query):给定一个字符串输入,解析后返回一个来自 client 的Job。大多数场景下,只需把字符串透传给 client 的submit函数即可;更复杂的输入解析(如"从一段话中抽取多个槽位值")也可在此完成。postprocess(output):拿到Job结果后,将其转换成 LLM 可以展示给用户的字符串。Gradio 组件的原生输出形态(文件路径、元组、对象等)通常不适合直接"投喂"给文本模型,这一步负责做收敛与格式化。- (可选)
_block_input(gr)/_block_output(gr):某些框架(文档中举例 MiniChain 这类需要感知组件类型的库)可能要求了解工具底层 Gradio 的输入/输出组件类型。默认实现会返回gr.Textbox();如需更精确的类型信息,可自行覆写这两个方法。注意gr参数是import gradio as gr得到的 gradio 模块对象,由GradioTool父类自动导入并注入,无需自己 import。
可以看到,设计哲学是"薄封装":工具类只需告诉系统(名字、描述、地址)以及两头(怎么发起调用、怎么把结果变成文本),中间的全部通信由 gradio_client 完成。
实例解读:StableDiffusionTool
文档以图片生成工具为范例,给出了 gradio_tools 内置 StableDiffusionTool 的参考实现(注意示例中导入写法 from gradio_tool import GradioTool 与上下文 from gradio_tools import ... 略有出入,实际使用时请以所安装的 gradio_tools 包公开的导入路径为准):
from gradio_tool import GradioTool
import os
class StableDiffusionTool(GradioTool):
"""Tool for calling stable diffusion from llm"""
def __init__(
self,
name="StableDiffusion",
description=(
"An image generator. Use this to generate images based on "
"text input. Input should be a description of what the image should "
"look like. The output will be a path to an image file."
),
src="gradio-client-demos/stable-diffusion",
token=None,
) -> None:
super().__init__(name, description, src, token)
def create_job(self, query: str) -> Job:
return self.client.submit(query, "", 9, fn_index=1)
def postprocess(self, output: str) -> str:
return [os.path.join(output, i) for i in os.listdir(output) if not i.endswith("json")][0]
def _block_input(self, gr) -> "gr.components.Component":
return gr.Textbox()
def _block_output(self, gr) -> "gr.components.Component":
return gr.Image()
文档对本实现的注解非常值得逐条对照源码理解:
self.client属性:所有GradioTool实例都自带一个指向底层应用的 gradio client,create_job中使用的正是它。映射到本仓库,self.client就是 gradio_client/client.py 中的Client类实例——其__init__接收src(Space 名或完整 URL)、token(访问私有 Space)、auth、download_files、ssl_verify等参数,随后探测应用配置与协议并完成端到端握手。create_job只是把参数透传给submit:self.client.submit(query, "", 9, fn_index=1)中,query是用户提示词,""与9分别是硬编码的负面提示词与采样数量。从本仓库 Client.submit 的实现 看,submit在后台线程中发起调用并立刻返回一个Job(fn_index用于在应用存在多个 API 端点时按索引选取目标端点,见其 docstring;predict则是等价的阻塞式调用,位于同文件更早处)。文档特别提醒:后续版本完全可以让工具解析输入串中的这些附加参数,而不必硬编码。postprocess取回第一张图:Stable Diffusion Space 的gallery会返回一组图片,此方法借助os模块遍历输出目录,过滤掉.json后缀(协议元数据文件),返回第一张图片的完整本地路径——这正是要交给 LLM 的字符串形态。_block_input/_block_output:声明该工具底层分别是文本输入与图片输出,为需要组件类型感知的第三方框架提供准确信息。
顺带一提,本仓库的 demo/stable-diffusion/run.py 就是一个可在本地起服务的 Stable Diffusion 演示应用:它把提示词、采样数、步数、引导系数(Guidance Scale)、随机种子暴露为 UI 控件,生成结果输出到 gr.Gallery。该文件验证了两点:其一,任何此类应用都能按"API 端点"被 client 寻址调用;其二,submit(query, "", 9, fn_index=1) 中逐位置传参的方式,本质上对应着上游应用某个端点按序暴露的参数(本工具额外依赖示例托管 Space 自身的布局,因此 fn_index=1 指向该托管应用的特定端点)。
链路复盘:一条用户指令如何穿越五层
把上面的代码串起来,一条完整指令的运行链路是:
- 用户把复合任务交给 Agent(LLM);
- LLM 依据各工具的
description决定调用顺序(如先 PromptGenerator 再 StableDiffusion); - 工具实例的
create_job通过gradio_client.Client.submit()向远程 Gradio 应用发起请求,得到后台运行的Job(submit非阻塞、返回后即可继续,符合 Agent 多步推理的节奏;Job在 client.py 中实现,其result()会阻塞等待结果返回); - 远程 Gradio 应用完成推理后,
postprocess把原生输出(文件、元组、对象)收敛成字符串; - LLM 拿到字符串继续推理,最终汇总成面向用户的自然语言答案。
在这一链路里,gradio_client 是本仓库真正落地通信协议的模块:例如 Job 的状态轮询依赖 Status 枚举与 StatusUpdate(定义见 gradio_client/utils.py),view_api() 则能打印/返回端点签名辅助调试(见 client.py 的 view_api 实现)。想进一步了解 client 的能力边界(predict/submit/回调/会话态等),可阅读指南 Getting Started with the Gradio Python client。
适用范围与版本演进提示
- 本文所复现的 Agent 组装代码(
from langchain.llms import OpenAI、initialize_agent(...)、agent="conversational-react-description")对应的是文档撰写时期 LangChain 的 API 形态。LangChain 的模块划分与 Agent 构造方式随版本迭代变化较大,若按原文运行遇到导入错误,请以你所安装的 langchain 版本为准调整(例如新版将 LLM 实现迁移至独立的langchain-openai等包,并提供新的 Agent 构造入口)。 gradio_tools是独立于本仓库的第三方库,其工具封装层面依赖的"应用即 API"能力则由本仓库的gradio_client提供;确保本地gradio_client为较新版本,可避免协议兼容问题。GradioTool的接口契约(含可选方法)并不绑定某个具体 Agent 框架,它同样适用于 MiniChain 等需要组件类型信息的框架,只不过这些框架会额外调用_block_input/_block_output。
结语
如文档结语所言,借助 gradio_tools,你可以让自己的 LLM 拥有访问生态中大量在运行的 Gradio Space 的能力——先写好 GradioTool 的六个要点(名字、精准描述、应用地址、create_job、postprocess,以及可选的组件类型声明),再把它加入 Agent 的武器库即可。本仓库侧的重点始终是 gradio_client 这条"翻译官"链路:它是工具实例与远端应用之间的唯一通信通道,理解了 Client.submit / Job / fn_index 的语义,你写的每一个新工具就都能精准命中上游应用的 API。文档也欢迎开发者将自己实现的工具提交回 gradio_tools 仓库,让更多 Agent 共享这些能力。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00