Gradio Agents & MCP 黑客马拉松
获奖者Gradio Agents & MCP 黑客马拉松
获奖者本指南将涵盖实现自定义组件前端所需的一切知识。
提示: Gradio 组件使用 Svelte。编写 Svelte 很有趣!如果你不熟悉它,我们建议查看其交互式[指南](https://learn.svelte.dev/tutorial/welcome-to-svelte)。
前端代码至少应包含以下三个文件:
Index.svelte
: 这是主要导出文件,组件的布局和逻辑应在此处。Example.svelte
: 这里定义了组件的示例视图。你可以随意添加额外的文件和子目录。如果你想导出任何额外的模块,请记住修改 package.json
文件
"exports": {
".": "./Index.svelte",
"./example": "./Example.svelte",
"./package.json": "./package.json"
},
你的组件应公开以下将从父 Gradio 应用程序传递下来的 props。
import type { LoadingStatus } from "@gradio/statustracker";
import type { Gradio } from "@gradio/utils";
export let gradio: Gradio<{
event_1: never;
event_2: never;
}>;
export let elem_id = "";
export let elem_classes: string[] = [];
export let scale: number | null = null;
export let min_width: number | undefined = undefined;
export let loading_status: LoadingStatus | undefined = undefined;
export let mode: "static" | "interactive";
elem_id
和 elem_classes
允许 Gradio 应用开发者使用 Python Blocks
类针对你的组件进行自定义 CSS 和 JavaScript。
scale
和 min_width
允许 Gradio 应用开发者控制你的组件在 UI 中占据的空间大小。
当组件是事件的输出时,loading_status
用于在组件上方显示加载状态。
mode
是父 Gradio 应用告诉你的组件应该显示交互
版本还是静态
版本的方式。
gradio
: gradio
对象由父 Gradio 应用创建。它存储了一些对你的组件有用的应用级配置,例如国际化。你必须使用它从组件分派事件。
一个最小的 Index.svelte
文件如下所示:
<script lang="ts">
import type { LoadingStatus } from "@gradio/statustracker";
import { Block } from "@gradio/atoms";
import { StatusTracker } from "@gradio/statustracker";
import type { Gradio } from "@gradio/utils";
export let gradio: Gradio<{
event_1: never;
event_2: never;
}>;
export let value = "";
export let elem_id = "";
export let elem_classes: string[] = [];
export let scale: number | null = null;
export let min_width: number | undefined = undefined;
export let loading_status: LoadingStatus | undefined = undefined;
export let mode: "static" | "interactive";
</script>
<Block
visible={true}
{elem_id}
{elem_classes}
{scale}
{min_width}
allow_overflow={false}
padding={true}
>
{#if loading_status}
<StatusTracker
autoscroll={gradio.autoscroll}
i18n={gradio.i18n}
{...loading_status}
/>
{/if}
<p>{value}</p>
</Block>
Example.svelte
文件应公开以下 props
export let value: string;
export let type: "gallery" | "table";
export let selected = false;
export let index: number;
value
: 应该显示的示例值。
type
: 这是一个变量,可以是 "gallery"
或 "table"
,具体取决于示例的显示方式。当示例对应于单个输入组件时,使用 "gallery"
形式;当用户有多个输入组件且需要填充所有组件时,使用 "table"
形式。
selected
: 你还可以通过使用 selected 变量来调整示例的显示方式(如果用户“选择”了特定示例)。
index
: 当前选中值的索引。
你的“非示例”组件接受的任何额外 props!
这是代码 Radio
组件的 Example.svelte
文件
<script lang="ts">
export let value: string;
export let type: "gallery" | "table";
export let selected = false;
</script>
<div
class:table={type === "table"}
class:gallery={type === "gallery"}
class:selected
>
{value}
</div>
<style>
.gallery {
padding: var(--size-1) var(--size-2);
}
</style>
如果你的组件处理文件,这些文件应该上传到后端服务器。@gradio/client
npm 包提供了 upload
和 prepare_files
实用函数来帮助你完成此操作。
prepare_files
函数会将浏览器的 File
数据类型转换为 gradio 的内部 FileData
类型。你应在组件中使用 FileData
数据来跟踪上传的文件。
upload
函数会将 FileData
值的数组上传到服务器。
这是一个从 <input>
元素加载文件并在其值更改时处理的示例。
<script lang="ts">
import { upload, prepare_files, type FileData } from "@gradio/client";
export let root;
export let value;
let uploaded_files;
async function handle_upload(file_data: FileData[]): Promise<void> {
await tick();
uploaded_files = await upload(file_data, root);
}
async function loadFiles(files: FileList): Promise<void> {
let _files: File[] = Array.from(files);
if (!files.length) {
return;
}
if (file_count === "single") {
_files = [files[0]];
}
let file_data = await prepare_files(_files);
await handle_upload(file_data);
}
async function loadFilesFromUpload(e: Event): Promise<void> {
const target = e.target;
if (!target.files) return;
await loadFiles(target.files);
}
</script>
<input
type="file"
on:change={loadFilesFromUpload}
multiple={true}
/>
该组件公开了一个名为 root
的 prop。这是由父 Gradio 应用程序传递下来的,它代表文件将上传和获取的基础 URL。
对于 WASM 支持,你应该从 Context
获取上传函数,并将其作为 upload
函数的第三个参数传递。
<script lang="ts">
import { getContext } from "svelte";
const upload_fn = getContext<typeof upload_files>("upload_files");
async function handle_upload(file_data: FileData[]): Promise<void> {
await tick();
await upload(file_data, root, upload_fn);
}
</script>
大多数 Gradio 前端组件都发布在 npm,这是一个 JavaScript 包仓库。这意味着你可以使用它们来节省时间,同时在组件中融入常见模式,例如文件上传。例如,@gradio/upload
包包含 Upload
和 ModifyUpload
组件,用于正确将文件上传到 Gradio 服务器。以下是如何使用它们来创建用户界面以上传和显示 PDF 文件。
<script>
import { type FileData, Upload, ModifyUpload } from "@gradio/upload";
import { Empty, UploadText, BlockLabel } from "@gradio/atoms";
</script>
<BlockLabel Icon={File} label={label || "PDF"} />
{#if value === null && interactive}
<Upload
filetype="application/pdf"
on:load={handle_load}
{root}
>
<UploadText type="file" i18n={gradio.i18n} />
</Upload>
{:else if value !== null}
{#if interactive}
<ModifyUpload i18n={gradio.i18n} on:clear={handle_clear}/>
{/if}
<iframe title={value.orig_name || "PDF"} src={value.data} height="{height}px" width="100%"></iframe>
{:else}
<Empty size="large"> <File/> </Empty>
{/if}
你还可以组合现有 Gradio 组件来创建完全独特的体验。例如,渲染聊天机器人对话的图库。可能性是无限的,请在此处阅读我们的 JavaScript 包文档。我们将在未来几周内添加更多包和文档!
你可以通过 Storybook 浏览我们的组件库。你将能够与我们的组件进行交互,并查看它们在各种状态下的表现。
对于那些对设计定制感兴趣的人,我们提供了包含我们调色板、半径、间距和所用图标的 CSS 变量——这样你就可以轻松地将自定义组件与我们核心组件的样式匹配起来。此 Storybook 将定期更新,包含任何新增内容或更改。
如果你想利用庞大的 Vite 生态系统,可以使用 gradio.config.js
文件来配置组件的构建过程。这允许你使用 tailwindcss、mdsvex 等工具。
目前,可以配置以下内容:
Vite 选项
plugins
: 要使用的 Vite 插件列表。Svelte 选项
preprocess
: 要使用的 Svelte 预处理器列表。extensions
: 要编译为 .svelte
文件的文件扩展名列表。build.target
: 构建目标,这可能对于支持较新的 JavaScript 功能是必要的。有关更多信息,请参阅 esbuild 文档。gradio.config.js
文件应放在组件的 frontend
目录的根目录中。当你创建新组件时,会为你创建一个默认配置文件。但你也可以创建自己的配置文件(如果不存在),并用它来自定义组件的构建过程。
自定义组件可以使用 Vite 插件来定制构建过程。有关更多信息,请查看 Vite 文档。
这里我们配置 TailwindCSS,这是一个实用优先的 CSS 框架。使用版本 4 预发布版设置最简单。
npm install tailwindcss@next @tailwindcss/vite@next
在 gradio.config.js
中
import tailwindcss from "@tailwindcss/vite";
export default {
plugins: [tailwindcss()]
};
然后创建一个 style.css
文件,内容如下
@import "tailwindcss";
将此文件导入 Index.svelte
。请注意,你需要导入包含 @import
的 CSS 文件,而不能只使用 <style>
标签并在其中使用 @import
。
<script lang="ts">
[...]
import "./style.css";
[...]
</script>
在 gradio.config.js
中,你还可以指定一些 Svelte 选项来应用于 Svelte 编译。在此示例中,我们将添加对 mdsvex
的支持,它是一个用于 Svelte 的 Markdown 预处理器。
为了实现这一点,我们需要在 gradio.config.js
的 svelte
对象中添加一个 Svelte 预处理器,并配置 extensions
字段。其他选项目前不支持。
首先,安装 mdsvex
插件
npm install mdsvex
然后将以下内容添加到 gradio.config.js
中
import { mdsvex } from "mdsvex";
export default {
svelte: {
preprocess: [
mdsvex()
],
extensions: [".svelte", ".svx"]
}
};
现在我们可以在组件的 frontend
目录中创建 mdsvex
文档,它们将被编译成 .svelte
文件。
<!-- HelloWorld.svx -->
<script lang="ts">
import { Block } from "@gradio/atoms";
export let title = "Hello World";
</script>
<Block label="Hello World">
# {title}
This is a markdown file.
</Block>
然后我们可以在组件中使用 HelloWorld.svx
文件
<script lang="ts">
import HelloWorld from "./HelloWorld.svx";
</script>
<HelloWorld />
你现在知道如何为组件创建令人愉悦的前端了!